@keenmate/pure-css 1.0.0-rc07 → 1.0.0-rc09

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