@keenmate/pure-css 1.0.0-rc06 → 1.0.0-rc08

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.
@@ -1,630 +1,429 @@
1
- // ============================================================================
2
- // BASE CSS VARIABLES OUTPUT MIXIN
3
- // ============================================================================
4
- // This mixin outputs all $base-* SCSS variables as --base-* CSS custom properties.
5
- // Include this in themes to enable web component theming.
6
- //
7
- // Usage in theme file:
8
- // @import '../base-css-variables';
9
- // :root {
10
- // @include output-base-css-variables;
11
- // }
12
- //
13
- // Web components consume these via fallback chains:
14
- // --ms-accent-color: var(--base-accent-color, #3b82f6);
15
- // ============================================================================
16
-
17
- // Make variables resolvable when this file is loaded as a @use module
18
- // (e.g. from main.scss). Legacy @import callers (themes) are unaffected —
19
- // Sass places @use'd members into the importing file's global scope, where
20
- // theme-set overrides already live.
21
- @use 'variables/index' as *;
22
-
23
- @mixin output-base-css-variables {
24
- // === Accent Colors ===
25
- --base-accent-color: #{$base-accent-color};
26
- --base-accent-color-hover: #{$base-accent-color-hover};
27
- --base-accent-color-active: #{$base-accent-color-active};
28
- --base-accent-color-light: #{$base-accent-color-light};
29
- --base-accent-color-light-hover: #{$base-accent-color-light-hover};
30
-
31
- // === Text Colors ===
32
- --base-text-color-1: #{$base-text-color-1};
33
- --base-text-color-2: #{$base-text-color-2};
34
- --base-text-color-3: #{$base-text-color-3};
35
- --base-text-color-4: #{$base-text-color-4};
36
- --base-text-color-on-accent: #{$base-text-color-on-accent};
37
-
38
- // === Background Colors (semantic) ===
39
- --base-main-bg: #{$base-main-bg};
40
- --base-page-bg: #{$base-page-bg};
41
- --base-subtle-bg: #{$base-subtle-bg};
42
- --base-inverse-bg: #{$base-inverse-bg};
43
- --base-overlay-bg: #{$base-overlay-bg};
44
- --base-shadow-color: #{$base-shadow-color};
45
- --base-hover-bg: #{$base-hover-bg};
46
- --base-active-bg: #{$base-active-bg};
47
- --base-disabled-bg: #{$base-disabled-bg};
48
- --base-elevated-bg: #{$base-elevated-bg};
49
-
50
- // === Border Colors ===
51
- --base-border-color: #{$base-border-color};
52
- --base-border: #{$base-border};
53
-
54
- // === Input Fields ===
55
- --base-input-bg: #{$base-input-bg};
56
- --base-input-color: #{$base-input-color};
57
- --base-input-border: #{$base-input-border};
58
- --base-input-border-hover: #{$base-input-border-hover};
59
- --base-input-border-focus: #{$base-input-border-focus};
60
- --base-input-placeholder-color: #{$base-input-placeholder-color};
61
- --base-input-bg-disabled: #{$base-input-bg-disabled};
62
-
63
- // === Input Size Heights ===
64
- --base-input-size-xs-height: #{$base-input-size-xs-height};
65
- --base-input-size-sm-height: #{$base-input-size-sm-height};
66
- --base-input-size-md-height: #{$base-input-size-md-height};
67
- --base-input-size-lg-height: #{$base-input-size-lg-height};
68
- --base-input-size-xl-height: #{$base-input-size-xl-height};
69
-
70
- // === Dropdown/Popover ===
71
- --base-dropdown-bg: #{$base-dropdown-bg};
72
- --base-dropdown-border: #{$base-dropdown-border};
73
- --base-dropdown-box-shadow: #{$base-dropdown-box-shadow};
74
-
75
- // === Tooltip ===
76
- --base-tooltip-bg: #{$base-tooltip-bg};
77
- --base-tooltip-text-color: #{$base-tooltip-text-color};
78
-
79
- // === Contextual Colors - Success ===
80
- --base-success-color: #{$base-success-color};
81
- --base-success-color-hover: #{$base-success-color-hover};
82
- --base-success-bg-light: #{$base-success-bg-light};
83
- --base-success-bg-subtle: #{$base-success-bg-subtle};
84
- --base-success-border: #{$base-success-border};
85
- --base-success-text: #{$base-success-text};
86
- --base-success-text-light: #{$base-success-text-light};
87
- --base-text-on-success: #{$base-text-on-success};
88
-
89
- // === Contextual Colors - Danger ===
90
- --base-danger-color: #{$base-danger-color};
91
- --base-danger-color-hover: #{$base-danger-color-hover};
92
- --base-danger-bg-light: #{$base-danger-bg-light};
93
- --base-danger-bg-subtle: #{$base-danger-bg-subtle};
94
- --base-danger-border: #{$base-danger-border};
95
- --base-danger-text: #{$base-danger-text};
96
- --base-danger-text-light: #{$base-danger-text-light};
97
- --base-text-on-danger: #{$base-text-on-danger};
98
-
99
- // === Contextual Colors - Warning ===
100
- --base-warning-color: #{$base-warning-color};
101
- --base-warning-color-hover: #{$base-warning-color-hover};
102
- --base-warning-bg-light: #{$base-warning-bg-light};
103
- --base-warning-bg-subtle: #{$base-warning-bg-subtle};
104
- --base-warning-border: #{$base-warning-border};
105
- --base-warning-text: #{$base-warning-text};
106
- --base-warning-text-light: #{$base-warning-text-light};
107
- --base-text-on-warning: #{$base-text-on-warning};
108
-
109
- // === Contextual Colors - Info ===
110
- --base-info-color: #{$base-info-color};
111
- --base-info-color-hover: #{$base-info-color-hover};
112
- --base-info-bg-light: #{$base-info-bg-light};
113
- --base-info-bg-subtle: #{$base-info-bg-subtle};
114
- --base-info-border: #{$base-info-border};
115
- --base-info-text: #{$base-info-text};
116
- --base-info-text-light: #{$base-info-text-light};
117
- --base-text-on-info: #{$base-text-on-info};
118
-
119
- // === Interactive States ===
120
- --base-hover-overlay: #{$base-hover-overlay};
121
- --base-active-overlay: #{$base-active-overlay};
122
- --base-focus-ring-color: #{$base-focus-ring-color};
123
- --base-focus-ring-width: #{$base-focus-ring-width};
124
-
125
- // === Typography ===
126
- --base-font-family: #{$base-font-family};
127
- --base-font-family-mono: #{$base-font-family-mono};
128
- --base-font-size-2xs: #{$base-font-size-2xs};
129
- --base-font-size-xs: #{$base-font-size-xs};
130
- --base-font-size-sm: #{$base-font-size-sm};
131
- --base-font-size-base: #{$base-font-size-base};
132
- --base-font-size-lg: #{$base-font-size-lg};
133
- --base-font-size-xl: #{$base-font-size-xl};
134
- --base-font-size-2xl: #{$base-font-size-2xl};
135
- --base-font-weight-normal: #{$base-font-weight-normal};
136
- --base-font-weight-medium: #{$base-font-weight-medium};
137
- --base-font-weight-semibold: #{$base-font-weight-semibold};
138
- --base-font-weight-bold: #{$base-font-weight-bold};
139
- --base-line-height-tight: #{$base-line-height-tight};
140
- --base-line-height-normal: #{$base-line-height-normal};
141
- --base-line-height-relaxed: #{$base-line-height-relaxed};
142
-
143
- // === Border Radius ===
144
- --base-border-radius-sm: #{$base-border-radius-sm};
145
- --base-border-radius-md: #{$base-border-radius-md};
146
- --base-border-radius-lg: #{$base-border-radius-lg};
147
- }
148
-
149
- // ============================================================================
150
- // DERIVED TOKENS — TEXT CONTRAST TIERS + SURFACE TINTS
151
- // ============================================================================
152
- // These tokens use `color-mix(... var(--pc-text-color-1) ...)` to derive
153
- // theme-aware contrast levels. They MUST be emitted at every selector that
154
- // could carry an override of --pc-text-color-1, because CSS custom property
155
- // substitution bakes nested var() references at the *defining element*, not
156
- // the using element. If we only defined these at `:root, .pc-mode-light`,
157
- // the light-mode text colour would be frozen into the value, and elements
158
- // inside `.pc-mode-dark` (which overrides --pc-text-color-1 at body) would
159
- // inherit the light-mode-baked tier values → low contrast on dark surfaces.
160
- //
161
- // Emitting at all three selectors causes each scope to recompute the tiers
162
- // against its own --pc-text-color-1. The selector list `:root, .pc-mode-light,
163
- // .pc-mode-dark` covers html, body in light mode, and body in dark mode —
164
- // regardless of which class layout each theme uses for mode switching.
165
- //
166
- // This is a TOP-LEVEL rule (not inside the mixin) because themes only call
167
- // the mixin from their light-mode block; they don't call it again in the
168
- // dark-mode block. Emitting at framework level means themes get correct
169
- // dark-mode tiers without changing any theme code.
170
- //
171
- // Override these per-theme by redefining them in the same scope you
172
- // override --pc-text-color-1.
173
- // ============================================================================
174
-
175
- :root,
176
- .pc-mode-light,
177
- .pc-mode-dark {
178
- --pc-text-strong: color-mix(in srgb, var(--pc-text-color-1) 85%, transparent);
179
- --pc-text-secondary: color-mix(in srgb, var(--pc-text-color-1) 70%, transparent);
180
- --pc-text-tertiary: color-mix(in srgb, var(--pc-text-color-1) 55%, transparent);
181
- --pc-surface-hover: color-mix(in srgb, var(--pc-text-color-1) 4%, transparent);
182
- --pc-surface-track: color-mix(in srgb, var(--pc-text-color-1) 12%, transparent);
183
- }
184
-
185
- // ============================================================================
186
- // PURE-CSS FOUNDATION TOKENS — the base runtime custom-property contract
187
- // ============================================================================
188
- // pure-css is a *foundation*: it ships only the BASE token contract — the
189
- // tokens its own CSS (grid / utilities / reboot / scrollbars) consumes, plus
190
- // the universal theming primitives (surfaces, text, accent, links, border,
191
- // the semantic role identities + their utility text colours, the theme
192
- // palette slots, and the border-radius scale).
193
- //
194
- // COMPONENT tokens (buttons, cards, tables, modals, badges, tooltips, panels,
195
- // command palette, multiselect, sentiment scale, form spacing, the derived
196
- // contextual/alert surfaces, admin layout chrome, …) are NOT emitted here —
197
- // they are pure-admin's contract, emitted by pure-admin's
198
- // `output-pc-component-variables` + `output-pc-alert-variables-{light,dark}`.
199
- // Those mixins read the same shared $-variable vocabulary defined in
200
- // `variables/*`, so themes still override one place; only the *emission* of
201
- // component custom properties lives with the components that use them.
202
- // ============================================================================
203
-
204
- @mixin output-pc-css-variables {
205
- // Tells the browser whether this scope is light or dark so native UA
206
- // elements (scrollbars, form controls) and `light-dark()` resolve correctly.
207
- // Override $theme-color-scheme before importing variables for always-dark
208
- // themes; for dual-mode themes leave `light` and add `color-scheme: dark;`
209
- // to the `.pc-mode-dark` block.
210
- color-scheme: #{$theme-color-scheme};
211
-
212
- // Surfaces
213
- --pc-main-bg: #{$main-bg};
214
- --pc-page-bg: #{$page-bg};
215
- --pc-subtle-bg: #{$subtle-bg};
216
-
217
- // Text
218
- --pc-text-color-1: #{$text-color-1};
219
- --pc-text-color-2: #{$text-color-2};
220
-
221
- // Accent — -light derives from --pc-accent at runtime so theme overrides cascade.
222
- --pc-accent: #{$accent-color};
223
- --pc-accent-hover: #{$accent-hover};
224
- --pc-accent-light: color-mix(in srgb, var(--pc-accent) 5%, transparent);
225
-
226
- // Links — derive from accent so theme overrides cascade automatically.
227
- // Hover mixes 50% toward currentColor (inherited text colour at the use site),
228
- // so it auto-darkens on light themes and auto-lightens on dark themes.
229
- --pc-link-color: var(--pc-accent);
230
- --pc-link-color-hover: color-mix(in srgb, var(--pc-link-color), currentColor 50%);
231
- --pc-link-color-visited: var(--pc-link-color);
232
-
233
- // Border — a live reference to --base-border-color (so a runtime --base-*
234
- // override cascades), with the build-time value as the literal fallback.
235
- --pc-border-color: var(--base-border-color, #{$border-color});
236
-
237
- // Semantic role identities — the single source for the four roles. Component
238
- // surfaces (--pc-*-bg, alerts, buttons) derive from these via var() in
239
- // pure-admin, so retuning a role here cascades everywhere.
240
- --pc-success: #{$base-success-color};
241
- --pc-warning: #{$base-warning-color};
242
- --pc-danger: #{$base-danger-color};
243
- --pc-info: #{$base-info-color};
244
-
245
- // Role text colours — consumed by the .text-{success,danger,warning,info}
246
- // utilities (utilities.scss). Kept in the base contract for that reason.
247
- --pc-success-text: #{$success-text};
248
- --pc-danger-text: #{$danger-text};
249
- --pc-warning-text: #{$warning-text};
250
- --pc-info-text: #{$info-text};
251
-
252
- // Theme palette slots (1–9) + paired contrast text. Consumed by the
253
- // .text-color-* utilities; themes override $color-N for branded palettes.
254
- --pc-color-1: #{$color-1};
255
- --pc-color-2: #{$color-2};
256
- --pc-color-3: #{$color-3};
257
- --pc-color-4: #{$color-4};
258
- --pc-color-5: #{$color-5};
259
- --pc-color-6: #{$color-6};
260
- --pc-color-7: #{$color-7};
261
- --pc-color-8: #{$color-8};
262
- --pc-color-9: #{$color-9};
263
- --pc-color-1-text: #{$color-1-text};
264
- --pc-color-2-text: #{$color-2-text};
265
- --pc-color-3-text: #{$color-3-text};
266
- --pc-color-4-text: #{$color-4-text};
267
- --pc-color-5-text: #{$color-5-text};
268
- --pc-color-6-text: #{$color-6-text};
269
- --pc-color-7-text: #{$color-7-text};
270
- --pc-color-8-text: #{$color-8-text};
271
- --pc-color-9-text: #{$color-9-text};
272
-
273
- // Border-radius scale — derived from the --base-border-radius-* contract (the
274
- // same unitless rem-multipliers the web/svelte components read; e.g.
275
- // web-multiselect: `calc(var(--base-border-radius-md) * --ms-rem)`). Multiplying
276
- // by 1rem yields px at pure-css's 10px rem base (0.6 → 0.6rem → 6px) and keeps
277
- // the scale live: overriding --base-border-radius-* at runtime re-rounds
278
- // pure-css's own elements and the components together, instead of the old baked
279
- // 2/4/8px literals that ignored the base contract. The $base-* multipliers are
280
- // the fallbacks. NOTE: --pc-border-radius (unsuffixed) is the MID (-md) step.
281
- --pc-border-radius-sm: calc(var(--base-border-radius-sm, #{$base-border-radius-sm}) * 1rem);
282
- --pc-border-radius: calc(var(--base-border-radius-md, #{$base-border-radius-md}) * 1rem);
283
- --pc-border-radius-lg: calc(var(--base-border-radius-lg, #{$base-border-radius-lg}) * 1rem);
284
- }
285
-
286
- // ============================================================================
287
- // COMPONENT CSS VARIABLES — pure-admin's contract (DEFINED here, EMITTED there)
288
- // ============================================================================
289
- // These emit the component-scoped --pc-* tokens (buttons, cards, tables,
290
- // panels, badges, tooltips, command palette, multiselect, sentiment scale,
291
- // form spacing, the derived contextual/alert surfaces, admin layout chrome).
292
- //
293
- // They are DEFINED in pure-css only because they read the shared $-variable
294
- // vocabulary that lives in `variables/*` (in scope here via `@use variables/
295
- // index as *`); a Sass mixin resolves those globals from its definition site,
296
- // so it must be authored where the vocabulary is visible.
297
- //
298
- // They are NOT part of pure-css's shipped output: base.scss / pure-css.scss do
299
- // NOT call them, so the foundation bundle emits base tokens only. Consumers
300
- // that ship the components (pure-admin core, themes) opt in by calling
301
- // output-pc-component-variables + output-pc-alert-variables-{light,dark}
302
- // alongside output-pc-css-variables. This keeps the EMISSION with the
303
- // components while the shared token vocabulary stays single-sourced.
304
- // ============================================================================
305
-
306
- @mixin output-pc-component-variables {
307
- // =========================================================================
308
- // SENTIMENT SCALE — 5-step direction-of-change (KPI / data-display).
309
- // Middle three alias the role colours so retuning --pc-success / --pc-danger
310
- // retunes the matching sentiment positions; outliers are explicit shades.
311
- // =========================================================================
312
- --pc-very-positive: #{$base-very-positive};
313
- --pc-positive: var(--pc-success);
314
- --pc-neutral: #{$base-neutral};
315
- --pc-negative: var(--pc-danger);
316
- --pc-very-negative: #{$base-very-negative};
317
-
318
- // =========================================================================
319
- // CHART / SPARKLINE — shared trendline sizing.
320
- // =========================================================================
321
- --pc-chart-trendline-height: 3rem;
322
- --pc-chart-trendline-stroke: 2.1; // SVG user-space units (viewBox-relative)
323
-
324
- // =========================================================================
325
- // DETAIL POPOVER — Bloomberg-dark by default regardless of host theme.
326
- // Override the five tokens to adopt a theme-aware popover instead.
327
- // =========================================================================
328
- --pc-detail-bg: rgba(15, 17, 21, 0.97);
329
- --pc-detail-text: #ffffff;
330
- --pc-detail-row-label: rgba(255, 255, 255, 0.75);
331
- --pc-detail-title: rgba(255, 255, 255, 0.55);
332
- --pc-detail-shadow: 0 1.4rem 3.6rem rgba(0, 0, 0, 0.55);
333
-
334
- // =========================================================================
335
- // LAYOUT COLORS
336
- // =========================================================================
337
-
338
- // Navbar
339
- --pc-navbar-bg: #{$navbar-bg};
340
- --pc-navbar-border-color: #{$navbar-border-color};
341
- --pc-navbar-text: #{$navbar-text};
342
- --pc-navbar-text-secondary: #{$navbar-text-secondary};
343
- --pc-navbar-profile-name-color: #{$navbar-profile-name-color};
344
-
345
- // Sidebar
346
- --pc-sidebar-bg: #{$sidebar-bg};
347
- --pc-sidebar-text: #{$sidebar-text};
348
- --pc-sidebar-text-secondary: #{$sidebar-text-secondary};
349
- --pc-sidebar-submenu-bg: #{$sidebar-submenu-bg};
350
- --pc-sidebar-submenu-hover-bg: #{$sidebar-submenu-hover-bg};
351
- --pc-sidebar-submenu-active-bg: #{$sidebar-submenu-active-bg};
352
- --pc-sidebar-submenu-active-text: #{$sidebar-submenu-active-text};
353
-
354
- // Footer
355
- --pc-footer-bg: #{$footer-bg};
356
- --pc-footer-border-color: #{$footer-border-color};
357
-
358
- // =========================================================================
359
- // BUTTON COLORS
360
- // =========================================================================
361
-
362
- // Primary (uses accent color)
363
- --pc-btn-primary-bg: #{$btn-primary-bg};
364
- --pc-btn-primary-bg-hover: #{$btn-primary-bg-hover};
365
- --pc-btn-primary-bg-light: color-mix(in srgb, var(--pc-btn-primary-bg) 5%, transparent);
366
- --pc-btn-primary-text: #{$btn-primary-text};
367
-
368
- // Secondary
369
- --pc-btn-secondary-bg: #{$btn-secondary-bg};
370
- --pc-btn-secondary-bg-hover: #{$btn-secondary-bg-hover};
371
- --pc-btn-secondary-text: #{$btn-secondary-text};
372
- --pc-btn-secondary-outline-color: var(--pc-btn-secondary-bg);
373
-
374
- // Success — bg references role colour for runtime cascade
375
- --pc-btn-success-bg: var(--pc-success);
376
- --pc-btn-success-bg-hover: #{$btn-success-bg-hover};
377
- --pc-btn-success-text: #{$btn-success-text};
378
-
379
- // Danger — bg references role colour for runtime cascade
380
- --pc-btn-danger-bg: var(--pc-danger);
381
- --pc-btn-danger-bg-hover: #{$btn-danger-bg-hover};
382
- --pc-btn-danger-text: #{$btn-danger-text};
383
-
384
- // Warning — bg references role colour for runtime cascade
385
- --pc-btn-warning-bg: var(--pc-warning);
386
- --pc-btn-warning-bg-hover: #{$btn-warning-bg-hover};
387
- --pc-btn-warning-text: #{$btn-warning-text};
388
-
389
- // Info — bg references role colour for runtime cascade
390
- --pc-btn-info-bg: var(--pc-info);
391
- --pc-btn-info-bg-hover: #{$btn-info-bg-hover};
392
- --pc-btn-info-text: #{$btn-info-text};
393
-
394
- // Light
395
- --pc-btn-light-bg: #{$btn-light-bg};
396
- --pc-btn-light-bg-hover: #{$btn-light-bg-hover};
397
- --pc-btn-light-text: #{$btn-light-text};
398
-
399
- // Dark
400
- --pc-btn-dark-bg: #{$btn-dark-bg};
401
- --pc-btn-dark-bg-hover: #{$btn-dark-bg-hover};
402
- --pc-btn-dark-text: #{$btn-dark-text};
403
-
404
- // =========================================================================
405
- // CONTEXTUAL/SEMANTIC SURFACES — derive from the base role identities.
406
- // -bg/-light/-subtle/-border derive at runtime so theme overrides cascade;
407
- // -bg-hover / -text-light stay compile-time. (The role text colours
408
- // --pc-{success,danger,warning,info}-text live in the base contract.)
409
- // =========================================================================
410
- --pc-success-bg: var(--pc-success);
411
- --pc-success-bg-hover: #{$success-bg-hover};
412
- --pc-success-bg-light: color-mix(in srgb, var(--pc-success) 10%, transparent);
413
- --pc-success-bg-subtle: color-mix(in srgb, var(--pc-success) 8%, transparent);
414
- --pc-success-border: color-mix(in srgb, var(--pc-success) 20%, transparent);
415
- --pc-success-text-light: #{$success-text-light};
416
-
417
- --pc-danger-bg: var(--pc-danger);
418
- --pc-danger-bg-hover: #{$danger-bg-hover};
419
- --pc-danger-bg-light: color-mix(in srgb, var(--pc-danger) 10%, transparent);
420
- --pc-danger-bg-subtle: color-mix(in srgb, var(--pc-danger) 8%, transparent);
421
- --pc-danger-border: color-mix(in srgb, var(--pc-danger) 20%, transparent);
422
- --pc-danger-text-light: #{$danger-text-light};
423
-
424
- --pc-warning-bg: var(--pc-warning);
425
- --pc-warning-bg-hover: #{$warning-bg-hover};
426
- --pc-warning-bg-light: color-mix(in srgb, var(--pc-warning) 10%, transparent);
427
- --pc-warning-bg-subtle: color-mix(in srgb, var(--pc-warning) 8%, transparent);
428
- --pc-warning-border: color-mix(in srgb, var(--pc-warning) 20%, transparent);
429
- --pc-warning-text-light: #{$warning-text-light};
430
-
431
- --pc-info-bg: var(--pc-info);
432
- --pc-info-bg-hover: #{$info-bg-hover};
433
- --pc-info-bg-light: color-mix(in srgb, var(--pc-info) 10%, transparent);
434
- --pc-info-bg-subtle: color-mix(in srgb, var(--pc-info) 8%, transparent);
435
- --pc-info-border: color-mix(in srgb, var(--pc-info) 20%, transparent);
436
- --pc-info-text-light: #{$info-text-light};
437
-
438
- // =========================================================================
439
- // CARD COLORS
440
- // =========================================================================
441
- --pc-card-bg: #{$card-bg};
442
- --pc-card-header-bg: #{$card-header-bg};
443
- --pc-card-footer-bg: #{$card-footer-bg};
444
- --pc-card-tabs-bg: #{$card-tabs-bg};
445
-
446
- // =========================================================================
447
- // INPUT/FORM COLORS
448
- // =========================================================================
449
- --pc-input-bg: #{$input-bg};
450
- --pc-input-border: #{$input-border};
451
- --pc-input-text: #{$input-text};
452
- --pc-input-focus-border-color: #{$input-focus-border-color};
453
- --pc-select-focus-border-color: #{$select-focus-border-color};
454
- --pc-textarea-focus-border-color: #{$textarea-focus-border-color};
455
-
456
- // Checkbox
457
- --pc-checkbox-border-color: #{$checkbox-border-color};
458
- --pc-checkbox-border-color-hover: #{$checkbox-border-color-hover};
459
- --pc-checkbox-border-color-checked: #{$checkbox-border-color-checked};
460
- --pc-checkbox-bg: #{$checkbox-bg};
461
- --pc-checkbox-bg-checked: #{$checkbox-bg-checked};
462
- --pc-checkbox-bg-indeterminate: #{$checkbox-bg-indeterminate};
463
- --pc-checkbox-checkmark-color: #{$checkbox-checkmark-color};
464
- --pc-checkbox-focus-shadow: #{$checkbox-focus-shadow};
465
-
466
- // Input group
467
- --pc-input-group-prepend-bg: #{$input-group-prepend-bg};
468
- --pc-input-group-prepend-text: #{$input-group-prepend-text};
469
- --pc-input-group-append-bg: #{$input-group-append-bg};
470
- --pc-input-group-append-text: #{$input-group-append-text};
471
-
472
- // =========================================================================
473
- // TABLE COLORS
474
- // =========================================================================
475
- --pc-table-bg: #{$table-bg};
476
- --pc-table-header-bg: #{$table-header-bg};
477
- --pc-table-stripe: #{$table-stripe};
478
- --pc-table-hover-bg: #{$table-hover-bg};
479
- --pc-table-hover-accent-color: #{$table-hover-accent-color};
480
-
481
- // =========================================================================
482
- // MODAL COLORS
483
- // =========================================================================
484
- --pc-modal-overlay-bg: #{$modal-overlay-bg};
485
- --pc-modal-content-bg: #{$modal-content-bg};
486
-
487
- // =========================================================================
488
- // BADGE COLORS
489
- // =========================================================================
490
- --pc-badge-success-bg: #{$badge-success-bg};
491
- --pc-badge-success-text: #{$badge-success-text};
492
- --pc-badge-warning-bg: #{$badge-warning-bg};
493
- --pc-badge-warning-text: #{$badge-warning-text};
494
- --pc-badge-info-bg: #{$badge-info-bg};
495
- --pc-badge-info-text: #{$badge-info-text};
496
- --pc-badge-danger-bg: #{$badge-danger-bg};
497
- --pc-badge-danger-text: #{$badge-danger-text};
498
-
499
- // Composite badge
500
- --pc-composite-badge-icon-bg: #{$composite-badge-icon-bg};
501
- --pc-composite-badge-label-bg: #{$composite-badge-label-bg};
502
- --pc-composite-badge-label-text: #{$composite-badge-label-text};
503
- --pc-composite-badge-label-hover-bg: #{$composite-badge-label-hover-bg};
504
-
505
- // =========================================================================
506
- // TOOLTIP & POPOVER COLORS
507
- // =========================================================================
508
- --pc-tooltip-bg: #{$tooltip-bg};
509
- --pc-tooltip-text: #{$tooltip-text};
510
- --pc-popover-content-bg: #{$popover-content-bg};
511
- --pc-popover-text-light: #{$popover-text-light};
512
- --pc-popover-text-dark: #{$popover-text-dark};
513
-
514
- // =========================================================================
515
- // LOADER COLORS
516
- // =========================================================================
517
- --pc-loader-overlay-bg: #{$loader-overlay-bg};
518
-
519
- // =========================================================================
520
- // PROFILE PANEL COLORS
521
- // =========================================================================
522
- --pc-profile-overlay-bg: #{$profile-overlay-bg};
523
-
524
- // =========================================================================
525
- // DETAIL PANEL COLORS
526
- // =========================================================================
527
- --pc-detail-panel-overlay-bg: #{$detail-panel-overlay-bg};
528
- --pc-detail-panel-selected-bg: #{$detail-panel-selected-bg};
529
- --pc-detail-panel-z-index: #{$detail-panel-z-index};
530
-
531
- // =========================================================================
532
- // COMMAND PALETTE COLORS
533
- // =========================================================================
534
- --pc-command-palette-backdrop-bg: #{$command-palette-backdrop-bg};
535
- --pc-command-palette-item-hover-bg: #{$command-palette-item-hover-bg};
536
- --pc-command-palette-item-active-bg: #{$command-palette-item-active-bg};
537
- --pc-command-palette-highlight-bg: #{$command-palette-highlight-bg};
538
- --pc-command-palette-highlight-text: #{$command-palette-highlight-text};
539
- --pc-command-palette-key-bg: #{$subtle-bg};
540
- --pc-command-palette-key-text: #{$text-color-1};
541
- --pc-command-palette-key-font-size: #{$font-size-xs};
542
- --pc-command-palette-key-font-weight: #{$font-weight-semibold};
543
-
544
- // =========================================================================
545
- // MULTISELECT COLORS
546
- // =========================================================================
547
- --pc-multiselect-dropdown-bg: #{$multiselect-dropdown-bg};
548
- --pc-multiselect-dropdown-border: #{$multiselect-dropdown-border};
549
- --pc-multiselect-dropdown-text: #{$multiselect-dropdown-text};
550
- --pc-multiselect-hint-bg: #{$multiselect-hint-bg};
551
- --pc-multiselect-hint-border: #{$multiselect-hint-border};
552
- --pc-multiselect-option-hover-bg: #{$multiselect-option-hover-bg};
553
- --pc-multiselect-pill-bg: #{$multiselect-pill-bg};
554
- --pc-multiselect-pill-border: #{$multiselect-pill-border};
555
-
556
- // =========================================================================
557
- // FORM SPACING — the complete anatomy of a form's spacing. Runtime-tunable;
558
- // the inline "gap" family chains to --pc-form-gap so one knob moves them all.
559
- // VERTICAL RHYTHM: --pc-label-gap (label→control), --pc-help-gap
560
- // (control→help), --pc-field-gap (field→field), --pc-form-actions-offset
561
- // (last field→actions row).
562
- // INLINE: --pc-form-gap (shared + label↔icon), --pc-choice-gap (between
563
- // options), --pc-choice-inner-gap (control↔label), --pc-form-actions-gap
564
- // (between buttons), --pc-field-horizontal-gap (label col↔input col).
565
- // =========================================================================
566
- --pc-form-gap: #{$form-gap};
567
- --pc-choice-gap: var(--pc-form-gap);
568
- --pc-choice-inner-gap: #{$spacing-sm};
569
- --pc-form-actions-gap: var(--pc-form-gap);
570
- --pc-field-horizontal-gap: #{$spacing-base};
571
- --pc-label-gap: #{$form-label-margin-bottom};
572
- --pc-help-gap: #{$form-help-margin-top};
573
- --pc-field-gap: #{$form-group-margin-bottom};
574
- --pc-form-actions-offset: #{$spacing-base};
575
- }
576
-
577
- // ============================================================================
578
- // ALERT COLOR DERIVATION MIXINS — also pure-admin's contract (see above).
579
- // ============================================================================
580
- // Derive alert colours from the semantic role surfaces (--pc-success-bg, etc.)
581
- // via color-mix(). Consumers call the light or dark variant after
582
- // output-pc-component-variables. Light: dark text on subtle backgrounds.
583
- // Dark: white text on tinted backgrounds. Not emitted by pure-css's own bundle.
584
- // ============================================================================
585
-
586
- // Light mode: dark text on subtle backgrounds
587
- @mixin output-pc-alert-variables-light {
588
- // Success
589
- --pc-alert-success-text: color-mix(in srgb, var(--pc-success-bg) #{$alert-text-mix-light}, black);
590
- --pc-alert-success-bg: color-mix(in srgb, var(--pc-success-bg) #{$alert-bg-opacity-light}%, transparent);
591
- --pc-alert-success-border: color-mix(in srgb, var(--pc-success-bg) #{$alert-border-opacity-light}%, transparent);
592
-
593
- // Danger
594
- --pc-alert-danger-text: color-mix(in srgb, var(--pc-danger-bg) #{$alert-text-mix-light}, black);
595
- --pc-alert-danger-bg: color-mix(in srgb, var(--pc-danger-bg) #{$alert-bg-opacity-light}%, transparent);
596
- --pc-alert-danger-border: color-mix(in srgb, var(--pc-danger-bg) #{$alert-border-opacity-light}%, transparent);
597
-
598
- // Warning
599
- --pc-alert-warning-text: color-mix(in srgb, var(--pc-warning-bg) #{$alert-text-mix-light}, black);
600
- --pc-alert-warning-bg: color-mix(in srgb, var(--pc-warning-bg) #{$alert-bg-opacity-light}%, transparent);
601
- --pc-alert-warning-border: color-mix(in srgb, var(--pc-warning-bg) #{$alert-border-opacity-light}%, transparent);
602
-
603
- // Info
604
- --pc-alert-info-text: color-mix(in srgb, var(--pc-info-bg) #{$alert-text-mix-light}, black);
605
- --pc-alert-info-bg: color-mix(in srgb, var(--pc-info-bg) #{$alert-bg-opacity-light}%, transparent);
606
- --pc-alert-info-border: color-mix(in srgb, var(--pc-info-bg) #{$alert-border-opacity-light}%, transparent);
607
- }
608
-
609
- // Dark mode: white text on tinted backgrounds (white text is always readable)
610
- @mixin output-pc-alert-variables-dark {
611
- // Success
612
- --pc-alert-success-text: #ffffff;
613
- --pc-alert-success-bg: color-mix(in srgb, var(--pc-success-bg) #{$alert-bg-opacity-dark}%, transparent);
614
- --pc-alert-success-border: color-mix(in srgb, var(--pc-success-bg) #{$alert-border-opacity-dark}%, transparent);
615
-
616
- // Danger
617
- --pc-alert-danger-text: #ffffff;
618
- --pc-alert-danger-bg: color-mix(in srgb, var(--pc-danger-bg) #{$alert-bg-opacity-dark}%, transparent);
619
- --pc-alert-danger-border: color-mix(in srgb, var(--pc-danger-bg) #{$alert-border-opacity-dark}%, transparent);
620
-
621
- // Warning
622
- --pc-alert-warning-text: #ffffff;
623
- --pc-alert-warning-bg: color-mix(in srgb, var(--pc-warning-bg) #{$alert-bg-opacity-dark}%, transparent);
624
- --pc-alert-warning-border: color-mix(in srgb, var(--pc-warning-bg) #{$alert-border-opacity-dark}%, transparent);
625
-
626
- // Info
627
- --pc-alert-info-text: #ffffff;
628
- --pc-alert-info-bg: color-mix(in srgb, var(--pc-info-bg) #{$alert-bg-opacity-dark}%, transparent);
629
- --pc-alert-info-border: color-mix(in srgb, var(--pc-info-bg) #{$alert-border-opacity-dark}%, transparent);
630
- }
1
+ // ============================================================================
2
+ // BASE CSS VARIABLES OUTPUT MIXIN
3
+ // ============================================================================
4
+ // This mixin outputs all $base-* SCSS variables as --base-* CSS custom properties.
5
+ // Include this in themes to enable web component theming.
6
+ //
7
+ // Usage in theme file:
8
+ // @import '../base-css-variables';
9
+ // :root {
10
+ // @include output-base-css-variables;
11
+ // }
12
+ //
13
+ // Web components consume these via fallback chains:
14
+ // --ms-accent-color: var(--base-accent-color, #3b82f6);
15
+ // ============================================================================
16
+
17
+ // Make variables resolvable when this file is loaded as a @use module
18
+ // (e.g. from main.scss). Legacy @import callers (themes) are unaffected —
19
+ // Sass places @use'd members into the importing file's global scope, where
20
+ // theme-set overrides already live.
21
+ @use 'variables/index' as *;
22
+
23
+ @mixin output-base-css-variables {
24
+ // === Accent Colors ===
25
+ --base-accent-color: #{$base-accent-color};
26
+ --base-accent-color-hover: #{$base-accent-color-hover};
27
+ --base-accent-color-active: #{$base-accent-color-active};
28
+ --base-accent-color-light: #{$base-accent-color-light};
29
+ --base-accent-color-light-hover: #{$base-accent-color-light-hover};
30
+
31
+ // === Primary role — canonical name for accent (WS7.5) ===
32
+ // Accent stays the SOURCE themes override (including runtime .pc-mode-dark /
33
+ // colour-variant overrides), so primary tracks it live in every scope. New
34
+ // consumers should read --base-primary-*; --base-accent-* is the legacy name.
35
+ --base-primary-color: var(--base-accent-color, #{$base-accent-color});
36
+ --base-primary-color-hover: var(--base-accent-color-hover, #{$base-accent-color-hover});
37
+ --base-primary-color-active: var(--base-accent-color-active, #{$base-accent-color-active});
38
+ --base-primary-color-light: var(--base-accent-color-light, #{$base-accent-color-light});
39
+ --base-primary-color-light-hover: var(--base-accent-color-light-hover, #{$base-accent-color-light-hover});
40
+
41
+ // === Secondary role (promoted into the contract, WS7.5) ===
42
+ --base-secondary-color: #{$base-secondary-color};
43
+ --base-secondary-color-hover: #{$base-secondary-color-hover};
44
+
45
+ // === Text Colors ===
46
+ --base-text-color-1: #{$base-text-color-1};
47
+ --base-text-color-2: #{$base-text-color-2};
48
+ --base-text-color-3: #{$base-text-color-3};
49
+ --base-text-color-4: #{$base-text-color-4};
50
+ --base-text-color-on-accent: #{$base-text-color-on-accent};
51
+ // "foreground on a role" convention = --base-text-on-<role> (WS7.7). on-primary
52
+ // aliases the legacy on-accent; on-secondary is new; on-{success,danger,warning,
53
+ // info} are emitted in their role sections below.
54
+ --base-text-on-primary: var(--base-text-color-on-accent, #{$base-text-color-on-accent});
55
+ --base-text-on-secondary: #{$base-text-on-secondary};
56
+
57
+ // === Background Colors (semantic) ===
58
+ --base-main-bg: #{$base-main-bg};
59
+ --base-page-bg: #{$base-page-bg};
60
+ --base-subtle-bg: #{$base-subtle-bg};
61
+ --base-inverse-bg: #{$base-inverse-bg};
62
+ --base-overlay-bg: #{$base-overlay-bg};
63
+ --base-shadow-color: #{$base-shadow-color};
64
+ --base-hover-bg: #{$base-hover-bg};
65
+ --base-active-bg: #{$base-active-bg};
66
+ --base-disabled-bg: #{$base-disabled-bg};
67
+ --base-elevated-bg: #{$base-elevated-bg};
68
+
69
+ // === Text on inverse surfaces ===
70
+ --base-text-inverted: #{$base-text-inverted};
71
+
72
+ // === Border Colors ===
73
+ // --base-border-width is a new additive knob for consumers composing their own
74
+ // borders. The shorthands stay emitted from their $var so themes that override
75
+ // the whole shorthand (e.g. an accent-coloured input border) keep winning —
76
+ // recomposing them from the -color tokens would silently drop those overrides. (WS7.1)
77
+ --base-border-width: #{$base-border-width};
78
+ --base-border-color: #{$base-border-color};
79
+ --base-border: #{$base-border};
80
+ --base-checkbox-border-color: #{$base-checkbox-border-color};
81
+
82
+ // === Input Fields ===
83
+ --base-input-bg: #{$base-input-bg};
84
+ --base-input-color: #{$base-input-color};
85
+ --base-input-border: #{$base-input-border};
86
+ --base-input-border-color: #{$base-input-border-color};
87
+ --base-input-border-hover: #{$base-input-border-hover};
88
+ --base-input-border-focus: #{$base-input-border-focus};
89
+ --base-input-placeholder-color: #{$base-input-placeholder-color};
90
+ --base-input-bg-disabled: #{$base-input-bg-disabled};
91
+ --base-input-clear-color: #{$base-input-clear-color};
92
+ --base-input-clear-bg-hover: #{$base-input-clear-bg-hover};
93
+
94
+ // === Input Size Heights ===
95
+ --base-input-size-xs-height: #{$base-input-size-xs-height};
96
+ --base-input-size-sm-height: #{$base-input-size-sm-height};
97
+ --base-input-size-md-height: #{$base-input-size-md-height};
98
+ --base-input-size-lg-height: #{$base-input-size-lg-height};
99
+ --base-input-size-xl-height: #{$base-input-size-xl-height};
100
+
101
+ // === Dropdown/Popover ===
102
+ --base-dropdown-bg: #{$base-dropdown-bg};
103
+ --base-dropdown-border: #{$base-dropdown-border};
104
+ --base-dropdown-box-shadow: #{$base-dropdown-box-shadow};
105
+
106
+ // === Tooltip ===
107
+ --base-tooltip-bg: #{$base-tooltip-bg};
108
+ --base-tooltip-text-color: #{$base-tooltip-text-color};
109
+ --base-tooltip-color: #{$base-tooltip-text-color}; // alias consumed by web-grid
110
+
111
+ // === Contextual Colors - Success ===
112
+ --base-success-color: #{$base-success-color};
113
+ --base-success-bg: #{$base-success-bg};
114
+ --base-success-color-hover: #{$base-success-color-hover};
115
+ --base-success-bg-light: #{$base-success-bg-light};
116
+ --base-success-bg-subtle: #{$base-success-bg-subtle};
117
+ --base-success-border: #{$base-success-border};
118
+ --base-success-text: #{$base-success-text};
119
+ --base-success-text-light: #{$base-success-text-light};
120
+ --base-text-on-success: #{$base-text-on-success};
121
+
122
+ // === Contextual Colors - Danger ===
123
+ --base-danger-color: #{$base-danger-color};
124
+ --base-danger-bg: #{$base-danger-bg};
125
+ --base-danger-color-hover: #{$base-danger-color-hover};
126
+ --base-danger-bg-light: #{$base-danger-bg-light};
127
+ --base-danger-bg-subtle: #{$base-danger-bg-subtle};
128
+ --base-danger-border: #{$base-danger-border};
129
+ --base-danger-text: #{$base-danger-text};
130
+ --base-danger-text-light: #{$base-danger-text-light};
131
+ --base-text-on-danger: #{$base-text-on-danger};
132
+
133
+ // === Contextual Colors - Warning ===
134
+ --base-warning-color: #{$base-warning-color};
135
+ --base-warning-bg: #{$base-warning-bg};
136
+ --base-warning-color-hover: #{$base-warning-color-hover};
137
+ --base-warning-bg-light: #{$base-warning-bg-light};
138
+ --base-warning-bg-subtle: #{$base-warning-bg-subtle};
139
+ --base-warning-border: #{$base-warning-border};
140
+ --base-warning-text: #{$base-warning-text};
141
+ --base-warning-text-light: #{$base-warning-text-light};
142
+ --base-text-on-warning: #{$base-text-on-warning};
143
+
144
+ // === Contextual Colors - Info ===
145
+ --base-info-color: #{$base-info-color};
146
+ --base-info-bg: #{$base-info-bg}; // solid role fill — role symmetry (WS7.4)
147
+ --base-info-color-hover: #{$base-info-color-hover};
148
+ --base-info-bg-light: #{$base-info-bg-light};
149
+ --base-info-bg-subtle: #{$base-info-bg-subtle};
150
+ --base-info-border: #{$base-info-border};
151
+ --base-info-text: #{$base-info-text};
152
+ --base-info-text-light: #{$base-info-text-light};
153
+ --base-text-on-info: #{$base-text-on-info};
154
+
155
+ // === Interactive States ===
156
+ --base-hover-overlay: #{$base-hover-overlay};
157
+ --base-active-overlay: #{$base-active-overlay};
158
+ --base-focus-ring-color: #{$base-focus-ring-color};
159
+ --base-focus-ring-width: #{$base-focus-ring-width};
160
+
161
+ // === Typography ===
162
+ --base-font-family: #{$base-font-family};
163
+ --base-font-family-mono: #{$base-font-family-mono};
164
+ --base-font-size-2xs: #{$base-font-size-2xs};
165
+ --base-font-size-xs: #{$base-font-size-xs};
166
+ --base-font-size-sm: #{$base-font-size-sm};
167
+ --base-font-size-base: #{$base-font-size-base};
168
+ --base-font-size-lg: #{$base-font-size-lg};
169
+ --base-font-size-xl: #{$base-font-size-xl};
170
+ --base-font-size-2xl: #{$base-font-size-2xl};
171
+ --base-font-weight-normal: #{$base-font-weight-normal};
172
+ --base-font-weight-medium: #{$base-font-weight-medium};
173
+ --base-font-weight-semibold: #{$base-font-weight-semibold};
174
+ --base-font-weight-bold: #{$base-font-weight-bold};
175
+ --base-line-height-tight: #{$base-line-height-tight};
176
+ --base-line-height-normal: #{$base-line-height-normal};
177
+ --base-line-height-relaxed: #{$base-line-height-relaxed};
178
+
179
+ // === Border Radius ===
180
+ --base-border-radius-sm: #{$base-border-radius-sm};
181
+ --base-border-radius-md: #{$base-border-radius-md};
182
+ --base-border-radius-lg: #{$base-border-radius-lg};
183
+
184
+ // === Rem base for web components ===
185
+ --base-rem: #{$base-rem};
186
+
187
+ // === Icons — shared mask-friendly SVG glyphs (theme swap point) ===
188
+ // Consumed via `mask: var(--base-icon-*); background: currentColor`. chevron =
189
+ // directional stroked angle (expanders/nav); caret-down = static solid triangle
190
+ // (dropdown affordance); close = the ✕ (close/clear/remove). Override any of the
191
+ // three to re-skin every consumer's affordance at once.
192
+ --base-icon-chevron: #{$base-icon-chevron};
193
+ --base-icon-caret-down: #{$base-icon-caret-down};
194
+ --base-icon-caret-up: #{$base-icon-caret-up};
195
+ --base-icon-close: #{$base-icon-close};
196
+ // clear (field-clear ✕) = distinct purpose from close, same default glyph: it
197
+ // FOLLOWS --base-icon-close at runtime, so overriding close moves clear too —
198
+ // override --base-icon-clear alone to diverge field-clear from close/remove.
199
+ --base-icon-clear: var(--base-icon-close, #{$base-icon-close});
200
+ // remove (take an ITEM out of a collection: chip/tag/row) = non-destructive,
201
+ // own purpose, same ✕ default; follows close at runtime like clear. NOT delete
202
+ // (which is the destructive trash glyph in the action group below).
203
+ --base-icon-remove: var(--base-icon-close, #{$base-icon-close});
204
+ // expand/collapse = the +/− swap-glyph disclosure pair (trees, accordions),
205
+ // distinct from the rotating chevron.
206
+ --base-icon-expand: #{$base-icon-expand};
207
+ --base-icon-collapse: #{$base-icon-collapse};
208
+
209
+ // === Action icons — CRUD verbs (distinct glyphs; read as actions) ===
210
+ // add = + (create/insert; independent knob from expand), edit = pencil,
211
+ // delete = trash (DESTRUCTIVE — a bin, deliberately not an ✕, so it never
212
+ // reads like close/remove).
213
+ --base-icon-add: #{$base-icon-add};
214
+ --base-icon-edit: #{$base-icon-edit};
215
+ --base-icon-delete: #{$base-icon-delete};
216
+
217
+ // === Utility icons ===
218
+ --base-icon-search: #{$base-icon-search};
219
+
220
+ // === Theme palette slots (1–9) + paired contrast text (WS7.6) ===
221
+ // Promoted into the --base-* contract so the branded/data-viz palette is
222
+ // themeable through the same namespace; --pc-color-N aliases these.
223
+ --base-color-1: #{$color-1};
224
+ --base-color-2: #{$color-2};
225
+ --base-color-3: #{$color-3};
226
+ --base-color-4: #{$color-4};
227
+ --base-color-5: #{$color-5};
228
+ --base-color-6: #{$color-6};
229
+ --base-color-7: #{$color-7};
230
+ --base-color-8: #{$color-8};
231
+ --base-color-9: #{$color-9};
232
+ --base-color-1-text: #{$color-1-text};
233
+ --base-color-2-text: #{$color-2-text};
234
+ --base-color-3-text: #{$color-3-text};
235
+ --base-color-4-text: #{$color-4-text};
236
+ --base-color-5-text: #{$color-5-text};
237
+ --base-color-6-text: #{$color-6-text};
238
+ --base-color-7-text: #{$color-7-text};
239
+ --base-color-8-text: #{$color-8-text};
240
+ --base-color-9-text: #{$color-9-text};
241
+
242
+ // === Spacing scale (WS7.9) ===
243
+ // Unitless multipliers (same convention as font-size/radius); consume as
244
+ // calc(var(--base-space-*) * var(--base-rem)). Mirrors $semantic-spacers.
245
+ --base-space-xs: 0.4;
246
+ --base-space-sm: 0.8;
247
+ --base-space-md: 1.2;
248
+ --base-space-base: 1.6;
249
+ --base-space-lg: 2.4;
250
+ --base-space-xl: 3.2;
251
+ --base-space-2xl: 4.8;
252
+
253
+ // === Elevation / shadow scale (WS7.10) ===
254
+ // Offsets fixed; colour referenced from --base-shadow-color so shadows theme
255
+ // with the surface. New scale (no prior consumer), so the unified shadow-colour
256
+ // is intentional.
257
+ --base-shadow-sm: 0 1px 3px var(--base-shadow-color);
258
+ --base-shadow-md: 0 2px 8px var(--base-shadow-color);
259
+ --base-shadow-lg: 0 4px 12px var(--base-shadow-color);
260
+
261
+ // === Motion — durations + easings (WS7.11) ===
262
+ --base-duration-fast: 0.1s;
263
+ --base-duration-normal: 0.15s;
264
+ --base-duration-medium: 0.25s;
265
+ --base-duration-slow: 0.3s;
266
+ --base-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
267
+ --base-ease-out: cubic-bezier(0, 0, 0.2, 1);
268
+ --base-ease-in: cubic-bezier(0.4, 0, 1, 1);
269
+
270
+ // === Z-index scale — generic stacking tiers (WS7.12) ===
271
+ // The shared contract the shell + overlays coordinate against. App-specific
272
+ // panel tiers live in pure-admin-core, not here.
273
+ --base-z-dropdown: #{$z-index-dropdown};
274
+ --base-z-modal-backdrop: #{$z-index-modal-backdrop};
275
+ --base-z-modal: #{$z-index-modal};
276
+ --base-z-popover: #{$z-index-popover};
277
+ --base-z-toast: #{$z-index-toast};
278
+ --base-z-tooltip: #{$z-index-tooltip};
279
+ }
280
+
281
+ // ============================================================================
282
+ // DERIVED TOKENS — TEXT CONTRAST TIERS + SURFACE TINTS
283
+ // ============================================================================
284
+ // These tokens use `color-mix(... var(--pc-text-color-1) ...)` to derive
285
+ // theme-aware contrast levels. They MUST be emitted at every selector that
286
+ // could carry an override of --pc-text-color-1, because CSS custom property
287
+ // substitution bakes nested var() references at the *defining element*, not
288
+ // the using element. If we only defined these at `:root, .pc-mode-light`,
289
+ // the light-mode text colour would be frozen into the value, and elements
290
+ // inside `.pc-mode-dark` (which overrides --pc-text-color-1 at body) would
291
+ // inherit the light-mode-baked tier values → low contrast on dark surfaces.
292
+ //
293
+ // Emitting at all three selectors causes each scope to recompute the tiers
294
+ // against its own --pc-text-color-1. The selector list `:root, .pc-mode-light,
295
+ // .pc-mode-dark` covers html, body in light mode, and body in dark mode —
296
+ // regardless of which class layout each theme uses for mode switching.
297
+ //
298
+ // This is a TOP-LEVEL rule (not inside the mixin) because themes only call
299
+ // the mixin from their light-mode block; they don't call it again in the
300
+ // dark-mode block. Emitting at framework level means themes get correct
301
+ // dark-mode tiers without changing any theme code.
302
+ //
303
+ // Override these per-theme by redefining them in the same scope you
304
+ // override --pc-text-color-1.
305
+ // ============================================================================
306
+
307
+ :root,
308
+ .pc-mode-light,
309
+ .pc-mode-dark {
310
+ --pc-text-strong: color-mix(in srgb, var(--pc-text-color-1) 85%, transparent);
311
+ --pc-text-secondary: color-mix(in srgb, var(--pc-text-color-1) 70%, transparent);
312
+ --pc-text-tertiary: color-mix(in srgb, var(--pc-text-color-1) 55%, transparent);
313
+ --pc-surface-hover: color-mix(in srgb, var(--pc-text-color-1) 4%, transparent);
314
+ --pc-surface-track: color-mix(in srgb, var(--pc-text-color-1) 12%, transparent);
315
+ }
316
+
317
+ // ============================================================================
318
+ // PURE-CSS FOUNDATION TOKENS — the base runtime custom-property contract
319
+ // ============================================================================
320
+ // pure-css is a *foundation*: it ships only the BASE token contract — the
321
+ // tokens its own CSS (grid / utilities / reboot / scrollbars) consumes, plus
322
+ // the universal theming primitives (surfaces, text, accent, links, border,
323
+ // the semantic role identities + their utility text colours, the theme
324
+ // palette slots, and the border-radius scale).
325
+ //
326
+ // COMPONENT tokens (buttons, cards, tables, modals, badges, tooltips, panels,
327
+ // command palette, sentiment scale, form spacing, the derived contextual/alert
328
+ // surfaces, admin layout chrome, …) live entirely in pure-admin-core now —
329
+ // both the `$`-vocabulary (core's `variables/_components.scss`) and the emit
330
+ // mixins (`output-pc-component-variables` / `-mode-variables` /
331
+ // `output-pc-alert-variables-{light,dark}`). They derive from the same $base-*
332
+ // source of truth defined here, so a theme still overrides one place; only the
333
+ // component layer itself lives next to the component CSS that consumes it.
334
+ // ============================================================================
335
+
336
+ @mixin output-pc-css-variables {
337
+ // Tells the browser whether this scope is light or dark so native UA
338
+ // elements (scrollbars, form controls) and `light-dark()` resolve correctly.
339
+ // Override $theme-color-scheme before importing variables for always-dark
340
+ // themes; for dual-mode themes leave `light` and add `color-scheme: dark;`
341
+ // to the `.pc-mode-dark` block.
342
+ color-scheme: #{$theme-color-scheme};
343
+
344
+ // Surfaces. NOTE: pure-admin's --pc-main-bg is the *page* surface and
345
+ // --pc-subtle-bg the *card* surface — a legacy naming inversion vs the
346
+ // --base-* model (--base-main-bg = card), so those two stay compile-time to
347
+ // avoid a value flip. --pc-page-bg maps cleanly and is relinked.
348
+ --pc-main-bg: #{$main-bg};
349
+ --pc-page-bg: var(--base-page-bg, #{$page-bg});
350
+ --pc-subtle-bg: #{$subtle-bg};
351
+
352
+ // Interaction-STATE surfaces — a distinct axis from the elevation ladder
353
+ // above (page/main/subtle). Track --base-hover/active-bg live so they follow
354
+ // a theme's per-mode overrides; equal to --pc-subtle-bg by default but
355
+ // overridable independently. Components must use these for :hover/:active
356
+ // fills — never a surface token like --pc-subtle-bg. (subtle de-conflation)
357
+ --pc-hover-bg: var(--base-hover-bg, #{$base-hover-bg});
358
+ --pc-active-bg: var(--base-active-bg, #{$base-active-bg});
359
+
360
+ // Text — follow the shared --base-* tokens at runtime.
361
+ --pc-text-color-1: var(--base-text-color-1, #{$text-color-1});
362
+ --pc-text-color-2: var(--base-text-color-2, #{$text-color-2});
363
+
364
+ // Accent — -light derives from --pc-accent at runtime so theme overrides cascade.
365
+ --pc-accent: var(--base-accent-color, #{$accent-color});
366
+ --pc-accent-hover: #{$accent-hover};
367
+ --pc-accent-light: color-mix(in srgb, var(--pc-accent) 5%, transparent);
368
+
369
+ // Links — derive from accent so theme overrides cascade automatically.
370
+ // Hover mixes 50% toward currentColor (inherited text colour at the use site),
371
+ // so it auto-darkens on light themes and auto-lightens on dark themes.
372
+ --pc-link-color: var(--pc-accent);
373
+ --pc-link-color-hover: color-mix(in srgb, var(--pc-link-color), currentColor 50%);
374
+ --pc-link-color-visited: var(--pc-link-color);
375
+
376
+ // Border — a live reference to --base-border-color (so a runtime --base-*
377
+ // override cascades), with the build-time value as the literal fallback.
378
+ --pc-border-color: var(--base-border-color, #{$border-color});
379
+
380
+ // Semantic role identities — the single source for the four roles. Component
381
+ // surfaces (--pc-*-bg, alerts, buttons) derive from these via var() in
382
+ // pure-admin, so retuning a role here cascades everywhere.
383
+ --pc-success: #{$base-success-color};
384
+ --pc-warning: #{$base-warning-color};
385
+ --pc-danger: #{$base-danger-color};
386
+ --pc-info: #{$base-info-color};
387
+
388
+ // Role text colours — consumed by the .text-{success,danger,warning,info}
389
+ // utilities (utilities.scss). Kept in the base contract for that reason.
390
+ --pc-success-text: #{$success-text};
391
+ --pc-danger-text: #{$danger-text};
392
+ --pc-warning-text: #{$warning-text};
393
+ --pc-info-text: #{$info-text};
394
+
395
+ // Theme palette slots (1–9) + paired contrast text. Consumed by the
396
+ // .text-color-* utilities; themes override $color-N for branded palettes.
397
+ // Alias the promoted --base-color-* palette (WS7.6) so overriding a slot in
398
+ // either namespace cascades; the $literal is the build-time fallback.
399
+ --pc-color-1: var(--base-color-1, #{$color-1});
400
+ --pc-color-2: var(--base-color-2, #{$color-2});
401
+ --pc-color-3: var(--base-color-3, #{$color-3});
402
+ --pc-color-4: var(--base-color-4, #{$color-4});
403
+ --pc-color-5: var(--base-color-5, #{$color-5});
404
+ --pc-color-6: var(--base-color-6, #{$color-6});
405
+ --pc-color-7: var(--base-color-7, #{$color-7});
406
+ --pc-color-8: var(--base-color-8, #{$color-8});
407
+ --pc-color-9: var(--base-color-9, #{$color-9});
408
+ --pc-color-1-text: var(--base-color-1-text, #{$color-1-text});
409
+ --pc-color-2-text: var(--base-color-2-text, #{$color-2-text});
410
+ --pc-color-3-text: var(--base-color-3-text, #{$color-3-text});
411
+ --pc-color-4-text: var(--base-color-4-text, #{$color-4-text});
412
+ --pc-color-5-text: var(--base-color-5-text, #{$color-5-text});
413
+ --pc-color-6-text: var(--base-color-6-text, #{$color-6-text});
414
+ --pc-color-7-text: var(--base-color-7-text, #{$color-7-text});
415
+ --pc-color-8-text: var(--base-color-8-text, #{$color-8-text});
416
+ --pc-color-9-text: var(--base-color-9-text, #{$color-9-text});
417
+
418
+ // Border-radius scale — derived from the --base-border-radius-* contract (the
419
+ // same unitless rem-multipliers the web/svelte components read; e.g.
420
+ // web-multiselect: `calc(var(--base-border-radius-md) * --ms-rem)`). Multiplying
421
+ // by 1rem yields px at pure-css's 10px rem base (0.6 → 0.6rem → 6px) and keeps
422
+ // the scale live: overriding --base-border-radius-* at runtime re-rounds
423
+ // pure-css's own elements and the components together, instead of the old baked
424
+ // 2/4/8px literals that ignored the base contract. The $base-* multipliers are
425
+ // the fallbacks. NOTE: --pc-border-radius (unsuffixed) is the MID (-md) step.
426
+ --pc-border-radius-sm: calc(var(--base-border-radius-sm, #{$base-border-radius-sm}) * 1rem);
427
+ --pc-border-radius: calc(var(--base-border-radius-md, #{$base-border-radius-md}) * 1rem);
428
+ --pc-border-radius-lg: calc(var(--base-border-radius-lg, #{$base-border-radius-lg}) * 1rem);
429
+ }