@attrus-ds/core 0.2.0 → 0.3.1

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