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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,76 @@
3
3
  All notable changes to `@keenmate/pure-css` are documented here. Format based on
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
5
 
6
+ ## [1.0.0-rc07] — 2026-09-08 [PUBLISHED]
7
+
8
+ The **shared theming knob** release. Before rc07 the same visual token (a tooltip
9
+ background, an input border, a dropdown surface) was produced *twice and
10
+ independently* — pure-admin's `--pc-*` component tokens were baked compile-time
11
+ literals, while the KeenMate web components read `--base-*` live — so they agreed
12
+ only by coincidence and diverged the instant a theme retuned `--base-*` at
13
+ runtime (every dual-mode theme does exactly this at `.pc-mode-dark`). rc07 makes
14
+ `--base-*` the single runtime knob: override one namespace and pure-admin
15
+ components + the web components re-theme together, in light and dark.
16
+
17
+ ### Added
18
+
19
+ - **Gap `--base-*` tokens the web components already read but pure-css never
20
+ emitted** — so they stop falling through to hardcoded component defaults and
21
+ actually theme: `--base-text-inverted`, `--base-checkbox-border-color`,
22
+ `--base-input-border-color` (+ the `--base-input-border` shorthand),
23
+ `--base-input-clear-color` / `--base-input-clear-bg-hover`, the solid role
24
+ fills `--base-success-bg` / `--base-danger-bg` / `--base-warning-bg`, and
25
+ `--base-rem`.
26
+
27
+ ### Changed
28
+
29
+ - **`--pc-*` component tokens now derive from `--base-*` at runtime.** ~40 themed
30
+ `--pc-*` tokens (buttons, cards, inputs, checkbox, input groups, tables, modal,
31
+ tooltip/popover, command palette, multiselect) were rewritten from baked
32
+ `#{$…}` literals to the guiding-rule form `var(--base-x, #{$fallback})`. The
33
+ `#{$fallback}` preserves today's compiled value, so **light-mode output is
34
+ unchanged** — but the token now follows any runtime `--base-*` override, shared
35
+ with the web components.
36
+ - **The app shell surfaces stay compile-time — deliberately not `--base-*`-derived.**
37
+ The navbar/sidebar/footer surface + text tokens (`--pc-navbar-*`,
38
+ `--pc-sidebar-*`, `--pc-footer-*`) are emitted as plain `#{$…}` literals, *not*
39
+ `var(--base-main-bg, …)`. The shell is a distinct brand surface a theme sets on
40
+ its own (e.g. a yellow navbar) independent of the `--base-*` card/page palette;
41
+ since `--base-main-bg` is always emitted, deriving the navbar from it would let
42
+ the base palette win and erase the brand colour. Standalone (`base.css`-only)
43
+ rendering is still covered — the shell CSS itself resolves
44
+ `var(--pc-navbar-bg, var(--base-main-bg))`, so the `--base-*` floor applies only
45
+ when no `--pc-*` is emitted (the rc06 contract), not as a runtime override of it.
46
+ - **Surface-token naming realigned with the `--base-*` model (B5).**
47
+ `--pc-main-bg` is now the **white surface** (`--base-main-bg`), `--pc-subtle-bg`
48
+ the **muted grey** (`--base-subtle-bg`), and `--pc-page-bg` remains the **grey
49
+ canvas**. Previously `--pc-main-bg` *was* the grey canvas and `--pc-subtle-bg`
50
+ *was* white — an inversion vs the `--base-*` vocabulary. pure-css's own shell
51
+ canvas usages (reboot `body`, `.pc-layout`, scrollbars) were repointed
52
+ `--pc-main-bg` → `--pc-page-bg` so the canvas stays grey. **Downstream code
53
+ reading `--pc-main-bg` / `--pc-subtle-bg` must re-check intent** — see
54
+ pure-admin-core rc19, which repoints its component surfaces accordingly.
55
+ - `$base-elevated-bg` default changed from the stray `#f5f5f5` to `$base-page-bg`.
56
+
57
+ ### Fixed
58
+
59
+ - **Broken `$`-link:** `$input-border` was a hardcoded `#ced4da` (the comment even
60
+ claimed it came from base) — reconnected to `$base-input-border-color`, so input
61
+ borders finally track the theme.
62
+ - **Semantic surface reconciliation** so pure-admin and the web components resolve
63
+ the *same* base token per surface: card/table headers + striped rows →
64
+ `--base-elevated-bg`, dropdown/popover → `--base-dropdown-bg`, table/multiselect
65
+ hover → `--base-hover-bg`, checkbox border → `--base-checkbox-border-color`.
66
+ - **Sidebar search box alignment + collapsed-rail gating (`_sidebar.scss`).** The
67
+ search input's inline padding was rebalanced to `0 $spacing-base 0 $spacing-sm`
68
+ so its magnifier lines up with the nav-row icons below it (margin `$spacing-sm` +
69
+ padding-left `$spacing-sm` = the `$spacing-base` nav inset) instead of sitting one
70
+ box-margin too far in. The collapsed-rail rules that shed the search frame/field
71
+ down to the submit icon were re-scoped from `.pc-layout__sidebar--icon-collapse`
72
+ to `.sidebar-hidden .pc-layout__sidebar--icon-collapse` — the mode class stays on
73
+ the element while the rail is expanded, so the unscoped rules were stripping the
74
+ search frame in the expanded state too.
75
+
6
76
  ## [1.0.0-rc06] — 2026-08-30
7
77
 
8
78
  ### Fixed
