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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,411 +1,491 @@
1
- # Changelog
2
-
3
- All notable changes to `@keenmate/pure-css` are documented here. Format based on
4
- [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
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
-
76
- ## [1.0.0-rc06] 2026-08-30
77
-
78
- ### Fixed
79
-
80
- - **The app shell now renders standalone — component `--pc-*` tokens fall back to
81
- `--base-*`.** rc05 relocated the shell into the foundation, but its CSS
82
- hard-referenced component tokens (`--pc-navbar-bg`, `--pc-sidebar-*`,
83
- `--pc-footer-*`, `--pc-card-bg`, `--pc-input-bg`) that pure-css does **not**
84
- emit those are pure-admin's `output-pc-component-variables` contract. So a
85
- consumer linking `base.css` / `pure-css.css` alone (keen-docs hit this) got an
86
- unstyled navbar/sidebar. Every such reference now carries a `--base-*` fallback
87
- traced from the token's own derivation: `var(--pc-navbar-bg, var(--base-main-bg))`,
88
- `var(--pc-sidebar-bg, var(--base-page-bg))`, navbar/sidebar text
89
- `--base-text-color-1/2`, borders `--base-border-color`, submenu surfaces
90
- `--base-subtle-bg`, input → `--base-input-bg`. This makes `--pc-*` an *optional*
91
- override layer over a guaranteed `--base-*` floorlink only the base vars and
92
- the shell just works; set `--pc-navbar-bg` to tune the bar independently of the
93
- page. 40 references across the eight shell partials.
94
- - **Dangling token references in `_fit-flyout.scss`.** The fit-flyout trigger
95
- referenced `--pc-accent-color` (defined nowhere the token is `--pc-accent`)
96
- with no fallback, so its focus outline was inert; and `--pc-hover-bg` (also
97
- undefined) with only an rgba literal. Repointed to
98
- `var(--pc-accent, var(--base-accent-color))` and
99
- `var(--pc-hover-bg, var(--base-hover-bg, rgba(…)))`.
100
-
101
- ### Changed
102
-
103
- - **Unified the `--pc-border-radius*` scale with the `--base-border-radius-*`
104
- contract the components already use.** pure-css shipped two disconnected radius
105
- systems: `--base-border-radius-sm/md/lg` (the unitless rem-multipliers
106
- `0.4/0.6/0.8` every web/svelte component reads — e.g. web-multiselect's
107
- `calc(var(--base-border-radius-md) * --ms-rem)`), and its OWN
108
- `--pc-border-radius-sm/base/lg` as hardcoded `2px/4px/8px` literals disconnected
109
- from the base layer. On one themed page a `<keen-web-multiselect>` and a pure-css
110
- `.rounded` element rounded differently, and a runtime `--base-border-radius-*`
111
- override re-rounded the components but not pure-css's own elements. The three
112
- `--pc-border-radius*` tokens now derive from the base contract
113
- `calc(var(--base-border-radius-{sm,md,lg}, <default>) * 1rem)` (unsuffixed
114
- `--pc-border-radius` = the `-md` mid step) mirroring how `--pc-border-color`
115
- already tracked `--base-border-color`. **Rendered radii change** to match the
116
- ecosystem: `-sm` 2px 4px, mid 4px 6px, `-lg` 8px (unchanged). Overriding
117
- `--base-border-radius-*` now re-rounds pure-css and the components together.
118
-
119
- ## [1.0.0-rc05] 2026-08-27 [PUBLISHED]
120
-
121
- ### Added
122
-
123
- - **The app shell moves into the foundation navbar, sidebar, and layout
124
- container.** pure-css was variables + grid + utilities; rc05 also relocates the
125
- structural app-shell layer out of pure-admin-core, so a standalone page (docs
126
- site, portal) gets the same navbar/sidebar/layout chrome as a full pure-admin
127
- app without pulling in the component library. Seven new partials, all `@use`d
128
- into the `pure-css.css` **bundle only** (base.css / grid.css / utilities.css
129
- untouched; no new standalone artifact):
130
- - `_navbar.scss` + `_navbar-elements.scss` the fixed navbar (`.pc-navbar`
131
- with `__inner`/`__start`/`__center`/`__end` regions) and its elements (burger
132
- menu, brand wordmark `.pc-app-header`, nav menu `.pc-navmenu`, page title
133
- `.pc-page-header`, profile button, theme switcher).
134
- - `_sidebar.scss` + `_sidebar-states.scss` the sidebar nav with nested
135
- submenus (`.pc-sidebar`, `.pc-layout__sidebar`, drag-to-resize
136
- `.pc-sidebar-resize`) and its hidden / icon-collapse / expanded states.
137
- - `_layout-container.scss` — the layout wrapper (`.pc-layout` with
138
- `__inner`/`__main`/`__content`/`__footer` and the `.pc-footer__*` regions),
139
- including sticky/scroll content modes. Emitting `.pc-layout__main` here also
140
- gives the grid's container-query responsive columns (`.pc-col-md-*`) their
141
- documented automatic containment context in the same bundle (the
142
- `_pa-grid.scss` note is corrected from the pre-rc04 `.pa-layout__main` to
143
- `.pc-layout__main`).
144
- - `_layout-responsive.scss` — the mobile/tablet media queries for the shell.
145
- - `_resize-handle.scss` — a mixin-only partial (emits nothing on its own)
146
- providing the shared grab-knob look `@use`d by the sidebar resize handle and
147
- splitter gutters.
148
- - `_fit-flyout.scss` the Fit engine's floating-menu sink
149
- (`.pc-fit-flyout__*`): a `•••` trigger + a `<body>`-parented panel that
150
- `fit.js` fills on demand when slots relocate out of the row.
151
-
152
- pure-admin-core keeps same-named partials that now just `@forward` these, so the
153
- shell is single-sourced in the foundation and the two can't drift.
154
-
155
- - **The shell's behaviour ships too — a dependency-free JS runtime (`src/js/`).**
156
- The shell is no longer styling-only: the foundation now carries the vanilla-JS
157
- runtime that drives it, so pure-css is no longer a CSS-only package. Shipped
158
- **as source** (no build step) via a new `./js` export (and `./js/*` for
159
- individual engines); `files` gains `src/js/`.
160
- - `pure-css.js` installs the `window.pureCss` namespacea tiny event bus,
161
- live viewport / OS-colour-scheme / capability-first device sources, overlay
162
- primitives (scroll-lock, keyboard-inset), an open-menu registry, a shared
163
- `config` baseline (single-sourced from SCSS via `--pc-*` vars), and
164
- `components.initAll(scope)`. Load-order-safe and stands alone when pure-admin
165
- is absent; `pure-admin.js` adopts the same buses by reference on top.
166
- - `fit.js` the Fit engine (`data-pc-fit` = hide / steps / relocate). It
167
- **absorbs the former `navbar-collapse.js`** (progressive nav folding via
168
- `data-pc-fit-nav`, sinking items to the sidebar or a generated "More" menu),
169
- so that separate file no longer exists.
170
- - `navbar-dropdown.js` (tap-toggle nav dropdowns/submenus),
171
- `sidebar-resize.js` (drag-to-resize the sidebar), and
172
- `container-breakpoint.js` (container-query breakpoint driver).
173
-
174
- Shell CSS is authored no-JS-safe, so styling degrades gracefully rather than
175
- breaking when the runtime isn't loaded.
176
-
177
- ### Fixed
178
-
179
- - **Migrated the dead `data-pa-nav-collapse` hook to `data-pc-fit-nav`.** The
180
- relocated nav-collapse CSS keyed on the pre-rc04 `pa-`-branded
181
- `[data-pa-nav-collapse]` attribute driven by the old `navbar-collapse.js`;
182
- since that engine is now merged into `fit.js` (which reads `data-pc-fit-nav`),
183
- the selectors in `_navbar-elements.scss` / `_layout-responsive.scss` were stale
184
- and matched nothing. Repointed at `[data-pc-fit-nav]` and corrected the
185
- companion comments (`navbar-collapse.js` `fit.js`). Also de-branded the fit
186
- hide-class `.pa-fit-hidden` `.pc-fit-hidden`.
187
-
188
- ### Internal
189
-
190
- - **GitHub Actions release workflow (`.github/workflows/release.yml`).** On a `v*.*.*`
191
- tag push, builds the CSS (`npm ci` + `npm run build`) and publishes a GitHub Release
192
- with a `pure-css-<version>.zip` (bundling `dist/`, `src/scss/`, `README.md`,
193
- `CHANGELOG.md`, `LICENSE` the same set as the package `files`, so the zip is a
194
- toolchain-free drop-in for consumers who don't use npm) plus a `.sha256` checksum.
195
- Auto-generated release notes; tags containing `-` (rc) publish as a pre-release.
196
- Mirrors pure-admin-core's release workflow, adapted for this single-package repo.
197
- - **Exhaustive, data-driven utilities e2e coverage.** Rewrote `e2e/utilities.spec.ts`
198
- from a handful of spot-checks into a hard value assertion for 655 of the 664 shipped
199
- utility classes (the 9 `auto` sizing classes `m-auto` + per-side, `w-auto`, `h-auto` —
200
- are layout-resolved and covered behaviourally instead). Each family measures every one
201
- of its classes' computed styles in a single in-browser pass, then diffs in Node so a
202
- failure lists exactly which classes are off; the expectations independently encode the
203
- 10px-rem contract and the documented scales rather than reading them back from the CSS,
204
- so a failure means the compiled output disagrees with the contract or the contract
205
- regressed. Renamed the fixture `test/utilities.html` → `test/utilities-scale.html` with
206
- definite-size `#w-parent` / `#h-parent` containers so percentage widths/heights resolve
207
- to known px. Test-only no change to shipped CSS.
208
-
209
- ## [1.0.0-rc04] 2026-08-26 [PUBLISHED]
210
-
211
- ### Changed (BREAKING)
212
-
213
- - **pure-css now ships only the BASE token contract — component tokens moved to
214
- the consumer that owns the components.** pure-css is a *foundation*: its
215
- bundles (`pure-css.css`, `base.css`) now emit only the ~46 base `--pc-*` tokens
216
- its own CSS consumes or exposes as universal theming primitives (surfaces,
217
- text, accent, links, border, the semantic role identities + their utility text
218
- colours, the theme palette slots, the radius scale). The ~165 **component**
219
- tokens (`--pc-btn-*`, `--pc-card-*`, `--pc-table-*`, `--pc-alert-*`, badges,
220
- tooltips, panels, command palette, multiselect, sentiment scale, form spacing,
221
- the derived contextual surfaces, admin layout chrome) are no longer emitted by
222
- the foundation. They are pure-admin's contract.
223
- - `output-pc-css-variables` is now base-only. The component tokens are emitted
224
- by the new **`output-pc-component-variables`** mixin (+ the existing
225
- `output-pc-alert-variables-{light,dark}`), which pure-css still *defines*
226
- (they read the shared `$`-variable vocabulary in `variables/*`, so they must
227
- be authored where that vocabulary is in scope) but does **not** call from its
228
- own bundle. Consumers that ship the components pure-admin core, every
229
- theme opt in by `@include output-pc-component-variables` alongside
230
- `output-pc-css-variables`.
231
- - **Theme authors / anyone calling the emit mixins must add
232
- `@include output-pc-component-variables;`** (after `output-pc-css-variables`)
233
- or lose every component token. Consumers of the *compiled* theme/core CSS are
234
- unaffected — the emitted token set is identical, just split across two mixins.
235
- - **Every emitted CSS variable de-branded from `--pa-*` to `--pc-*`.** pure-css is
236
- a *foundation*, but it still emitted its entire runtime custom-property surface
237
- under pure-admin's `pa` brand. The full `--pa-*` set (~210 vars: `--pa-accent`,
238
- `--pa-text-color-*`, `--pa-card-bg`, `--pa-border-*`, the contextual /alert sets,
239
- `--pa-color-1..9` + `-text`, the new `--pc-*` form-spacing family already shipped
240
- this cut, etc.) is renamed to `--pc-*`. This completes the same de-branding the
241
- grid/mode classes started above nothing pure-admin-branded remains in the
242
- foundation's output.
243
- - **The emit mixins move too:** `output-pa-css-variables` `output-pc-css-variables`,
244
- `output-pa-alert-variables-light` / `-dark` `output-pc-alert-variables-*`.
245
- (`output-base-css-variables` is unchanged `--base-*` is a separate, neutral
246
- web-component contract and stays.)
247
- - **Untouched:** `--base-*` (web-component bridge), `--page-loader-*` (pre-FOUC
248
- loader), and the `.pa-color-{name}` colour-variant **class** (a class, not a
249
- `--pa-` variable).
250
- - **Migration:** a boundary-aware replace of the string `--pa-` → `--pc-` across
251
- markup, stylesheets, inline `style="--pa-…"`, JS `getPropertyValue`/`setProperty`
252
- calls, and every theme's `:root` / dark-mode `--pa-*` override block. Safe
253
- because the leading `--` + trailing `-` can't match `--base-*` or `--page-loader-*`.
254
- pure-admin, its demo, all 16 themes, and the svelte/keen wrappers migrate in
255
- lockstep with this release.
256
- - **Grid classes renamed from the consumer-branded `pa-` to the foundation's own
257
- `pc-` prefix.** `.pa-row` → `.pc-row`, `.pa-col*` → `.pc-col*` (all percentage /
258
- fraction / responsive / `--grow`/`--shrink`/`--no-padding` variants),
259
- `.pa-offset*` `.pc-offset*`, `.pa-cq` `.pc-cq`, `.pa-hide*` → `.pc-hide*`,
260
- `.pa-show*` → `.pc-show*`. The grid is a pure-css *foundation* primitive, so it
261
- should not carry pure-admin's (`pa`) brand this de-couples it. **No dual-emit:**
262
- the old `pa-*` grid classes are gone. Consumers must migrate markup
263
- (`class="pa-col-1-2"` `class="pc-col-1-2"`) a boundary-aware find/replace
264
- (careful: `pa-col` is a substring of `pa-color-*`, which must NOT be touched).
265
- pure-admin, its demo, and the svelte/keen wrappers are migrated in lockstep.
266
- - **Light/dark mode scope classes renamed `.pa-mode-*` → `.pc-mode-*`.**
267
- The light/dark scopes the foundation emits its variables against (and that apps
268
- toggle on `<body>`) are foundation-owned, so they move to the `pc-` prefix too.
269
- `output-pc-css-variables` now emits at `:root, .pc-mode-light, .pc-mode-dark`.
270
- Consumers toggling the class in JS (`classList.add('pc-mode-dark')`) and themes'
271
- dark-mode blocks migrate in lockstep. (Safe replace: the string `pa-mode-`
272
- `pc-mode-`; `pa-modal` is untouched since `mode` `moda`.)
273
-
274
- ### Added
275
-
276
- - **Sizing utilities consolidated into the foundation.** The universal sizing/flex
277
- utilities that had been left in pure-admin now live here, so a standalone
278
- pure-css page has the full set: viewport heights `h-full` / `h-screen` /
279
- `min-h-full` / `min-h-screen` / `max-h-full` / `max-h-screen`, and the
280
- Tailwind-style flex shorthands `flex-1` / `flex-auto` / `flex-initial` /
281
- `flex-none` / `flex-grow` / `flex-shrink` (alongside the existing
282
- `flex-grow-0/1`, `flex-shrink-0/1`). pure-css already owned the width/height %
283
- + rem scales (`w-*`/`h-*`, `wr-*`/`hr-*`) and the full min/max families
284
- (`minw-*`/`maxh-*`/`minwr-*`/`maxhr-*`/…); pure-admin's duplicate rem-height
285
- `h-Nx`/`min-h-Nx`/`max-h-Nx` set (byte-identical to `hr-N`/`minhr-N`/`maxhr-N`)
286
- is retired in favour of the foundation's `hr-`/`wr-` naming (`r` = rem).
287
- - **Complete form-spacing contract as runtime CSS variables, under a pure-css-owned
288
- `--pc-` namespace.** `output-pc-css-variables` now emits the full anatomy of a
289
- form's spacing at `:root`, so every consumer (pure-admin, keen-docs,
290
- keen-pure-admin) shares one contract instead of re-declaring `var()` chains or
291
- being stuck with compile-time-only margins:
292
- - Vertical rhythm: `--pc-label-gap` (label → control), `--pc-help-gap`
293
- (control help/error), `--pc-field-gap` (field field),
294
- `--pc-form-actions-offset` (last field actions row).
295
- - Inline gaps: `--pc-form-gap` (shared + label↔inline-icon), `--pc-choice-gap`
296
- (between options), `--pc-choice-inner-gap` (control↔label), `--pc-form-actions-gap`
297
- (between buttons), `--pc-field-horizontal-gap` (horizontal label col↔input col).
298
-
299
- The inline "gap" family chains to `--pc-form-gap` (one knob moves them all);
300
- every var is also overridable on its own scope. These are the first
301
- foundation-owned runtime vars to use `--pc-` rather than the legacy
302
- consumer-branded `--pa-` prefix — new foundation tokens should follow suit.
303
-
304
- ### Changed
305
-
306
- - **Renamed the misleading `$form-scale` token to `$form-gap`.** It reads like an
307
- input-sizing multiplier but is only ever consumed as a `gap:` value the small
308
- gap between adjacent form bits (a label and its inline icon, footer action
309
- buttons, checkbox/radio group options). `$form-scale` is kept as a `!default`
310
- alias of `$form-gap`, so existing overrides keep working; it will be retired in
311
- a major. (pure-admin reads the gap through `var(--pc-form-gap, …)`, so it is
312
- also runtime-tunable.)
313
-
314
- ## [1.0.0-rc03] 2026-08-21 [PUBLISHED]
315
-
316
- ### Changed
317
-
318
- - **BREAKING renamed the top-bar region tokens from `header` to `navbar`.** The
319
- foundation's top-region tokens named the bar as a *component block* rather than a
320
- layout region, which read as misleading once pure-admin's navbar component dropped its
321
- legacy `pa-header__*` block naming. Renamed:
322
- - SCSS variables: `$header-height` → `$navbar-height`, `$header-bg` → `$navbar-bg`,
323
- `$header-border-color` `$navbar-border-color`, `$header-text` → `$navbar-text`,
324
- `$header-text-secondary` → `$navbar-text-secondary`,
325
- `$header-profile-name-color` `$navbar-profile-name-color`,
326
- `$z-index-header` `$z-index-navbar`.
327
- - CSS variables: `--pa-header-bg` `--pa-navbar-bg`,
328
- `--pa-header-border-color` `--pa-navbar-border-color`,
329
- `--pa-header-text` → `--pa-navbar-text`,
330
- `--pa-header-text-secondary` → `--pa-navbar-text-secondary`,
331
- `--pa-header-profile-name-color` `--pa-navbar-profile-name-color`.
332
- - `$footer-height` still mirrors the bar height (now `$navbar-height`); component-header
333
- tokens (`$card-header-*`, `$table-header-*`) are unaffected.
334
-
335
- ### Removed
336
-
337
- - **Dead `$header-brand-padding-left` variable.** Superseded by the navbar's flex `gap`;
338
- no live rule consumed it (only a stale comment referenced it).
339
-
340
- ## [1.0.0-rc02] 2026-08-05 [PUBLISHED]
341
-
342
- ### Added
343
-
344
- - **Reboot layer (`reboot.scss`) the reset the foundation always assumed.** Emits
345
- `html { font-size: 10px }` (the 10px rem base every pure-css rem value is authored
346
- against — `$font-size-base: 1.6rem` is 16px *only* at a 10px root), a `box-sizing:
347
- border-box` reset, neutral base styling for standard elements (headings, paragraphs,
348
- links, lists, blockquotes, `hr`, `figure`), the `body` font/colour/background, and the
349
- `button/input/select/textarea/label { font: inherit }` reset. Relocated from
350
- pure-admin-core's `core-components/_base.scss` so it sits with the rem-scale variables
351
- that depend on it. Analogous to Bootstrap's Reboot.
352
- - **New `reboot.css` build artifact** + `./reboot` export, and `reboot` is now part of the
353
- `pure-css.css` bundle (emitted before grid/utilities).
354
- - **Themed scrollbars (`scrollbars.scss`).** The global `*::-webkit-scrollbar` + Firefox
355
- `scrollbar-width`/`scrollbar-color` styling (thin scrollbars coloured from the `--pa-*`
356
- cascade), relocated from pure-admin-core's `core-components/_scrollbars.scss`. Global browser
357
- chrome belongs with the foundation's consistent-appearance promise, so a standalone pure-css
358
- page gets the same themed scrollbars as a full pure-admin app instead of native ones. Part of
359
- the `pure-css.css` bundle, plus a standalone `scrollbars.css` artifact + `./scrollbars` export.
360
-
361
- ### Fixed
362
-
363
- - **Standalone consumers no longer render 1.6× too large.** Before, the 10px base lived
364
- only in pure-admin-core, so a page linking `pure-css.css` (or `base.css`) on its own
365
- inherited the browser's 16px root and every rem was 1.6× oversized. The bundle now ships
366
- the 10px base itself, so the sizing scale is correct out of the box.
367
-
368
- ## [1.0.0-rc01] 2026-08-04
369
-
370
- Initial extraction of the CSS foundation out of `@keenmate/pure-admin-core`.
371
-
372
- ### Fixed
373
-
374
- - **Border/rounded utilities now resolve (were inert).** `.border` / `.border-{top,right,bottom,left}`
375
- and `.rounded` / `.rounded-{lg,top,…}` referenced bare `--border-color` / `--border-radius`
376
- variables the framework never emits — so they fell back to a `currentColor` border and no radius
377
- (a latent bug inherited from pure-admin-core). Repointed them at the emitted `--pa-border-color` /
378
- `--pa-border-radius(-lg)` (themed from `--base-*`). Now `base.css` + `utilities.css` are
379
- **self-sufficient** the border/radius utilities work standalone, no host shim.
380
- - **`--pa-border-color` is now a live reference** emitted as `var(--base-border-color, <literal>)`
381
- instead of a baked literal (it's a pure pass-through, no derivation lost). So it and the `.border`
382
- utilities that read it follow a **runtime** `--base-border-color` override (a theme or dark-mode
383
- class toggling it at `:root`/`.pa-mode-dark`), not just build-time themes.
384
-
385
- ### Added
386
-
387
- - **`--base-*` theming contract** `src/scss/variables/*` (the `$base-*` source of truth plus the
388
- derived typography/spacing/colors/layout/system/components modules) and
389
- `_base-css-variables.scss` (the mixin emitting `--base-*` and derived `--pa-*` custom properties).
390
- - **Native flexbox grid** `_pa-grid.scss` (`.pa-row` / `.pa-col`: percentage columns in 5%
391
- increments, intuitive fractions, container-query responsive variants, offsets, visibility helpers),
392
- relocated from pure-admin-core's `core-components/_grid.scss`. Replaces the legacy PureCSS
393
- `.pure-g` / `.pure-u-*` grid, which pure-admin had already stopped using — so pure-css ships the
394
- grid consumers actually use, not the deprecated one.
395
- - **Utilities** — `utilities.scss` (spacing / flex / display / width-height classes) plus the generic
396
- `.font-family-system/-sans/-serif/-mono` classes from `_fonts.scss` (core keeps `_fonts.scss`
397
- standalone; here it `@use`s into utilities so all foundation utilities ship together). Adds
398
- `.gap-*` / `.gap-x-*` / `.gap-y-*` (flex/grid gap, same `$spacers` scale) the one spacing family
399
- core lacked, needed to express flex layouts with utilities.
400
- - **Build entries & artifacts** `pure-css.scss` (full bundle), `base.scss` (variables only),
401
- `grid.scss` (grid only), and the existing `utilities.scss`, compiled to
402
- `dist/css/{pure-css,base,grid,utilities}.css`. `dist/` is committed for toolchain-free vendoring.
403
- - Package tooling: `package.json` (`@keenmate/pure-css`, `exports` for `.`/`./base`/`./grid`/
404
- `./utilities`/`./scss`), `Makefile`, `README`, this changelog.
405
-
406
- ### Notes
407
-
408
- - **pure-admin-core consumes this package** as its single source for the foundation (thin
409
- `@import`/`@forward` shims for the variables, `--base-*`/`--pa-*` emit mixins, utilities, and the
410
- grid). The two no longer carry duplicate copies, so compiled `--base-*` values and grid output
411
- match core's `dist/css/main.css` exactly.
1
+ # Changelog
2
+
3
+ All notable changes to `@keenmate/pure-css` are documented here. Format based on
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
+
6
+ ## [1.0.0-rc08] — 2026-09-10 [PUBLISHED]
7
+
8
+ The **foundation-only + coherent-contract** release. rc08 finishes what rc07
9
+ started: pure-css sheds pure-admin's component vocabulary to become a true
10
+ foundation, the `--base-*` contract is cleaned up into a coherent, fully-named
11
+ token API, a shared themeable icon layer lands, and the default palette is
12
+ rebased onto pure-admin **Corporate**. The canonical `--base-*` list now lives in
13
+ the parent package [`@keenmate/base-css-variables`](https://www.npmjs.com/package/@keenmate/base-css-variables);
14
+ pure-css mirrors it and a drift guard keeps the two honest.
15
+
16
+ ### ⚠ Breaking
17
+
18
+ - **The `--pc-*` component layer moved to `@keenmate/pure-admin-core`.** pure-css
19
+ no longer ships `variables/_components.scss` or emits the component token
20
+ mixins (`output-pc-component-variables`, `output-pc-component-mode-variables`,
21
+ `output-pc-alert-variables-{light,dark}`) — the whole buttons / cards / tables /
22
+ modals / tabs / alerts / badges / panels / command-palette / multiselect /
23
+ sentiment / form-spacing vocabulary. pure-css is now **foundation-only**: the
24
+ `--base-*` bridge plus the base `--pc-*` tokens (surfaces, text, accent, links,
25
+ border, the semantic role identities, the theme palette slots, the radius
26
+ scale). Anything that relied on pure-css emitting component `--pc-*` tokens must
27
+ now take them from **pure-admin-core ≥ 2.9.0-rc20**, which owns the mixins and
28
+ the `$`-vocabulary. Consumers of the compiled `dist/css/*` are unaffected; only
29
+ SCSS consumers that `@include`d the component mixins need the core bump.
30
+
31
+ ### Added
32
+
33
+ - **A shared, themeable icon contract — 13 `--base-icon-*` tokens.** `chevron`,
34
+ `caret-down`, `caret-up`, `close`, `clear`, `remove`, `expand`, `collapse`,
35
+ `add`, `edit`, `delete`, `search` (Lucide defaults), emitted as percent-encoded
36
+ SVG data-URIs meant to be painted via `mask` + `background: currentColor`. One
37
+ `--base-icon-*` override re-skins the shell, pure-admin components, and the web
38
+ components together. The dismiss family (`close`/`clear`/`remove`) cascades off
39
+ `--base-icon-close`; the CRUD family (`add`/`edit`/`delete`) reads as distinct
40
+ verbs (delete is a trash bin, not an ✕). Two disclosure models are documented:
41
+ chevron **rotates one glyph**, expand/collapse **swaps two**.
42
+ - **A coherent `--base-*` token API (WS7).** `--base-border-width`; the
43
+ `--base-primary-*` role set as aliases of accent; `--base-secondary-color(-hover)`
44
+ + `--base-text-on-secondary`; `--base-text-on-{primary,danger,success,warning,info}`
45
+ (the `text-on-<role>` convention); `--base-info-bg` (role symmetry); the brand
46
+ palette `--base-color-1..9` (+ `-text`), aliased by `--pc-color-N`; and the
47
+ non-colour scales `--base-space-*`, `--base-shadow-{sm,md,lg}`,
48
+ `--base-duration-*` + `--base-ease-*`, and `--base-z-*`.
49
+ - **`--pc-hover-bg` / `--pc-active-bg`** base tokens, so component hover/active
50
+ states read a dedicated interaction-state axis instead of borrowing the
51
+ recessed `--base-subtle-bg` surface.
52
+ - **`component-reset` a Shadow-DOM reset entry** (`./component-reset`,
53
+ `dist/css/component-reset.css`). The counterpart to `reboot` for web components:
54
+ a `:host` box-sizing + inherited-typography reset pinned to `--base-*` so a host
55
+ page can't bleed into a component's shadow root. Sets no `rem` base; pair with
56
+ `base`. This brings the build to **7 artifacts**.
57
+
58
+ ### Changed
59
+
60
+ - **Default theme rebased onto pure-admin Corporate.** `$base-*` defaults now
61
+ track Corporate accent `#0ea5e9`, slate text/surfaces, role hues emerald /
62
+ red / amber / cyan and the palette is sourced from `$base-color-1..9`. This
63
+ changes pure-css's **un-themed default look**; themed apps are unaffected since
64
+ every theme sets its own `--base-*`. (Verified: of the reconciled defaults, only
65
+ `--base-input-border-color` the one un-owned token — shifts themed output.)
66
+ - **`--base-disabled-bg`** given its own distinct value (`#f1f3f5`) instead of
67
+ colliding with the hover/subtle surface.
68
+ - **The shell chevrons are now SVG masks, not a `›` text glyph.** The sidebar
69
+ collapse chevron and the navbar "more" chevron render `--base-icon-chevron` via
70
+ a mask box (rotated on open); the `fit.js` injectors emit empty spans painted by
71
+ CSS.
72
+
73
+ ### Removed
74
+
75
+ - Dead `--pc-multiselect-*` and the simple `--pc-badge-*` tokens (web-multiselect
76
+ themes off its own `--ms-*` namespace; badges read `--pc-btn-*` / `--pc-color-*`).
77
+
78
+ ### Internal
79
+
80
+ - **`@keenmate/base-css-variables` is the canonical `--base-*` parent.** pure-css
81
+ mirrors its token list into `$base-*` SCSS; `scripts/check-base-parity.mjs`
82
+ fails the build if the emitted `--base-*` names drift from the contract (4 dead
83
+ tokens allow-listed). Going-forward rule: author a new `--base-*` token in
84
+ base-css-variables first, then mirror it here.
85
+
86
+ ## [1.0.0-rc07] 2026-09-08 [PUBLISHED]
87
+
88
+ The **shared theming knob** release. Before rc07 the same visual token (a tooltip
89
+ background, an input border, a dropdown surface) was produced *twice and
90
+ independently* pure-admin's `--pc-*` component tokens were baked compile-time
91
+ literals, while the KeenMate web components read `--base-*` liveso they agreed
92
+ only by coincidence and diverged the instant a theme retuned `--base-*` at
93
+ runtime (every dual-mode theme does exactly this at `.pc-mode-dark`). rc07 makes
94
+ `--base-*` the single runtime knob: override one namespace and pure-admin
95
+ components + the web components re-theme together, in light and dark.
96
+
97
+ ### Added
98
+
99
+ - **Gap `--base-*` tokens the web components already read but pure-css never
100
+ emitted** — so they stop falling through to hardcoded component defaults and
101
+ actually theme: `--base-text-inverted`, `--base-checkbox-border-color`,
102
+ `--base-input-border-color` (+ the `--base-input-border` shorthand),
103
+ `--base-input-clear-color` / `--base-input-clear-bg-hover`, the solid role
104
+ fills `--base-success-bg` / `--base-danger-bg` / `--base-warning-bg`, and
105
+ `--base-rem`.
106
+
107
+ ### Changed
108
+
109
+ - **`--pc-*` component tokens now derive from `--base-*` at runtime.** ~40 themed
110
+ `--pc-*` tokens (buttons, cards, inputs, checkbox, input groups, tables, modal,
111
+ tooltip/popover, command palette, multiselect) were rewritten from baked
112
+ `#{$…}` literals to the guiding-rule form `var(--base-x, #{$fallback})`. The
113
+ `#{$fallback}` preserves today's compiled value, so **light-mode output is
114
+ unchanged** but the token now follows any runtime `--base-*` override, shared
115
+ with the web components.
116
+ - **The app shell surfaces stay compile-time deliberately not `--base-*`-derived.**
117
+ The navbar/sidebar/footer surface + text tokens (`--pc-navbar-*`,
118
+ `--pc-sidebar-*`, `--pc-footer-*`) are emitted as plain `#{$…}` literals, *not*
119
+ `var(--base-main-bg, …)`. The shell is a distinct brand surface a theme sets on
120
+ its own (e.g. a yellow navbar) independent of the `--base-*` card/page palette;
121
+ since `--base-main-bg` is always emitted, deriving the navbar from it would let
122
+ the base palette win and erase the brand colour. Standalone (`base.css`-only)
123
+ rendering is still covered the shell CSS itself resolves
124
+ `var(--pc-navbar-bg, var(--base-main-bg))`, so the `--base-*` floor applies only
125
+ when no `--pc-*` is emitted (the rc06 contract), not as a runtime override of it.
126
+ - **Surface-token naming realigned with the `--base-*` model (B5).**
127
+ `--pc-main-bg` is now the **white surface** (`--base-main-bg`), `--pc-subtle-bg`
128
+ the **muted grey** (`--base-subtle-bg`), and `--pc-page-bg` remains the **grey
129
+ canvas**. Previously `--pc-main-bg` *was* the grey canvas and `--pc-subtle-bg`
130
+ *was* white an inversion vs the `--base-*` vocabulary. pure-css's own shell
131
+ canvas usages (reboot `body`, `.pc-layout`, scrollbars) were repointed
132
+ `--pc-main-bg` `--pc-page-bg` so the canvas stays grey. **Downstream code
133
+ reading `--pc-main-bg` / `--pc-subtle-bg` must re-check intent** — see
134
+ pure-admin-core rc19, which repoints its component surfaces accordingly.
135
+ - `$base-elevated-bg` default changed from the stray `#f5f5f5` to `$base-page-bg`.
136
+
137
+ ### Fixed
138
+
139
+ - **Broken `$`-link:** `$input-border` was a hardcoded `#ced4da` (the comment even
140
+ claimed it came from base) reconnected to `$base-input-border-color`, so input
141
+ borders finally track the theme.
142
+ - **Semantic surface reconciliation** so pure-admin and the web components resolve
143
+ the *same* base token per surface: card/table headers + striped rows →
144
+ `--base-elevated-bg`, dropdown/popover `--base-dropdown-bg`, table/multiselect
145
+ hover `--base-hover-bg`, checkbox border `--base-checkbox-border-color`.
146
+ - **Sidebar search box alignment + collapsed-rail gating (`_sidebar.scss`).** The
147
+ search input's inline padding was rebalanced to `0 $spacing-base 0 $spacing-sm`
148
+ so its magnifier lines up with the nav-row icons below it (margin `$spacing-sm` +
149
+ padding-left `$spacing-sm` = the `$spacing-base` nav inset) instead of sitting one
150
+ box-margin too far in. The collapsed-rail rules that shed the search frame/field
151
+ down to the submit icon were re-scoped from `.pc-layout__sidebar--icon-collapse`
152
+ to `.sidebar-hidden .pc-layout__sidebar--icon-collapse` the mode class stays on
153
+ the element while the rail is expanded, so the unscoped rules were stripping the
154
+ search frame in the expanded state too.
155
+
156
+ ## [1.0.0-rc06] 2026-08-30
157
+
158
+ ### Fixed
159
+
160
+ - **The app shell now renders standalone component `--pc-*` tokens fall back to
161
+ `--base-*`.** rc05 relocated the shell into the foundation, but its CSS
162
+ hard-referenced component tokens (`--pc-navbar-bg`, `--pc-sidebar-*`,
163
+ `--pc-footer-*`, `--pc-card-bg`, `--pc-input-bg`) that pure-css does **not**
164
+ emit those are pure-admin's `output-pc-component-variables` contract. So a
165
+ consumer linking `base.css` / `pure-css.css` alone (keen-docs hit this) got an
166
+ unstyled navbar/sidebar. Every such reference now carries a `--base-*` fallback
167
+ traced from the token's own derivation: `var(--pc-navbar-bg, var(--base-main-bg))`,
168
+ `var(--pc-sidebar-bg, var(--base-page-bg))`, navbar/sidebar text
169
+ `--base-text-color-1/2`, borders `--base-border-color`, submenu surfaces
170
+ `--base-subtle-bg`, input → `--base-input-bg`. This makes `--pc-*` an *optional*
171
+ override layer over a guaranteed `--base-*` floor — link only the base vars and
172
+ the shell just works; set `--pc-navbar-bg` to tune the bar independently of the
173
+ page. 40 references across the eight shell partials.
174
+ - **Dangling token references in `_fit-flyout.scss`.** The fit-flyout trigger
175
+ referenced `--pc-accent-color` (defined nowhere — the token is `--pc-accent`)
176
+ with no fallback, so its focus outline was inert; and `--pc-hover-bg` (also
177
+ undefined) with only an rgba literal. Repointed to
178
+ `var(--pc-accent, var(--base-accent-color))` and
179
+ `var(--pc-hover-bg, var(--base-hover-bg, rgba(…)))`.
180
+
181
+ ### Changed
182
+
183
+ - **Unified the `--pc-border-radius*` scale with the `--base-border-radius-*`
184
+ contract the components already use.** pure-css shipped two disconnected radius
185
+ systems: `--base-border-radius-sm/md/lg` (the unitless rem-multipliers
186
+ `0.4/0.6/0.8` every web/svelte component reads — e.g. web-multiselect's
187
+ `calc(var(--base-border-radius-md) * --ms-rem)`), and its OWN
188
+ `--pc-border-radius-sm/base/lg` as hardcoded `2px/4px/8px` literals disconnected
189
+ from the base layer. On one themed page a `<keen-web-multiselect>` and a pure-css
190
+ `.rounded` element rounded differently, and a runtime `--base-border-radius-*`
191
+ override re-rounded the components but not pure-css's own elements. The three
192
+ `--pc-border-radius*` tokens now derive from the base contract —
193
+ `calc(var(--base-border-radius-{sm,md,lg}, <default>) * 1rem)` (unsuffixed
194
+ `--pc-border-radius` = the `-md` mid step) mirroring how `--pc-border-color`
195
+ already tracked `--base-border-color`. **Rendered radii change** to match the
196
+ ecosystem: `-sm` 2px → 4px, mid 4px 6px, `-lg` 8px (unchanged). Overriding
197
+ `--base-border-radius-*` now re-rounds pure-css and the components together.
198
+
199
+ ## [1.0.0-rc05]2026-08-27 [PUBLISHED]
200
+
201
+ ### Added
202
+
203
+ - **The app shell moves into the foundation navbar, sidebar, and layout
204
+ container.** pure-css was variables + grid + utilities; rc05 also relocates the
205
+ structural app-shell layer out of pure-admin-core, so a standalone page (docs
206
+ site, portal) gets the same navbar/sidebar/layout chrome as a full pure-admin
207
+ app without pulling in the component library. Seven new partials, all `@use`d
208
+ into the `pure-css.css` **bundle only** (base.css / grid.css / utilities.css
209
+ untouched; no new standalone artifact):
210
+ - `_navbar.scss` + `_navbar-elements.scss` — the fixed navbar (`.pc-navbar`
211
+ with `__inner`/`__start`/`__center`/`__end` regions) and its elements (burger
212
+ menu, brand wordmark `.pc-app-header`, nav menu `.pc-navmenu`, page title
213
+ `.pc-page-header`, profile button, theme switcher).
214
+ - `_sidebar.scss` + `_sidebar-states.scss` the sidebar nav with nested
215
+ submenus (`.pc-sidebar`, `.pc-layout__sidebar`, drag-to-resize
216
+ `.pc-sidebar-resize`) and its hidden / icon-collapse / expanded states.
217
+ - `_layout-container.scss` the layout wrapper (`.pc-layout` with
218
+ `__inner`/`__main`/`__content`/`__footer` and the `.pc-footer__*` regions),
219
+ including sticky/scroll content modes. Emitting `.pc-layout__main` here also
220
+ gives the grid's container-query responsive columns (`.pc-col-md-*`) their
221
+ documented automatic containment context in the same bundle (the
222
+ `_pa-grid.scss` note is corrected from the pre-rc04 `.pa-layout__main` to
223
+ `.pc-layout__main`).
224
+ - `_layout-responsive.scss` — the mobile/tablet media queries for the shell.
225
+ - `_resize-handle.scss` a mixin-only partial (emits nothing on its own)
226
+ providing the shared grab-knob look `@use`d by the sidebar resize handle and
227
+ splitter gutters.
228
+ - `_fit-flyout.scss` the Fit engine's floating-menu sink
229
+ (`.pc-fit-flyout__*`): a `•••` trigger + a `<body>`-parented panel that
230
+ `fit.js` fills on demand when slots relocate out of the row.
231
+
232
+ pure-admin-core keeps same-named partials that now just `@forward` these, so the
233
+ shell is single-sourced in the foundation and the two can't drift.
234
+
235
+ - **The shell's behaviour ships too a dependency-free JS runtime (`src/js/`).**
236
+ The shell is no longer styling-only: the foundation now carries the vanilla-JS
237
+ runtime that drives it, so pure-css is no longer a CSS-only package. Shipped
238
+ **as source** (no build step) via a new `./js` export (and `./js/*` for
239
+ individual engines); `files` gains `src/js/`.
240
+ - `pure-css.js` installs the `window.pureCss` namespace a tiny event bus,
241
+ live viewport / OS-colour-scheme / capability-first device sources, overlay
242
+ primitives (scroll-lock, keyboard-inset), an open-menu registry, a shared
243
+ `config` baseline (single-sourced from SCSS via `--pc-*` vars), and
244
+ `components.initAll(scope)`. Load-order-safe and stands alone when pure-admin
245
+ is absent; `pure-admin.js` adopts the same buses by reference on top.
246
+ - `fit.js` the Fit engine (`data-pc-fit` = hide / steps / relocate). It
247
+ **absorbs the former `navbar-collapse.js`** (progressive nav folding via
248
+ `data-pc-fit-nav`, sinking items to the sidebar or a generated "More" menu),
249
+ so that separate file no longer exists.
250
+ - `navbar-dropdown.js` (tap-toggle nav dropdowns/submenus),
251
+ `sidebar-resize.js` (drag-to-resize the sidebar), and
252
+ `container-breakpoint.js` (container-query breakpoint driver).
253
+
254
+ Shell CSS is authored no-JS-safe, so styling degrades gracefully rather than
255
+ breaking when the runtime isn't loaded.
256
+
257
+ ### Fixed
258
+
259
+ - **Migrated the dead `data-pa-nav-collapse` hook to `data-pc-fit-nav`.** The
260
+ relocated nav-collapse CSS keyed on the pre-rc04 `pa-`-branded
261
+ `[data-pa-nav-collapse]` attribute driven by the old `navbar-collapse.js`;
262
+ since that engine is now merged into `fit.js` (which reads `data-pc-fit-nav`),
263
+ the selectors in `_navbar-elements.scss` / `_layout-responsive.scss` were stale
264
+ and matched nothing. Repointed at `[data-pc-fit-nav]` and corrected the
265
+ companion comments (`navbar-collapse.js` `fit.js`). Also de-branded the fit
266
+ hide-class `.pa-fit-hidden` → `.pc-fit-hidden`.
267
+
268
+ ### Internal
269
+
270
+ - **GitHub Actions release workflow (`.github/workflows/release.yml`).** On a `v*.*.*`
271
+ tag push, builds the CSS (`npm ci` + `npm run build`) and publishes a GitHub Release
272
+ with a `pure-css-<version>.zip` (bundling `dist/`, `src/scss/`, `README.md`,
273
+ `CHANGELOG.md`, `LICENSE` — the same set as the package `files`, so the zip is a
274
+ toolchain-free drop-in for consumers who don't use npm) plus a `.sha256` checksum.
275
+ Auto-generated release notes; tags containing `-` (rc) publish as a pre-release.
276
+ Mirrors pure-admin-core's release workflow, adapted for this single-package repo.
277
+ - **Exhaustive, data-driven utilities e2e coverage.** Rewrote `e2e/utilities.spec.ts`
278
+ from a handful of spot-checks into a hard value assertion for 655 of the 664 shipped
279
+ utility classes (the 9 `auto` sizing classes — `m-auto` + per-side, `w-auto`, `h-auto`
280
+ are layout-resolved and covered behaviourally instead). Each family measures every one
281
+ of its classes' computed styles in a single in-browser pass, then diffs in Node so a
282
+ failure lists exactly which classes are off; the expectations independently encode the
283
+ 10px-rem contract and the documented scales rather than reading them back from the CSS,
284
+ so a failure means the compiled output disagrees with the contract or the contract
285
+ regressed. Renamed the fixture `test/utilities.html` → `test/utilities-scale.html` with
286
+ definite-size `#w-parent` / `#h-parent` containers so percentage widths/heights resolve
287
+ to known px. Test-only no change to shipped CSS.
288
+
289
+ ## [1.0.0-rc04] 2026-08-26 [PUBLISHED]
290
+
291
+ ### Changed (BREAKING)
292
+
293
+ - **pure-css now ships only the BASE token contract — component tokens moved to
294
+ the consumer that owns the components.** pure-css is a *foundation*: its
295
+ bundles (`pure-css.css`, `base.css`) now emit only the ~46 base `--pc-*` tokens
296
+ its own CSS consumes or exposes as universal theming primitives (surfaces,
297
+ text, accent, links, border, the semantic role identities + their utility text
298
+ colours, the theme palette slots, the radius scale). The ~165 **component**
299
+ tokens (`--pc-btn-*`, `--pc-card-*`, `--pc-table-*`, `--pc-alert-*`, badges,
300
+ tooltips, panels, command palette, multiselect, sentiment scale, form spacing,
301
+ the derived contextual surfaces, admin layout chrome) are no longer emitted by
302
+ the foundation. They are pure-admin's contract.
303
+ - `output-pc-css-variables` is now base-only. The component tokens are emitted
304
+ by the new **`output-pc-component-variables`** mixin (+ the existing
305
+ `output-pc-alert-variables-{light,dark}`), which pure-css still *defines*
306
+ (they read the shared `$`-variable vocabulary in `variables/*`, so they must
307
+ be authored where that vocabulary is in scope) but does **not** call from its
308
+ own bundle. Consumers that ship the components pure-admin core, every
309
+ theme opt in by `@include output-pc-component-variables` alongside
310
+ `output-pc-css-variables`.
311
+ - **Theme authors / anyone calling the emit mixins must add
312
+ `@include output-pc-component-variables;`** (after `output-pc-css-variables`)
313
+ or lose every component token. Consumers of the *compiled* theme/core CSS are
314
+ unaffectedthe emitted token set is identical, just split across two mixins.
315
+ - **Every emitted CSS variable de-branded from `--pa-*` to `--pc-*`.** pure-css is
316
+ a *foundation*, but it still emitted its entire runtime custom-property surface
317
+ under pure-admin's `pa` brand. The full `--pa-*` set (~210 vars: `--pa-accent`,
318
+ `--pa-text-color-*`, `--pa-card-bg`, `--pa-border-*`, the contextual /alert sets,
319
+ `--pa-color-1..9` + `-text`, the new `--pc-*` form-spacing family already shipped
320
+ this cut, etc.) is renamed to `--pc-*`. This completes the same de-branding the
321
+ grid/mode classes started above — nothing pure-admin-branded remains in the
322
+ foundation's output.
323
+ - **The emit mixins move too:** `output-pa-css-variables` → `output-pc-css-variables`,
324
+ `output-pa-alert-variables-light` / `-dark` `output-pc-alert-variables-*`.
325
+ (`output-base-css-variables` is unchanged — `--base-*` is a separate, neutral
326
+ web-component contract and stays.)
327
+ - **Untouched:** `--base-*` (web-component bridge), `--page-loader-*` (pre-FOUC
328
+ loader), and the `.pa-color-{name}` colour-variant **class** (a class, not a
329
+ `--pa-` variable).
330
+ - **Migration:** a boundary-aware replace of the string `--pa-` → `--pc-` across
331
+ markup, stylesheets, inline `style="--pa-…"`, JS `getPropertyValue`/`setProperty`
332
+ calls, and every theme's `:root` / dark-mode `--pa-*` override block. Safe
333
+ because the leading `--` + trailing `-` can't match `--base-*` or `--page-loader-*`.
334
+ pure-admin, its demo, all 16 themes, and the svelte/keen wrappers migrate in
335
+ lockstep with this release.
336
+ - **Grid classes renamed from the consumer-branded `pa-` to the foundation's own
337
+ `pc-` prefix.** `.pa-row` `.pc-row`, `.pa-col*` `.pc-col*` (all percentage /
338
+ fraction / responsive / `--grow`/`--shrink`/`--no-padding` variants),
339
+ `.pa-offset*` → `.pc-offset*`, `.pa-cq` → `.pc-cq`, `.pa-hide*` → `.pc-hide*`,
340
+ `.pa-show*` → `.pc-show*`. The grid is a pure-css *foundation* primitive, so it
341
+ should not carry pure-admin's (`pa`) brand — this de-couples it. **No dual-emit:**
342
+ the old `pa-*` grid classes are gone. Consumers must migrate markup
343
+ (`class="pa-col-1-2"` → `class="pc-col-1-2"`) — a boundary-aware find/replace
344
+ (careful: `pa-col` is a substring of `pa-color-*`, which must NOT be touched).
345
+ pure-admin, its demo, and the svelte/keen wrappers are migrated in lockstep.
346
+ - **Light/dark mode scope classes renamed `.pa-mode-*` `.pc-mode-*`.**
347
+ The light/dark scopes the foundation emits its variables against (and that apps
348
+ toggle on `<body>`) are foundation-owned, so they move to the `pc-` prefix too.
349
+ `output-pc-css-variables` now emits at `:root, .pc-mode-light, .pc-mode-dark`.
350
+ Consumers toggling the class in JS (`classList.add('pc-mode-dark')`) and themes'
351
+ dark-mode blocks migrate in lockstep. (Safe replace: the string `pa-mode-` →
352
+ `pc-mode-`; `pa-modal` is untouched since `mode` `moda`.)
353
+
354
+ ### Added
355
+
356
+ - **Sizing utilities consolidated into the foundation.** The universal sizing/flex
357
+ utilities that had been left in pure-admin now live here, so a standalone
358
+ pure-css page has the full set: viewport heights `h-full` / `h-screen` /
359
+ `min-h-full` / `min-h-screen` / `max-h-full` / `max-h-screen`, and the
360
+ Tailwind-style flex shorthands `flex-1` / `flex-auto` / `flex-initial` /
361
+ `flex-none` / `flex-grow` / `flex-shrink` (alongside the existing
362
+ `flex-grow-0/1`, `flex-shrink-0/1`). pure-css already owned the width/height %
363
+ + rem scales (`w-*`/`h-*`, `wr-*`/`hr-*`) and the full min/max families
364
+ (`minw-*`/`maxh-*`/`minwr-*`/`maxhr-*`/…); pure-admin's duplicate rem-height
365
+ `h-Nx`/`min-h-Nx`/`max-h-Nx` set (byte-identical to `hr-N`/`minhr-N`/`maxhr-N`)
366
+ is retired in favour of the foundation's `hr-`/`wr-` naming (`r` = rem).
367
+ - **Complete form-spacing contract as runtime CSS variables, under a pure-css-owned
368
+ `--pc-` namespace.** `output-pc-css-variables` now emits the full anatomy of a
369
+ form's spacing at `:root`, so every consumer (pure-admin, keen-docs,
370
+ keen-pure-admin) shares one contract instead of re-declaring `var()` chains or
371
+ being stuck with compile-time-only margins:
372
+ - Vertical rhythm: `--pc-label-gap` (label → control), `--pc-help-gap`
373
+ (control → help/error), `--pc-field-gap` (field → field),
374
+ `--pc-form-actions-offset` (last field actions row).
375
+ - Inline gaps: `--pc-form-gap` (shared + label↔inline-icon), `--pc-choice-gap`
376
+ (between options), `--pc-choice-inner-gap` (control↔label), `--pc-form-actions-gap`
377
+ (between buttons), `--pc-field-horizontal-gap` (horizontal label col↔input col).
378
+
379
+ The inline "gap" family chains to `--pc-form-gap` (one knob moves them all);
380
+ every var is also overridable on its own scope. These are the first
381
+ foundation-owned runtime vars to use `--pc-` rather than the legacy
382
+ consumer-branded `--pa-` prefixnew foundation tokens should follow suit.
383
+
384
+ ### Changed
385
+
386
+ - **Renamed the misleading `$form-scale` token to `$form-gap`.** It reads like an
387
+ input-sizing multiplier but is only ever consumed as a `gap:` value the small
388
+ gap between adjacent form bits (a label and its inline icon, footer action
389
+ buttons, checkbox/radio group options). `$form-scale` is kept as a `!default`
390
+ alias of `$form-gap`, so existing overrides keep working; it will be retired in
391
+ a major. (pure-admin reads the gap through `var(--pc-form-gap, …)`, so it is
392
+ also runtime-tunable.)
393
+
394
+ ## [1.0.0-rc03] 2026-08-21 [PUBLISHED]
395
+
396
+ ### Changed
397
+
398
+ - **BREAKING renamed the top-bar region tokens from `header` to `navbar`.** The
399
+ foundation's top-region tokens named the bar as a *component block* rather than a
400
+ layout region, which read as misleading once pure-admin's navbar component dropped its
401
+ legacy `pa-header__*` block naming. Renamed:
402
+ - SCSS variables: `$header-height` `$navbar-height`, `$header-bg` → `$navbar-bg`,
403
+ `$header-border-color` `$navbar-border-color`, `$header-text` `$navbar-text`,
404
+ `$header-text-secondary` `$navbar-text-secondary`,
405
+ `$header-profile-name-color` → `$navbar-profile-name-color`,
406
+ `$z-index-header` → `$z-index-navbar`.
407
+ - CSS variables: `--pa-header-bg` → `--pa-navbar-bg`,
408
+ `--pa-header-border-color` `--pa-navbar-border-color`,
409
+ `--pa-header-text` `--pa-navbar-text`,
410
+ `--pa-header-text-secondary` `--pa-navbar-text-secondary`,
411
+ `--pa-header-profile-name-color` `--pa-navbar-profile-name-color`.
412
+ - `$footer-height` still mirrors the bar height (now `$navbar-height`); component-header
413
+ tokens (`$card-header-*`, `$table-header-*`) are unaffected.
414
+
415
+ ### Removed
416
+
417
+ - **Dead `$header-brand-padding-left` variable.** Superseded by the navbar's flex `gap`;
418
+ no live rule consumed it (only a stale comment referenced it).
419
+
420
+ ## [1.0.0-rc02] — 2026-08-05 [PUBLISHED]
421
+
422
+ ### Added
423
+
424
+ - **Reboot layer (`reboot.scss`) — the reset the foundation always assumed.** Emits
425
+ `html { font-size: 10px }` (the 10px rem base every pure-css rem value is authored
426
+ against — `$font-size-base: 1.6rem` is 16px *only* at a 10px root), a `box-sizing:
427
+ border-box` reset, neutral base styling for standard elements (headings, paragraphs,
428
+ links, lists, blockquotes, `hr`, `figure`), the `body` font/colour/background, and the
429
+ `button/input/select/textarea/label { font: inherit }` reset. Relocated from
430
+ pure-admin-core's `core-components/_base.scss` so it sits with the rem-scale variables
431
+ that depend on it. Analogous to Bootstrap's Reboot.
432
+ - **New `reboot.css` build artifact** + `./reboot` export, and `reboot` is now part of the
433
+ `pure-css.css` bundle (emitted before grid/utilities).
434
+ - **Themed scrollbars (`scrollbars.scss`).** The global `*::-webkit-scrollbar` + Firefox
435
+ `scrollbar-width`/`scrollbar-color` styling (thin scrollbars coloured from the `--pa-*`
436
+ cascade), relocated from pure-admin-core's `core-components/_scrollbars.scss`. Global browser
437
+ chrome belongs with the foundation's consistent-appearance promise, so a standalone pure-css
438
+ page gets the same themed scrollbars as a full pure-admin app instead of native ones. Part of
439
+ the `pure-css.css` bundle, plus a standalone `scrollbars.css` artifact + `./scrollbars` export.
440
+
441
+ ### Fixed
442
+
443
+ - **Standalone consumers no longer render 1.6× too large.** Before, the 10px base lived
444
+ only in pure-admin-core, so a page linking `pure-css.css` (or `base.css`) on its own
445
+ inherited the browser's 16px root and every rem was 1.6× oversized. The bundle now ships
446
+ the 10px base itself, so the sizing scale is correct out of the box.
447
+
448
+ ## [1.0.0-rc01] — 2026-08-04
449
+
450
+ Initial extraction of the CSS foundation out of `@keenmate/pure-admin-core`.
451
+
452
+ ### Fixed
453
+
454
+ - **Border/rounded utilities now resolve (were inert).** `.border` / `.border-{top,right,bottom,left}`
455
+ and `.rounded` / `.rounded-{lg,top,…}` referenced bare `--border-color` / `--border-radius`
456
+ variables the framework never emits — so they fell back to a `currentColor` border and no radius
457
+ (a latent bug inherited from pure-admin-core). Repointed them at the emitted `--pa-border-color` /
458
+ `--pa-border-radius(-lg)` (themed from `--base-*`). Now `base.css` + `utilities.css` are
459
+ **self-sufficient** — the border/radius utilities work standalone, no host shim.
460
+ - **`--pa-border-color` is now a live reference** — emitted as `var(--base-border-color, <literal>)`
461
+ instead of a baked literal (it's a pure pass-through, no derivation lost). So it — and the `.border`
462
+ utilities that read it — follow a **runtime** `--base-border-color` override (a theme or dark-mode
463
+ class toggling it at `:root`/`.pa-mode-dark`), not just build-time themes.
464
+
465
+ ### Added
466
+
467
+ - **`--base-*` theming contract** — `src/scss/variables/*` (the `$base-*` source of truth plus the
468
+ derived typography/spacing/colors/layout/system/components modules) and
469
+ `_base-css-variables.scss` (the mixin emitting `--base-*` and derived `--pa-*` custom properties).
470
+ - **Native flexbox grid** — `_pa-grid.scss` (`.pa-row` / `.pa-col`: percentage columns in 5%
471
+ increments, intuitive fractions, container-query responsive variants, offsets, visibility helpers),
472
+ relocated from pure-admin-core's `core-components/_grid.scss`. Replaces the legacy PureCSS
473
+ `.pure-g` / `.pure-u-*` grid, which pure-admin had already stopped using — so pure-css ships the
474
+ grid consumers actually use, not the deprecated one.
475
+ - **Utilities** — `utilities.scss` (spacing / flex / display / width-height classes) plus the generic
476
+ `.font-family-system/-sans/-serif/-mono` classes from `_fonts.scss` (core keeps `_fonts.scss`
477
+ standalone; here it `@use`s into utilities so all foundation utilities ship together). Adds
478
+ `.gap-*` / `.gap-x-*` / `.gap-y-*` (flex/grid gap, same `$spacers` scale) — the one spacing family
479
+ core lacked, needed to express flex layouts with utilities.
480
+ - **Build entries & artifacts** — `pure-css.scss` (full bundle), `base.scss` (variables only),
481
+ `grid.scss` (grid only), and the existing `utilities.scss`, compiled to
482
+ `dist/css/{pure-css,base,grid,utilities}.css`. `dist/` is committed for toolchain-free vendoring.
483
+ - Package tooling: `package.json` (`@keenmate/pure-css`, `exports` for `.`/`./base`/`./grid`/
484
+ `./utilities`/`./scss`), `Makefile`, `README`, this changelog.
485
+
486
+ ### Notes
487
+
488
+ - **pure-admin-core consumes this package** as its single source for the foundation (thin
489
+ `@import`/`@forward` shims for the variables, `--base-*`/`--pa-*` emit mixins, utilities, and the
490
+ grid). The two no longer carry duplicate copies, so compiled `--base-*` values and grid output
491
+ match core's `dist/css/main.css` exactly.