@luxfi/ui 7.4.5 → 7.4.7
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/dist/accordion.d.cts +74 -0
- package/dist/accordion.d.ts +74 -0
- package/dist/alert.cjs +3 -7
- package/dist/alert.d.cts +30 -0
- package/dist/alert.d.ts +30 -0
- package/dist/alert.js +3 -7
- package/dist/auth.cjs +481 -0
- package/dist/auth.d.cts +80 -0
- package/dist/auth.d.ts +80 -0
- package/dist/auth.js +456 -0
- package/dist/avatar.d.cts +25 -0
- package/dist/avatar.d.ts +25 -0
- package/dist/badge.cjs +4 -8
- package/dist/badge.d.cts +19 -0
- package/dist/badge.d.ts +19 -0
- package/dist/badge.js +4 -8
- package/dist/bank.d.cts +83 -0
- package/dist/bank.d.ts +83 -0
- package/dist/button.cjs +3 -7
- package/dist/button.d.cts +55 -0
- package/dist/button.d.ts +55 -0
- package/dist/button.js +3 -7
- package/dist/checkbox.d.cts +32 -0
- package/dist/checkbox.d.ts +32 -0
- package/dist/chrome.d.cts +93 -0
- package/dist/chrome.d.ts +93 -0
- package/dist/close-button.d.cts +9 -0
- package/dist/close-button.d.ts +9 -0
- package/dist/collapsible.cjs +3 -7
- package/dist/collapsible.d.cts +23 -0
- package/dist/collapsible.d.ts +23 -0
- package/dist/collapsible.js +3 -7
- package/dist/color-mode.d.cts +25 -0
- package/dist/color-mode.d.ts +25 -0
- package/dist/dialog.d.cts +118 -0
- package/dist/dialog.d.ts +118 -0
- package/dist/drawer.d.cts +36 -0
- package/dist/drawer.d.ts +36 -0
- package/dist/empty-state.d.cts +13 -0
- package/dist/empty-state.d.ts +13 -0
- package/dist/expiration-selector.d.cts +16 -0
- package/dist/expiration-selector.d.ts +16 -0
- package/dist/field.d.cts +24 -0
- package/dist/field.d.ts +24 -0
- package/dist/greeks-display.d.cts +14 -0
- package/dist/greeks-display.d.ts +14 -0
- package/dist/gui.d.cts +2 -0
- package/dist/gui.d.ts +2 -0
- package/dist/heading.d.cts +10 -0
- package/dist/heading.d.ts +10 -0
- package/dist/iam.d.cts +65 -0
- package/dist/iam.d.ts +65 -0
- package/dist/icon-button.cjs +3 -7
- package/dist/icon-button.d.cts +33 -0
- package/dist/icon-button.d.ts +33 -0
- package/dist/icon-button.js +3 -7
- package/dist/icons.cjs +0 -1
- package/dist/icons.d.cts +1 -0
- package/dist/icons.d.ts +1 -0
- package/dist/icons.js +0 -1
- package/dist/identity.d.cts +64 -0
- package/dist/identity.d.ts +64 -0
- package/dist/image.cjs +3 -7
- package/dist/image.d.cts +57 -0
- package/dist/image.d.ts +57 -0
- package/dist/image.js +3 -7
- package/dist/index.cjs +9 -8
- package/dist/index.d.cts +64 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.js +9 -9
- package/dist/input-group.d.cts +17 -0
- package/dist/input-group.d.ts +17 -0
- package/dist/input.d.cts +17 -0
- package/dist/input.d.ts +17 -0
- package/dist/link.cjs +3 -7
- package/dist/link.d.cts +37 -0
- package/dist/link.d.ts +37 -0
- package/dist/link.js +3 -7
- package/dist/lux.config.d.cts +433 -0
- package/dist/lux.config.d.ts +433 -0
- package/dist/menu.d.cts +84 -0
- package/dist/menu.d.ts +84 -0
- package/dist/next.cjs +11 -1
- package/dist/next.d.cts +32 -0
- package/dist/next.d.ts +32 -0
- package/dist/next.js +11 -1
- package/dist/option-chain.d.cts +37 -0
- package/dist/option-chain.d.ts +37 -0
- package/dist/option-position.d.cts +29 -0
- package/dist/option-position.d.ts +29 -0
- package/dist/pin-input.d.cts +25 -0
- package/dist/pin-input.d.ts +25 -0
- package/dist/pnl-diagram.d.cts +11 -0
- package/dist/pnl-diagram.d.ts +11 -0
- package/dist/popover.d.cts +73 -0
- package/dist/popover.d.ts +73 -0
- package/dist/progress-circle.d.cts +47 -0
- package/dist/progress-circle.d.ts +47 -0
- package/dist/progress.d.cts +28 -0
- package/dist/progress.d.ts +28 -0
- package/dist/provider.d.cts +25 -0
- package/dist/provider.d.ts +25 -0
- package/dist/radio.d.cts +53 -0
- package/dist/radio.d.ts +53 -0
- package/dist/rating.d.cts +14 -0
- package/dist/rating.d.ts +14 -0
- package/dist/select.cjs +3 -7
- package/dist/select.d.cts +130 -0
- package/dist/select.d.ts +130 -0
- package/dist/select.js +3 -7
- package/dist/separator.d.cts +13 -0
- package/dist/separator.d.ts +13 -0
- package/dist/skeleton.cjs +8 -7
- package/dist/skeleton.d.cts +76 -0
- package/dist/skeleton.d.ts +76 -0
- package/dist/skeleton.js +8 -8
- package/dist/slider.d.cts +24 -0
- package/dist/slider.d.ts +24 -0
- package/dist/strategy-builder.d.cts +26 -0
- package/dist/strategy-builder.d.ts +26 -0
- package/dist/switch.d.cts +27 -0
- package/dist/switch.d.ts +27 -0
- package/dist/table.cjs +3 -7
- package/dist/table.d.cts +107 -0
- package/dist/table.d.ts +107 -0
- package/dist/table.js +3 -7
- package/dist/tabs.d.cts +78 -0
- package/dist/tabs.d.ts +78 -0
- package/dist/tag.cjs +4 -8
- package/dist/tag.d.cts +21 -0
- package/dist/tag.d.ts +21 -0
- package/dist/tag.js +4 -8
- package/dist/textarea.d.cts +13 -0
- package/dist/textarea.d.ts +13 -0
- package/dist/toaster.d.cts +29 -0
- package/dist/toaster.d.ts +29 -0
- package/dist/tooltip.cjs +1 -1
- package/dist/tooltip.d.cts +38 -0
- package/dist/tooltip.d.ts +38 -0
- package/dist/tooltip.js +1 -1
- package/dist/use-narrow.d.cts +12 -0
- package/dist/use-narrow.d.ts +12 -0
- package/dist/utils.d.cts +5 -0
- package/dist/utils.d.ts +5 -0
- package/dist/vite.cjs +4 -3
- package/dist/vite.d.cts +29 -0
- package/dist/vite.d.ts +29 -0
- package/dist/vite.js +4 -3
- package/dist/white-label.d.cts +59 -0
- package/dist/white-label.d.ts +59 -0
- package/package.json +12 -2
- package/src/auth.tsx +198 -0
- package/src/engine.ts +24 -3
- package/src/index.ts +1 -1
- package/src/next.ts +10 -0
- package/src/skeleton.tsx +36 -7
- package/src/tooltip.tsx +13 -5
- package/src/vite.ts +4 -9
- package/tokens.css +828 -317
package/tokens.css
CHANGED
|
@@ -1,438 +1,949 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
2
|
+
* @luxfi/ui — THE canonical token set.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Lux is monochrome. One achromatic ladder, plus exactly two hues reserved for
|
|
5
|
+
* state (error, success). Nothing else carries colour: no orange, no amber, no
|
|
6
|
+
* gold, no tan. Every value below either IS a ladder rung or is `var()`-derived
|
|
7
|
+
* from one — so a hostname can retheme the fleet by overriding a handful of
|
|
8
|
+
* custom properties, with no rebuild.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* Layers, in resolution order:
|
|
11
|
+
* 1. ladder --lux-n-* achromatic, hue-free (Tailwind `neutral`)
|
|
12
|
+
* 2. brand hooks --lux-accent white-label-by-hostname overrides ONLY these
|
|
13
|
+
* 3. state --lux-state-* the only permitted hues (error / success)
|
|
14
|
+
* 4. semantic --color-* what components actually name
|
|
15
|
+
* 5. aliases shadcn (--background … --chart-*) so a Tailwind surface can
|
|
16
|
+
* drop its hand-rolled palette and import this instead
|
|
10
17
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* gray.100 = #F5F5F5 gray.600 = #525252
|
|
14
|
-
* gray.200 = #E5E5E5 gray.700 = #404040
|
|
15
|
-
* gray.300 = #D4D4D4 gray.800 = #262626
|
|
16
|
-
* gray.400 = #A3A3A3 gray.900 = #171717
|
|
18
|
+
* Light mode is :root. Dark mode activates via `.dark` (next-themes class
|
|
19
|
+
* strategy) or [data-theme='dark'].
|
|
17
20
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* blackAlpha.200 = rgba(16,17,18,0.08) whiteAlpha.200 = rgba(255,255,255,0.08)
|
|
21
|
-
* blackAlpha.300 = rgba(16,17,18,0.16) whiteAlpha.300 = rgba(255,255,255,0.16)
|
|
22
|
-
* blackAlpha.400 = rgba(16,17,18,0.24) whiteAlpha.400 = rgba(255,255,255,0.24)
|
|
23
|
-
* blackAlpha.500 = rgba(16,17,18,0.36) whiteAlpha.500 = rgba(255,255,255,0.36)
|
|
24
|
-
* blackAlpha.600 = rgba(16,17,18,0.48) whiteAlpha.600 = rgba(255,255,255,0.48)
|
|
25
|
-
* blackAlpha.700 = rgba(16,17,18,0.64) whiteAlpha.700 = rgba(255,255,255,0.64)
|
|
26
|
-
* blackAlpha.800 = rgba(16,17,18,0.80) whiteAlpha.800 = rgba(255,255,255,0.80)
|
|
27
|
-
* blackAlpha.900 = rgba(16,17,18,0.92) whiteAlpha.900 = rgba(255,255,255,0.92)
|
|
21
|
+
* Rule: a component may not contain a colour literal. If a value is missing
|
|
22
|
+
* here, add it here.
|
|
28
23
|
*/
|
|
29
24
|
|
|
30
25
|
/* ================================================================
|
|
31
|
-
|
|
26
|
+
1 — THE LADDER. Achromatic: R = G = B at every rung.
|
|
27
|
+
================================================================ */
|
|
28
|
+
:root {
|
|
29
|
+
--lux-n-0: #FFFFFF;
|
|
30
|
+
--lux-n-50: #FAFAFA;
|
|
31
|
+
--lux-n-100: #F5F5F5;
|
|
32
|
+
--lux-n-200: #E5E5E5;
|
|
33
|
+
--lux-n-300: #D4D4D4;
|
|
34
|
+
--lux-n-400: #A3A3A3;
|
|
35
|
+
--lux-n-500: #737373;
|
|
36
|
+
--lux-n-600: #525252;
|
|
37
|
+
--lux-n-700: #404040;
|
|
38
|
+
--lux-n-800: #262626;
|
|
39
|
+
--lux-n-900: #171717;
|
|
40
|
+
--lux-n-950: #0A0A0A;
|
|
41
|
+
--lux-n-1000: #000000;
|
|
42
|
+
|
|
43
|
+
/* The opacity ladder — the real palette for overlays and hairlines. */
|
|
44
|
+
--lux-ink-04: rgba(16, 17, 18, 0.04);
|
|
45
|
+
--lux-ink-06: rgba(16, 17, 18, 0.06);
|
|
46
|
+
--lux-ink-08: rgba(16, 17, 18, 0.08);
|
|
47
|
+
--lux-ink-10: rgba(16, 17, 18, 0.10);
|
|
48
|
+
--lux-ink-16: rgba(16, 17, 18, 0.16);
|
|
49
|
+
--lux-ink-24: rgba(16, 17, 18, 0.24);
|
|
50
|
+
--lux-ink-36: rgba(16, 17, 18, 0.36);
|
|
51
|
+
--lux-ink-48: rgba(16, 17, 18, 0.48);
|
|
52
|
+
--lux-ink-64: rgba(16, 17, 18, 0.64);
|
|
53
|
+
--lux-ink-80: rgba(16, 17, 18, 0.80);
|
|
54
|
+
--lux-ink-92: rgba(16, 17, 18, 0.92);
|
|
55
|
+
--lux-paper-04: rgba(255, 255, 255, 0.04);
|
|
56
|
+
--lux-paper-06: rgba(255, 255, 255, 0.06);
|
|
57
|
+
--lux-paper-08: rgba(255, 255, 255, 0.08);
|
|
58
|
+
--lux-paper-10: rgba(255, 255, 255, 0.10);
|
|
59
|
+
--lux-paper-12: rgba(255, 255, 255, 0.12);
|
|
60
|
+
--lux-paper-16: rgba(255, 255, 255, 0.16);
|
|
61
|
+
--lux-paper-24: rgba(255, 255, 255, 0.24);
|
|
62
|
+
--lux-paper-36: rgba(255, 255, 255, 0.36);
|
|
63
|
+
--lux-paper-48: rgba(255, 255, 255, 0.48);
|
|
64
|
+
--lux-paper-64: rgba(255, 255, 255, 0.64);
|
|
65
|
+
--lux-paper-80: rgba(255, 255, 255, 0.80);
|
|
66
|
+
--lux-paper-92: rgba(255, 255, 255, 0.92);
|
|
67
|
+
|
|
68
|
+
/* ------------------------------------------------------------
|
|
69
|
+
2 — BRAND HOOKS. resolveWhiteLabel(host) writes these two and
|
|
70
|
+
nothing else. Default is monochrome: the accent is the ink.
|
|
71
|
+
------------------------------------------------------------ */
|
|
72
|
+
--lux-accent: var(--lux-n-900);
|
|
73
|
+
--lux-accent-fg: var(--lux-n-0);
|
|
74
|
+
|
|
75
|
+
/* ------------------------------------------------------------
|
|
76
|
+
3 — STATE. The ONLY permitted hues. Both meet WCAG AA (>=4.5:1)
|
|
77
|
+
as text on the --lux-n-50 card fill.
|
|
78
|
+
------------------------------------------------------------ */
|
|
79
|
+
--lux-state-error: #B91C1C;
|
|
80
|
+
--lux-state-success: #1A7A47;
|
|
81
|
+
/* Attention/pending is NOT a hue in Lux. It is the loudest neutral. */
|
|
82
|
+
--lux-state-notice: var(--lux-n-600);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ================================================================
|
|
86
|
+
4 — SEMANTIC (light). Every value is a var() off the ladder.
|
|
32
87
|
================================================================ */
|
|
33
88
|
:root {
|
|
34
89
|
/* --- Backgrounds --- */
|
|
35
|
-
--color-bg-primary:
|
|
36
|
-
--color-bg-info:
|
|
37
|
-
--color-bg-body:
|
|
90
|
+
--color-bg-primary: var(--lux-n-0);
|
|
91
|
+
--color-bg-info: var(--lux-n-50);
|
|
92
|
+
--color-bg-body: var(--lux-n-0);
|
|
38
93
|
|
|
39
94
|
/* --- Foregrounds --- */
|
|
40
|
-
--color-fg-info:
|
|
95
|
+
--color-fg-info: var(--lux-n-600);
|
|
41
96
|
|
|
42
97
|
/* --- Text --- */
|
|
43
|
-
--color-text-primary:
|
|
44
|
-
--color-text-secondary:
|
|
45
|
-
--color-text-error:
|
|
46
|
-
--color-text-success:
|
|
98
|
+
--color-text-primary: var(--lux-ink-80);
|
|
99
|
+
--color-text-secondary: var(--lux-n-500);
|
|
100
|
+
--color-text-error: var(--lux-state-error);
|
|
101
|
+
--color-text-success: var(--lux-state-success);
|
|
102
|
+
|
|
103
|
+
/* --- Status foreground (AA >=4.5:1 on the --lux-n-50 card bg) --- */
|
|
104
|
+
--color-status-good: var(--lux-state-success);
|
|
105
|
+
--color-status-warn: var(--lux-state-notice);
|
|
106
|
+
--color-status-bad: var(--lux-state-error);
|
|
47
107
|
|
|
48
108
|
/* --- Headings --- */
|
|
49
|
-
--color-heading:
|
|
109
|
+
--color-heading: var(--lux-ink-80);
|
|
50
110
|
|
|
51
111
|
/* --- Icons --- */
|
|
52
|
-
--color-icon-primary:
|
|
53
|
-
--color-icon-secondary:
|
|
112
|
+
--color-icon-primary: var(--lux-n-500);
|
|
113
|
+
--color-icon-secondary: var(--lux-n-400);
|
|
54
114
|
|
|
55
115
|
/* --- Borders --- */
|
|
56
|
-
--color-border-divider:
|
|
57
|
-
--color-border-error:
|
|
58
|
-
--color-border-info:
|
|
116
|
+
--color-border-divider: var(--lux-ink-06);
|
|
117
|
+
--color-border-error: var(--lux-state-error);
|
|
118
|
+
--color-border-info: var(--lux-n-400);
|
|
59
119
|
|
|
60
120
|
/* --- Links --- */
|
|
61
|
-
--color-link-primary:
|
|
62
|
-
--color-link-primary-hover:
|
|
63
|
-
--color-link-secondary:
|
|
64
|
-
--color-link-subtle:
|
|
65
|
-
--color-link-subtle-hover:
|
|
66
|
-
--color-link-menu:
|
|
67
|
-
--color-link-underlaid-bg:
|
|
68
|
-
--color-link-nav-fg:
|
|
69
|
-
--color-link-nav-fg-hover:
|
|
70
|
-
--color-link-nav-fg-selected:
|
|
71
|
-
--color-link-nav-fg-active:
|
|
72
|
-
--color-link-nav-bg-selected:
|
|
121
|
+
--color-link-primary: var(--lux-n-700);
|
|
122
|
+
--color-link-primary-hover: var(--lux-n-600);
|
|
123
|
+
--color-link-secondary: var(--lux-n-500);
|
|
124
|
+
--color-link-subtle: var(--lux-ink-80);
|
|
125
|
+
--color-link-subtle-hover: var(--lux-ink-80);
|
|
126
|
+
--color-link-menu: var(--lux-ink-80);
|
|
127
|
+
--color-link-underlaid-bg: var(--lux-n-100);
|
|
128
|
+
--color-link-nav-fg: var(--lux-ink-80);
|
|
129
|
+
--color-link-nav-fg-hover: var(--lux-n-600);
|
|
130
|
+
--color-link-nav-fg-selected: var(--lux-n-900);
|
|
131
|
+
--color-link-nav-fg-active: var(--lux-n-600);
|
|
132
|
+
--color-link-nav-bg-selected: var(--lux-n-100);
|
|
73
133
|
|
|
74
134
|
/* --- Buttons --- */
|
|
75
|
-
--color-button-solid-bg:
|
|
76
|
-
--color-button-solid-text:
|
|
77
|
-
--color-button-outline-fg:
|
|
78
|
-
--color-button-subtle-fg:
|
|
79
|
-
--color-button-subtle-bg:
|
|
80
|
-
--color-button-dropdown-fg:
|
|
81
|
-
--color-button-dropdown-border:
|
|
82
|
-
--color-button-header-fg:
|
|
83
|
-
--color-button-header-fg-selected:
|
|
84
|
-
--color-button-header-fg-highlighted:
|
|
85
|
-
--color-button-header-border:
|
|
86
|
-
--color-button-header-bg-selected:
|
|
87
|
-
--color-button-header-bg-highlighted:
|
|
88
|
-
--color-button-pagination-fg:
|
|
89
|
-
--color-button-pagination-border:
|
|
90
|
-
--color-button-icon-background-bg:
|
|
91
|
-
--color-button-hero-bg:
|
|
92
|
-
--color-button-hero-fg:
|
|
93
|
-
--color-button-hero-bg-hover:
|
|
94
|
-
--color-button-hero-fg-hover:
|
|
95
|
-
--color-button-hero-bg-selected:
|
|
96
|
-
--color-button-hero-fg-selected:
|
|
97
|
-
--color-button-segmented-fg:
|
|
98
|
-
--color-button-icon-bg:
|
|
135
|
+
--color-button-solid-bg: var(--lux-accent);
|
|
136
|
+
--color-button-solid-text: var(--lux-accent-fg);
|
|
137
|
+
--color-button-outline-fg: var(--lux-n-900);
|
|
138
|
+
--color-button-subtle-fg: var(--lux-ink-80);
|
|
139
|
+
--color-button-subtle-bg: var(--lux-ink-08);
|
|
140
|
+
--color-button-dropdown-fg: var(--lux-ink-80);
|
|
141
|
+
--color-button-dropdown-border: var(--lux-n-100);
|
|
142
|
+
--color-button-header-fg: var(--lux-ink-80);
|
|
143
|
+
--color-button-header-fg-selected: var(--lux-ink-80);
|
|
144
|
+
--color-button-header-fg-highlighted: var(--lux-ink-80);
|
|
145
|
+
--color-button-header-border: var(--lux-n-100);
|
|
146
|
+
--color-button-header-bg-selected: var(--lux-ink-04);
|
|
147
|
+
--color-button-header-bg-highlighted: var(--lux-n-200);
|
|
148
|
+
--color-button-pagination-fg: var(--lux-ink-80);
|
|
149
|
+
--color-button-pagination-border: var(--lux-n-100);
|
|
150
|
+
--color-button-icon-background-bg: var(--lux-n-50);
|
|
151
|
+
--color-button-hero-bg: var(--lux-accent);
|
|
152
|
+
--color-button-hero-fg: var(--lux-accent-fg);
|
|
153
|
+
--color-button-hero-bg-hover: var(--lux-n-600);
|
|
154
|
+
--color-button-hero-fg-hover: var(--lux-n-0);
|
|
155
|
+
--color-button-hero-bg-selected: var(--lux-paper-06);
|
|
156
|
+
--color-button-hero-fg-selected: var(--lux-ink-80);
|
|
157
|
+
--color-button-segmented-fg: var(--lux-ink-80);
|
|
158
|
+
--color-button-icon-bg: var(--lux-ink-04);
|
|
99
159
|
|
|
100
160
|
/* --- Hover / Selected --- */
|
|
101
|
-
--color-hover:
|
|
102
|
-
--color-selected-control-bg:
|
|
103
|
-
--color-selected-control-text:
|
|
104
|
-
--color-selected-option-bg:
|
|
161
|
+
--color-hover: var(--lux-n-600);
|
|
162
|
+
--color-selected-control-bg: var(--lux-n-100);
|
|
163
|
+
--color-selected-control-text: var(--lux-n-900);
|
|
164
|
+
--color-selected-option-bg: var(--lux-n-700);
|
|
105
165
|
|
|
106
166
|
/* --- Navigation --- */
|
|
107
|
-
--color-nav-bg-selected:
|
|
108
|
-
--color-nav-text-selected:
|
|
167
|
+
--color-nav-bg-selected: var(--lux-n-100);
|
|
168
|
+
--color-nav-text-selected: var(--lux-n-900);
|
|
109
169
|
|
|
110
170
|
/* --- Inputs --- */
|
|
111
|
-
--color-input-fg:
|
|
112
|
-
--color-input-bg:
|
|
113
|
-
--color-input-bg-readonly:
|
|
114
|
-
--color-input-border:
|
|
115
|
-
--color-input-border-hover:
|
|
116
|
-
--color-input-border-focus:
|
|
117
|
-
|
|
171
|
+
--color-input-fg: var(--lux-n-800);
|
|
172
|
+
--color-input-bg: var(--lux-n-0);
|
|
173
|
+
--color-input-bg-readonly: var(--lux-n-200);
|
|
174
|
+
--color-input-border: var(--lux-n-100);
|
|
175
|
+
--color-input-border-hover: var(--lux-n-200);
|
|
176
|
+
--color-input-border-focus: var(--lux-n-600);
|
|
177
|
+
/* n-400 on white is 2.5:1 — under the 3:1 non-text minimum. n-500 clears it. */
|
|
178
|
+
--color-input-placeholder: var(--lux-n-500);
|
|
118
179
|
|
|
119
180
|
/* --- Tags --- */
|
|
120
|
-
--color-tag-subtle-bg:
|
|
121
|
-
--color-tag-subtle-fg:
|
|
122
|
-
--color-tag-clickable-bg:
|
|
123
|
-
--color-tag-clickable-fg:
|
|
124
|
-
--color-tag-filter-bg:
|
|
125
|
-
--color-tag-select-bg:
|
|
126
|
-
--color-tag-select-fg:
|
|
127
|
-
--color-tag-select-selected-bg:
|
|
128
|
-
--color-tag-select-selected-fg:
|
|
129
|
-
|
|
130
|
-
/* --- Badges ---
|
|
131
|
-
|
|
132
|
-
|
|
181
|
+
--color-tag-subtle-bg: var(--lux-ink-04);
|
|
182
|
+
--color-tag-subtle-fg: var(--lux-ink-80);
|
|
183
|
+
--color-tag-clickable-bg: var(--lux-n-100);
|
|
184
|
+
--color-tag-clickable-fg: var(--lux-ink-80);
|
|
185
|
+
--color-tag-filter-bg: var(--lux-n-100);
|
|
186
|
+
--color-tag-select-bg: var(--lux-n-100);
|
|
187
|
+
--color-tag-select-fg: var(--lux-n-500);
|
|
188
|
+
--color-tag-select-selected-bg: var(--lux-n-700);
|
|
189
|
+
--color-tag-select-selected-fg: var(--lux-paper-80);
|
|
190
|
+
|
|
191
|
+
/* --- Badges ---
|
|
192
|
+
The colour NAMES are a legacy API (call sites say colorScheme="orange").
|
|
193
|
+
They are one monochrome ramp now; only green/red keep a hue, because they
|
|
194
|
+
carry state rather than decoration. */
|
|
195
|
+
--color-badge-gray-bg: var(--lux-ink-04);
|
|
196
|
+
--color-badge-gray-fg: var(--lux-ink-80);
|
|
133
197
|
--color-badge-green-bg: #F0FFF4;
|
|
134
|
-
--color-badge-green-fg:
|
|
198
|
+
--color-badge-green-fg: var(--lux-state-success);
|
|
135
199
|
--color-badge-red-bg: #FFF5F5;
|
|
136
|
-
--color-badge-red-fg:
|
|
137
|
-
--color-badge-purple-bg:
|
|
138
|
-
--color-badge-purple-fg:
|
|
139
|
-
--color-badge-orange-bg:
|
|
140
|
-
--color-badge-orange-fg:
|
|
141
|
-
--color-badge-blue-bg:
|
|
142
|
-
--color-badge-blue-fg:
|
|
143
|
-
--color-badge-yellow-bg:
|
|
144
|
-
--color-badge-yellow-fg:
|
|
145
|
-
--color-badge-teal-bg:
|
|
146
|
-
--color-badge-teal-fg:
|
|
147
|
-
--color-badge-cyan-bg:
|
|
148
|
-
--color-badge-cyan-fg:
|
|
149
|
-
--color-badge-pink-bg:
|
|
150
|
-
--color-badge-pink-fg:
|
|
151
|
-
--color-badge-purple-alt-bg:
|
|
152
|
-
--color-badge-purple-alt-fg:
|
|
153
|
-
--color-badge-blue-alt-bg:
|
|
154
|
-
--color-badge-blue-alt-fg:
|
|
155
|
-
--color-badge-bright-gray-bg:
|
|
156
|
-
--color-badge-bright-gray-fg:
|
|
200
|
+
--color-badge-red-fg: var(--lux-state-error);
|
|
201
|
+
--color-badge-purple-bg: var(--lux-n-100);
|
|
202
|
+
--color-badge-purple-fg: var(--lux-n-600);
|
|
203
|
+
--color-badge-orange-bg: var(--lux-n-100);
|
|
204
|
+
--color-badge-orange-fg: var(--lux-n-600);
|
|
205
|
+
--color-badge-blue-bg: var(--lux-n-100);
|
|
206
|
+
--color-badge-blue-fg: var(--lux-n-600);
|
|
207
|
+
--color-badge-yellow-bg: var(--lux-n-100);
|
|
208
|
+
--color-badge-yellow-fg: var(--lux-n-600);
|
|
209
|
+
--color-badge-teal-bg: var(--lux-n-100);
|
|
210
|
+
--color-badge-teal-fg: var(--lux-n-600);
|
|
211
|
+
--color-badge-cyan-bg: var(--lux-n-100);
|
|
212
|
+
--color-badge-cyan-fg: var(--lux-n-600);
|
|
213
|
+
--color-badge-pink-bg: var(--lux-n-100);
|
|
214
|
+
--color-badge-pink-fg: var(--lux-n-600);
|
|
215
|
+
--color-badge-purple-alt-bg: var(--lux-n-100);
|
|
216
|
+
--color-badge-purple-alt-fg: var(--lux-ink-80);
|
|
217
|
+
--color-badge-blue-alt-bg: var(--lux-n-100);
|
|
218
|
+
--color-badge-blue-alt-fg: var(--lux-ink-80);
|
|
219
|
+
--color-badge-bright-gray-bg: var(--lux-n-100);
|
|
220
|
+
--color-badge-bright-gray-fg: var(--lux-n-600);
|
|
157
221
|
--color-badge-bright-green-bg: #C6F6D5;
|
|
158
222
|
--color-badge-bright-green-fg: #25855A;
|
|
159
223
|
--color-badge-bright-red-bg: #FED7D7;
|
|
160
224
|
--color-badge-bright-red-fg: #C53030;
|
|
161
|
-
--color-badge-bright-blue-bg:
|
|
162
|
-
--color-badge-bright-blue-fg:
|
|
163
|
-
--color-badge-bright-yellow-bg:
|
|
164
|
-
--color-badge-bright-yellow-fg:
|
|
165
|
-
--color-badge-bright-teal-bg:
|
|
166
|
-
--color-badge-bright-teal-fg:
|
|
167
|
-
--color-badge-bright-cyan-bg:
|
|
168
|
-
--color-badge-bright-cyan-fg:
|
|
169
|
-
--color-badge-bright-orange-bg:
|
|
170
|
-
--color-badge-bright-orange-fg:
|
|
171
|
-
--color-badge-bright-purple-bg:
|
|
172
|
-
--color-badge-bright-purple-fg:
|
|
173
|
-
--color-badge-bright-pink-bg:
|
|
174
|
-
--color-badge-bright-pink-fg:
|
|
225
|
+
--color-badge-bright-blue-bg: var(--lux-n-200);
|
|
226
|
+
--color-badge-bright-blue-fg: var(--lux-n-700);
|
|
227
|
+
--color-badge-bright-yellow-bg: var(--lux-n-200);
|
|
228
|
+
--color-badge-bright-yellow-fg: var(--lux-n-700);
|
|
229
|
+
--color-badge-bright-teal-bg: var(--lux-n-200);
|
|
230
|
+
--color-badge-bright-teal-fg: var(--lux-n-700);
|
|
231
|
+
--color-badge-bright-cyan-bg: var(--lux-n-200);
|
|
232
|
+
--color-badge-bright-cyan-fg: var(--lux-n-700);
|
|
233
|
+
--color-badge-bright-orange-bg: var(--lux-n-200);
|
|
234
|
+
--color-badge-bright-orange-fg: var(--lux-n-700);
|
|
235
|
+
--color-badge-bright-purple-bg: var(--lux-n-200);
|
|
236
|
+
--color-badge-bright-purple-fg: var(--lux-n-700);
|
|
237
|
+
--color-badge-bright-pink-bg: var(--lux-n-200);
|
|
238
|
+
--color-badge-bright-pink-fg: var(--lux-n-700);
|
|
175
239
|
|
|
176
240
|
/* --- Alerts --- */
|
|
177
|
-
--color-alert-fg:
|
|
178
|
-
--color-alert-bg-info:
|
|
179
|
-
--color-alert-bg-warning:
|
|
180
|
-
--color-alert-bg-warning-table:
|
|
241
|
+
--color-alert-fg: var(--lux-ink-80);
|
|
242
|
+
--color-alert-bg-info: var(--lux-ink-04);
|
|
243
|
+
--color-alert-bg-warning: var(--lux-n-200);
|
|
244
|
+
--color-alert-bg-warning-table: var(--lux-n-50);
|
|
181
245
|
--color-alert-bg-success: #C6F6D5;
|
|
182
246
|
--color-alert-bg-error: #FED7D7;
|
|
183
247
|
|
|
184
248
|
/* --- Dialogs / Popovers / Drawers --- */
|
|
185
|
-
--color-dialog-bg:
|
|
186
|
-
--color-dialog-fg:
|
|
187
|
-
--color-popover-bg:
|
|
188
|
-
--color-popover-
|
|
189
|
-
--color-
|
|
249
|
+
--color-dialog-bg: var(--lux-n-0);
|
|
250
|
+
--color-dialog-fg: var(--lux-ink-80);
|
|
251
|
+
--color-popover-bg: var(--lux-n-0);
|
|
252
|
+
--color-popover-border: var(--lux-ink-10);
|
|
253
|
+
--color-popover-shadow: var(--lux-ink-08);
|
|
254
|
+
--color-drawer-bg: var(--lux-n-0);
|
|
190
255
|
|
|
191
256
|
/* --- Tooltip --- */
|
|
192
|
-
--color-tooltip-bg:
|
|
193
|
-
--color-tooltip-fg:
|
|
257
|
+
--color-tooltip-bg: var(--lux-n-900);
|
|
258
|
+
--color-tooltip-fg: var(--lux-n-0);
|
|
194
259
|
|
|
195
260
|
/* --- Table --- */
|
|
196
|
-
--color-table-header-bg:
|
|
197
|
-
--color-table-header-fg:
|
|
261
|
+
--color-table-header-bg: var(--lux-ink-06);
|
|
262
|
+
--color-table-header-fg: var(--lux-ink-64);
|
|
198
263
|
|
|
199
264
|
/* --- Tabs --- */
|
|
200
|
-
--color-tabs-solid-fg:
|
|
201
|
-
--color-tabs-
|
|
202
|
-
--color-tabs-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
--color-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
--color-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
--color-graph-line:
|
|
265
|
+
--color-tabs-solid-fg: var(--lux-n-900);
|
|
266
|
+
--color-tabs-solid-bg: var(--lux-n-0);
|
|
267
|
+
--color-tabs-solid-fg-selected: var(--lux-n-0);
|
|
268
|
+
--color-tabs-solid-bg-selected: var(--lux-n-900);
|
|
269
|
+
--color-tabs-secondary-fg: var(--lux-n-500);
|
|
270
|
+
--color-tabs-secondary-fg-selected: var(--lux-n-900);
|
|
271
|
+
--color-tabs-radio-fg: var(--lux-n-500);
|
|
272
|
+
--color-tabs-radio-bg-selected: var(--lux-n-0);
|
|
273
|
+
--color-tabs-radio-fg-selected: var(--lux-n-900);
|
|
274
|
+
|
|
275
|
+
--color-tabs-secondary-border: var(--lux-n-300);
|
|
276
|
+
|
|
277
|
+
/* --- Controls --- */
|
|
278
|
+
--color-switch-bg: var(--lux-n-300);
|
|
279
|
+
--color-progress-track: var(--lux-n-100);
|
|
280
|
+
|
|
281
|
+
/* --- Chrome / charts --- */
|
|
282
|
+
--color-stats-bg: var(--lux-n-50);
|
|
283
|
+
--color-topbar-bg: var(--lux-n-50);
|
|
284
|
+
--color-graph-line: var(--lux-n-500);
|
|
220
285
|
--color-graph-gradient-start: rgba(163, 163, 163, 0.3);
|
|
221
286
|
--color-graph-gradient-stop: rgba(163, 163, 163, 0);
|
|
222
287
|
|
|
288
|
+
/* --- Skeleton --- */
|
|
289
|
+
--color-skeleton-start: var(--lux-n-100);
|
|
290
|
+
--color-skeleton-end: var(--lux-n-200);
|
|
291
|
+
|
|
223
292
|
/* --- Scrollbar --- */
|
|
224
|
-
--color-scrollbar-thumb:
|
|
293
|
+
--color-scrollbar-thumb: var(--lux-ink-16);
|
|
225
294
|
|
|
226
295
|
/* --- Selection --- */
|
|
227
|
-
--color-selection-bg:
|
|
296
|
+
--color-selection-bg: var(--lux-n-200);
|
|
297
|
+
|
|
298
|
+
/* --- Raw palette (an alias surface; the ladder is the source) --- */
|
|
299
|
+
--color-gray-50: var(--lux-n-50);
|
|
300
|
+
--color-gray-100: var(--lux-n-100);
|
|
301
|
+
--color-gray-200: var(--lux-n-200);
|
|
302
|
+
--color-gray-300: var(--lux-n-300);
|
|
303
|
+
--color-gray-400: var(--lux-n-400);
|
|
304
|
+
--color-gray-500: var(--lux-n-500);
|
|
305
|
+
--color-gray-600: var(--lux-n-600);
|
|
306
|
+
--color-gray-700: var(--lux-n-700);
|
|
307
|
+
--color-gray-800: var(--lux-n-800);
|
|
308
|
+
--color-gray-900: var(--lux-n-900);
|
|
309
|
+
--color-white: var(--lux-n-0);
|
|
310
|
+
--color-black: var(--lux-n-1000);
|
|
311
|
+
/* The two state ramps — the only rungs in this file that carry a hue.
|
|
312
|
+
Monotone, like the warm ramps, and likewise not flipped in `.dark`. */
|
|
313
|
+
--color-green-50: #F0FFF4;
|
|
314
|
+
--color-green-100: #C6F6D5;
|
|
315
|
+
--color-green-200: #9AE6B4;
|
|
316
|
+
--color-green-500: var(--lux-state-success);
|
|
317
|
+
--color-green-800: #22543D;
|
|
318
|
+
--color-red-50: #FFF5F5;
|
|
319
|
+
--color-red-100: #FED7D7;
|
|
320
|
+
--color-red-200: #FEB2B2;
|
|
321
|
+
--color-red-500: var(--lux-state-error);
|
|
322
|
+
--color-red-600: #C53030;
|
|
323
|
+
--color-red-800: #822727;
|
|
324
|
+
/* ------------------------------------------------------------
|
|
325
|
+
THE WARM RAMPS, DEFANGED.
|
|
326
|
+
Tailwind v4 compiles `bg-orange-100` to `background-color:
|
|
327
|
+
var(--color-orange-100)`, so redefining the rung here retints every
|
|
328
|
+
warm utility on every surface that imports this file — no component
|
|
329
|
+
edit, no rebuild. The ramps stay MONOTONE (low rung = light, high rung
|
|
330
|
+
= dark) in both modes, exactly like Tailwind's, so an author's
|
|
331
|
+
`bg-orange-50 dark:bg-yellow-900` still reads pale-on-light and
|
|
332
|
+
dark-on-dark. They are therefore NOT overridden in `.dark` below.
|
|
333
|
+
A rung is a rung; a warning is `--color-status-warn`.
|
|
334
|
+
------------------------------------------------------------ */
|
|
335
|
+
--color-orange-50: var(--lux-n-50);
|
|
336
|
+
--color-orange-100: var(--lux-n-100);
|
|
337
|
+
--color-orange-200: var(--lux-n-200);
|
|
338
|
+
--color-orange-300: var(--lux-n-300);
|
|
339
|
+
--color-orange-400: var(--lux-n-400);
|
|
340
|
+
--color-orange-500: var(--lux-n-500);
|
|
341
|
+
--color-orange-600: var(--lux-n-600);
|
|
342
|
+
--color-orange-700: var(--lux-n-700);
|
|
343
|
+
--color-orange-800: var(--lux-n-800);
|
|
344
|
+
--color-orange-900: var(--lux-n-900);
|
|
345
|
+
--color-orange-950: var(--lux-n-950);
|
|
346
|
+
--color-amber-50: var(--color-orange-50);
|
|
347
|
+
--color-amber-100: var(--color-orange-100);
|
|
348
|
+
--color-amber-200: var(--color-orange-200);
|
|
349
|
+
--color-amber-300: var(--color-orange-300);
|
|
350
|
+
--color-amber-400: var(--color-orange-400);
|
|
351
|
+
--color-amber-500: var(--color-orange-500);
|
|
352
|
+
--color-amber-600: var(--color-orange-600);
|
|
353
|
+
--color-amber-700: var(--color-orange-700);
|
|
354
|
+
--color-amber-800: var(--color-orange-800);
|
|
355
|
+
--color-amber-900: var(--color-orange-900);
|
|
356
|
+
--color-amber-950: var(--color-orange-950);
|
|
357
|
+
--color-yellow-50: var(--color-orange-50);
|
|
358
|
+
--color-yellow-100: var(--color-orange-100);
|
|
359
|
+
--color-yellow-200: var(--color-orange-200);
|
|
360
|
+
--color-yellow-300: var(--color-orange-300);
|
|
361
|
+
--color-yellow-400: var(--color-orange-400);
|
|
362
|
+
--color-yellow-500: var(--color-orange-500);
|
|
363
|
+
--color-yellow-600: var(--color-orange-600);
|
|
364
|
+
--color-yellow-700: var(--color-orange-700);
|
|
365
|
+
--color-yellow-800: var(--color-orange-800);
|
|
366
|
+
--color-yellow-900: var(--color-orange-900);
|
|
367
|
+
--color-yellow-950: var(--color-orange-950);
|
|
368
|
+
/* Tailwind's warm neutral. Lux has exactly one neutral, and it is not warm. */
|
|
369
|
+
--color-stone-50: var(--lux-n-50);
|
|
370
|
+
--color-stone-100: var(--lux-n-100);
|
|
371
|
+
--color-stone-200: var(--lux-n-200);
|
|
372
|
+
--color-stone-300: var(--lux-n-300);
|
|
373
|
+
--color-stone-400: var(--lux-n-400);
|
|
374
|
+
--color-stone-500: var(--lux-n-500);
|
|
375
|
+
--color-stone-600: var(--lux-n-600);
|
|
376
|
+
--color-stone-700: var(--lux-n-700);
|
|
377
|
+
--color-stone-800: var(--lux-n-800);
|
|
378
|
+
--color-stone-900: var(--lux-n-900);
|
|
379
|
+
--color-stone-950: var(--lux-n-950);
|
|
380
|
+
--color-blackAlpha-50: var(--lux-ink-04);
|
|
381
|
+
--color-blackAlpha-100: var(--lux-ink-06);
|
|
382
|
+
--color-blackAlpha-200: var(--lux-ink-08);
|
|
383
|
+
--color-blackAlpha-300: var(--lux-ink-16);
|
|
384
|
+
--color-blackAlpha-400: var(--lux-ink-24);
|
|
385
|
+
--color-blackAlpha-500: var(--lux-ink-36);
|
|
386
|
+
--color-blackAlpha-600: var(--lux-ink-48);
|
|
387
|
+
--color-blackAlpha-700: var(--lux-ink-64);
|
|
388
|
+
--color-blackAlpha-800: var(--lux-ink-80);
|
|
389
|
+
--color-blackAlpha-900: var(--lux-ink-92);
|
|
390
|
+
--color-whiteAlpha-50: var(--lux-paper-04);
|
|
391
|
+
--color-whiteAlpha-100: var(--lux-paper-06);
|
|
392
|
+
--color-whiteAlpha-200: var(--lux-paper-08);
|
|
393
|
+
--color-whiteAlpha-300: var(--lux-paper-16);
|
|
394
|
+
--color-whiteAlpha-400: var(--lux-paper-24);
|
|
395
|
+
--color-whiteAlpha-500: var(--lux-paper-36);
|
|
396
|
+
--color-whiteAlpha-600: var(--lux-paper-48);
|
|
397
|
+
--color-whiteAlpha-700: var(--lux-paper-64);
|
|
398
|
+
--color-whiteAlpha-800: var(--lux-paper-80);
|
|
399
|
+
--color-whiteAlpha-900: var(--lux-paper-92);
|
|
400
|
+
|
|
401
|
+
/* --- Chakra legacy aliases (used by migrated components) --- */
|
|
402
|
+
--chakra-colors-bg-primary: var(--color-bg-primary);
|
|
403
|
+
--chakra-colors-text-primary: var(--color-text-primary);
|
|
404
|
+
--chakra-colors-text-secondary: var(--color-text-secondary);
|
|
405
|
+
--chakra-colors-icon-secondary: var(--color-icon-secondary);
|
|
406
|
+
--chakra-colors-border-divider: var(--color-border-divider);
|
|
407
|
+
--chakra-colors-link-primary: var(--color-link-primary);
|
|
408
|
+
--chakra-colors-link-primary-hover: var(--color-link-primary-hover);
|
|
409
|
+
--chakra-colors-hover: var(--color-hover);
|
|
410
|
+
--chakra-colors-gray-100: var(--color-gray-100);
|
|
411
|
+
--chakra-colors-whiteAlpha-50: var(--color-whiteAlpha-50);
|
|
412
|
+
--chakra-colors-whiteAlpha-100: var(--color-whiteAlpha-100);
|
|
228
413
|
|
|
229
414
|
/* --- Shadows --- */
|
|
230
415
|
--shadow-action-bar: 0 4px 4px -4px rgb(0 0 0 / 10%), 0 2px 4px -4px rgb(0 0 0 / 6%);
|
|
231
416
|
--shadow-popover: 0px 15px 50px -12px rgba(0, 0, 0, 0.25);
|
|
232
417
|
--shadow-drawer: 0px 4px 6px -2px rgba(0, 0, 0, 0.05), 0px 10px 15px -3px rgba(0, 0, 0, 0.1);
|
|
418
|
+
|
|
419
|
+
/* ------------------------------------------------------------
|
|
420
|
+
5 — SHADCN / TAILWIND ALIASES (light).
|
|
421
|
+
A surface imports this file and deletes its own palette block.
|
|
422
|
+
------------------------------------------------------------ */
|
|
423
|
+
--background: var(--lux-n-0);
|
|
424
|
+
--foreground: var(--lux-n-900);
|
|
425
|
+
--card: var(--lux-n-0);
|
|
426
|
+
--card-foreground: var(--lux-n-900);
|
|
427
|
+
--popover: var(--lux-n-0);
|
|
428
|
+
--popover-foreground: var(--lux-n-900);
|
|
429
|
+
--primary: var(--lux-accent);
|
|
430
|
+
--primary-foreground: var(--lux-accent-fg);
|
|
431
|
+
--secondary: var(--lux-n-100);
|
|
432
|
+
--secondary-foreground: var(--lux-n-900);
|
|
433
|
+
--muted: var(--lux-n-100);
|
|
434
|
+
--muted-foreground: var(--lux-n-500);
|
|
435
|
+
--accent: var(--lux-n-100);
|
|
436
|
+
--accent-foreground: var(--lux-n-900);
|
|
437
|
+
--destructive: var(--lux-state-error);
|
|
438
|
+
--destructive-foreground: var(--lux-n-0);
|
|
439
|
+
/* success / warning / info as shadcn-style pairs. `warning` is achromatic —
|
|
440
|
+
it used to be hsl(38 96% 57%), which is where lux.market got its tan. */
|
|
441
|
+
--success: var(--lux-state-success);
|
|
442
|
+
--success-foreground: var(--lux-n-0);
|
|
443
|
+
--warning: var(--lux-state-notice);
|
|
444
|
+
--warning-foreground: var(--lux-n-0);
|
|
445
|
+
--info: var(--lux-n-700);
|
|
446
|
+
--info-foreground: var(--lux-n-0);
|
|
447
|
+
--border: var(--lux-n-200);
|
|
448
|
+
--input: var(--lux-n-200);
|
|
449
|
+
--ring: var(--lux-n-400);
|
|
450
|
+
/* Charts: five achromatic steps, ordered by contrast, not by hue. */
|
|
451
|
+
--chart-1: var(--lux-n-900);
|
|
452
|
+
--chart-2: var(--lux-n-600);
|
|
453
|
+
--chart-3: var(--lux-n-400);
|
|
454
|
+
--chart-4: var(--lux-n-700);
|
|
455
|
+
--chart-5: var(--lux-n-300);
|
|
456
|
+
--sidebar: var(--lux-n-50);
|
|
457
|
+
--sidebar-foreground: var(--lux-n-900);
|
|
458
|
+
--sidebar-primary: var(--lux-accent);
|
|
459
|
+
--sidebar-primary-foreground: var(--lux-accent-fg);
|
|
460
|
+
--sidebar-accent: var(--lux-n-100);
|
|
461
|
+
--sidebar-accent-foreground: var(--lux-n-900);
|
|
462
|
+
--sidebar-border: var(--lux-n-200);
|
|
463
|
+
--sidebar-ring: var(--lux-n-400);
|
|
233
464
|
}
|
|
234
465
|
|
|
235
466
|
/* ================================================================
|
|
236
467
|
DARK MODE
|
|
237
468
|
================================================================ */
|
|
238
|
-
.dark
|
|
469
|
+
.dark,
|
|
470
|
+
[data-theme='dark'] {
|
|
471
|
+
/* Brand hooks invert: on ink, the accent is the paper. */
|
|
472
|
+
--lux-accent: var(--lux-n-0);
|
|
473
|
+
--lux-accent-fg: var(--lux-n-900);
|
|
474
|
+
|
|
475
|
+
/* State, lightened for a dark ground (AA >=4.5:1 on --lux-n-900). */
|
|
476
|
+
--lux-state-error: #FCA5A5;
|
|
477
|
+
--lux-state-success: #6EE7A8;
|
|
478
|
+
--lux-state-notice: var(--lux-n-300);
|
|
479
|
+
|
|
239
480
|
/* --- Backgrounds --- */
|
|
240
|
-
--color-bg-primary:
|
|
241
|
-
--color-bg-info:
|
|
242
|
-
--color-bg-body:
|
|
481
|
+
--color-bg-primary: var(--lux-n-900);
|
|
482
|
+
--color-bg-info: var(--lux-n-800);
|
|
483
|
+
--color-bg-body: var(--lux-n-1000);
|
|
243
484
|
|
|
244
485
|
/* --- Foregrounds --- */
|
|
245
|
-
--color-fg-info:
|
|
486
|
+
--color-fg-info: var(--lux-n-300);
|
|
246
487
|
|
|
247
488
|
/* --- Text --- */
|
|
248
|
-
--color-text-primary:
|
|
249
|
-
--color-text-secondary:
|
|
250
|
-
--color-text-error:
|
|
251
|
-
--color-text-success:
|
|
489
|
+
--color-text-primary: var(--lux-paper-80);
|
|
490
|
+
--color-text-secondary: var(--lux-n-400);
|
|
491
|
+
--color-text-error: var(--lux-state-error);
|
|
492
|
+
--color-text-success: var(--lux-state-success);
|
|
493
|
+
|
|
494
|
+
/* --- Status foreground --- */
|
|
495
|
+
--color-status-good: var(--lux-state-success);
|
|
496
|
+
--color-status-warn: var(--lux-state-notice);
|
|
497
|
+
--color-status-bad: var(--lux-state-error);
|
|
252
498
|
|
|
253
499
|
/* --- Headings --- */
|
|
254
|
-
--color-heading:
|
|
500
|
+
--color-heading: var(--lux-paper-80);
|
|
255
501
|
|
|
256
502
|
/* --- Icons --- */
|
|
257
|
-
--color-icon-primary:
|
|
258
|
-
--color-icon-secondary:
|
|
503
|
+
--color-icon-primary: var(--lux-n-400);
|
|
504
|
+
--color-icon-secondary: var(--lux-n-500);
|
|
259
505
|
|
|
260
506
|
/* --- Borders --- */
|
|
261
|
-
--color-border-divider:
|
|
262
|
-
--color-border-error:
|
|
263
|
-
--color-border-info:
|
|
507
|
+
--color-border-divider: var(--lux-paper-06);
|
|
508
|
+
--color-border-error: var(--lux-state-error);
|
|
509
|
+
--color-border-info: var(--lux-n-500);
|
|
264
510
|
|
|
265
511
|
/* --- Links --- */
|
|
266
|
-
--color-link-primary:
|
|
267
|
-
--color-link-primary-hover:
|
|
268
|
-
--color-link-secondary:
|
|
269
|
-
--color-link-subtle:
|
|
270
|
-
--color-link-subtle-hover:
|
|
271
|
-
--color-link-menu:
|
|
272
|
-
--color-link-underlaid-bg:
|
|
273
|
-
--color-link-nav-fg:
|
|
274
|
-
--color-link-nav-fg-hover:
|
|
275
|
-
--color-link-nav-fg-selected:
|
|
276
|
-
--color-link-nav-fg-active:
|
|
277
|
-
--color-link-nav-bg-selected:
|
|
512
|
+
--color-link-primary: var(--lux-n-300);
|
|
513
|
+
--color-link-primary-hover: var(--lux-n-200);
|
|
514
|
+
--color-link-secondary: var(--lux-n-400);
|
|
515
|
+
--color-link-subtle: var(--lux-paper-80);
|
|
516
|
+
--color-link-subtle-hover: var(--lux-paper-80);
|
|
517
|
+
--color-link-menu: var(--lux-paper-80);
|
|
518
|
+
--color-link-underlaid-bg: var(--lux-n-800);
|
|
519
|
+
--color-link-nav-fg: var(--lux-paper-80);
|
|
520
|
+
--color-link-nav-fg-hover: var(--lux-n-200);
|
|
521
|
+
--color-link-nav-fg-selected: var(--lux-n-0);
|
|
522
|
+
--color-link-nav-fg-active: var(--lux-n-200);
|
|
523
|
+
--color-link-nav-bg-selected: var(--lux-n-800);
|
|
278
524
|
|
|
279
525
|
/* --- Buttons --- */
|
|
280
|
-
--color-button-solid-bg:
|
|
281
|
-
--color-button-solid-text:
|
|
282
|
-
--color-button-outline-fg:
|
|
283
|
-
--color-button-subtle-fg:
|
|
284
|
-
--color-button-subtle-bg:
|
|
285
|
-
--color-button-dropdown-fg:
|
|
286
|
-
--color-button-dropdown-border:
|
|
287
|
-
--color-button-header-fg:
|
|
288
|
-
--color-button-header-fg-selected:
|
|
289
|
-
--color-button-header-fg-highlighted:
|
|
290
|
-
--color-button-header-border:
|
|
291
|
-
--color-button-header-bg-selected:
|
|
292
|
-
--color-button-header-bg-highlighted:
|
|
293
|
-
--color-button-pagination-fg:
|
|
294
|
-
--color-button-pagination-border:
|
|
295
|
-
--color-button-icon-background-bg:
|
|
296
|
-
--color-button-hero-bg:
|
|
297
|
-
--color-button-hero-fg:
|
|
298
|
-
--color-button-hero-bg-hover:
|
|
299
|
-
--color-button-hero-fg-hover:
|
|
300
|
-
--color-button-hero-bg-selected:
|
|
301
|
-
--color-button-hero-fg-selected:
|
|
302
|
-
--color-button-segmented-fg:
|
|
303
|
-
--color-button-icon-bg:
|
|
526
|
+
--color-button-solid-bg: var(--lux-accent);
|
|
527
|
+
--color-button-solid-text: var(--lux-accent-fg);
|
|
528
|
+
--color-button-outline-fg: var(--lux-n-0);
|
|
529
|
+
--color-button-subtle-fg: var(--lux-paper-80);
|
|
530
|
+
--color-button-subtle-bg: var(--lux-paper-08);
|
|
531
|
+
--color-button-dropdown-fg: var(--lux-paper-80);
|
|
532
|
+
--color-button-dropdown-border: var(--lux-n-800);
|
|
533
|
+
--color-button-header-fg: var(--lux-paper-80);
|
|
534
|
+
--color-button-header-fg-selected: var(--lux-paper-80);
|
|
535
|
+
--color-button-header-fg-highlighted: var(--lux-paper-80);
|
|
536
|
+
--color-button-header-border: var(--lux-n-800);
|
|
537
|
+
--color-button-header-bg-selected: var(--lux-paper-04);
|
|
538
|
+
--color-button-header-bg-highlighted: var(--lux-n-700);
|
|
539
|
+
--color-button-pagination-fg: var(--lux-paper-80);
|
|
540
|
+
--color-button-pagination-border: var(--lux-n-800);
|
|
541
|
+
--color-button-icon-background-bg: var(--lux-n-800);
|
|
542
|
+
--color-button-hero-bg: var(--lux-accent);
|
|
543
|
+
--color-button-hero-fg: var(--lux-accent-fg);
|
|
544
|
+
--color-button-hero-bg-hover: var(--lux-n-200);
|
|
545
|
+
--color-button-hero-fg-hover: var(--lux-n-900);
|
|
546
|
+
--color-button-hero-bg-selected: var(--lux-paper-06);
|
|
547
|
+
--color-button-hero-fg-selected: var(--lux-paper-80);
|
|
548
|
+
--color-button-segmented-fg: var(--lux-paper-80);
|
|
549
|
+
--color-button-icon-bg: var(--lux-paper-04);
|
|
304
550
|
|
|
305
551
|
/* --- Hover / Selected --- */
|
|
306
|
-
--color-hover:
|
|
307
|
-
--color-selected-control-bg:
|
|
308
|
-
--color-selected-control-text:
|
|
309
|
-
--color-selected-option-bg:
|
|
552
|
+
--color-hover: var(--lux-n-200);
|
|
553
|
+
--color-selected-control-bg: var(--lux-n-800);
|
|
554
|
+
--color-selected-control-text: var(--lux-n-0);
|
|
555
|
+
--color-selected-option-bg: var(--lux-n-700);
|
|
310
556
|
|
|
311
557
|
/* --- Navigation --- */
|
|
312
|
-
--color-nav-bg-selected:
|
|
313
|
-
--color-nav-text-selected:
|
|
558
|
+
--color-nav-bg-selected: var(--lux-n-800);
|
|
559
|
+
--color-nav-text-selected: var(--lux-n-0);
|
|
314
560
|
|
|
315
561
|
/* --- Inputs --- */
|
|
316
|
-
--color-input-fg:
|
|
317
|
-
--color-input-bg:
|
|
318
|
-
--color-input-bg-readonly:
|
|
319
|
-
--color-input-border:
|
|
320
|
-
--color-input-border-hover:
|
|
321
|
-
--color-input-border-focus:
|
|
322
|
-
--color-input-placeholder:
|
|
562
|
+
--color-input-fg: var(--lux-n-200);
|
|
563
|
+
--color-input-bg: var(--lux-n-900);
|
|
564
|
+
--color-input-bg-readonly: var(--lux-n-800);
|
|
565
|
+
--color-input-border: var(--lux-n-800);
|
|
566
|
+
--color-input-border-hover: var(--lux-n-700);
|
|
567
|
+
--color-input-border-focus: var(--lux-n-400);
|
|
568
|
+
--color-input-placeholder: var(--lux-n-500);
|
|
323
569
|
|
|
324
570
|
/* --- Tags --- */
|
|
325
|
-
--color-tag-subtle-bg:
|
|
326
|
-
--color-tag-subtle-fg:
|
|
327
|
-
--color-tag-clickable-bg:
|
|
328
|
-
--color-tag-clickable-fg:
|
|
329
|
-
--color-tag-filter-bg:
|
|
330
|
-
--color-tag-select-bg:
|
|
331
|
-
--color-tag-select-fg:
|
|
332
|
-
--color-tag-select-selected-bg:
|
|
333
|
-
--color-tag-select-selected-fg:
|
|
571
|
+
--color-tag-subtle-bg: var(--lux-paper-06);
|
|
572
|
+
--color-tag-subtle-fg: var(--lux-paper-80);
|
|
573
|
+
--color-tag-clickable-bg: var(--lux-n-800);
|
|
574
|
+
--color-tag-clickable-fg: var(--lux-paper-80);
|
|
575
|
+
--color-tag-filter-bg: var(--lux-n-800);
|
|
576
|
+
--color-tag-select-bg: var(--lux-n-800);
|
|
577
|
+
--color-tag-select-fg: var(--lux-n-400);
|
|
578
|
+
--color-tag-select-selected-bg: var(--lux-n-700);
|
|
579
|
+
--color-tag-select-selected-fg: var(--lux-paper-80);
|
|
334
580
|
|
|
335
581
|
/* --- Badges --- */
|
|
336
|
-
--color-badge-gray-bg:
|
|
337
|
-
--color-badge-gray-fg:
|
|
582
|
+
--color-badge-gray-bg: var(--lux-paper-06);
|
|
583
|
+
--color-badge-gray-fg: var(--lux-paper-80);
|
|
338
584
|
--color-badge-green-bg: #22543D;
|
|
339
585
|
--color-badge-green-fg: #9AE6B4;
|
|
340
586
|
--color-badge-red-bg: #822727;
|
|
341
587
|
--color-badge-red-fg: #FEB2B2;
|
|
342
|
-
--color-badge-purple-bg:
|
|
343
|
-
--color-badge-purple-fg:
|
|
344
|
-
--color-badge-orange-bg:
|
|
345
|
-
--color-badge-orange-fg:
|
|
346
|
-
--color-badge-blue-bg:
|
|
347
|
-
--color-badge-blue-fg:
|
|
348
|
-
--color-badge-yellow-bg:
|
|
349
|
-
--color-badge-yellow-fg:
|
|
350
|
-
--color-badge-teal-bg:
|
|
351
|
-
--color-badge-teal-fg:
|
|
352
|
-
--color-badge-cyan-bg:
|
|
353
|
-
--color-badge-cyan-fg:
|
|
354
|
-
--color-badge-pink-bg:
|
|
355
|
-
--color-badge-pink-fg:
|
|
356
|
-
--color-badge-purple-alt-bg:
|
|
357
|
-
--color-badge-purple-alt-fg:
|
|
358
|
-
--color-badge-blue-alt-bg:
|
|
359
|
-
--color-badge-blue-alt-fg:
|
|
360
|
-
--color-badge-bright-gray-bg:
|
|
361
|
-
--color-badge-bright-gray-fg:
|
|
588
|
+
--color-badge-purple-bg: var(--lux-n-800);
|
|
589
|
+
--color-badge-purple-fg: var(--lux-n-300);
|
|
590
|
+
--color-badge-orange-bg: var(--lux-n-800);
|
|
591
|
+
--color-badge-orange-fg: var(--lux-n-300);
|
|
592
|
+
--color-badge-blue-bg: var(--lux-n-800);
|
|
593
|
+
--color-badge-blue-fg: var(--lux-n-300);
|
|
594
|
+
--color-badge-yellow-bg: var(--lux-n-800);
|
|
595
|
+
--color-badge-yellow-fg: var(--lux-n-300);
|
|
596
|
+
--color-badge-teal-bg: var(--lux-n-800);
|
|
597
|
+
--color-badge-teal-fg: var(--lux-n-300);
|
|
598
|
+
--color-badge-cyan-bg: var(--lux-n-800);
|
|
599
|
+
--color-badge-cyan-fg: var(--lux-n-300);
|
|
600
|
+
--color-badge-pink-bg: var(--lux-n-800);
|
|
601
|
+
--color-badge-pink-fg: var(--lux-n-300);
|
|
602
|
+
--color-badge-purple-alt-bg: var(--lux-n-800);
|
|
603
|
+
--color-badge-purple-alt-fg: var(--lux-paper-80);
|
|
604
|
+
--color-badge-blue-alt-bg: var(--lux-n-800);
|
|
605
|
+
--color-badge-blue-alt-fg: var(--lux-paper-80);
|
|
606
|
+
--color-badge-bright-gray-bg: var(--lux-n-800);
|
|
607
|
+
--color-badge-bright-gray-fg: var(--lux-n-200);
|
|
362
608
|
--color-badge-bright-green-bg: #22543D;
|
|
363
609
|
--color-badge-bright-green-fg: #9AE6B4;
|
|
364
610
|
--color-badge-bright-red-bg: #822727;
|
|
365
611
|
--color-badge-bright-red-fg: #FEB2B2;
|
|
366
|
-
--color-badge-bright-blue-bg:
|
|
367
|
-
--color-badge-bright-blue-fg:
|
|
368
|
-
--color-badge-bright-yellow-bg:
|
|
369
|
-
--color-badge-bright-yellow-fg:
|
|
370
|
-
--color-badge-bright-teal-bg:
|
|
371
|
-
--color-badge-bright-teal-fg:
|
|
372
|
-
--color-badge-bright-cyan-bg:
|
|
373
|
-
--color-badge-bright-cyan-fg:
|
|
374
|
-
--color-badge-bright-orange-bg:
|
|
375
|
-
--color-badge-bright-orange-fg:
|
|
376
|
-
--color-badge-bright-purple-bg:
|
|
377
|
-
--color-badge-bright-purple-fg:
|
|
378
|
-
--color-badge-bright-pink-bg:
|
|
379
|
-
--color-badge-bright-pink-fg:
|
|
612
|
+
--color-badge-bright-blue-bg: var(--lux-n-700);
|
|
613
|
+
--color-badge-bright-blue-fg: var(--lux-n-200);
|
|
614
|
+
--color-badge-bright-yellow-bg: var(--lux-n-700);
|
|
615
|
+
--color-badge-bright-yellow-fg: var(--lux-n-200);
|
|
616
|
+
--color-badge-bright-teal-bg: var(--lux-n-700);
|
|
617
|
+
--color-badge-bright-teal-fg: var(--lux-n-200);
|
|
618
|
+
--color-badge-bright-cyan-bg: var(--lux-n-700);
|
|
619
|
+
--color-badge-bright-cyan-fg: var(--lux-n-200);
|
|
620
|
+
--color-badge-bright-orange-bg: var(--lux-n-700);
|
|
621
|
+
--color-badge-bright-orange-fg: var(--lux-n-200);
|
|
622
|
+
--color-badge-bright-purple-bg: var(--lux-n-700);
|
|
623
|
+
--color-badge-bright-purple-fg: var(--lux-n-200);
|
|
624
|
+
--color-badge-bright-pink-bg: var(--lux-n-700);
|
|
625
|
+
--color-badge-bright-pink-fg: var(--lux-n-200);
|
|
380
626
|
|
|
381
627
|
/* --- Alerts --- */
|
|
382
|
-
--color-alert-fg:
|
|
383
|
-
--color-alert-bg-info:
|
|
384
|
-
--color-alert-bg-warning:
|
|
385
|
-
--color-alert-bg-warning-table:
|
|
628
|
+
--color-alert-fg: var(--lux-paper-80);
|
|
629
|
+
--color-alert-bg-info: var(--lux-paper-06);
|
|
630
|
+
--color-alert-bg-warning: var(--lux-paper-08);
|
|
631
|
+
--color-alert-bg-warning-table: var(--lux-paper-06);
|
|
386
632
|
--color-alert-bg-success: #1C4532;
|
|
387
633
|
--color-alert-bg-error: #63171B;
|
|
388
634
|
|
|
389
635
|
/* --- Dialogs / Popovers / Drawers --- */
|
|
390
|
-
--color-dialog-bg:
|
|
391
|
-
--color-dialog-fg:
|
|
392
|
-
--color-popover-bg:
|
|
393
|
-
--color-popover-
|
|
394
|
-
--color-
|
|
636
|
+
--color-dialog-bg: var(--lux-n-900);
|
|
637
|
+
--color-dialog-fg: var(--lux-paper-80);
|
|
638
|
+
--color-popover-bg: var(--lux-n-900);
|
|
639
|
+
--color-popover-border: var(--lux-paper-12);
|
|
640
|
+
--color-popover-shadow: var(--lux-paper-16);
|
|
641
|
+
--color-drawer-bg: var(--lux-n-900);
|
|
395
642
|
|
|
396
643
|
/* --- Tooltip --- */
|
|
397
|
-
--color-tooltip-bg:
|
|
398
|
-
--color-tooltip-fg:
|
|
644
|
+
--color-tooltip-bg: var(--lux-n-900);
|
|
645
|
+
--color-tooltip-fg: var(--lux-n-0);
|
|
399
646
|
|
|
400
647
|
/* --- Table --- */
|
|
401
|
-
--color-table-header-bg:
|
|
402
|
-
--color-table-header-fg:
|
|
648
|
+
--color-table-header-bg: var(--lux-paper-06);
|
|
649
|
+
--color-table-header-fg: var(--lux-paper-64);
|
|
403
650
|
|
|
404
651
|
/* --- Tabs --- */
|
|
405
|
-
--color-tabs-solid-fg:
|
|
406
|
-
--color-tabs-
|
|
407
|
-
--color-tabs-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
--color-
|
|
652
|
+
--color-tabs-solid-fg: var(--lux-n-0);
|
|
653
|
+
--color-tabs-solid-bg: var(--lux-n-900);
|
|
654
|
+
--color-tabs-solid-fg-selected: var(--lux-n-900);
|
|
655
|
+
--color-tabs-solid-bg-selected: var(--lux-n-0);
|
|
656
|
+
--color-tabs-secondary-fg: var(--lux-n-400);
|
|
657
|
+
--color-tabs-secondary-fg-selected: var(--lux-n-0);
|
|
658
|
+
--color-tabs-radio-fg: var(--lux-n-400);
|
|
659
|
+
--color-tabs-radio-bg-selected: var(--lux-n-800);
|
|
660
|
+
--color-tabs-radio-fg-selected: var(--lux-n-0);
|
|
661
|
+
|
|
662
|
+
--color-tabs-secondary-border: var(--lux-n-600);
|
|
663
|
+
|
|
664
|
+
/* --- Controls --- */
|
|
665
|
+
--color-switch-bg: var(--lux-paper-24);
|
|
666
|
+
--color-progress-track: var(--lux-paper-06);
|
|
667
|
+
|
|
668
|
+
/* --- Chrome / charts --- */
|
|
669
|
+
--color-stats-bg: var(--lux-paper-04);
|
|
670
|
+
--color-topbar-bg: var(--lux-paper-04);
|
|
671
|
+
--color-graph-line: var(--lux-paper-48);
|
|
672
|
+
--color-graph-gradient-start: rgba(255, 255, 255, 0.15);
|
|
673
|
+
--color-graph-gradient-stop: rgba(255, 255, 255, 0);
|
|
674
|
+
--shadow-drawer: 0px 15px 40px 0px rgba(0, 0, 0, 0.4), 0px 5px 10px 0px rgba(0, 0, 0, 0.2), 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
|
|
411
675
|
|
|
412
676
|
/* --- Skeleton --- */
|
|
413
|
-
--color-skeleton-start:
|
|
414
|
-
--color-skeleton-end:
|
|
677
|
+
--color-skeleton-start: var(--lux-n-800);
|
|
678
|
+
--color-skeleton-end: var(--lux-n-700);
|
|
415
679
|
|
|
416
|
-
/* ---
|
|
417
|
-
--color-
|
|
680
|
+
/* --- Scrollbar --- */
|
|
681
|
+
--color-scrollbar-thumb: var(--lux-paper-16);
|
|
418
682
|
|
|
419
|
-
/* ---
|
|
420
|
-
--color-
|
|
421
|
-
|
|
683
|
+
/* --- Selection --- */
|
|
684
|
+
--color-selection-bg: var(--lux-n-700);
|
|
685
|
+
|
|
686
|
+
/* The warm ramps are NOT redefined here on purpose — see the light block.
|
|
687
|
+
They are monotone in both modes so `dark:bg-yellow-900` still means
|
|
688
|
+
"dark". A call site that needs ink that FLIPS with the mode wants
|
|
689
|
+
--color-status-warn, which is a semantic token, not a palette rung. */
|
|
690
|
+
|
|
691
|
+
/* ------------------------------------------------------------
|
|
692
|
+
SHADCN / TAILWIND ALIASES (dark)
|
|
693
|
+
------------------------------------------------------------ */
|
|
694
|
+
--background: var(--lux-n-1000);
|
|
695
|
+
--foreground: var(--lux-n-50);
|
|
696
|
+
--card: var(--lux-n-950);
|
|
697
|
+
--card-foreground: var(--lux-n-50);
|
|
698
|
+
--popover: var(--lux-n-950);
|
|
699
|
+
--popover-foreground: var(--lux-n-50);
|
|
700
|
+
--primary: var(--lux-accent);
|
|
701
|
+
--primary-foreground: var(--lux-accent-fg);
|
|
702
|
+
--secondary: var(--lux-n-900);
|
|
703
|
+
--secondary-foreground: var(--lux-n-50);
|
|
704
|
+
--muted: var(--lux-n-900);
|
|
705
|
+
--muted-foreground: var(--lux-n-400);
|
|
706
|
+
--accent: var(--lux-n-900);
|
|
707
|
+
--accent-foreground: var(--lux-n-50);
|
|
708
|
+
--destructive: var(--lux-state-error);
|
|
709
|
+
--destructive-foreground: var(--lux-n-950);
|
|
710
|
+
--success: var(--lux-state-success);
|
|
711
|
+
--success-foreground: var(--lux-n-950);
|
|
712
|
+
--warning: var(--lux-state-notice);
|
|
713
|
+
--warning-foreground: var(--lux-n-950);
|
|
714
|
+
--info: var(--lux-n-300);
|
|
715
|
+
--info-foreground: var(--lux-n-950);
|
|
716
|
+
--border: var(--lux-paper-10);
|
|
717
|
+
--input: var(--lux-paper-12);
|
|
718
|
+
--ring: var(--lux-n-500);
|
|
719
|
+
--chart-1: var(--lux-n-50);
|
|
720
|
+
--chart-2: var(--lux-n-400);
|
|
721
|
+
--chart-3: var(--lux-n-500);
|
|
722
|
+
--chart-4: var(--lux-n-300);
|
|
723
|
+
--chart-5: var(--lux-n-600);
|
|
724
|
+
--sidebar: var(--lux-n-950);
|
|
725
|
+
--sidebar-foreground: var(--lux-n-50);
|
|
726
|
+
--sidebar-primary: var(--lux-accent);
|
|
727
|
+
--sidebar-primary-foreground: var(--lux-accent-fg);
|
|
728
|
+
--sidebar-accent: var(--lux-n-900);
|
|
729
|
+
--sidebar-accent-foreground: var(--lux-n-50);
|
|
730
|
+
--sidebar-border: var(--lux-paper-10);
|
|
731
|
+
--sidebar-ring: var(--lux-n-500);
|
|
732
|
+
}
|
|
422
733
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
734
|
+
/* ================================================================
|
|
735
|
+
6 — MOTION. One system: five durations, four curves, six moves.
|
|
736
|
+
|
|
737
|
+
Two rules make "smooth" measurable. Both were established by
|
|
738
|
+
benchmark, not by taste, and the second one is the one that bites.
|
|
739
|
+
|
|
740
|
+
1. WHAT you animate. A decorative animation may touch `transform`
|
|
741
|
+
and `opacity` and nothing else. Those two are the only properties
|
|
742
|
+
the compositor can run off the main thread, so they survive a
|
|
743
|
+
busy CPU. Animating width / height / top / left / margin /
|
|
744
|
+
background-position forces layout or paint every frame. Worse,
|
|
745
|
+
the layout ones also register as layout shift: the explorer's
|
|
746
|
+
mobile drawer animated `left` and scored CLS 0.726 every time it
|
|
747
|
+
opened — Google calls anything over 0.25 "poor". The same drawer
|
|
748
|
+
on `transform` scores 0.
|
|
749
|
+
|
|
750
|
+
2. HOW MANY things animate. Keep it O(1) in the size of the page.
|
|
751
|
+
Every independently animated element is a compositor layer to
|
|
752
|
+
allocate, rasterise and composite. Past a few hundred, that count
|
|
753
|
+
— not the property — is the bottleneck, and rule 1 alone will
|
|
754
|
+
happily walk you off a cliff. The measurements are in 6c.
|
|
755
|
+
|
|
756
|
+
The one deliberate exception is a disclosure widget (accordion,
|
|
757
|
+
collapsible). There the box change IS the content the user asked
|
|
758
|
+
for, not decoration, so animating its height is correct. Decoration
|
|
759
|
+
animates transform; disclosure animates the box it discloses.
|
|
760
|
+
|
|
761
|
+
Durations are named for their ROLE so a caller cannot pick "300ms
|
|
762
|
+
because it felt right". Exits are shorter than entrances — by the
|
|
763
|
+
time a thing leaves the user has already decided, and waiting on it
|
|
764
|
+
reads as lag.
|
|
765
|
+
================================================================ */
|
|
766
|
+
:root {
|
|
767
|
+
/* --- Durations -------------------------------------------------- */
|
|
768
|
+
--lux-dur-press: 80ms; /* tap acknowledgement */
|
|
769
|
+
--lux-dur-hover: 120ms; /* pointer feedback */
|
|
770
|
+
--lux-dur-exit: 140ms; /* something leaves */
|
|
771
|
+
--lux-dur-enter: 200ms; /* something appears */
|
|
772
|
+
--lux-dur-move: 280ms; /* a panel travels across the viewport */
|
|
773
|
+
|
|
774
|
+
/* --- Curves ----------------------------------------------------- */
|
|
775
|
+
--lux-ease: cubic-bezier(0.4, 0, 0.2, 1); /* A -> B */
|
|
776
|
+
--lux-ease-out: cubic-bezier(0.16, 1, 0.3, 1); /* entering */
|
|
777
|
+
--lux-ease-in: cubic-bezier(0.7, 0, 0.84, 0); /* leaving */
|
|
778
|
+
--lux-ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); /* press */
|
|
779
|
+
|
|
780
|
+
/* --- Distances. Enter offsets are one value, not a per-component
|
|
781
|
+
guess. Both collapse to 0 under reduced motion. -------------- */
|
|
782
|
+
--lux-lift: 2px; /* hover raise */
|
|
783
|
+
--lux-rise: 8px; /* enter offset */
|
|
784
|
+
}
|
|
427
785
|
|
|
428
|
-
|
|
429
|
-
|
|
786
|
+
/* --- The six moves. transform + opacity only. --------------------- */
|
|
787
|
+
@keyframes lux-fade-in { from { opacity: 0 } to { opacity: 1 } }
|
|
788
|
+
@keyframes lux-fade-out { from { opacity: 1 } to { opacity: 0 } }
|
|
430
789
|
|
|
431
|
-
|
|
432
|
-
--
|
|
790
|
+
@keyframes lux-rise-in {
|
|
791
|
+
from { opacity: 0; transform: translate3d(0, var(--lux-rise), 0) }
|
|
792
|
+
to { opacity: 1; transform: translate3d(0, 0, 0) }
|
|
793
|
+
}
|
|
433
794
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
795
|
+
@keyframes lux-scale-in {
|
|
796
|
+
from { opacity: 0; transform: scale(0.96) }
|
|
797
|
+
to { opacity: 1; transform: scale(1) }
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
@keyframes lux-scale-out {
|
|
801
|
+
from { opacity: 1; transform: scale(1) }
|
|
802
|
+
to { opacity: 0; transform: scale(0.96) }
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/* The loading sweep — ONE per page, never one per skeleton. See 6c. */
|
|
806
|
+
@keyframes lux-sweep {
|
|
807
|
+
from { transform: translate3d(-100%, 0, 0) }
|
|
808
|
+
to { transform: translate3d(350%, 0, 0) }
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
@keyframes lux-spin { to { transform: rotate(360deg) } }
|
|
812
|
+
|
|
813
|
+
/* ================================================================
|
|
814
|
+
6b — The primitives. Every surface reaches for these, never for a
|
|
815
|
+
hand-rolled keyframe.
|
|
816
|
+
================================================================ */
|
|
817
|
+
|
|
818
|
+
.lux-enter { animation: lux-rise-in var(--lux-dur-enter) var(--lux-ease-out) both }
|
|
819
|
+
.lux-exit { animation: lux-fade-out var(--lux-dur-exit) var(--lux-ease-in) both }
|
|
820
|
+
|
|
821
|
+
/* Floating surfaces — menu, popover, tooltip, dialog. They grow from
|
|
822
|
+
where they were summoned rather than sliding in from nowhere. */
|
|
823
|
+
.lux-pop { animation: lux-scale-in var(--lux-dur-enter) var(--lux-ease-out) both }
|
|
824
|
+
.lux-pop-exit { animation: lux-scale-out var(--lux-dur-exit) var(--lux-ease-in) both }
|
|
825
|
+
|
|
826
|
+
/* A list cascades by setting --lux-i on each row; one property, no JS. */
|
|
827
|
+
.lux-stagger { animation-delay: calc(var(--lux-i, 0) * 40ms) }
|
|
828
|
+
|
|
829
|
+
/* Hover / press feedback. `transform` and `opacity` are the only
|
|
830
|
+
transitioned properties, so this is safe on any element. */
|
|
831
|
+
.lux-interactive {
|
|
832
|
+
transition:
|
|
833
|
+
transform var(--lux-dur-hover) var(--lux-ease-out),
|
|
834
|
+
opacity var(--lux-dur-hover) var(--lux-ease-out);
|
|
835
|
+
}
|
|
836
|
+
.lux-interactive:hover { transform: translate3d(0, calc(-1 * var(--lux-lift)), 0) }
|
|
837
|
+
.lux-interactive:active { transform: scale(0.98); transition-duration: var(--lux-dur-press) }
|
|
838
|
+
.lux-interactive:disabled,
|
|
839
|
+
.lux-interactive[aria-disabled='true'] { transform: none }
|
|
840
|
+
|
|
841
|
+
/* ================================================================
|
|
842
|
+
6c — The loading state. Two primitives, one job each.
|
|
843
|
+
|
|
844
|
+
`.lux-skeleton` RESERVES SPACE. `.lux-loading` SAYS WORK IS IN
|
|
845
|
+
FLIGHT. Keeping those apart is what makes the whole thing cheap,
|
|
846
|
+
because only the second one moves — once for the page, not once per
|
|
847
|
+
skeleton.
|
|
848
|
+
|
|
849
|
+
This is the part that is counter-intuitive, so here are the numbers
|
|
850
|
+
that settled it. Chromium, 390x844 @3x, 4x CPU throttle, 5s samples,
|
|
851
|
+
n = concurrently-mounted skeletons:
|
|
852
|
+
|
|
853
|
+
n=600 bgpos 79.6fps sheen 57.2fps pulse 115.4fps bar 120fps
|
|
854
|
+
n=1460 bgpos 33.6fps sheen 23.0fps pulse 39.0fps bar 120fps
|
|
855
|
+
n=3000 bgpos 13.8fps sheen 5.4fps pulse 18.2fps bar 120fps
|
|
856
|
+
|
|
857
|
+
bgpos = per-element background-position gradient (what we shipped)
|
|
858
|
+
sheen = per-element transform on a ::after (the "obvious" fix)
|
|
859
|
+
pulse = per-element opacity keyframe
|
|
860
|
+
bar = flat skeletons + ONE page-level sweep (what we ship now)
|
|
861
|
+
|
|
862
|
+
Read the middle column twice. Rewriting the shimmer as a per-element
|
|
863
|
+
`transform` — obeying "animate transform and opacity only" to the
|
|
864
|
+
letter — made it 32% SLOWER than the background-position version it
|
|
865
|
+
replaced, and at n=3000 it produced a single 2.5-SECOND frame.
|
|
866
|
+
|
|
867
|
+
The property rule is necessary and not sufficient. Past a few
|
|
868
|
+
hundred elements the dominant cost is the NUMBER of independently
|
|
869
|
+
animated elements: each one is a compositor layer to allocate,
|
|
870
|
+
rasterise and composite, and `overflow:hidden` on each adds a
|
|
871
|
+
render surface on top. Only the O(1) design is flat in n — 120fps
|
|
872
|
+
at 600, at 1460 and at 3000, identical to animating nothing.
|
|
873
|
+
|
|
874
|
+
So: a skeleton is a promise about layout and nothing else. It
|
|
875
|
+
occupies exactly the space the real content will (zero CLS) and it
|
|
876
|
+
holds still.
|
|
877
|
+
================================================================ */
|
|
878
|
+
.lux-skeleton {
|
|
879
|
+
background: var(--color-skeleton-start);
|
|
880
|
+
/* Nothing inside a skeleton is readable yet; say so once, here. */
|
|
881
|
+
color: transparent;
|
|
882
|
+
user-select: none;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/* The one moving part. Fixed, 2px, above everything, out of flow — so it
|
|
886
|
+
cannot shift layout and cannot tint content. Mount it while any request
|
|
887
|
+
is in flight; unmount it when they land. One per page. */
|
|
888
|
+
.lux-loading {
|
|
889
|
+
position: fixed;
|
|
890
|
+
inset: 0 0 auto;
|
|
891
|
+
height: 2px;
|
|
892
|
+
z-index: 60;
|
|
893
|
+
overflow: hidden;
|
|
894
|
+
background: var(--color-skeleton-start);
|
|
895
|
+
pointer-events: none;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
.lux-loading::after {
|
|
899
|
+
content: '';
|
|
900
|
+
position: absolute;
|
|
901
|
+
inset: 0;
|
|
902
|
+
width: 40%;
|
|
903
|
+
background: linear-gradient(
|
|
904
|
+
90deg,
|
|
905
|
+
transparent 0%,
|
|
906
|
+
var(--color-skeleton-end) 50%,
|
|
907
|
+
transparent 100%
|
|
908
|
+
);
|
|
909
|
+
animation: lux-sweep 1.1s var(--lux-ease) infinite;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/* ================================================================
|
|
913
|
+
6d — Reduced motion.
|
|
914
|
+
|
|
915
|
+
Belt AND braces, because either alone leaks:
|
|
916
|
+
- zeroing the TOKENS catches anything that reads them, including
|
|
917
|
+
inline styles and the Web Animations API, which !important
|
|
918
|
+
cannot reach;
|
|
919
|
+
- the global override catches every hand-rolled transition that
|
|
920
|
+
never adopted a token.
|
|
921
|
+
Unscoped on purpose. A reduced-motion rule that only applies inside
|
|
922
|
+
one component is a rule the rest of the app ignores.
|
|
923
|
+
|
|
924
|
+
Motion goes; FEEDBACK stays. State changes still land, instantly.
|
|
925
|
+
================================================================ */
|
|
926
|
+
@media (prefers-reduced-motion: reduce) {
|
|
927
|
+
:root {
|
|
928
|
+
--lux-dur-press: 1ms;
|
|
929
|
+
--lux-dur-hover: 1ms;
|
|
930
|
+
--lux-dur-exit: 1ms;
|
|
931
|
+
--lux-dur-enter: 1ms;
|
|
932
|
+
--lux-dur-move: 1ms;
|
|
933
|
+
--lux-lift: 0px;
|
|
934
|
+
--lux-rise: 0px;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
*,
|
|
938
|
+
*::before,
|
|
939
|
+
*::after {
|
|
940
|
+
animation-duration: 1ms !important;
|
|
941
|
+
animation-iteration-count: 1 !important;
|
|
942
|
+
transition-duration: 1ms !important;
|
|
943
|
+
scroll-behavior: auto !important;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/* A sweep that runs once and freezes mid-track is a smear. Drop the
|
|
947
|
+
motion; the bar itself stays, so "work in flight" is still visible. */
|
|
948
|
+
.lux-loading::after { animation: none; width: 100%; opacity: 0.5 }
|
|
438
949
|
}
|