package/README.md CHANGED
@@ -4,18 +4,20 @@ The KeenMate CSS **foundation** — the `--base-*` theming contract, the flexbox
4
4
  utility classes — extracted from [`@keenmate/pure-admin-core`](https://github.com/KeenMate/pure-admin)
5
5
  so it can be consumed on its own.
6
6
 
7
+ ## What's New in 1.0.0-rc07
8
+
9
+ - **Theming — one runtime knob re-themes pure-admin components and the web components together** — before rc07 the same visual token was produced twice and independently: pure-admin's `--pc-*` component tokens were baked as compile-time literals, while the KeenMate web components read `--base-*` live, so they agreed only by coincidence and diverged the instant a theme retuned `--base-*` at runtime (every dark-mode toggle does exactly this at `.pc-mode-dark`). ~40 themed `--pc-*` tokens in `_base-css-variables.scss` (buttons, cards, inputs, checkbox, input groups, tables, modal, tooltip/popover, command palette, multiselect) were rewritten from `#{$…}` literals to the guiding-rule form `var(--base-x, #{$fallback})`. The `#{$fallback}` preserves today's compiled value so light-mode output is byte-for-byte unchanged, but each token now follows any runtime `--base-*` override — the same knob the web components already read.
10
+ - **App shell — navbar/sidebar/footer surfaces stay a distinct brand colour, deliberately not `--base-*`-derived** — the shell's surface + text tokens (`--pc-navbar-*`, `--pc-sidebar-*`, `--pc-footer-*`) are emitted as plain `#{$…}` literals, *not* `var(--base-main-bg, …)`. A theme sets the shell's brand (e.g. a yellow navbar) independently of the `--base-*` card/page palette, and since `--base-main-bg` is always emitted, deriving the navbar from it would let the base palette win and erase the brand. Standalone (`base.css`-only) rendering still works because the shell CSS resolves `var(--pc-navbar-bg, var(--base-main-bg))` — the `--base-*` floor applies only when no `--pc-*` is emitted (the rc06 contract), never as a runtime override of it.
11
+ - **Theming — gap `--base-*` tokens the web components read but pure-css never emitted** — several `--base-*` vars the components already consumed were falling through to hardcoded component defaults because pure-css didn't emit them, so they couldn't be themed. rc07 emits them: `--base-text-inverted`, `--base-checkbox-border-color`, `--base-input-border-color` (+ the `--base-input-border` shorthand), `--base-input-clear-color` / `--base-input-clear-bg-hover`, the solid role fills `--base-success-bg` / `--base-danger-bg` / `--base-warning-bg`, and `--base-rem`.
12
+ - **Surfaces — `--pc-main-bg` / `--pc-subtle-bg` naming realigned with the `--base-*` model** — `--pc-main-bg` is now the **white surface** and `--pc-subtle-bg` the **muted grey**, matching `--base-main-bg` / `--base-subtle-bg`; previously the two were inverted (`--pc-main-bg` *was* the grey canvas). pure-css's own canvas usages (reboot `body`, `.pc-layout`, scrollbars) were repointed `--pc-main-bg` → `--pc-page-bg` so the page canvas stays grey. **Downstream code reading `--pc-main-bg` / `--pc-subtle-bg` must re-check intent** — see pure-admin-core rc19.
13
+ - **Fixed — input borders finally track the theme** — `$input-border` was a hardcoded `#ced4da` (its own comment wrongly claimed it came from base); it's reconnected to `$base-input-border-color`. Also a semantic surface reconciliation so pure-admin and the web components resolve the *same* base token per surface (card/table headers + striped rows → `--base-elevated-bg`, dropdown/popover → `--base-dropdown-bg`, hover → `--base-hover-bg`).
14
+ - **Fixed — sidebar search box alignment + collapsed-rail gating** — the search input's inline padding was rebalanced (`0 $spacing-base 0 $spacing-sm`) so its magnifier lines up with the nav-row icons below it, and the collapsed-rail rules that strip the search down to the submit icon were re-scoped from `.pc-layout__sidebar--icon-collapse` to `.sidebar-hidden .pc-layout__sidebar--icon-collapse` — the mode class stays on the element while the rail is expanded, so the unscoped rules were stripping the search frame in the expanded state too.
15
+
7
16
  ## What's New in 1.0.0-rc06
8
17
 
9
18
  - **The app shell renders standalone — no `--pc-*` component setup required** — rc05 moved the shell into the foundation, but its CSS referenced component tokens (`--pc-navbar-bg`, `--pc-sidebar-*`, `--pc-card-bg`, …) that pure-css doesn't emit, so linking `base.css` / `pure-css.css` alone gave an unstyled navbar/sidebar (keen-docs hit this). Every such reference now falls back to a `--base-*` var that pure-css *does* emit — `var(--pc-navbar-bg, var(--base-main-bg))` and friends, 40 in all, each traced from the token's real derivation. That's a clean two-tier contract: link the base vars and the shell just works out of the box; set the `--pc-*` token only when you want to fine-tune a piece independently. Also fixed two dangling refs in the fit flyout (`--pc-accent-color` → `--pc-accent`, plus a `--base-hover-bg` tier for `--pc-hover-bg`).
10
19
  - **One border-radius scale across the whole ecosystem** — pure-css shipped two disconnected radius systems: the `--base-border-radius-sm/md/lg` multipliers every web/svelte component reads (e.g. web-multiselect), and its own `--pc-border-radius*` as hardcoded 2/4/8px literals that ignored the base layer — so a `<keen-web-multiselect>` and a pure-css `.rounded` element rounded differently on the same theme, and a runtime `--base-border-radius-*` override moved the components but not pure-css's own elements. The `--pc-border-radius*` tokens now derive from `--base-border-radius-*` (`calc(var(--base-border-radius-md, 0.6) * 1rem)`), so radii match the components and one override re-rounds everything together. Rendered corners change slightly: small 2px→4px, medium 4px→6px, large unchanged.
11
20
 
12
- ## What's New in 1.0.0-rc05
13
-
14
- - **App shell — the navbar, sidebar, and layout container join the foundation** — pure-css has been variables + grid + utilities since the extraction; rc05 relocates the structural *app-shell* layer out of `@keenmate/pure-admin-core`, so a standalone page gets the same navbar/sidebar/layout chrome as a full admin app without pulling in the 40+ component library. Eight new partials (`_navbar.scss`, `_navbar-elements.scss`, `_sidebar.scss`, `_sidebar-states.scss`, `_layout-container.scss`, `_layout-responsive.scss`, `_resize-handle.scss`, `_fit-flyout.scss`) `@use` into the `pure-css.css` bundle — `base.css`, `grid.css` and `utilities.css` are untouched and there's no new CSS artifact. The emitted surface is `pc-`-branded like the rest of the foundation: the fixed navbar (`.pc-navbar` + `__start`/`__center`/`__end`, burger, brand `.pc-app-header`, `.pc-navmenu`, profile button, theme switcher), the nested sidebar with hidden/icon-collapse/expanded states and a drag-to-resize handle (`.pc-sidebar`, `.pc-layout__sidebar`, `.pc-sidebar-resize`), and the layout wrapper (`.pc-layout` + `__main`/`__content`/`__footer`) with mobile/tablet media queries. pure-admin-core now `@forward`s same-named partials instead of owning copies, so the shell is single-sourced here and can't drift.
15
- - **The shell now brings its own behaviour — pure-css is no longer CSS-only** — the shell's JavaScript ships with the foundation as a small, dependency-free runtime under `src/js/`, exposed as source (no build step) via a new `./js` export. `pure-css.js` installs `window.pureCss` — an event bus, live viewport / OS-colour-scheme / capability-first device sources, overlay primitives (scroll-lock, keyboard-inset), an open-menu registry, a shared `config` baseline single-sourced from the SCSS via `--pc-*` vars, and `components.initAll(scope)` — and the shell engines hang off it: `fit.js` (the `data-pc-fit` fit engine, which also absorbed the former `navbar-collapse.js` progressive nav-folding via `data-pc-fit-nav`, so that file no longer exists), `navbar-dropdown.js`, `sidebar-resize.js`, and `container-breakpoint.js`. The runtime is load-order-safe and stands alone when pure-admin is absent; the shell CSS is authored no-JS-safe, so styling degrades gracefully rather than breaking when the runtime isn't loaded.
16
- - **The grid's automatic responsive context now ships in the same bundle** — `_pa-grid.scss`'s container-query responsive columns (`.pc-col-md-*`, …) need a containment-context ancestor, documented as `.pc-layout__main`. That selector previously lived only in pure-admin-core, so the note was aspirational for a standalone pure-css page; with `_layout-container.scss` relocated into the bundle, `.pc-layout__main` is emitted here and the responsive variants get their context out of the box (the stale comment still read `.pa-layout__main` from before the rc04 de-brand — corrected to `.pc-layout__main`).
17
- - **Toolchain-free zip distribution via GitHub Releases** — a new `.github/workflows/release.yml` builds the CSS on every `v*.*.*` tag push and publishes a GitHub Release carrying `pure-css-<version>.zip` (the same file set as the npm package — `dist/`, `src/scss/`, `README.md`, `CHANGELOG.md`, `LICENSE`) plus a `.sha256` checksum, so consumers who don't use npm can vendor the built foundation as a drop-in. rc tags (those containing `-`) publish as GitHub pre-releases. Mirrors pure-admin-core's release workflow, adapted for this single-package repo.
18
-
19
21
  ## Why
20
22
 
21
23
  Any surface that isn't a full admin app — a docs site, a marketing page, a standalone widget host —
package/dist/css/base.css CHANGED
@@ -28,16 +28,21 @@
28
28
  --base-hover-bg: #e9ecef;
29
29
  --base-active-bg: rgb(85.5830753354%, 87.5490196078%, 89.5149638803%);
30
30
  --base-disabled-bg: #e9ecef;
31
- --base-elevated-bg: #f5f5f5;
31
+ --base-elevated-bg: #f8f9fa;
32
+ --base-text-inverted: #ffffff;
32
33
  --base-border-color: #e1e5e9;
33
34
  --base-border: 1px solid #e1e5e9;
35
+ --base-checkbox-border-color: #e1e5e9;
34
36
  --base-input-bg: #ffffff;
35
37
  --base-input-color: #495057;
36
38
  --base-input-border: 1px solid #ced4da;
39
+ --base-input-border-color: #ced4da;
37
40
  --base-input-border-hover: 1px solid #b8bfc6;
38
41
  --base-input-border-focus: 1px solid #007bff;
39
42
  --base-input-placeholder-color: #a3b1bf;
40
43
  --base-input-bg-disabled: rgba(255, 255, 255, 0.5);
44
+ --base-input-clear-color: #7a8a99;
45
+ --base-input-clear-bg-hover: #e9ecef;
41
46
  --base-input-size-xs-height: 3.1;
42
47
  --base-input-size-sm-height: 3.3;
43
48
  --base-input-size-md-height: 3.5;
@@ -48,7 +53,9 @@
48
53
  --base-dropdown-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
49
54
  --base-tooltip-bg: #2c3e50;
50
55
  --base-tooltip-text-color: #ffffff;
56
+ --base-tooltip-color: #ffffff;
51
57
  --base-success-color: #22c55e;
58
+ --base-success-bg: #22c55e;
52
59
  --base-success-color-hover: rgb(10.3896103896%, 60.1986249045%, 28.7242169595%);
53
60
  --base-success-bg-light: rgba(34, 197, 94, 0.1);
54
61
  --base-success-bg-subtle: rgba(34, 197, 94, 0.08);
@@ -57,6 +64,7 @@
57
64
  --base-success-text-light: #d4edda;
58
65
  --base-text-on-success: #ffffff;
59
66
  --base-danger-color: #ef4444;
67
+ --base-danger-bg: #ef4444;
60
68
  --base-danger-color-hover: rgb(92.1491355163%, 8.2430213465%, 8.2430213465%);
61
69
  --base-danger-bg-light: rgba(239, 68, 68, 0.1);
62
70
  --base-danger-bg-subtle: rgba(239, 68, 68, 0.08);
@@ -65,6 +73,7 @@
65
73
  --base-danger-text-light: #f8d7da;
66
74
  --base-text-on-danger: #ffffff;
67
75
  --base-warning-color: #f97316;
76
+ --base-warning-bg: #f97316;
68
77
  --base-warning-color-hover: rgb(84.1086225285%, 35.7371400443%, 2.1658872754%);
69
78
  --base-warning-bg-light: rgba(249, 115, 22, 0.1);
70
79
  --base-warning-bg-subtle: rgba(249, 115, 22, 0.08);
@@ -103,13 +112,14 @@
103
112
  --base-border-radius-sm: 0.4;
104
113
  --base-border-radius-md: 0.6;
105
114
  --base-border-radius-lg: 0.8;
115
+ --base-rem: 1rem;
106
116
  color-scheme: light;
107
- --pc-main-bg: #f8f9fa;
108
- --pc-page-bg: #f8f9fa;
109
- --pc-subtle-bg: #ffffff;
110
- --pc-text-color-1: #2c3e50;
111
- --pc-text-color-2: #6c757d;
112
- --pc-accent: #007bff;
117
+ --pc-main-bg: #ffffff;
118
+ --pc-page-bg: var(--base-page-bg, #f8f9fa);
119
+ --pc-subtle-bg: #e9ecef;
120
+ --pc-text-color-1: var(--base-text-color-1, #2c3e50);
121
+ --pc-text-color-2: var(--base-text-color-2, #6c757d);
122
+ --pc-accent: var(--base-accent-color, #007bff);
113
123
  --pc-accent-hover: rgba(0, 123, 255, 0.12);
114
124
  --pc-accent-light: color-mix(in srgb, var(--pc-accent) 5%, transparent);
115
125
  --pc-link-color: var(--pc-accent);
@@ -91,7 +91,7 @@ body {
91
91
  font-family: var(--base-font-family);
92
92
  font-size: 1.6rem;
93
93
  color: var(--pc-text-color-1);
94
- background-color: var(--pc-main-bg);
94
+ background-color: var(--pc-page-bg);
95
95
  line-height: 1.5;
96
96
  }
97
97
 
@@ -111,14 +111,14 @@ label {
111
111
  }
112
112
 
113
113
  *::-webkit-scrollbar-track {
114
- background: var(--pc-main-bg);
114
+ background: var(--pc-page-bg);
115
115
  border-radius: var(--pc-border-radius-sm);
116
116
  }
117
117
 
118
118
  *::-webkit-scrollbar-thumb {
119
119
  background: var(--pc-border-color);
120
120
  border-radius: var(--pc-border-radius-sm);
121
- border: 1px solid var(--pc-main-bg);
121
+ border: 1px solid var(--pc-page-bg);
122
122
  }
123
123
  *::-webkit-scrollbar-thumb:hover {
124
124
  background: var(--pc-accent);
@@ -128,13 +128,13 @@ label {
128
128
  }
129
129
 
130
130
  *::-webkit-scrollbar-corner {
131
- background: var(--pc-main-bg);
131
+ background: var(--pc-page-bg);
132
132
  }
133
133
 
134
134
  /* Firefox */
135
135
  * {
136
136
  scrollbar-width: thin;
137
- scrollbar-color: var(--pc-border-color) var(--pc-main-bg);
137
+ scrollbar-color: var(--pc-border-color) var(--pc-page-bg);
138
138
  }
139
139
 
140
140
  .pc-row {
@@ -2423,7 +2423,7 @@ body.loaded .pc-sidebar__link {
2423
2423
  width: calc(100% - 0.8rem * 2);
2424
2424
  margin: 0.8rem;
2425
2425
  height: 3.5rem;
2426
- padding: 0 1.6rem;
2426
+ padding: 0 1.6rem 0 0.8rem;
2427
2427
  color: var(--pc-text-color-2);
2428
2428
  background-color: var(--pc-input-bg, var(--base-input-bg));
2429
2429
  border: 1px solid var(--pc-border-color);
@@ -2442,7 +2442,7 @@ body.loaded .pc-sidebar__search {
2442
2442
  border-color: #007bff;
2443
2443
  color: var(--pc-sidebar-text, var(--base-text-color-1));
2444
2444
  }
2445
- .pc-layout__sidebar--icon-collapse .pc-sidebar__search {
2445
+ .sidebar-hidden .pc-layout__sidebar--icon-collapse .pc-sidebar__search {
2446
2446
  width: auto;
2447
2447
  margin: 0;
2448
2448
  padding: 0.8rem 1.6rem;
@@ -2486,10 +2486,10 @@ body.loaded .pc-sidebar__search {
2486
2486
  .pc-sidebar__search--input .pc-sidebar__search-field::-webkit-search-decoration, .pc-sidebar__search--input .pc-sidebar__search-field::-webkit-search-cancel-button {
2487
2487
  -webkit-appearance: none;
2488
2488
  }
2489
- .pc-layout__sidebar--icon-collapse .pc-sidebar__search--input {
2489
+ .sidebar-hidden .pc-layout__sidebar--icon-collapse .pc-sidebar__search--input {
2490
2490
  justify-content: center;
2491
2491
  }
2492
- .pc-layout__sidebar--icon-collapse .pc-sidebar__search--input .pc-sidebar__search-field {
2492
+ .sidebar-hidden .pc-layout__sidebar--icon-collapse .pc-sidebar__search--input .pc-sidebar__search-field {
2493
2493
  display: none;
2494
2494
  }
2495
2495
  .pc-sidebar__toggle {
@@ -2806,7 +2806,7 @@ body.pc-layout--sticky {
2806
2806
  .pc-layout {
2807
2807
  max-width: 100%;
2808
2808
  margin: 4.8rem auto 0;
2809
- background-color: var(--pc-main-bg);
2809
+ background-color: var(--pc-page-bg);
2810
2810
  overflow: visible;
2811
2811
  display: flex;
2812
2812
  flex-direction: column;
@@ -5961,16 +5961,21 @@ body.pc-layout--sticky .pc-layout__inner {
5961
5961
  --base-hover-bg: #e9ecef;
5962
5962
  --base-active-bg: rgb(85.5830753354%, 87.5490196078%, 89.5149638803%);
5963
5963
  --base-disabled-bg: #e9ecef;
5964
- --base-elevated-bg: #f5f5f5;
5964
+ --base-elevated-bg: #f8f9fa;
5965
+ --base-text-inverted: #ffffff;
5965
5966
  --base-border-color: #e1e5e9;
5966
5967
  --base-border: 1px solid #e1e5e9;
5968
+ --base-checkbox-border-color: #e1e5e9;
5967
5969
  --base-input-bg: #ffffff;
5968
5970
  --base-input-color: #495057;
5969
5971
  --base-input-border: 1px solid #ced4da;
5972
+ --base-input-border-color: #ced4da;
5970
5973
  --base-input-border-hover: 1px solid #b8bfc6;
5971
5974
  --base-input-border-focus: 1px solid #007bff;
5972
5975
  --base-input-placeholder-color: #a3b1bf;
5973
5976
  --base-input-bg-disabled: rgba(255, 255, 255, 0.5);
5977
+ --base-input-clear-color: #7a8a99;
5978
+ --base-input-clear-bg-hover: #e9ecef;
5974
5979
  --base-input-size-xs-height: 3.1;
5975
5980
  --base-input-size-sm-height: 3.3;
5976
5981
  --base-input-size-md-height: 3.5;
@@ -5981,7 +5986,9 @@ body.pc-layout--sticky .pc-layout__inner {
5981
5986
  --base-dropdown-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
5982
5987
  --base-tooltip-bg: #2c3e50;
5983
5988
  --base-tooltip-text-color: #ffffff;
5989
+ --base-tooltip-color: #ffffff;
5984
5990
  --base-success-color: #22c55e;
5991
+ --base-success-bg: #22c55e;
5985
5992
  --base-success-color-hover: rgb(10.3896103896%, 60.1986249045%, 28.7242169595%);
5986
5993
  --base-success-bg-light: rgba(34, 197, 94, 0.1);
5987
5994
  --base-success-bg-subtle: rgba(34, 197, 94, 0.08);
@@ -5990,6 +5997,7 @@ body.pc-layout--sticky .pc-layout__inner {
5990
5997
  --base-success-text-light: #d4edda;
5991
5998
  --base-text-on-success: #ffffff;
5992
5999
  --base-danger-color: #ef4444;
6000
+ --base-danger-bg: #ef4444;
5993
6001
  --base-danger-color-hover: rgb(92.1491355163%, 8.2430213465%, 8.2430213465%);
5994
6002
  --base-danger-bg-light: rgba(239, 68, 68, 0.1);
5995
6003
  --base-danger-bg-subtle: rgba(239, 68, 68, 0.08);
@@ -5998,6 +6006,7 @@ body.pc-layout--sticky .pc-layout__inner {
5998
6006
  --base-danger-text-light: #f8d7da;
5999
6007
  --base-text-on-danger: #ffffff;
6000
6008
  --base-warning-color: #f97316;
6009
+ --base-warning-bg: #f97316;
6001
6010
  --base-warning-color-hover: rgb(84.1086225285%, 35.7371400443%, 2.1658872754%);
6002
6011
  --base-warning-bg-light: rgba(249, 115, 22, 0.1);
6003
6012
  --base-warning-bg-subtle: rgba(249, 115, 22, 0.08);
@@ -6036,13 +6045,14 @@ body.pc-layout--sticky .pc-layout__inner {
6036
6045
  --base-border-radius-sm: 0.4;
6037
6046
  --base-border-radius-md: 0.6;
6038
6047
  --base-border-radius-lg: 0.8;
6048
+ --base-rem: 1rem;
6039
6049
  color-scheme: light;
6040
- --pc-main-bg: #f8f9fa;
6041
- --pc-page-bg: #f8f9fa;
6042
- --pc-subtle-bg: #ffffff;
6043
- --pc-text-color-1: #2c3e50;
6044
- --pc-text-color-2: #6c757d;
6045
- --pc-accent: #007bff;
6050
+ --pc-main-bg: #ffffff;
6051
+ --pc-page-bg: var(--base-page-bg, #f8f9fa);
6052
+ --pc-subtle-bg: #e9ecef;
6053
+ --pc-text-color-1: var(--base-text-color-1, #2c3e50);
6054
+ --pc-text-color-2: var(--base-text-color-2, #6c757d);
6055
+ --pc-accent: var(--base-accent-color, #007bff);
6046
6056
  --pc-accent-hover: rgba(0, 123, 255, 0.12);
6047
6057
  --pc-accent-light: color-mix(in srgb, var(--pc-accent) 5%, transparent);
6048
6058
  --pc-link-color: var(--pc-accent);
@@ -80,7 +80,7 @@ body {
80
80
  font-family: var(--base-font-family);
81
81
  font-size: 1.6rem;
82
82
  color: var(--pc-text-color-1);
83
- background-color: var(--pc-main-bg);
83
+ background-color: var(--pc-page-bg);
84
84
  line-height: 1.5;
85
85
  }
86
86
 
@@ -5,14 +5,14 @@
5
5
  }
6
6
 
7
7
  *::-webkit-scrollbar-track {
8
- background: var(--pc-main-bg);
8
+ background: var(--pc-page-bg);
9
9
  border-radius: var(--pc-border-radius-sm);
10
10
  }
11
11
 
12
12
  *::-webkit-scrollbar-thumb {
13
13
  background: var(--pc-border-color);
14
14
  border-radius: var(--pc-border-radius-sm);
15
- border: 1px solid var(--pc-main-bg);
15
+ border: 1px solid var(--pc-page-bg);
16
16
  }
17
17
  *::-webkit-scrollbar-thumb:hover {
18
18
  background: var(--pc-accent);
@@ -22,11 +22,11 @@
22
22
  }
23
23
 
24
24
  *::-webkit-scrollbar-corner {
25
- background: var(--pc-main-bg);
25
+ background: var(--pc-page-bg);
26
26
  }
27
27
 
28
28
  /* Firefox */
29
29
  * {
30
30
  scrollbar-width: thin;
31
- scrollbar-color: var(--pc-border-color) var(--pc-main-bg);
31
+ scrollbar-color: var(--pc-border-color) var(--pc-page-bg);
32
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keenmate/pure-css",
3
- "version": "1.0.0-rc06",
3
+ "version": "1.0.0-rc07",
4
4
  "description": "The KeenMate CSS foundation — --base-* theming contract, PureCSS grid and utility classes. Extracted from pure-admin-core so docs sites, standalone pages and every web/svelte component share one theming layer.",
5
5
  "style": "dist/css/pure-css.css",
6
6
  "exports": {
@@ -47,18 +47,25 @@
47
47
  --base-disabled-bg: #{$base-disabled-bg};
48
48
  --base-elevated-bg: #{$base-elevated-bg};
49
49
 
50
+ // === Text on inverse surfaces ===
51
+ --base-text-inverted: #{$base-text-inverted};
52
+
50
53
  // === Border Colors ===
51
54
  --base-border-color: #{$base-border-color};
52
55
  --base-border: #{$base-border};
56
+ --base-checkbox-border-color: #{$base-checkbox-border-color};
53
57
 
54
58
  // === Input Fields ===
55
59
  --base-input-bg: #{$base-input-bg};
56
60
  --base-input-color: #{$base-input-color};
57
61
  --base-input-border: #{$base-input-border};
62
+ --base-input-border-color: #{$base-input-border-color};
58
63
  --base-input-border-hover: #{$base-input-border-hover};
59
64
  --base-input-border-focus: #{$base-input-border-focus};
60
65
  --base-input-placeholder-color: #{$base-input-placeholder-color};
61
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};
62
69
 
63
70
  // === Input Size Heights ===
64
71
  --base-input-size-xs-height: #{$base-input-size-xs-height};
@@ -75,9 +82,11 @@
75
82
  // === Tooltip ===
76
83
  --base-tooltip-bg: #{$base-tooltip-bg};
77
84
  --base-tooltip-text-color: #{$base-tooltip-text-color};
85
+ --base-tooltip-color: #{$base-tooltip-text-color}; // alias consumed by web-grid
78
86
 
79
87
  // === Contextual Colors - Success ===
80
88
  --base-success-color: #{$base-success-color};
89
+ --base-success-bg: #{$base-success-bg};
81
90
  --base-success-color-hover: #{$base-success-color-hover};
82
91
  --base-success-bg-light: #{$base-success-bg-light};
83
92
  --base-success-bg-subtle: #{$base-success-bg-subtle};
@@ -88,6 +97,7 @@
88
97
 
89
98
  // === Contextual Colors - Danger ===
90
99
  --base-danger-color: #{$base-danger-color};
100
+ --base-danger-bg: #{$base-danger-bg};
91
101
  --base-danger-color-hover: #{$base-danger-color-hover};
92
102
  --base-danger-bg-light: #{$base-danger-bg-light};
93
103
  --base-danger-bg-subtle: #{$base-danger-bg-subtle};
@@ -98,6 +108,7 @@
98
108
 
99
109
  // === Contextual Colors - Warning ===
100
110
  --base-warning-color: #{$base-warning-color};
111
+ --base-warning-bg: #{$base-warning-bg};
101
112
  --base-warning-color-hover: #{$base-warning-color-hover};
102
113
  --base-warning-bg-light: #{$base-warning-bg-light};
103
114
  --base-warning-bg-subtle: #{$base-warning-bg-subtle};
@@ -144,6 +155,9 @@
144
155
  --base-border-radius-sm: #{$base-border-radius-sm};
145
156
  --base-border-radius-md: #{$base-border-radius-md};
146
157
  --base-border-radius-lg: #{$base-border-radius-lg};
158
+
159
+ // === Rem base for web components ===
160
+ --base-rem: #{$base-rem};
147
161
  }
148
162
 
149
163
  // ============================================================================
@@ -209,17 +223,20 @@
209
223
  // to the `.pc-mode-dark` block.
210
224
  color-scheme: #{$theme-color-scheme};
211
225
 
212
- // Surfaces
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.
213
230
  --pc-main-bg: #{$main-bg};
214
- --pc-page-bg: #{$page-bg};
231
+ --pc-page-bg: var(--base-page-bg, #{$page-bg});
215
232
  --pc-subtle-bg: #{$subtle-bg};
216
233
 
217
- // Text
218
- --pc-text-color-1: #{$text-color-1};
219
- --pc-text-color-2: #{$text-color-2};
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});
220
237
 
221
238
  // Accent — -light derives from --pc-accent at runtime so theme overrides cascade.
222
- --pc-accent: #{$accent-color};
239
+ --pc-accent: var(--base-accent-color, #{$accent-color});
223
240
  --pc-accent-hover: #{$accent-hover};
224
241
  --pc-accent-light: color-mix(in srgb, var(--pc-accent) 5%, transparent);
225
242
 
@@ -335,6 +352,14 @@
335
352
  // LAYOUT COLORS
336
353
  // =========================================================================
337
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
+
338
363
  // Navbar
339
364
  --pc-navbar-bg: #{$navbar-bg};
340
365
  --pc-navbar-border-color: #{$navbar-border-color};
@@ -360,10 +385,10 @@
360
385
  // =========================================================================
361
386
 
362
387
  // Primary (uses accent color)
363
- --pc-btn-primary-bg: #{$btn-primary-bg};
364
- --pc-btn-primary-bg-hover: #{$btn-primary-bg-hover};
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});
365
390
  --pc-btn-primary-bg-light: color-mix(in srgb, var(--pc-btn-primary-bg) 5%, transparent);
366
- --pc-btn-primary-text: #{$btn-primary-text};
391
+ --pc-btn-primary-text: var(--base-text-color-on-accent, #{$btn-primary-text});
367
392
 
368
393
  // Secondary
369
394
  --pc-btn-secondary-bg: #{$btn-secondary-bg};
@@ -373,28 +398,28 @@
373
398
 
374
399
  // Success — bg references role colour for runtime cascade
375
400
  --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};
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});
378
403
 
379
404
  // Danger — bg references role colour for runtime cascade
380
405
  --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};
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});
383
408
 
384
409
  // Warning — bg references role colour for runtime cascade
385
410
  --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};
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});
388
413
 
389
414
  // Info — bg references role colour for runtime cascade
390
415
  --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};
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});
393
418
 
394
419
  // 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};
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});
398
423
 
399
424
  // Dark
400
425
  --pc-btn-dark-bg: #{$btn-dark-bg};
@@ -408,81 +433,81 @@
408
433
  // --pc-{success,danger,warning,info}-text live in the base contract.)
409
434
  // =========================================================================
410
435
  --pc-success-bg: var(--pc-success);
411
- --pc-success-bg-hover: #{$success-bg-hover};
436
+ --pc-success-bg-hover: var(--base-success-color-hover, #{$success-bg-hover});
412
437
  --pc-success-bg-light: color-mix(in srgb, var(--pc-success) 10%, transparent);
413
438
  --pc-success-bg-subtle: color-mix(in srgb, var(--pc-success) 8%, transparent);
414
439
  --pc-success-border: color-mix(in srgb, var(--pc-success) 20%, transparent);
415
- --pc-success-text-light: #{$success-text-light};
440
+ --pc-success-text-light: var(--base-success-text-light, #{$success-text-light});
416
441
 
417
442
  --pc-danger-bg: var(--pc-danger);
418
- --pc-danger-bg-hover: #{$danger-bg-hover};
443
+ --pc-danger-bg-hover: var(--base-danger-color-hover, #{$danger-bg-hover});
419
444
  --pc-danger-bg-light: color-mix(in srgb, var(--pc-danger) 10%, transparent);
420
445
  --pc-danger-bg-subtle: color-mix(in srgb, var(--pc-danger) 8%, transparent);
421
446
  --pc-danger-border: color-mix(in srgb, var(--pc-danger) 20%, transparent);
422
- --pc-danger-text-light: #{$danger-text-light};
447
+ --pc-danger-text-light: var(--base-danger-text-light, #{$danger-text-light});
423
448
 
424
449
  --pc-warning-bg: var(--pc-warning);
425
- --pc-warning-bg-hover: #{$warning-bg-hover};
450
+ --pc-warning-bg-hover: var(--base-warning-color-hover, #{$warning-bg-hover});
426
451
  --pc-warning-bg-light: color-mix(in srgb, var(--pc-warning) 10%, transparent);
427
452
  --pc-warning-bg-subtle: color-mix(in srgb, var(--pc-warning) 8%, transparent);
428
453
  --pc-warning-border: color-mix(in srgb, var(--pc-warning) 20%, transparent);
429
- --pc-warning-text-light: #{$warning-text-light};
454
+ --pc-warning-text-light: var(--base-warning-text-light, #{$warning-text-light});
430
455
 
431
456
  --pc-info-bg: var(--pc-info);
432
- --pc-info-bg-hover: #{$info-bg-hover};
457
+ --pc-info-bg-hover: var(--base-info-color-hover, #{$info-bg-hover});
433
458
  --pc-info-bg-light: color-mix(in srgb, var(--pc-info) 10%, transparent);
434
459
  --pc-info-bg-subtle: color-mix(in srgb, var(--pc-info) 8%, transparent);
435
460
  --pc-info-border: color-mix(in srgb, var(--pc-info) 20%, transparent);
436
- --pc-info-text-light: #{$info-text-light};
461
+ --pc-info-text-light: var(--base-info-text-light, #{$info-text-light});
437
462
 
438
463
  // =========================================================================
439
464
  // CARD COLORS
440
465
  // =========================================================================
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};
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});
445
470
 
446
471
  // =========================================================================
447
472
  // INPUT/FORM COLORS
448
473
  // =========================================================================
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};
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});
463
488
  --pc-checkbox-checkmark-color: #{$checkbox-checkmark-color};
464
489
  --pc-checkbox-focus-shadow: #{$checkbox-focus-shadow};
465
490
 
466
- // Input group
491
+ // Input group (prepend/append bg are the secondary grey — compile-time)
467
492
  --pc-input-group-prepend-bg: #{$input-group-prepend-bg};
468
- --pc-input-group-prepend-text: #{$input-group-prepend-text};
493
+ --pc-input-group-prepend-text: var(--base-text-color-2, #{$input-group-prepend-text});
469
494
  --pc-input-group-append-bg: #{$input-group-append-bg};
470
- --pc-input-group-append-text: #{$input-group-append-text};
495
+ --pc-input-group-append-text: var(--base-text-color-2, #{$input-group-append-text});
471
496
 
472
497
  // =========================================================================
473
498
  // TABLE COLORS
474
499
  // =========================================================================
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};
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});
480
505
 
481
506
  // =========================================================================
482
507
  // MODAL COLORS
483
508
  // =========================================================================
484
- --pc-modal-overlay-bg: #{$modal-overlay-bg};
485
- --pc-modal-content-bg: #{$modal-content-bg};
509
+ --pc-modal-overlay-bg: var(--base-overlay-bg, #{$modal-overlay-bg});
510
+ --pc-modal-content-bg: var(--base-main-bg, #{$modal-content-bg});
486
511
 
487
512
  // =========================================================================
488
513
  // BADGE COLORS
@@ -505,9 +530,9 @@
505
530
  // =========================================================================
506
531
  // TOOLTIP & POPOVER COLORS
507
532
  // =========================================================================
508
- --pc-tooltip-bg: #{$tooltip-bg};
509
- --pc-tooltip-text: #{$tooltip-text};
510
- --pc-popover-content-bg: #{$popover-content-bg};
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});
511
536
  --pc-popover-text-light: #{$popover-text-light};
512
537
  --pc-popover-text-dark: #{$popover-text-dark};
513
538
 
@@ -536,22 +561,22 @@
536
561
  --pc-command-palette-item-active-bg: #{$command-palette-item-active-bg};
537
562
  --pc-command-palette-highlight-bg: #{$command-palette-highlight-bg};
538
563
  --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};
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});
541
566
  --pc-command-palette-key-font-size: #{$font-size-xs};
542
567
  --pc-command-palette-key-font-weight: #{$font-weight-semibold};
543
568
 
544
569
  // =========================================================================
545
570
  // MULTISELECT COLORS
546
571
  // =========================================================================
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};
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});
555
580
 
556
581
  // =========================================================================
557
582
  // FORM SPACING — the complete anatomy of a form's spacing. Runtime-tunable;
@@ -14,7 +14,7 @@ body.pc-layout--sticky {
14
14
  .pc-layout {
15
15
  max-width: 100%;
16
16
  margin: $navbar-height auto 0;
17
- background-color: var(--pc-main-bg);
17
+ background-color: var(--pc-page-bg);
18
18
  overflow: visible; // Allow tooltips to escape
19
19
  display: flex;
20
20
  flex-direction: column;
@@ -191,11 +191,13 @@ body.pc-layout--sticky .pc-layout__sidebar {
191
191
  // Sized on the md input height (35px) to match the navbar search boxes,
192
192
  // rather than the icon + $sidebar-padding metric of a nav row (40px). Trade-off:
193
193
  // it sits ~5px shorter than the links below it. Block padding is dropped (fixed
194
- // height + align-items:center owns the vertical); inline uses $spacing-base
195
- // (the inline half of the two-value $sidebar-padding don't pass that token to
196
- // a single axis).
194
+ // height + align-items:center owns the vertical).
195
+ // Inline padding: right = $spacing-base (the nav-row inset); left = $spacing-sm
196
+ // so that margin ($spacing-sm) + padding-left ($spacing-sm) = $spacing-base —
197
+ // landing the magnifier exactly where the nav-row icons below it sit, instead
198
+ // of one box-margin too far in.
197
199
  height: #{$base-input-size-md-height}rem;
198
- padding: 0 $spacing-base;
200
+ padding: 0 $spacing-base 0 $spacing-sm;
199
201
  color: var(--pc-text-color-2);
200
202
  background-color: var(--pc-input-bg, var(--base-input-bg));
201
203
  border: $border-width-base solid var(--pc-border-color);
@@ -219,9 +221,13 @@ body.pc-layout--sticky .pc-layout__sidebar {
219
221
  color: var(--pc-sidebar-text, var(--base-text-color-1));
220
222
  }
221
223
 
222
- // Collapsed sidebar: drop the frame, icon-only, matching link padding so the
223
- // icon lands in the same column as every other sidebar icon.
224
- .pc-layout__sidebar--icon-collapse & {
224
+ // Collapsed rail ONLY (icon-collapse mode AND actually collapsed, i.e.
225
+ // body.sidebar-hidden): drop the frame, icon-only, matching link padding so
226
+ // the icon lands in the same column as every other sidebar icon. Must be
227
+ // gated by .sidebar-hidden — .pc-layout__sidebar--icon-collapse is the MODE
228
+ // class and stays on the element while the rail is expanded, so an unscoped
229
+ // rule would strip the search frame in the expanded state too.
230
+ .sidebar-hidden .pc-layout__sidebar--icon-collapse & {
225
231
  width: auto;
226
232
  margin: 0;
227
233
  padding: $sidebar-padding;
@@ -283,9 +289,11 @@ body.pc-layout--sticky .pc-layout__sidebar {
283
289
  }
284
290
  }
285
291
 
286
- // Collapsed rail: the input variant sheds its field and centres on the submit
287
- // icon; clicking it submits with an empty query (the bare results page).
288
- .pc-layout__sidebar--icon-collapse &--input {
292
+ // Collapsed rail ONLY: the input variant sheds its field and centres on the
293
+ // submit icon; clicking it submits with an empty query (the bare results
294
+ // page). Gated by .sidebar-hidden so the field reappears when the icon-collapse
295
+ // rail is expanded (see frame rule above for why the mode class isn't enough).
296
+ .sidebar-hidden .pc-layout__sidebar--icon-collapse &--input {
289
297
  justify-content: center;
290
298
 
291
299
  .pc-sidebar__search-field {
@@ -119,7 +119,7 @@ body {
119
119
  font-family: var(--base-font-family);
120
120
  font-size: 1.6rem; // 16px default text (with 10px rem base)
121
121
  color: var(--pc-text-color-1);
122
- background-color: var(--pc-main-bg);
122
+ background-color: var(--pc-page-bg);
123
123
  line-height: $line-height-base;
124
124
  }
125
125
 
@@ -19,14 +19,14 @@
19
19
  }
20
20
 
21
21
  *::-webkit-scrollbar-track {
22
- background: var(--pc-main-bg);
22
+ background: var(--pc-page-bg);
23
23
  border-radius: var(--pc-border-radius-sm);
24
24
  }
25
25
 
26
26
  *::-webkit-scrollbar-thumb {
27
27
  background: var(--pc-border-color);
28
28
  border-radius: var(--pc-border-radius-sm);
29
- border: $border-width-base solid var(--pc-main-bg);
29
+ border: $border-width-base solid var(--pc-page-bg);
30
30
 
31
31
  &:hover {
32
32
  background: var(--pc-accent);
@@ -38,11 +38,11 @@
38
38
  }
39
39
 
40
40
  *::-webkit-scrollbar-corner {
41
- background: var(--pc-main-bg);
41
+ background: var(--pc-page-bg);
42
42
  }
43
43
 
44
44
  /* Firefox */
45
45
  * {
46
46
  scrollbar-width: thin;
47
- scrollbar-color: var(--pc-border-color) var(--pc-main-bg);
47
+ scrollbar-color: var(--pc-border-color) var(--pc-page-bg);
48
48
  }
@@ -43,7 +43,12 @@ $base-subtle-bg: #e9ecef !default; // Muted areas, dividers
43
43
  $base-inverse-bg: #2c3e50 !default; // Inverse background (tooltips, dark elements)
44
44
  $base-overlay-bg: rgba(0, 0, 0, 0.5) !default; // Modal/overlay background
45
45
  $base-shadow-color: rgba(0, 0, 0, 0.15) !default; // Shadow color for elevation
46
- $base-elevated-bg: #f5f5f5 !default; // Header row, striped rows, elevated surfaces
46
+ // Elevated surface (header rows, striped rows, popovers/toolbars). Defaults to
47
+ // the page background so the default theme's header appearance is unchanged, but
48
+ // themes can override it independently to create a distinct raised tone.
49
+ $base-elevated-bg: $base-page-bg !default;
50
+ // Text on inverse/dark surfaces (web-component bridge: --base-text-inverted).
51
+ $base-text-inverted: #ffffff !default;
47
52
 
48
53
  // Interactive state backgrounds
49
54
  $base-hover-bg: $base-subtle-bg !default; // Hover state background
@@ -57,6 +62,8 @@ $base-disabled-bg: $base-subtle-bg !default; // Disabled element background
57
62
 
58
63
  $base-border-color: #e1e5e9 !default;
59
64
  $base-border: 1px solid $base-border-color !default;
65
+ // Checkbox/radio border (web-component bridge: --base-checkbox-border-color).
66
+ $base-checkbox-border-color: $base-border-color !default;
60
67
 
61
68
  // =============================================================================
62
69
  // INPUT FIELDS
@@ -65,11 +72,20 @@ $base-border: 1px solid $base-border-color !default;
65
72
 
66
73
  $base-input-bg: $base-main-bg !default;
67
74
  $base-input-color: #495057 !default;
68
- $base-input-border: 1px solid #ced4da !default;
75
+ // Input border as a colour (single source) + the 1px shorthand web components
76
+ // read via --base-input-border. Note: pure-admin's own inputs currently border
77
+ // off --base-border-color (#e1e5e9), not this (#ced4da) — a deliberate divergence
78
+ // kept to preserve appearance; see _colors.scss $input-border.
79
+ $base-input-border-color: #ced4da !default;
80
+ $base-input-border: 1px solid $base-input-border-color !default;
69
81
  $base-input-border-hover: 1px solid #b8bfc6 !default;
70
82
  $base-input-border-focus: 1px solid $base-accent-color !default;
71
83
  $base-input-placeholder-color: $base-text-color-4 !default;
72
84
  $base-input-bg-disabled: rgba($base-input-bg, 0.5) !default;
85
+ // Inline clear ("×") affordance inside inputs (web-component bridge:
86
+ // --base-input-clear-color / --base-input-clear-bg-hover).
87
+ $base-input-clear-color: $base-text-color-3 !default;
88
+ $base-input-clear-bg-hover: $base-hover-bg !default;
73
89
 
74
90
  // Input size heights (unitless multipliers for x10px base)
75
91
  $base-input-size-xs-height: 3.1 !default; // 31px
@@ -101,6 +117,7 @@ $base-tooltip-text-color: #ffffff !default;
101
117
  // =============================================================================
102
118
 
103
119
  $base-success-color: #22c55e !default; // Tailwind green-500 — aligns with --pc-positive in the sentiment scale
120
+ $base-success-bg: $base-success-color !default; // Solid role fill (web-component bridge: --base-success-bg)
104
121
  $base-success-color-hover: color.adjust($base-success-color, $lightness: -10%) !default;
105
122
  $base-success-bg-light: rgba($base-success-color, 0.1) !default;
106
123
  $base-success-bg-subtle: rgba($base-success-color, 0.08) !default;
@@ -115,6 +132,7 @@ $base-text-on-success: #ffffff !default;
115
132
  // =============================================================================
116
133
 
117
134
  $base-danger-color: #ef4444 !default; // Tailwind red-500 — aligns with --pc-negative in the sentiment scale
135
+ $base-danger-bg: $base-danger-color !default; // Solid role fill (web-component bridge: --base-danger-bg)
118
136
  $base-danger-color-hover: color.adjust($base-danger-color, $lightness: -10%) !default;
119
137
  $base-danger-bg-light: rgba($base-danger-color, 0.1) !default;
120
138
  $base-danger-bg-subtle: rgba($base-danger-color, 0.08) !default;
@@ -129,6 +147,7 @@ $base-text-on-danger: #ffffff !default;
129
147
  // =============================================================================
130
148
 
131
149
  $base-warning-color: #f97316 !default; // Tailwind orange-500 — also serves as the off-target axis in KPI components
150
+ $base-warning-bg: $base-warning-color !default; // Solid role fill (web-component bridge: --base-warning-bg)
132
151
  $base-warning-color-hover: color.adjust($base-warning-color, $lightness: -10%) !default;
133
152
  $base-warning-bg-light: rgba($base-warning-color, 0.1) !default;
134
153
  $base-warning-bg-subtle: rgba($base-warning-color, 0.08) !default;
@@ -210,6 +229,11 @@ $base-border-radius-sm: 0.4 !default; // 4px
210
229
  $base-border-radius-md: 0.6 !default; // 6px
211
230
  $base-border-radius-lg: 0.8 !default; // 8px
212
231
 
232
+ // Rem base for web components (bridge: --base-rem). They size themselves as
233
+ // `calc(<unitless-multiplier> * var(--base-rem, 10px))`. pure-css pins
234
+ // `html { font-size: 10px }` (reboot), so `1rem` tracks that base adaptively.
235
+ $base-rem: 1rem !default;
236
+
213
237
  // =============================================================================
214
238
  // COMPONENT-SPECIFIC DERIVED VALUES
215
239
  // Variables that components need, derived from base
@@ -12,9 +12,12 @@
12
12
  // LAYOUT COLORS (derived from base)
13
13
  // =============================================================================
14
14
 
15
- $main-bg: $base-page-bg !default;
15
+ // Surface tokens aligned with --base-*: main = the primary/raised surface (white),
16
+ // page = the canvas behind it (grey), subtle = a muted tone. (Previously main was
17
+ // wired to the page grey and subtle to white — an inversion vs --base-*.)
18
+ $main-bg: $base-main-bg !default;
16
19
  $page-bg: $base-page-bg !default;
17
- $subtle-bg: $base-main-bg !default;
20
+ $subtle-bg: $base-subtle-bg !default;
18
21
  $text-color-1: $base-text-color-1 !default;
19
22
  $text-color-2: $base-text-color-2 !default;
20
23
  $border-color: $base-border-color !default;
@@ -48,27 +51,30 @@ $accent-light: $base-accent-color-light !default;
48
51
  // CARD COLORS (derived from base surfaces)
49
52
  // =============================================================================
50
53
 
54
+ // Body surfaces → main-bg; header/tab chrome → elevated-bg (defaults to page-bg,
55
+ // so unchanged by default; themeable independently). Reconciled so these resolve
56
+ // to the same base tokens the web components read.
51
57
  $card-bg: $base-main-bg !default;
52
- $card-header-bg: $base-page-bg !default;
58
+ $card-header-bg: $base-elevated-bg !default;
53
59
  $card-footer-bg: $base-main-bg !default;
54
- $card-tabs-bg: $base-page-bg !default;
60
+ $card-tabs-bg: $base-elevated-bg !default;
55
61
 
56
62
  // =============================================================================
57
63
  // INPUT COLORS (derived from base input vars)
58
64
  // =============================================================================
59
65
 
60
66
  $input-bg: $base-input-bg !default;
61
- $input-border: #ced4da !default; // Extracted from base-input-border
67
+ $input-border: $base-input-border-color !default; // single-sourced from base (was hardcoded #ced4da)
62
68
  $input-text: $base-input-color !default;
63
69
 
64
70
  // =============================================================================
65
71
  // TABLE COLORS (derived from base surfaces)
66
72
  // =============================================================================
67
73
 
68
- $table-stripe: $base-page-bg !default;
74
+ $table-stripe: $base-elevated-bg !default; // striped/elevated rows → elevated-bg (= page-bg default)
69
75
  $table-bg: $base-main-bg !default;
70
- $table-header-bg: $base-page-bg !default;
71
- $table-hover-bg: $base-page-bg !default;
76
+ $table-header-bg: $base-elevated-bg !default; // header chrome → elevated-bg (= page-bg default)
77
+ $table-hover-bg: $base-hover-bg !default; // RECONCILED: was page-bg; now the shared hover surface
72
78
 
73
79
  // Table row hover accent (border)
74
80
  $table-hover-accent-width: 0 !default;
@@ -177,7 +183,7 @@ $tooltip-text: $base-tooltip-text-color !default;
177
183
 
178
184
  $popover-text-light: #ffffff !default;
179
185
  $popover-text-dark: #000000 !default;
180
- $popover-content-bg: $base-main-bg !default;
186
+ $popover-content-bg: $base-dropdown-bg !default; // floating surface → dropdown-bg (= main-bg default)
181
187
 
182
188
  // =============================================================================
183
189
  // CODE LANGUAGE COLORS (standalone - not themed)
@@ -276,7 +276,7 @@ $form-group-margin-compact: 1.2rem !default; // 12px (was 0.75rem)
276
276
  // Custom checkbox appearance (tri-state support)
277
277
  $checkbox-border-radius: $border-radius !default; // Match input border-radius
278
278
  $checkbox-border-width: $border-width-base !default; // 1px
279
- $checkbox-border-color: $border-color !default; // Default border
279
+ $checkbox-border-color: $base-checkbox-border-color !default; // reconciled: shared checkbox-border knob (= border-color default)
280
280
  $checkbox-border-color-hover: $accent-color !default; // Hover border
281
281
  $checkbox-border-color-checked: $accent-color !default; // Checked border
282
282
  $checkbox-bg: $card-bg !default; // Unchecked background
@@ -291,17 +291,17 @@ $checkbox-transition: $transition-fast !default;
291
291
  // ============================================================================
292
292
  $multiselect-input-padding-v: $input-padding-v !default;
293
293
  $multiselect-input-padding-h: $input-padding-h !default;
294
- $multiselect-dropdown-bg: $card-bg !default;
294
+ $multiselect-dropdown-bg: $base-dropdown-bg !default; // reconciled: floating surface → dropdown-bg (= main-bg default)
295
295
  $multiselect-dropdown-border: $border-color !default;
296
296
  $multiselect-dropdown-text: $text-color-1 !default;
297
297
  $multiselect-dropdown-shadow: $shadow-lg !default;
298
298
  $multiselect-dropdown-max-height: 32rem !default; // 320px (was 20rem)
299
- $multiselect-hint-bg: $main-bg !default;
299
+ $multiselect-hint-bg: $page-bg !default; // canvas tone (was $main-bg, which is now the white surface)
300
300
  $multiselect-hint-border: $border-color !default;
301
301
  $multiselect-hint-padding: $spacing-sm !default;
302
302
  $multiselect-option-padding-v: $spacing-sm !default;
303
303
  $multiselect-option-padding-h: $spacing-md !default;
304
- $multiselect-option-hover-bg: $main-bg !default;
304
+ $multiselect-option-hover-bg: $base-hover-bg !default; // RECONCILED: was main-bg; now the shared hover surface
305
305
  $multiselect-pill-bg: $accent-light !default;
306
306
  $multiselect-pill-border: $accent-color !default;
307
307
  $multiselect-pill-padding: $spacing-xs $spacing-sm !default;