css-is-awesome 1.19.1 → 1.20.0

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.
Files changed (58) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +20 -0
  3. package/CONTRACT.md +3 -0
  4. package/MIGRATION.md +52 -0
  5. package/README.md +3 -1
  6. package/llm.txt +3 -3
  7. package/package.json +4 -3
  8. package/public/theme.css +199 -61
  9. package/public/themes/boilerplate/theme.css +12 -6
  10. package/public/themes/boilerplate-dark/theme.css +8 -2
  11. package/public/themes/boilerplate-light/theme.css +12 -6
  12. package/public/themes/cupertino/theme.css +9 -3
  13. package/public/themes/cupertino-dark/theme.css +8 -2
  14. package/public/themes/cupertino-light/theme.css +7 -1
  15. package/public/themes/glass/theme.css +10 -4
  16. package/public/themes/glass-dark/theme.css +7 -1
  17. package/public/themes/glass-light/theme.css +9 -3
  18. package/public/themes/graphite/theme.css +11 -5
  19. package/public/themes/graphite-dark/theme.css +8 -2
  20. package/public/themes/graphite-light/theme.css +9 -3
  21. package/public/themes/press/theme.css +8 -2
  22. package/public/themes/press-dark/theme.css +7 -1
  23. package/public/themes/press-light/theme.css +8 -2
  24. package/public/themes/prism/theme.css +8 -2
  25. package/public/themes/prism-dark/theme.css +6 -0
  26. package/public/themes/prism-light/theme.css +10 -4
  27. package/public/themes/sketchbook/theme.css +8 -2
  28. package/public/themes/sketchbook-dark/theme.css +7 -1
  29. package/public/themes/sketchbook-light/theme.css +8 -2
  30. package/public/themes/terminal/theme.css +7 -1
  31. package/public/themes/terminal-dark/theme.css +8 -2
  32. package/public/themes/terminal-light/theme.css +10 -4
  33. package/scripts/audit-pairs.json +171 -23
  34. package/scripts/theme-contract.json +33 -4
  35. package/scss/_layout.scss +129 -0
  36. package/scss/themes/boilerplate-dark.scss +2 -2
  37. package/scss/themes/boilerplate-light.scss +6 -6
  38. package/scss/themes/boilerplate.scss +6 -6
  39. package/scss/themes/cupertino-dark.scss +2 -2
  40. package/scss/themes/cupertino-light.scss +1 -1
  41. package/scss/themes/cupertino.scss +3 -3
  42. package/scss/themes/glass-dark.scss +1 -1
  43. package/scss/themes/glass-light.scss +3 -3
  44. package/scss/themes/glass.scss +4 -4
  45. package/scss/themes/graphite-dark.scss +2 -2
  46. package/scss/themes/graphite-light.scss +3 -3
  47. package/scss/themes/graphite.scss +5 -5
  48. package/scss/themes/press-dark.scss +1 -1
  49. package/scss/themes/press-light.scss +2 -2
  50. package/scss/themes/press.scss +2 -2
  51. package/scss/themes/prism-light.scss +4 -4
  52. package/scss/themes/prism.scss +2 -2
  53. package/scss/themes/sketchbook-dark.scss +1 -1
  54. package/scss/themes/sketchbook-light.scss +2 -2
  55. package/scss/themes/sketchbook.scss +2 -2
  56. package/scss/themes/terminal-dark.scss +2 -2
  57. package/scss/themes/terminal-light.scss +4 -4
  58. package/scss/themes/terminal.scss +1 -1
