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

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