@attrus-ds/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +27 -0
- package/README.md +123 -0
- package/dist/assets/flags/Brazil-rounded.svg +16 -0
- package/dist/assets/flags/Brazil-square.svg +17 -0
- package/dist/assets/flags/Chile-rounded.svg +11 -0
- package/dist/assets/flags/Chile-square.svg +11 -0
- package/dist/assets/flags/Colombia-rounded.svg +10 -0
- package/dist/assets/flags/Colombia-square.svg +10 -0
- package/dist/assets/flags/EUA-rounded.svg +11 -0
- package/dist/assets/flags/EUA-square.svg +11 -0
- package/dist/assets/flags/EUR-rounded.svg +9 -0
- package/dist/assets/flags/EUR-square.svg +9 -0
- package/dist/assets/flags/Mexico-rounded.svg +19 -0
- package/dist/assets/flags/Mexico-square.svg +19 -0
- package/dist/assets/icon-attrus-dark.svg +3 -0
- package/dist/assets/icon-attrus-light.svg +3 -0
- package/dist/assets/logo-attrus-dark.svg +8 -0
- package/dist/assets/logo-attrus-light.svg +8 -0
- package/dist/css/components/buttons.css +301 -0
- package/dist/css/components/callout.css +195 -0
- package/dist/css/components/cards.css +272 -0
- package/dist/css/components/combobox.css +303 -0
- package/dist/css/components/empty-states.css +61 -0
- package/dist/css/components/inputs.css +1027 -0
- package/dist/css/components/number-input.css +138 -0
- package/dist/css/components/overlays.css +405 -0
- package/dist/css/components/primitives.css +305 -0
- package/dist/css/components/sidebar.css +179 -0
- package/dist/css/components/status-pills.css +207 -0
- package/dist/css/components/stepper.css +309 -0
- package/dist/css/components/table.css +600 -0
- package/dist/css/components/tabs.css +319 -0
- package/dist/css/components/toast.css +239 -0
- package/dist/css/components/tooltip.css +226 -0
- package/dist/css/components/topbar.css +148 -0
- package/dist/css/fonts.css +91 -0
- package/dist/css/index.css +23 -0
- package/dist/css/tokens.css +691 -0
- package/dist/fonts/LICENSE-JetBrainsMono.txt +93 -0
- package/dist/fonts/LICENSE-Lato.txt +93 -0
- package/dist/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-600-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-100-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-300-italic.woff2 +0 -0
- package/dist/fonts/lato-latin-300-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-400-italic.woff2 +0 -0
- package/dist/fonts/lato-latin-400-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-700-italic.woff2 +0 -0
- package/dist/fonts/lato-latin-700-normal.woff2 +0 -0
- package/dist/fonts/lato-latin-900-normal.woff2 +0 -0
- package/dist/tokens/attrus-tokens.flat.json +1235 -0
- package/dist/tokens/attrus-tokens.json +1090 -0
- package/package.json +46 -0
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
CABIROS — ATTRUS Design System
|
|
3
|
+
colors_and_type.css
|
|
4
|
+
----
|
|
5
|
+
Sober, serious, professional. Dashboards for financial
|
|
6
|
+
operations across LATAM. Cool bluish grays. Deep navy.
|
|
7
|
+
Primary brand blue. Liquid-glass-friendly translucency.
|
|
8
|
+
============================================================ */
|
|
9
|
+
|
|
10
|
+
/* ---------- Webfont: Lato ---------- */
|
|
11
|
+
|
|
12
|
+
:root {
|
|
13
|
+
/* ============================================================
|
|
14
|
+
1. BASE PALETTE — raw color tokens
|
|
15
|
+
============================================================ */
|
|
16
|
+
|
|
17
|
+
/* --- Brand (from manual: Lato + 4 HEX stops) --- */
|
|
18
|
+
--brand-attrus-ink: #0F0F1A; /* almost-black, blue-tinted */
|
|
19
|
+
--brand-attrus-navy: #002142; /* deep navy */
|
|
20
|
+
--brand-attrus-blue: #003399; /* PRIMARY brand blue */
|
|
21
|
+
--brand-attrus-sky: #3399FF; /* bright accent / highlight */
|
|
22
|
+
--brand-attrus-logo-ink: #000033; /* per logo SVG fills */
|
|
23
|
+
|
|
24
|
+
/* --- Neutrals (cool, with a subtle bluish tint — never pure) --- */
|
|
25
|
+
/* Pure achromatic primitives — referenced by transparency tokens */
|
|
26
|
+
--color-pure-white: #FFFFFF;
|
|
27
|
+
--color-pure-black: #000000;
|
|
28
|
+
--color-shadow-tint: var(--color-neutral-900); /* default — blue-tinted ink, aligned to neutral scale */
|
|
29
|
+
--shadow-tint-success-color: var(--color-success-900); /* green-tinted ink */
|
|
30
|
+
--shadow-tint-warning-color: var(--color-warning-900); /* amber-tinted ink */
|
|
31
|
+
--shadow-tint-danger-color: var(--color-danger-900); /* wine-tinted ink */
|
|
32
|
+
--shadow-tint-info-color: var(--color-info-900); /* steel-blue-tinted ink */
|
|
33
|
+
|
|
34
|
+
--color-neutral-0: var(--color-pure-white);
|
|
35
|
+
--color-neutral-25: #FAFBFD; /* app canvas bg */
|
|
36
|
+
--color-neutral-50: #F4F6FA; /* rows, subdued surfaces */
|
|
37
|
+
--color-neutral-100: #EDF0F5; /* hover, very soft chips */
|
|
38
|
+
--color-neutral-150: #E3E8F0; /* dividers, borders */
|
|
39
|
+
--color-neutral-200: #D6DCE7; /* stronger borders */
|
|
40
|
+
--color-neutral-300: #B8C1D1; /* placeholder */
|
|
41
|
+
--color-neutral-400: #8A94A8; /* muted text */
|
|
42
|
+
--color-neutral-500: #5E6A82; /* secondary text */
|
|
43
|
+
--color-neutral-600: #3F4A61; /* strong secondary */
|
|
44
|
+
--color-neutral-700: #27304A; /* headings on light */
|
|
45
|
+
--color-neutral-800: #141B2E; /* near-surface dark */
|
|
46
|
+
--color-neutral-900: #0A0F1F; /* inverse surface (never pure black) */
|
|
47
|
+
--color-neutral-950: #05081A; /* deepest inverse */
|
|
48
|
+
|
|
49
|
+
/* --- Inverse "ink" tones (variants of neutral-900/-950, used by inverse layer) --- */
|
|
50
|
+
--color-ink-base: #0B1230; /* near-black navy */
|
|
51
|
+
--color-ink-raised: #111A3D; /* card on inverse */
|
|
52
|
+
--color-ink-deep: #0A1128; /* deeper than base — wells, alt rows */
|
|
53
|
+
--color-ink-hover: #15214A; /* hover state on inverse */
|
|
54
|
+
|
|
55
|
+
/* --- Brand primary · Navy (institutional — logo, headings, primary surfaces)
|
|
56
|
+
10-stop scale anchored at -500: #002142 (ATTRUS Navy from brand book).
|
|
57
|
+
Interpolated in OKLCH from anchor for uniform perceptual distance.
|
|
58
|
+
Dominant brand colour — 40% of usage per brand book. */
|
|
59
|
+
--color-brand-primary-50: #E5EBF2;
|
|
60
|
+
--color-brand-primary-100: #C2CDDB;
|
|
61
|
+
--color-brand-primary-200: #8E9FB8;
|
|
62
|
+
--color-brand-primary-300: #5F7596;
|
|
63
|
+
--color-brand-primary-400: #2F4F75;
|
|
64
|
+
--color-brand-primary-500: #002142; /* ★ ATTRUS Navy — brand primary */
|
|
65
|
+
--color-brand-primary-600: #001D3A;
|
|
66
|
+
--color-brand-primary-700: #001830;
|
|
67
|
+
--color-brand-primary-800: #001226;
|
|
68
|
+
--color-brand-primary-900: #000C1A;
|
|
69
|
+
|
|
70
|
+
/* --- Brand secondary · Royal (support — highlights, secondary blocks)
|
|
71
|
+
10-stop scale anchored at -500: #003399 (ATTRUS Royal from brand book).
|
|
72
|
+
Used for accent surfaces with more presence than Sky but less than Navy.
|
|
73
|
+
10% of brand usage. */
|
|
74
|
+
--color-brand-secondary-50: #EAF1FF;
|
|
75
|
+
--color-brand-secondary-100: #D1DEFF;
|
|
76
|
+
--color-brand-secondary-200: #A3BEFF;
|
|
77
|
+
--color-brand-secondary-300: #6B95FB;
|
|
78
|
+
--color-brand-secondary-400: #3F6DEF;
|
|
79
|
+
--color-brand-secondary-500: #003399; /* brand */
|
|
80
|
+
--color-brand-secondary-600: #002A80;
|
|
81
|
+
--color-brand-secondary-700: #002166;
|
|
82
|
+
--color-brand-secondary-800: #001A4D;
|
|
83
|
+
--color-brand-secondary-900: #001133;
|
|
84
|
+
|
|
85
|
+
/* --- Brand accent · Sky (action — CTAs, links, highlights)
|
|
86
|
+
10-stop scale anchored at -500: #3399FF (ATTRUS Sky from brand book).
|
|
87
|
+
Used for primary actions and call-outs only — 3% of brand usage.
|
|
88
|
+
Stops 50/200/400/600/800/900 interpolated in OKLCH for uniform perceptual distance.
|
|
89
|
+
Dark stops (700-900) used as inverse surfaces in dark mode;
|
|
90
|
+
light stops (50-200) for foreground text on those surfaces. */
|
|
91
|
+
--color-brand-accent-50: #ECF5FF;
|
|
92
|
+
--color-brand-accent-100: #D9ECFF;
|
|
93
|
+
--color-brand-accent-200: #ADD2FF;
|
|
94
|
+
--color-brand-accent-300: #7AB8FF;
|
|
95
|
+
--color-brand-accent-400: #549EFF;
|
|
96
|
+
--color-brand-accent-500: #3399FF; /* accent */
|
|
97
|
+
--color-brand-accent-600: #2880DD;
|
|
98
|
+
--color-brand-accent-700: #1E6DC4;
|
|
99
|
+
--color-brand-accent-800: #155198;
|
|
100
|
+
--color-brand-accent-900: #0E3B70;
|
|
101
|
+
|
|
102
|
+
/* --- Semantic feedback (subdued, sober) — perceptually calibrated 10-stop scales (OKLCH) ---
|
|
103
|
+
Anchors at 50/100/500/700/900 are immutable (preserved from the original 5-stop palette).
|
|
104
|
+
Stops 200/300/400/600/800 are interpolated in OKLCH for uniform perceptual distance.
|
|
105
|
+
info-900 is derived from the average L/C trajectory of the other three families' 700→900. */
|
|
106
|
+
--color-success-50: #E8F5EE;
|
|
107
|
+
--color-success-100: #CDEBD9;
|
|
108
|
+
--color-success-200: #9CCEAF;
|
|
109
|
+
--color-success-300: #74B68C;
|
|
110
|
+
--color-success-400: #499D69;
|
|
111
|
+
--color-success-500: #1F8A4C;
|
|
112
|
+
--color-success-600: #1A7A43;
|
|
113
|
+
--color-success-700: #136236;
|
|
114
|
+
--color-success-800: #0E4F2B;
|
|
115
|
+
--color-success-900: #0A3D21;
|
|
116
|
+
|
|
117
|
+
--color-warning-50: #FDF5E3;
|
|
118
|
+
--color-warning-100: #FAE8BE;
|
|
119
|
+
--color-warning-200: #E4C790;
|
|
120
|
+
--color-warning-300: #D2AC69;
|
|
121
|
+
--color-warning-400: #C19040;
|
|
122
|
+
--color-warning-500: #B47A12;
|
|
123
|
+
--color-warning-600: #A16B0F;
|
|
124
|
+
--color-warning-700: #84560A;
|
|
125
|
+
--color-warning-800: #694307;
|
|
126
|
+
--color-warning-900: #4F3105;
|
|
127
|
+
|
|
128
|
+
--color-danger-50: #FCEBEA;
|
|
129
|
+
--color-danger-100: #F7CFCD;
|
|
130
|
+
--color-danger-200: #EBA4A0;
|
|
131
|
+
--color-danger-300: #DE807A;
|
|
132
|
+
--color-danger-400: #CF5B54;
|
|
133
|
+
--color-danger-500: #C23934;
|
|
134
|
+
--color-danger-600: #AB312D;
|
|
135
|
+
--color-danger-700: #8A2622;
|
|
136
|
+
--color-danger-800: #6C1D1A;
|
|
137
|
+
--color-danger-900: #4F1512;
|
|
138
|
+
|
|
139
|
+
--color-info-50: #E6F0FB;
|
|
140
|
+
--color-info-100: #C5DCF4;
|
|
141
|
+
--color-info-200: #93BBE8;
|
|
142
|
+
--color-info-300: #6B9FDD;
|
|
143
|
+
--color-info-400: #4383D1;
|
|
144
|
+
--color-info-500: #1F6BC7;
|
|
145
|
+
--color-info-600: #1A5EAF;
|
|
146
|
+
--color-info-700: #144B8C;
|
|
147
|
+
--color-info-800: #0D3A6E;
|
|
148
|
+
--color-info-900: #072951;
|
|
149
|
+
|
|
150
|
+
/* ============================================================
|
|
151
|
+
2. SEMANTIC TOKENS — reference the base palette
|
|
152
|
+
Roles: default | secondary | muted | accent | placeholder
|
|
153
|
+
Contexts: fg (text/icon), bg (surface), br (border)
|
|
154
|
+
============================================================ */
|
|
155
|
+
|
|
156
|
+
/* Default (light) theme — the 60% whites/light grays */
|
|
157
|
+
--color-background-canvas: var(--color-neutral-25); /* app background */
|
|
158
|
+
--color-background-surface: var(--color-neutral-0); /* card / container */
|
|
159
|
+
--color-background-subtle: var(--color-neutral-50); /* row / nested */
|
|
160
|
+
--color-background-raised: var(--color-neutral-0); /* floating panels */
|
|
161
|
+
--color-background-sunken: var(--color-neutral-100); /* inputs, wells */
|
|
162
|
+
--color-background-hover: var(--color-neutral-100);
|
|
163
|
+
--color-background-press: var(--color-neutral-150);
|
|
164
|
+
--color-background-selected: var(--color-brand-secondary-50);
|
|
165
|
+
|
|
166
|
+
/* ─────────────────────────────────────────────────────────────────────────
|
|
167
|
+
INVERSE LAYER — contextual contrast surface, NOT dark theme
|
|
168
|
+
─────────────────────────────────────────────────────────────────────────
|
|
169
|
+
Inverse is a deliberate high-contrast surface usable inside ANY theme.
|
|
170
|
+
Use it for: institutional sidebars, premium hero panels, KPI emphasis
|
|
171
|
+
cards, command palettes, modal overlays — surfaces where contrast is the
|
|
172
|
+
intent, not the ambient theme.
|
|
173
|
+
|
|
174
|
+
Key rule (ATTRUS): inverse is ALWAYS the dark "preto-azulado" — even when
|
|
175
|
+
dark theme arrives. In dark theme, surface becomes dark and inverse stays
|
|
176
|
+
dark too, but inverse keeps a deliberate, branded character (deeper navy,
|
|
177
|
+
brand-tinted) that distinguishes it from the ambient surface.
|
|
178
|
+
|
|
179
|
+
Decision matrix:
|
|
180
|
+
Use --color-background-surface → ambient surface of current theme
|
|
181
|
+
Use --color-background-inverse → deliberate contrast vs. ambient
|
|
182
|
+
Use --color-background-inverse-brand → premium brand emphasis on inverse
|
|
183
|
+
|
|
184
|
+
Anti-patterns:
|
|
185
|
+
✗ Using inverse to fake dark mode (use a real theme switch)
|
|
186
|
+
✗ Mixing inverse and surface tokens in the same component without intent
|
|
187
|
+
✗ Hard-coding #0B1230 / white instead of inverse tokens
|
|
188
|
+
───────────────────────────────────────────────────────────────────────── */
|
|
189
|
+
--color-background-inverse: var(--color-ink-base);
|
|
190
|
+
--color-background-inverse-surface: var(--color-ink-raised);
|
|
191
|
+
--color-background-inverse-subtle: var(--color-ink-deep);
|
|
192
|
+
--color-background-inverse-hover: var(--color-ink-hover);
|
|
193
|
+
|
|
194
|
+
/* Scrim — modal/drawer/sheet backdrop. Same in light and dark themes.
|
|
195
|
+
Pairs --color-scrim (tint) with --scrim-blur (depth via backdrop-filter).
|
|
196
|
+
The lower tint (0.32) works because blur alone separates focus from background;
|
|
197
|
+
fallback for browsers without backdrop-filter is in components/overlays.css. */
|
|
198
|
+
--color-scrim: rgba(10, 15, 31, 0.32);
|
|
199
|
+
--scrim-blur: 6px;
|
|
200
|
+
--color-background-inverse-press: color-mix(in srgb, var(--color-ink-hover) 70%, var(--color-pure-white));
|
|
201
|
+
--color-background-inverse-selected: color-mix(in srgb, var(--color-brand-secondary-500) 22%, var(--color-ink-base));
|
|
202
|
+
--color-background-inverse-brand: var(--color-brand-primary-500); /* CTA / hero with brand weight — Navy */
|
|
203
|
+
|
|
204
|
+
/* Foreground (text + icons) on LIGHT surfaces */
|
|
205
|
+
--color-foreground-default: var(--color-neutral-800); /* primary copy / headings */
|
|
206
|
+
--color-foreground-secondary: var(--color-neutral-600); /* hierarchy step 2 */
|
|
207
|
+
--color-foreground-muted: var(--color-neutral-500); /* captions, helper */
|
|
208
|
+
--color-foreground-placeholder: var(--color-neutral-300); /* disabled + placeholder */
|
|
209
|
+
--color-foreground-accent: var(--color-brand-accent-700); /* accent / highlight TEXT — accent-700 #1E6DC4 (5.20:1 on white). NOT Sky-500: that fails AA as text (2.94:1). For decorative Sky fills use --color-brand-accent-500 directly. */
|
|
210
|
+
--color-foreground-brand: var(--color-brand-primary-500); /* institutional brand text/icon — Navy */
|
|
211
|
+
--color-foreground-highlight: var(--color-brand-accent-700); /* links, selected TEXT — accent-700 #1E6DC4 (legible on light). */
|
|
212
|
+
--color-foreground-on-solid: var(--color-neutral-0); /* text on any solid/strong fill (brand, ink, navy, dark hovers) */
|
|
213
|
+
--color-foreground-disabled: var(--color-neutral-300);
|
|
214
|
+
|
|
215
|
+
/* Foreground on INVERSE (dark navy/ink) surfaces */
|
|
216
|
+
--color-foreground-inverse-default: var(--color-neutral-50);
|
|
217
|
+
--color-foreground-inverse-secondary: var(--color-neutral-300);
|
|
218
|
+
--color-foreground-inverse-muted: var(--color-neutral-400);
|
|
219
|
+
--color-foreground-inverse-placeholder: var(--color-neutral-500);
|
|
220
|
+
--color-foreground-inverse-accent: var(--color-brand-accent-500);
|
|
221
|
+
--color-foreground-inverse-highlight: var(--color-brand-accent-300);
|
|
222
|
+
--color-foreground-inverse-disabled: var(--color-neutral-600);
|
|
223
|
+
|
|
224
|
+
/* Borders */
|
|
225
|
+
--color-border-subtle: var(--color-neutral-100);
|
|
226
|
+
--color-border-default: var(--color-neutral-150);
|
|
227
|
+
--color-border-strong: var(--color-neutral-200);
|
|
228
|
+
--color-border-focus: var(--color-brand-accent-500);
|
|
229
|
+
--color-border-accent: var(--color-brand-accent-500);
|
|
230
|
+
--color-border-success: var(--color-success-500);
|
|
231
|
+
--color-border-warning: var(--color-warning-500);
|
|
232
|
+
--color-border-danger: var(--color-danger-500);
|
|
233
|
+
--color-border-info: var(--color-info-500);
|
|
234
|
+
--color-border-inverse: color-mix(in srgb, var(--color-pure-white) 10%, transparent);
|
|
235
|
+
--color-border-inverse-strong: color-mix(in srgb, var(--color-pure-white) 18%, transparent);
|
|
236
|
+
|
|
237
|
+
/* White-alpha overlays — for chips, ghost buttons, hairlines on dark/brand surfaces.
|
|
238
|
+
Use these instead of rgba(255,255,255,…) literals. */
|
|
239
|
+
--color-overlay-white-08: color-mix(in srgb, var(--color-pure-white) 8%, transparent);
|
|
240
|
+
--color-overlay-white-12: color-mix(in srgb, var(--color-pure-white) 12%, transparent);
|
|
241
|
+
--color-overlay-white-14: color-mix(in srgb, var(--color-pure-white) 14%, transparent);
|
|
242
|
+
--color-overlay-white-16: color-mix(in srgb, var(--color-pure-white) 16%, transparent);
|
|
243
|
+
--color-overlay-white-18: color-mix(in srgb, var(--color-pure-white) 18%, transparent);
|
|
244
|
+
--color-overlay-white-22: color-mix(in srgb, var(--color-pure-white) 22%, transparent);
|
|
245
|
+
|
|
246
|
+
/* Semantic fg/bg pairs (status chips, alerts) */
|
|
247
|
+
--color-feedback-success-foreground: var(--color-success-700);
|
|
248
|
+
--color-feedback-success-foreground-muted: var(--color-success-500);
|
|
249
|
+
--color-feedback-success-foreground-subtle: color-mix(in srgb, var(--color-success-500) 70%, var(--color-foreground-muted));
|
|
250
|
+
--color-feedback-success-background: var(--color-success-50);
|
|
251
|
+
--color-feedback-success-border: var(--color-success-100);
|
|
252
|
+
--color-feedback-warning-foreground: var(--color-warning-700);
|
|
253
|
+
--color-feedback-warning-foreground-muted: var(--color-warning-500);
|
|
254
|
+
--color-feedback-warning-foreground-subtle: color-mix(in srgb, var(--color-warning-500) 70%, var(--color-foreground-muted));
|
|
255
|
+
--color-feedback-warning-background: var(--color-warning-50);
|
|
256
|
+
--color-feedback-warning-border: var(--color-warning-100);
|
|
257
|
+
--color-feedback-danger-foreground: var(--color-danger-700);
|
|
258
|
+
--color-feedback-danger-foreground-muted: var(--color-danger-500);
|
|
259
|
+
--color-feedback-danger-foreground-subtle: color-mix(in srgb, var(--color-danger-500) 70%, var(--color-foreground-muted));
|
|
260
|
+
--color-feedback-danger-background: var(--color-danger-50);
|
|
261
|
+
--color-feedback-danger-border: var(--color-danger-100);
|
|
262
|
+
--color-feedback-info-foreground: var(--color-info-700);
|
|
263
|
+
--color-feedback-info-foreground-muted: var(--color-info-500);
|
|
264
|
+
--color-feedback-info-foreground-subtle: color-mix(in srgb, var(--color-info-500) 70%, var(--color-foreground-muted));
|
|
265
|
+
--color-feedback-info-background: var(--color-info-50);
|
|
266
|
+
--color-feedback-info-border: var(--color-info-100);
|
|
267
|
+
|
|
268
|
+
/* Semantic foregrounds on INVERSE surfaces (chips/banners over dark) */
|
|
269
|
+
--color-feedback-success-foreground-on-inverse: var(--color-success-100);
|
|
270
|
+
--color-feedback-success-foreground-on-inverse-muted: color-mix(in srgb, var(--color-success-100) 70%, var(--color-foreground-inverse-muted));
|
|
271
|
+
--color-feedback-warning-foreground-on-inverse: var(--color-warning-100);
|
|
272
|
+
--color-feedback-warning-foreground-on-inverse-muted: color-mix(in srgb, var(--color-warning-100) 70%, var(--color-foreground-inverse-muted));
|
|
273
|
+
--color-feedback-danger-foreground-on-inverse: var(--color-danger-100);
|
|
274
|
+
--color-feedback-danger-foreground-on-inverse-muted: color-mix(in srgb, var(--color-danger-100) 70%, var(--color-foreground-inverse-muted));
|
|
275
|
+
--color-feedback-info-foreground-on-inverse: var(--color-info-100);
|
|
276
|
+
--color-feedback-info-foreground-on-inverse-muted: color-mix(in srgb, var(--color-info-100) 70%, var(--color-foreground-inverse-muted));
|
|
277
|
+
|
|
278
|
+
/* ============================================================
|
|
279
|
+
3. GRADIENTS — primary brand + layers
|
|
280
|
+
============================================================ */
|
|
281
|
+
--grad-brand: linear-gradient(135deg, #001A4D 0%, #003399 50%, #3399FF 100%);
|
|
282
|
+
--grad-brand-soft: linear-gradient(135deg, #002A80 0%, #003399 100%);
|
|
283
|
+
--grad-ink: linear-gradient(160deg, #0B1230 0%, #001A4D 55%, #002A80 100%);
|
|
284
|
+
--grad-hero: linear-gradient(180deg, #001133 0%, #003399 100%);
|
|
285
|
+
--grad-sheen: linear-gradient(120deg,
|
|
286
|
+
color-mix(in srgb, var(--color-pure-white) 14%, transparent) 0%,
|
|
287
|
+
color-mix(in srgb, var(--color-pure-white) 0%, transparent) 40%,
|
|
288
|
+
color-mix(in srgb, var(--color-pure-white) 0%, transparent) 60%,
|
|
289
|
+
color-mix(in srgb, var(--color-pure-white) 8%, transparent) 100%);
|
|
290
|
+
--grad-surface-top: linear-gradient(180deg,
|
|
291
|
+
color-mix(in srgb, var(--color-pure-white) 65%, transparent) 0%,
|
|
292
|
+
color-mix(in srgb, var(--color-pure-white) 0%, transparent) 100%);
|
|
293
|
+
--grad-radial-glow: radial-gradient(1200px 500px at 20% -10%,
|
|
294
|
+
color-mix(in srgb, var(--color-brand-accent-500) 25%, transparent) 0%,
|
|
295
|
+
color-mix(in srgb, var(--color-brand-accent-500) 0%, transparent) 60%);
|
|
296
|
+
--grad-data-pos: linear-gradient(180deg,
|
|
297
|
+
color-mix(in srgb, var(--color-success-500) 35%, transparent) 0%,
|
|
298
|
+
color-mix(in srgb, var(--color-success-500) 0%, transparent) 100%);
|
|
299
|
+
--grad-data-neg: linear-gradient(180deg,
|
|
300
|
+
color-mix(in srgb, var(--color-danger-500) 35%, transparent) 0%,
|
|
301
|
+
color-mix(in srgb, var(--color-danger-500) 0%, transparent) 100%);
|
|
302
|
+
--grad-data-brand: linear-gradient(180deg,
|
|
303
|
+
color-mix(in srgb, var(--color-brand-accent-500) 30%, transparent) 0%,
|
|
304
|
+
color-mix(in srgb, var(--color-brand-accent-500) 0%, transparent) 100%);
|
|
305
|
+
|
|
306
|
+
/* ============================================================
|
|
307
|
+
3b. DATA VISUALIZATION — chart palettes & structure
|
|
308
|
+
Categorical = qualitative series (distinct, on-brand, cool).
|
|
309
|
+
Sequential = single-hue magnitude ramp (Sky).
|
|
310
|
+
Diverging = danger ← neutral → success (variance/heatmap).
|
|
311
|
+
Structure = grid / axis / track / reference (semantic → theme).
|
|
312
|
+
Categorical gets dark-theme overrides (lift the dark hues);
|
|
313
|
+
ramps + structure follow semantic tokens automatically.
|
|
314
|
+
============================================================ */
|
|
315
|
+
/* Categorical — order chosen for max adjacent contrast */
|
|
316
|
+
--dataviz-cat-1: #003399; /* Royal — brand-anchored series 1 */
|
|
317
|
+
--dataviz-cat-2: #3399FF; /* Sky */
|
|
318
|
+
--dataviz-cat-3: #0F9A8C; /* Teal */
|
|
319
|
+
--dataviz-cat-4: #C68A1A; /* Gold */
|
|
320
|
+
--dataviz-cat-5: #6B5CE0; /* Violet */
|
|
321
|
+
--dataviz-cat-6: #CC4F7A; /* Rose */
|
|
322
|
+
--dataviz-cat-7: #18A0B8; /* Cyan */
|
|
323
|
+
--dataviz-cat-8: #5E6A82; /* Slate (neutral-500) */
|
|
324
|
+
|
|
325
|
+
/* Sequential — Sky single-hue ramp (low → high). Reuses accent stops. */
|
|
326
|
+
--dataviz-seq-1: var(--color-brand-accent-100); /* #D9ECFF */
|
|
327
|
+
--dataviz-seq-2: var(--color-brand-accent-200); /* #ADD2FF */
|
|
328
|
+
--dataviz-seq-3: var(--color-brand-accent-300); /* #7AB8FF */
|
|
329
|
+
--dataviz-seq-4: var(--color-brand-accent-500); /* #3399FF */
|
|
330
|
+
--dataviz-seq-5: var(--color-brand-accent-700); /* #1E6DC4 */
|
|
331
|
+
--dataviz-seq-6: var(--color-brand-accent-900); /* #0E3B70 */
|
|
332
|
+
|
|
333
|
+
/* Diverging — danger ← neutral mid → success (7 stops) */
|
|
334
|
+
--dataviz-div-1: var(--color-danger-500); /* most negative */
|
|
335
|
+
--dataviz-div-2: var(--color-danger-300);
|
|
336
|
+
--dataviz-div-3: var(--color-danger-100);
|
|
337
|
+
--dataviz-div-mid: var(--color-neutral-100); /* neutral midpoint */
|
|
338
|
+
--dataviz-div-5: var(--color-success-100);
|
|
339
|
+
--dataviz-div-6: var(--color-success-300);
|
|
340
|
+
--dataviz-div-7: var(--color-success-500); /* most positive */
|
|
341
|
+
|
|
342
|
+
/* Semantic data encodings */
|
|
343
|
+
--dataviz-positive: var(--color-success-500);
|
|
344
|
+
--dataviz-negative: var(--color-danger-500);
|
|
345
|
+
--dataviz-neutral: var(--color-neutral-400);
|
|
346
|
+
|
|
347
|
+
/* Structure — grid, axis, track, reference lines */
|
|
348
|
+
--dataviz-grid: var(--color-border-subtle); /* gridlines */
|
|
349
|
+
--dataviz-axis: var(--color-border-strong); /* axis baseline */
|
|
350
|
+
--dataviz-axis-label: var(--color-foreground-muted); /* tick labels */
|
|
351
|
+
--dataviz-track: var(--color-background-subtle); /* empty bar / gauge track */
|
|
352
|
+
--dataviz-reference: var(--color-foreground-muted); /* dashed target/avg line */
|
|
353
|
+
|
|
354
|
+
/* ============================================================
|
|
355
|
+
4. LIQUID GLASS — transparent / frosted layers
|
|
356
|
+
Use with backdrop-filter: blur().
|
|
357
|
+
============================================================ */
|
|
358
|
+
--glass-white: color-mix(in srgb, var(--color-pure-white) 58%, transparent);
|
|
359
|
+
--glass-white-hi: color-mix(in srgb, var(--color-pure-white) 78%, transparent);
|
|
360
|
+
--glass-white-lo: color-mix(in srgb, var(--color-pure-white) 38%, transparent);
|
|
361
|
+
--glass-tint: color-mix(in srgb, var(--color-neutral-50) 55%, transparent); /* bluish white */
|
|
362
|
+
--glass-ink: color-mix(in srgb, var(--color-background-inverse) 55%, transparent); /* dark navy */
|
|
363
|
+
--glass-ink-hi: color-mix(in srgb, var(--color-background-inverse) 78%, transparent);
|
|
364
|
+
--glass-ink-lo: color-mix(in srgb, var(--color-background-inverse) 35%, transparent);
|
|
365
|
+
--glass-blur: saturate(140%) blur(18px);
|
|
366
|
+
--glass-blur-sm: saturate(130%) blur(10px);
|
|
367
|
+
--glass-blur-lg: saturate(160%) blur(28px);
|
|
368
|
+
--glass-border: 1px solid color-mix(in srgb, var(--color-pure-white) 45%, transparent);
|
|
369
|
+
--glass-border-dark: 1px solid color-mix(in srgb, var(--color-pure-white) 10%, transparent);
|
|
370
|
+
|
|
371
|
+
/* ============================================================
|
|
372
|
+
5. RADII — mostly softly rounded; buttons fully rounded
|
|
373
|
+
============================================================ */
|
|
374
|
+
--radius-2xs: 2px; /* never-square minimum — tiny chips, ticks, dividers */
|
|
375
|
+
--radius-xs: 4px;
|
|
376
|
+
--radius-sm: 6px;
|
|
377
|
+
--radius-sm-md: 8px; /* in-between — avatar tiles, square icon buttons */
|
|
378
|
+
--radius-md: 10px; /* cards, inputs — softly rounded */
|
|
379
|
+
--radius-md-lg: 12px; /* in-between — medium cards, drawer rows */
|
|
380
|
+
--radius-lg: 14px; /* containers */
|
|
381
|
+
--radius-lg-xl: 16px; /* in-between — hero / large panels */
|
|
382
|
+
--radius-xl: 20px; /* hero / large panels */
|
|
383
|
+
--radius-2xl: 28px;
|
|
384
|
+
--radius-pill: 999px; /* BUTTONS — fully rounded */
|
|
385
|
+
|
|
386
|
+
/* ============================================================
|
|
387
|
+
6. SHADOWS — soft, blue-tinted, multi-layer
|
|
388
|
+
============================================================ */
|
|
389
|
+
--shadow-xs: 0 1px 2px color-mix(in srgb, var(--color-shadow-tint) 5%, transparent);
|
|
390
|
+
--shadow-sm: 0 1px 2px color-mix(in srgb, var(--color-shadow-tint) 6%, transparent),
|
|
391
|
+
0 2px 6px color-mix(in srgb, var(--color-shadow-tint) 4%, transparent);
|
|
392
|
+
--shadow-md: 0 2px 4px color-mix(in srgb, var(--color-shadow-tint) 6%, transparent),
|
|
393
|
+
0 8px 20px color-mix(in srgb, var(--color-shadow-tint) 6%, transparent);
|
|
394
|
+
--shadow-lg: 0 4px 8px color-mix(in srgb, var(--color-shadow-tint) 6%, transparent),
|
|
395
|
+
0 20px 40px color-mix(in srgb, var(--color-shadow-tint) 10%, transparent);
|
|
396
|
+
--shadow-xl: 0 12px 24px color-mix(in srgb, var(--color-shadow-tint) 10%, transparent),
|
|
397
|
+
0 32px 80px color-mix(in srgb, var(--color-shadow-tint) 18%, transparent);
|
|
398
|
+
--shadow-2xl: 0 24px 48px color-mix(in srgb, var(--color-shadow-tint) 14%, transparent),
|
|
399
|
+
0 48px 120px color-mix(in srgb, var(--color-shadow-tint) 24%, transparent); /* deepest — modals, drawers, floating overlays above scrim */
|
|
400
|
+
--shadow-focus: 0 0 0 4px color-mix(in srgb, var(--color-brand-accent-500) 22%, transparent);
|
|
401
|
+
--shadow-focus-sky: 0 0 0 4px color-mix(in srgb, var(--color-brand-accent-500) 25%, transparent);
|
|
402
|
+
--shadow-focus-success: 0 0 0 4px color-mix(in srgb, var(--color-success-500) 22%, transparent);
|
|
403
|
+
--shadow-focus-warning: 0 0 0 4px color-mix(in srgb, var(--color-warning-500) 22%, transparent);
|
|
404
|
+
--shadow-focus-danger: 0 0 0 4px color-mix(in srgb, var(--color-danger-500) 22%, transparent);
|
|
405
|
+
--shadow-focus-info: 0 0 0 4px color-mix(in srgb, var(--color-info-500) 22%, transparent);
|
|
406
|
+
|
|
407
|
+
/* Semantic elevation — for status cards, toasts, banners, action buttons */
|
|
408
|
+
--shadow-success-sm: 0 1px 2px color-mix(in srgb, var(--shadow-tint-success-color) 8%, transparent),
|
|
409
|
+
0 4px 12px color-mix(in srgb, var(--shadow-tint-success-color) 12%, transparent);
|
|
410
|
+
--shadow-success-md: 0 4px 8px color-mix(in srgb, var(--shadow-tint-success-color) 10%, transparent),
|
|
411
|
+
0 16px 32px color-mix(in srgb, var(--shadow-tint-success-color) 16%, transparent);
|
|
412
|
+
--shadow-warning-sm: 0 1px 2px color-mix(in srgb, var(--shadow-tint-warning-color) 8%, transparent),
|
|
413
|
+
0 4px 12px color-mix(in srgb, var(--shadow-tint-warning-color) 12%, transparent);
|
|
414
|
+
--shadow-warning-md: 0 4px 8px color-mix(in srgb, var(--shadow-tint-warning-color) 10%, transparent),
|
|
415
|
+
0 16px 32px color-mix(in srgb, var(--shadow-tint-warning-color) 16%, transparent);
|
|
416
|
+
--shadow-danger-sm: 0 1px 2px color-mix(in srgb, var(--shadow-tint-danger-color) 8%, transparent),
|
|
417
|
+
0 4px 12px color-mix(in srgb, var(--shadow-tint-danger-color) 14%, transparent);
|
|
418
|
+
--shadow-danger-md: 0 4px 8px color-mix(in srgb, var(--shadow-tint-danger-color) 12%, transparent),
|
|
419
|
+
0 16px 32px color-mix(in srgb, var(--shadow-tint-danger-color) 18%, transparent);
|
|
420
|
+
--shadow-info-sm: 0 1px 2px color-mix(in srgb, var(--shadow-tint-info-color) 8%, transparent),
|
|
421
|
+
0 4px 12px color-mix(in srgb, var(--shadow-tint-info-color) 12%, transparent);
|
|
422
|
+
--shadow-info-md: 0 4px 8px color-mix(in srgb, var(--shadow-tint-info-color) 10%, transparent),
|
|
423
|
+
0 16px 32px color-mix(in srgb, var(--shadow-tint-info-color) 16%, transparent);
|
|
424
|
+
--shadow-inset: inset 0 1px 0 color-mix(in srgb, var(--color-pure-white) 60%, transparent),
|
|
425
|
+
inset 0 -1px 0 color-mix(in srgb, var(--color-shadow-tint) 4%, transparent);
|
|
426
|
+
--shadow-glass: 0 1px 0 color-mix(in srgb, var(--color-pure-white) 50%, transparent) inset,
|
|
427
|
+
0 10px 30px color-mix(in srgb, var(--color-shadow-tint) 12%, transparent);
|
|
428
|
+
--shadow-glass-dark: 0 1px 0 color-mix(in srgb, var(--color-pure-white) 8%, transparent) inset,
|
|
429
|
+
0 10px 40px color-mix(in srgb, var(--color-pure-black) 35%, transparent);
|
|
430
|
+
|
|
431
|
+
/* ============================================================
|
|
432
|
+
7. SPACING — 4px base; dense, data-heavy layouts
|
|
433
|
+
============================================================ */
|
|
434
|
+
--space-0: 0;
|
|
435
|
+
--space-1: 2px;
|
|
436
|
+
--space-2: 4px;
|
|
437
|
+
--space-2-5: 6px; /* half-step — dense chips, tight icon gaps */
|
|
438
|
+
--space-3: 8px;
|
|
439
|
+
--space-3-5: 10px; /* half-step — control padding, list-row gaps */
|
|
440
|
+
--space-4: 12px;
|
|
441
|
+
--space-4-5: 14px; /* half-step — card padding, section gaps */
|
|
442
|
+
--space-5: 16px;
|
|
443
|
+
--space-6: 20px;
|
|
444
|
+
--space-7: 24px;
|
|
445
|
+
--space-8: 32px;
|
|
446
|
+
--space-9: 40px;
|
|
447
|
+
--space-10: 48px;
|
|
448
|
+
--space-12: 64px;
|
|
449
|
+
--space-14: 80px;
|
|
450
|
+
--space-16: 96px;
|
|
451
|
+
|
|
452
|
+
/* ============================================================
|
|
453
|
+
7b. ICONOGRAPHY — Lucide; sized to pair with type scale
|
|
454
|
+
============================================================ */
|
|
455
|
+
--icon-xs: 12px; /* helper text, micro caption (paired w/ 11–12px text) */
|
|
456
|
+
--icon-sm: 14px; /* input affix, dense inline (paired w/ 13px text) */
|
|
457
|
+
--icon-md: 16px; /* default — buttons, nav, body (paired w/ 14px text) */
|
|
458
|
+
--icon-lg: 20px; /* iconography grid, prominent CTAs (paired w/ 16+ text) */
|
|
459
|
+
--icon-xl: 24px; /* hero, empty states, splash (paired w/ 18+ text) */
|
|
460
|
+
|
|
461
|
+
/* Stroke widths — Lucide */
|
|
462
|
+
--icon-stroke: 1.75; /* default — slightly bolder than 1.5, calmer than 2 */
|
|
463
|
+
--icon-stroke-bold: 2; /* close buttons, X marks, indicators where weight matters */
|
|
464
|
+
--icon-stroke-thin: 1.5; /* decorative / large hero icons where 1.75 looks heavy */
|
|
465
|
+
|
|
466
|
+
/* ============================================================
|
|
467
|
+
7c. MOTION — durations + easings for transitions/animations
|
|
468
|
+
============================================================ */
|
|
469
|
+
/* Easing — single curve across the system; "out-expo-ish" for snappy UI */
|
|
470
|
+
--ease-standard: cubic-bezier(.2, .8, .2, 1);
|
|
471
|
+
--ease-emphasis: cubic-bezier(.2, .9, .15, 1); /* slightly more overshoot — for entries */
|
|
472
|
+
--ease-linear: linear; /* loading bars, scrubbers */
|
|
473
|
+
|
|
474
|
+
/* Durations — paired with --ease-standard unless noted */
|
|
475
|
+
--duration-instant: 80ms; /* micro feedback (tap echo) */
|
|
476
|
+
--duration-fast: 140ms; /* hover, focus, color shifts */
|
|
477
|
+
--duration-base: 200ms; /* default for most UI */
|
|
478
|
+
--duration-slow: 320ms; /* expansions, reveals */
|
|
479
|
+
--duration-slower: 480ms; /* page-level transitions */
|
|
480
|
+
--duration-deliberate: 640ms; /* overlays — modal/drawer entry */
|
|
481
|
+
|
|
482
|
+
/* Pre-composed transition shorthand (most common cases) */
|
|
483
|
+
--transition-fast: 140ms var(--ease-standard); /* default for buttons/inputs */
|
|
484
|
+
--transition-base: 200ms var(--ease-standard);
|
|
485
|
+
--transition-slow: 320ms var(--ease-standard);
|
|
486
|
+
|
|
487
|
+
/* ============================================================
|
|
488
|
+
8. TYPOGRAPHY — Lato family per brand manual
|
|
489
|
+
============================================================ */
|
|
490
|
+
--font-sans: 'Lato', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
491
|
+
--font-mono: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, Consolas, monospace;
|
|
492
|
+
--font-display: 'Lato', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
493
|
+
|
|
494
|
+
/* Weights (per manual) */
|
|
495
|
+
--w-light: 300;
|
|
496
|
+
--w-regular: 400;
|
|
497
|
+
--w-medium: 500; /* Lato doesn't ship 500 natively; maps to 400 */
|
|
498
|
+
--w-semibold: 600;
|
|
499
|
+
--w-bold: 700;
|
|
500
|
+
--w-extrabold: 800;
|
|
501
|
+
--w-black: 900;
|
|
502
|
+
|
|
503
|
+
/* Type scale (px) */
|
|
504
|
+
--fs-xxs: 10px;
|
|
505
|
+
--fs-xs: 11px;
|
|
506
|
+
--fs-sm: 12px;
|
|
507
|
+
--fs-md: 13px; /* default UI */
|
|
508
|
+
--fs-base:14px; /* default body */
|
|
509
|
+
--fs-lg: 16px;
|
|
510
|
+
--fs-xl: 18px;
|
|
511
|
+
--fs-2xl: 20px;
|
|
512
|
+
--fs-3xl: 24px;
|
|
513
|
+
--fs-4xl: 28px;
|
|
514
|
+
--fs-5xl: 32px;
|
|
515
|
+
--fs-6xl: 40px;
|
|
516
|
+
--fs-7xl: 56px;
|
|
517
|
+
--fs-8xl: 72px;
|
|
518
|
+
|
|
519
|
+
/* Line heights */
|
|
520
|
+
--lh-tight: 1.15;
|
|
521
|
+
--lh-snug: 1.3;
|
|
522
|
+
--lh-normal: 1.5;
|
|
523
|
+
--lh-relaxed: 1.65;
|
|
524
|
+
|
|
525
|
+
/* Letter spacing — per Lato manual rules */
|
|
526
|
+
--ls-display: -0.03em; /* 32–80px headlines */
|
|
527
|
+
--ls-tight: -0.01em; /* large numerics / stat values — between display and body */
|
|
528
|
+
--ls-title: -0.015em; /* 16–32px titles (manual says -5%, but -5% looks tight on screens; using -1.5%) */
|
|
529
|
+
--ls-body: 0em; /* <16px body */
|
|
530
|
+
--ls-label: 0.02em; /* small caps / labels */
|
|
531
|
+
--ls-caps: 0.08em;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/* ============================================================
|
|
535
|
+
DARK THEME — [data-theme="dark"] remaps the AMBIENT semantic
|
|
536
|
+
tokens to a dark ink ramp. Components consume semantic tokens,
|
|
537
|
+
so they flip automatically — no per-component dark CSS needed.
|
|
538
|
+
Philosophy: the INVERSE layer stays a deliberate, brand-tinted
|
|
539
|
+
dark even here (see note in :root), distinct from the ambient
|
|
540
|
+
surface. Raw palette + brand/accent scales are theme-agnostic.
|
|
541
|
+
Toggle via JS (theme-toggle.js): sets data-theme on <html>,
|
|
542
|
+
persists to localStorage, seeds from prefers-color-scheme.
|
|
543
|
+
============================================================ */
|
|
544
|
+
[data-theme="dark"] {
|
|
545
|
+
color-scheme: dark;
|
|
546
|
+
|
|
547
|
+
/* Ambient surfaces — dark ink ramp (canvas deepest → surface raised) */
|
|
548
|
+
--color-background-canvas: var(--color-ink-deep); /* #0A1128 — app background */
|
|
549
|
+
--color-background-surface: var(--color-ink-raised); /* #111A3D — cards sit above canvas */
|
|
550
|
+
--color-background-subtle: var(--color-ink-base); /* #0B1230 — nested rows / wells-lite */
|
|
551
|
+
--color-background-raised: var(--color-ink-raised);
|
|
552
|
+
--color-background-sunken: color-mix(in srgb, var(--color-pure-black) 28%, var(--color-ink-deep)); /* inputs / wells — deeper */
|
|
553
|
+
--color-background-hover: color-mix(in srgb, var(--color-pure-white) 6%, var(--color-ink-raised));
|
|
554
|
+
--color-background-press: color-mix(in srgb, var(--color-pure-white) 10%, var(--color-ink-raised));
|
|
555
|
+
--color-background-selected: var(--color-background-inverse-selected);
|
|
556
|
+
|
|
557
|
+
/* Inverse layer — stays distinct: a brand-tinted dark, lifted off the ambient ink */
|
|
558
|
+
--color-background-inverse: color-mix(in srgb, var(--color-brand-primary-500) 24%, var(--color-ink-base));
|
|
559
|
+
--color-background-inverse-surface: color-mix(in srgb, var(--color-brand-primary-500) 30%, var(--color-ink-raised));
|
|
560
|
+
--color-background-inverse-subtle: color-mix(in srgb, var(--color-brand-primary-500) 18%, var(--color-ink-deep));
|
|
561
|
+
|
|
562
|
+
/* Foreground — light on dark */
|
|
563
|
+
--color-foreground-default: var(--color-neutral-50);
|
|
564
|
+
--color-foreground-secondary: var(--color-neutral-300);
|
|
565
|
+
--color-foreground-muted: var(--color-neutral-400);
|
|
566
|
+
--color-foreground-placeholder: var(--color-neutral-600);
|
|
567
|
+
--color-foreground-accent: var(--color-brand-accent-400); /* Sky lightens on dark for contrast (light used accent-700) */
|
|
568
|
+
--color-foreground-highlight: var(--color-brand-accent-300); /* links on dark */
|
|
569
|
+
--color-foreground-brand: var(--color-brand-secondary-200);/* Navy is invisible on dark → light royal */
|
|
570
|
+
--color-foreground-disabled: var(--color-neutral-600);
|
|
571
|
+
/* --color-foreground-on-solid stays neutral-0 (white text on Royal/accent fills) */
|
|
572
|
+
|
|
573
|
+
/* Borders — white-alpha hairlines */
|
|
574
|
+
--color-border-subtle: color-mix(in srgb, var(--color-pure-white) 8%, transparent);
|
|
575
|
+
--color-border-default: color-mix(in srgb, var(--color-pure-white) 12%, transparent);
|
|
576
|
+
--color-border-strong: color-mix(in srgb, var(--color-pure-white) 20%, transparent);
|
|
577
|
+
/* focus / accent borders stay Sky-500 — reads well on dark */
|
|
578
|
+
|
|
579
|
+
/* Feedback pairs flip: light foreground + dark-tinted background */
|
|
580
|
+
--color-feedback-success-foreground: var(--color-success-300);
|
|
581
|
+
--color-feedback-success-background: color-mix(in srgb, var(--color-success-500) 18%, var(--color-ink-base));
|
|
582
|
+
--color-feedback-success-border: color-mix(in srgb, var(--color-success-500) 34%, transparent);
|
|
583
|
+
--color-feedback-warning-foreground: var(--color-warning-300);
|
|
584
|
+
--color-feedback-warning-background: color-mix(in srgb, var(--color-warning-500) 18%, var(--color-ink-base));
|
|
585
|
+
--color-feedback-warning-border: color-mix(in srgb, var(--color-warning-500) 34%, transparent);
|
|
586
|
+
--color-feedback-danger-foreground: var(--color-danger-300);
|
|
587
|
+
--color-feedback-danger-background: color-mix(in srgb, var(--color-danger-500) 18%, var(--color-ink-base));
|
|
588
|
+
--color-feedback-danger-border: color-mix(in srgb, var(--color-danger-500) 34%, transparent);
|
|
589
|
+
--color-feedback-info-foreground: var(--color-info-300);
|
|
590
|
+
--color-feedback-info-background: color-mix(in srgb, var(--color-info-500) 18%, var(--color-ink-base));
|
|
591
|
+
--color-feedback-info-border: color-mix(in srgb, var(--color-info-500) 34%, transparent);
|
|
592
|
+
|
|
593
|
+
/* Surface-top sheen reads wrong on dark → neutralize */
|
|
594
|
+
--grad-surface-top: linear-gradient(180deg, color-mix(in srgb, var(--color-pure-white) 6%, transparent) 0%, transparent 100%);
|
|
595
|
+
|
|
596
|
+
/* Data-viz categorical — lift the dark hues so every series reads on dark ink.
|
|
597
|
+
Ramps (seq/div) + structure follow the semantic tokens already remapped above. */
|
|
598
|
+
--dataviz-cat-1: #6B95FB; /* Royal 300 — 500 is invisible on dark */
|
|
599
|
+
--dataviz-cat-2: #7AB8FF; /* Sky, lightened */
|
|
600
|
+
--dataviz-cat-3: #2BC2B1; /* Teal, lightened */
|
|
601
|
+
--dataviz-cat-4: #E0AC45; /* Gold, lightened */
|
|
602
|
+
--dataviz-cat-5: #9385F2; /* Violet, lightened */
|
|
603
|
+
--dataviz-cat-6: #E87BA1; /* Rose, lightened */
|
|
604
|
+
--dataviz-cat-7: #3FC4DC; /* Cyan, lightened */
|
|
605
|
+
--dataviz-cat-8: #A6B0C4; /* Slate, lightened */
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/* ============================================================
|
|
609
|
+
9. SEMANTIC TYPE CLASSES — ready-to-use
|
|
610
|
+
============================================================ */
|
|
611
|
+
|
|
612
|
+
html, body {
|
|
613
|
+
font-family: var(--font-sans);
|
|
614
|
+
font-size: var(--fs-base);
|
|
615
|
+
line-height: var(--lh-normal);
|
|
616
|
+
color: var(--color-foreground-default);
|
|
617
|
+
background: var(--color-background-canvas);
|
|
618
|
+
-webkit-font-smoothing: antialiased;
|
|
619
|
+
-moz-osx-font-smoothing: grayscale;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.display-xl { font-family: var(--font-display); font-weight: var(--w-black); font-size: var(--fs-8xl); line-height: var(--lh-tight); letter-spacing: var(--ls-display); }
|
|
623
|
+
.display-lg { font-family: var(--font-display); font-weight: var(--w-extrabold);font-size: var(--fs-7xl); line-height: var(--lh-tight); letter-spacing: var(--ls-display); }
|
|
624
|
+
.display { font-family: var(--font-display); font-weight: var(--w-bold); font-size: var(--fs-6xl); line-height: var(--lh-tight); letter-spacing: var(--ls-display); }
|
|
625
|
+
|
|
626
|
+
h1, .h1 { font-weight: var(--w-bold); font-size: var(--fs-5xl); line-height: var(--lh-tight); letter-spacing: var(--ls-display); }
|
|
627
|
+
h2, .h2 { font-weight: var(--w-bold); font-size: var(--fs-4xl); line-height: var(--lh-snug); letter-spacing: var(--ls-title); }
|
|
628
|
+
h3, .h3 { font-weight: var(--w-bold); font-size: var(--fs-3xl); line-height: var(--lh-snug); letter-spacing: var(--ls-title); }
|
|
629
|
+
h4, .h4 { font-weight: var(--w-semibold); font-size: var(--fs-2xl); line-height: var(--lh-snug); letter-spacing: var(--ls-title); }
|
|
630
|
+
h5, .h5 { font-weight: var(--w-semibold); font-size: var(--fs-xl); line-height: var(--lh-snug); letter-spacing: var(--ls-title); }
|
|
631
|
+
h6, .h6 { font-weight: var(--w-semibold); font-size: var(--fs-lg); line-height: var(--lh-snug); letter-spacing: var(--ls-body); }
|
|
632
|
+
|
|
633
|
+
.body-lg { font-size: var(--fs-lg); line-height: var(--lh-relaxed); }
|
|
634
|
+
.body { font-size: var(--fs-base);line-height: var(--lh-normal); }
|
|
635
|
+
.body-sm { font-size: var(--fs-md); line-height: var(--lh-normal); }
|
|
636
|
+
.caption { font-size: var(--fs-sm); line-height: var(--lh-normal); color: var(--color-foreground-muted); }
|
|
637
|
+
.overline { font-size: var(--fs-xs); line-height: var(--lh-normal); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--color-foreground-muted); font-weight: var(--w-semibold); }
|
|
638
|
+
.label { font-size: var(--fs-sm); font-weight: var(--w-semibold); letter-spacing: var(--ls-label); }
|
|
639
|
+
|
|
640
|
+
.mono, code, pre, kbd { font-family: var(--font-mono); font-size: .92em; }
|
|
641
|
+
|
|
642
|
+
/* Numbers that must line up in tables */
|
|
643
|
+
.tabular { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' on, 'lnum' on; }
|
|
644
|
+
|
|
645
|
+
/* Utility text colors */
|
|
646
|
+
.fg-default { color: var(--color-foreground-default); }
|
|
647
|
+
.fg-secondary { color: var(--color-foreground-secondary); }
|
|
648
|
+
.color-foreground-muted { color: var(--color-foreground-muted); }
|
|
649
|
+
.fg-accent { color: var(--color-foreground-accent); }
|
|
650
|
+
.fg-highlight { color: var(--color-foreground-highlight); }
|
|
651
|
+
.fg-placeholder { color: var(--color-foreground-placeholder); }
|
|
652
|
+
|
|
653
|
+
/* Inverse layer helper — apply to any container to flip to dark */
|
|
654
|
+
.inverse {
|
|
655
|
+
background: var(--color-background-inverse);
|
|
656
|
+
color: var(--color-foreground-inverse-default);
|
|
657
|
+
}
|
|
658
|
+
.inverse .fg-secondary { color: var(--color-foreground-inverse-secondary); }
|
|
659
|
+
.inverse .color-foreground-muted { color: var(--color-foreground-inverse-muted); }
|
|
660
|
+
.inverse .fg-accent { color: var(--color-foreground-inverse-accent); }
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
/* ---- doc-back link (fixed top-left on every preview page) ---- */
|
|
664
|
+
.doc-back {
|
|
665
|
+
position: fixed;
|
|
666
|
+
top: var(--space-5);
|
|
667
|
+
left: var(--space-5);
|
|
668
|
+
z-index: 1000;
|
|
669
|
+
display: inline-flex;
|
|
670
|
+
align-items: center;
|
|
671
|
+
gap: var(--space-2);
|
|
672
|
+
font-family: var(--font-sans);
|
|
673
|
+
font-size: var(--fs-xs);
|
|
674
|
+
font-weight: var(--w-semibold);
|
|
675
|
+
letter-spacing: 0;
|
|
676
|
+
text-transform: none;
|
|
677
|
+
color: var(--color-foreground-secondary);
|
|
678
|
+
text-decoration: none;
|
|
679
|
+
padding: var(--space-2) var(--space-3);
|
|
680
|
+
border: 1px solid var(--color-border-default);
|
|
681
|
+
border-radius: var(--radius-pill);
|
|
682
|
+
background: var(--color-background-surface);
|
|
683
|
+
box-shadow: var(--shadow-sm);
|
|
684
|
+
transition: var(--transition-fast);
|
|
685
|
+
}
|
|
686
|
+
.doc-back:hover {
|
|
687
|
+
color: var(--color-foreground-default);
|
|
688
|
+
border-color: var(--color-border-strong);
|
|
689
|
+
box-shadow: var(--shadow-md);
|
|
690
|
+
}
|
|
691
|
+
.doc-back svg, .doc-back i { width: 14px; height: 14px; stroke-width: var(--icon-stroke); }
|