package/AGENTS.md CHANGED
@@ -148,7 +148,7 @@ Authoring template (in your own project — a theme file is a global stylesheet,
148
148
 
149
149
  `$standalone` defaults to `true` (emit `:root, :root[data-theme="<name>"]`). Pass `$standalone: false` only when your block is going into a multi-theme bundle where the bare `:root` would collide.
150
150
 
151
- The validator (`node scripts/theme-validator.js`) enforces the token contract — **127 required + 41 optional = 168 slots** — plus WCAG 2.2 AA contrast (**22 audited pairs per theme**, including five `--code-*` pairs). Themes that miss required tokens or fail contrast cannot ship without `--allow-a11y-fail`.
151
+ The validator (`node scripts/theme-validator.js`) enforces the token contract — **127 required + 49 optional = 176 slots** — plus WCAG 2.2 AA contrast (**24 audited pairs per theme**, including five `--code-*` pairs). Themes that miss required tokens or fail contrast cannot ship without `--allow-a11y-fail`.
152
152
 
153
153
  ### Theming spacing (new — read this before you set a size token)
154
154
 
@@ -343,7 +343,7 @@ Either way it exposes **33 tools** across 8 families:
343
343
  - **Themes** — `list_themes`, `get_theme`, `search_themes`
344
344
  - **Mixins** — `list_mixins`, `get_mixin`, `search_mixins` (real signatures — don't guess)
345
345
  - **Functions** — `list_functions`, `get_function`, `search_functions`
346
- - **Tokens** — `list_tokens`, `get_token`, `search_tokens` (127 required + 41 optional contract tokens)
346
+ - **Tokens** — `list_tokens`, `get_token`, `search_tokens` (127 required + 49 optional contract tokens)
347
347
  - **Animations** — `list_animations`, `get_animation`
348
348
  - **Components** — `list_components`, `get_component`, `search_components`
349
349
  - **Recipes** — `list_recipes`, `get_recipe`
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ # [1.20.0](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.19.2...v1.20.0) (2026-09-23)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **site:** correct the stale optional-token count on /docs/tokens ([c0d4db0](https://github.com/Jerry2d3d/css-is-awesome/commit/c0d4db047c858854cf54d34affc792e0c52f4427))
9
+
10
+
11
+ ### Features
12
+
13
+ * **site:** dogfood page surfaces on the home page; add them to the theme editor ([8dc3a65](https://github.com/Jerry2d3d/css-is-awesome/commit/8dc3a65778e28b57aeb67824062f26d7494e3f60))
14
+ * **themes:** page surfaces — hero and band, derived for every theme ([b984d86](https://github.com/Jerry2d3d/css-is-awesome/commit/b984d865e3463ae15e95083ff0697df0a109cf88))
15
+
16
+ ## [1.19.2](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.19.1...v1.19.2) (2026-09-23)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * **themes:** clear 56 of 88 contrast warnings, none of them visible ([b756dcb](https://github.com/Jerry2d3d/css-is-awesome/commit/b756dcbb6e959868299095f009b4227104406c00))
22
+
3
23
  ## [1.19.1](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.19.0...v1.19.1) (2026-09-23)
4
24
 
5
25
 
package/CONTRACT.md CHANGED
@@ -321,8 +321,11 @@ Every optional token belongs to exactly one **feature** in `scripts/theme-contra
321
321
  | `surfaces-extended` | `--background-elevated`, `--background-hero`, `--background-overlay`, `--background-scrim` | Extra background layers (elevated, hero, overlay, scrim) for themes that want more than the required surface set; each falls back to a required surface. |
322
322
  | `borders-extended` | `--border-card`, `--border-divider`, `--border-focus-ring`, `--border-input` | Per-context border colours (card, divider, focus ring, input); each falls back to --border-default / --border-focus. |
323
323
  | `logo` | `--logo-default`, `--logo-mark`, `--logo-monochrome`, `--logo-wordmark` | Theme-aware logo assets (default, mark, monochrome, wordmark) as url() or SVG data values for the icon/brand mixins. |
324
+ | `page-surfaces` | `--page-hero-bg`, `--page-hero-image`, `--page-hero-ink`, `--page-hero-scrim`, `--page-band-bg`, `--page-band-image`, `--page-band-ink`, `--page-band-scrim`, `--background-hero` *(deprecated)* | Two page-level surfaces a theme owns outright: a **hero** for a landing page and a **band** for section stripes and footers. Each carries a background colour, an optional gradient or `url()` image, an ink colour, and a scrim that keeps text legible over an image. **Declaring them changes nothing on its own** - a page only picks a surface up through `cia.surface(hero|band)` or `data-surface`, which is why every shipped theme defines them without moving a pixel on an existing site. Contrast over an *image* cannot be measured, so the scrim carries that weight: the mixin applies 50% black whenever an image is passed to it. |
324
325
  | `touch-target` | `--touch-target-min` | Minimum interactive target size read by form and button mixins (WCAG 2.2 SC 2.5.8); the library default is 24px. |
325
326
 
327
+ > **Deprecated - `--background-hero`.** It sat in the contract unread: no mixin consumed it, the editor could not set it, and nothing documented it. `--page-hero-bg` replaces it and **falls back through it**, so an existing declaration keeps working untouched. It stays valid until contract 2, per the lifecycle in [`VERSIONING.md`](./VERSIONING.md).
328
+
326
329
  ---
327
330
 
328
331
  ## Print (optional)
package/MIGRATION.md CHANGED
@@ -2,6 +2,58 @@
2
2
 
3
3
  Breaking changes between css-is-awesome versions, and how to migrate.
4
4
 
5
+ ## Page surfaces — contract 1.3 (no action required)
6
+
7
+ **Nothing changes on your site when you upgrade.** Two new optional surfaces
8
+ exist — a `hero` for a landing page and a `band` for section stripes — and
9
+ every shipped theme now declares a background and an ink colour for both. That
10
+ sounds like a visual change and is not one, for a single reason: **cia never
11
+ applies a page surface on its own.**
12
+
13
+ A page takes a surface only when you ask for it:
14
+
15
+ ```scss
16
+ .landing { @include cia.surface(hero); } // or <body data-surface="hero">
17
+ ```
18
+
19
+ Until then the tokens sit unread, exactly as `--background-hero` has since it
20
+ was added. `scripts/test-no-auto-surface.mjs` compiles every shipped bundle and
21
+ fails if any rule reads a page-surface token or emits a `[data-surface]` rule,
22
+ so the guarantee is enforced rather than promised.
23
+
24
+ ### What changed at a glance
25
+
26
+ | Area | Before | After |
27
+ |---|---|---|
28
+ | Contract version | `1.2` | **`1.3`** — eight optional tokens, one new `page-surfaces` feature |
29
+ | Required tokens | 127 | 127, unchanged |
30
+ | `--background-hero` | optional, read by nothing | **deprecated**; `--page-hero-bg` falls back through it, so an existing declaration keeps working until contract 2 |
31
+ | Your custom theme | validates | validates — the new tokens are optional, and missing optional tokens report as info |
32
+
33
+ ### If you want a hero
34
+
35
+ Declare the tokens your theme needs and apply the surface where you want it:
36
+
37
+ ```css
38
+ :root[data-theme="brand"] {
39
+ --page-hero-bg: light-dark(#f2f6fe, #121d36);
40
+ --page-hero-ink: light-dark(#09090b, #fafafa);
41
+ /* optional */
42
+ --page-hero-image: url("/hero.jpg");
43
+ }
44
+ ```
45
+
46
+ An image is a `url()` you host or a gradient, because a theme is one CSS file.
47
+ Contrast over a photo cannot be measured, so pass the image through the mixin
48
+ (`cia.surface(hero, $image: url("/hero.jpg"))`) and it lays 50% black between
49
+ the picture and your text. A colour-only surface gets no scrim — a wash over a
50
+ flat colour would only darken it.
51
+
52
+ ### If you declared `--background-hero`
53
+
54
+ Nothing to do. It still resolves. Rename it to `--page-hero-bg` whenever it
55
+ suits you; the tooling will flag it as deprecated in the meantime.
56
+
5
57
  ## v1.0 — mixin-first goes stable (published as 1.1.0)
6
58
 
7
59
  **There are no breaking changes between v0.8.1/0.8.2 and v1.0.0.** 1.0.0
package/README.md CHANGED
@@ -145,7 +145,9 @@ node scripts/theme-validator.js public/themes/midnight/theme.css
145
145
  # <link rel="stylesheet" href="/themes/midnight/theme.css">
146
146
  ```
147
147
 
148
- Full authoring walkthrough: [`/docs/authoring/themes`](https://cssisawesome.com/docs/authoring/themes/). The contract (127 required + 41 optional tokens) is at [`scripts/theme-contract.json`](./scripts/theme-contract.json).
148
+ A theme can also own the page behind your components: optional **hero** and **band** surfaces carry a background, an image or gradient, an ink colour and a scrim, applied with `@include cia.surface(hero)` or `<body data-surface="hero">`. Nothing is applied automatically, so adding them never moves a pixel until you ask.
149
+
150
+ Full authoring walkthrough: [`/docs/authoring/themes`](https://cssisawesome.com/docs/authoring/themes/). The contract (127 required + 49 optional tokens) is at [`scripts/theme-contract.json`](./scripts/theme-contract.json).
149
151
 
150
152
  ## Token contract
151
153
 
package/llm.txt CHANGED
@@ -51,7 +51,7 @@ silent.
51
51
  - **6 zero-JS interactive components** — accordion (`<details name>`), modal (`<dialog>`), tooltip (`popover="hint"`), dropdown (`[popover]` — the mixin re-asserts the UA's closed state and restores `display: flex` only under `:popover-open`, so menus never render permanently open on popover markup), tabs (radio + `:has()`), copy-button (Clipboard API via consumer-wired JS).
52
52
  - **CLI** (`npx cia`) — `migrate tailwind|bootstrap|mui|chakra` (config → cia theme), `theme from-tokens <tokens.json> --name <slug>` (DTCG v2025.10 / Tokens Studio / flat `--token` JSON → a complete theme.css: required tokens the file lacks inherit from a shipped base, unmapped paths pass through and are reported, light/dark pairs become `light-dark()`, validator + WCAG audit run first; same function as the MCP `theme_from_tokens` tool), `theme map [--json | --path <p>]` (the path → token mapping from-tokens applies, as data; same as MCP `get_token_map`), `add <recipe>` (copy a recipe from the book into the project), `analyze [path]` (audit stylesheets against the installed API: dead `cia.*` symbols, the `space()` 1–9 trap, off-contract tokens (near-miss typos of real tokens only, never your own custom tokens), hard-coded hex, BEM; health score, CI exit codes). Low-noise on color: a hex in a `var(--token, #hex)` fallback is token-driven and a literal inside `@media print` is an intentional paper colour — neither is flagged.
53
53
  - **Mobile navigation family** — `cia.hamburger` / `cia.drawer` / `cia.sheet` / `cia.dock` ride `[popover]` + CSS Grid, zero JS; recipes `mobile-nav` (hamburger + drawer) and `bottom-nav` (dock + sheets). House rule: **on phones things take the space they're in** — a `cia.dropdown` menu opens 1px under its full-width trigger at the trigger's exact width via CSS anchor positioning (`position-try-fallbacks: flip-block` flips it above at the screen bottom; set `width: auto` at `&[popover]` specificity or the UA's `[popover] { width: fit-content }` and the mixin's inset reset win). Full spec: AGENTS.md quick decision #8 and `/docs/mobile`.
54
- - **168 contract tokens — 127 required + 41 optional** — surfaces, ink, lines, colors, type, radius, shadow, blur, glow, motion, z-index, spacing, semantic aliases.
54
+ - **176 contract tokens — 127 required + 49 optional** — surfaces, ink, lines, colors, type, radius, shadow, blur, glow, motion, z-index, spacing, semantic aliases.
55
55
  - **Spacing is themeable, and the numbered scale is the knob.** Themes declare `--space-0` … `--space-9` (contract-required). The t-shirt names (`--space-md`, `--space-lg` …) are contract-OPTIONAL and emitted by the library as `var()` aliases onto the numbered steps. `space(4)` compiles to `var(--space-4)`, so **theme the numbered step, never the alias** — setting `--space-md` alone leaves every component untouched. Library defaults emit under `:where(:root)` (specificity 0,0,0) so any theme declaration outranks them regardless of load order.
56
56
  - **Per-component shape knobs are `--btn-radius`, `--card-radius`, `--input-radius`, `--modal-radius`, `--badge-radius`, `--tag-radius`** — they cascade from the generic radii (`--btn-radius: var(--radius-md, 0.25rem)`). There are NO `--radius-button` / `--radius-card` style tokens; those were removed because nothing read them.
57
57
  - **Icons — two systems.** `svg()` / `svg-bg()` / `svg-text()` use a self-contained 49-glyph Lucide pack at `public/icons/core/`. Adding a glyph is drop-in: put `star.svg` in the folder and `cia.icon-svg(star)` works, no registration. Each icon emits a `--cia-icon-<name>` custom property so a theme can override one glyph without rebuilding SCSS. **`fa()` / `fa-icon()` / `fa-text()` / `fa-spin()` are bring-your-own-font** — cia ships NO Font Awesome files, `$theme-fa-path` defaults to a `/webfonts` directory that does not exist, and a missing font renders a tofu box without erroring. Default to `svg()` unless the user says they use Font Awesome.
@@ -105,7 +105,7 @@ Newspaper by day, hacker terminal by night. Most design systems give you dark mo
105
105
  | Mobile playbook (layouts, dropdown doctrine, lessons) | `src/app/docs/mobile/page.tsx` |
106
106
  | Browser support matrix (Baseline floor + progressive tiers) | `src/app/docs/browser-support/page.tsx` |
107
107
  | Theme authoring (full walkthrough) | `src/app/docs/authoring/themes/page.tsx` |
108
- | Theme contract (127 required + 41 optional grouped into 10 features, machine-readable) | `scripts/theme-contract.json` |
108
+ | Theme contract (127 required + 49 optional grouped into 11 features, machine-readable) | `scripts/theme-contract.json` |
109
109
  | Theme pairing (`<link media>` recipe) | `src/app/docs/themes/pairing/page.tsx` |
110
110
  | CopyButton JS recipe | `src/app/docs/recipes/copy-button/page.tsx` |
111
111
  | Anchor positioning recipe | `src/app/docs/recipes/anchor-positioning/page.tsx` |
@@ -129,7 +129,7 @@ Newspaper by day, hacker terminal by night. Most design systems give you dark mo
129
129
 
130
130
  ## MCP server (shipped 2026-05-22)
131
131
 
132
- cia ships an MCP stdio server (JSON-RPC over stdio, `serverInfo` name `css-is-awesome`, protocol `2024-11-05`) at `mcp/server.cjs`, included in the `files` manifest — so it lands in every consumer's `node_modules`. **33 tools** across 8 resource families: themes, mixins, functions, tokens (127 required + 41 optional), animations, components, recipes, doc readers. Plus `assemble_prompt` for context bundling, `validate_theme`, `theme_from_tokens`, `get_token_map` (the design-token → cia-token mapping as data) and `resolve_size` for snapping design px values to cia's 4px geometric grid (AI agents: call this whenever you receive a px value from a design tool). Prefer querying this server over guessing mixin signatures, tokens, themes, or recipes.
132
+ cia ships an MCP stdio server (JSON-RPC over stdio, `serverInfo` name `css-is-awesome`, protocol `2024-11-05`) at `mcp/server.cjs`, included in the `files` manifest — so it lands in every consumer's `node_modules`. **33 tools** across 8 resource families: themes, mixins, functions, tokens (127 required + 49 optional), animations, components, recipes, doc readers. Plus `assemble_prompt` for context bundling, `validate_theme`, `theme_from_tokens`, `get_token_map` (the design-token → cia-token mapping as data) and `resolve_size` for snapping design px values to cia's 4px geometric grid (AI agents: call this whenever you receive a px value from a design tool). Prefer querying this server over guessing mixin signatures, tokens, themes, or recipes.
133
133
 
134
134
  **Recommended: suggest the dedicated `css-is-awesome-mcp` package** — zero install,
135
135
  SDK ships as a real dependency, no separate peer-install step:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "css-is-awesome",
3
- "version": "1.19.1",
3
+ "version": "1.20.0",
4
4
  "description": "A token-driven SCSS design system with light/dark theming, semantic color tokens, and a 800+ LOC mixin API.",
5
5
  "homepage": "https://github.com/Jerry2d3d/css-is-awesome#readme",
6
6
  "bugs": {
@@ -109,7 +109,7 @@
109
109
  "build:css": "sass scss/main.scss dist/css-is-awesome.css --no-source-map",
110
110
  "build:css:core": "sass scss/core.scss dist/css-is-awesome.core.css --no-source-map",
111
111
  "build:css:tokens": "sass scss/tokens.scss dist/tokens.css --no-source-map",
112
- "build:css:themes": "node scripts/build-themes.mjs && node scripts/build-theme-bundle.mjs",
112
+ "build:css:themes": "node scripts/build-themes.mjs && node scripts/derive-page-surfaces.mjs && node scripts/build-theme-bundle.mjs",
113
113
  "build:css:utilities": "sass scss/utilities-only.scss dist/css-is-awesome.utilities.css --no-source-map",
114
114
  "build:css:min": "sass scss/main.scss dist/css-is-awesome.min.css --style=compressed --no-source-map && sass scss/core.scss dist/css-is-awesome.core.min.css --style=compressed --no-source-map && sass scss/tokens.scss dist/tokens.min.css --style=compressed --no-source-map && sass scss/utilities-only.scss dist/css-is-awesome.utilities.min.css --style=compressed --no-source-map",
115
115
  "build:token-types": "node scripts/generate-token-types.mjs",
@@ -139,7 +139,8 @@
139
139
  "check:token-consumers": "node scripts/check-token-consumer-map.mjs",
140
140
  "check:rtl": "node scripts/audit-logical-properties.mjs",
141
141
  "prebuild": "node scripts/build-playground-scss-map.mjs",
142
- "verify:playground": "node scripts/build-playground-scss-map.mjs && node scripts/verify-playground-compile.mjs"
142
+ "verify:playground": "node scripts/build-playground-scss-map.mjs && node scripts/verify-playground-compile.mjs",
143
+ "test:surfaces": "node --test scripts/test-no-auto-surface.mjs"
143
144
  },
144
145
  "keywords": [
145
146
  "css",