css-is-awesome 1.19.2 → 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.
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +13 -0
- package/CONTRACT.md +3 -0
- package/MIGRATION.md +52 -0
- package/README.md +3 -1
- package/llm.txt +3 -3
- package/package.json +4 -3
- package/public/theme.css +138 -0
- package/public/themes/boilerplate/theme.css +6 -0
- package/public/themes/boilerplate-dark/theme.css +6 -0
- package/public/themes/boilerplate-light/theme.css +6 -0
- package/public/themes/cupertino/theme.css +6 -0
- package/public/themes/cupertino-dark/theme.css +6 -0
- package/public/themes/cupertino-light/theme.css +6 -0
- package/public/themes/glass/theme.css +6 -0
- package/public/themes/glass-dark/theme.css +6 -0
- package/public/themes/glass-light/theme.css +6 -0
- package/public/themes/graphite/theme.css +6 -0
- package/public/themes/graphite-dark/theme.css +6 -0
- package/public/themes/graphite-light/theme.css +6 -0
- package/public/themes/press/theme.css +6 -0
- package/public/themes/press-dark/theme.css +6 -0
- package/public/themes/press-light/theme.css +6 -0
- package/public/themes/prism/theme.css +6 -0
- package/public/themes/prism-dark/theme.css +6 -0
- package/public/themes/prism-light/theme.css +6 -0
- package/public/themes/sketchbook/theme.css +6 -0
- package/public/themes/sketchbook-dark/theme.css +6 -0
- package/public/themes/sketchbook-light/theme.css +6 -0
- package/public/themes/terminal/theme.css +6 -0
- package/public/themes/terminal-dark/theme.css +6 -0
- package/public/themes/terminal-light/theme.css +6 -0
- package/scripts/audit-pairs.json +171 -23
- package/scripts/theme-contract.json +33 -4
- package/scss/_layout.scss +129 -0
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 +
|
|
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 +
|
|
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,18 @@
|
|
|
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
|
+
|
|
3
16
|
## [1.19.2](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.19.1...v1.19.2) (2026-09-23)
|
|
4
17
|
|
|
5
18
|
|
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
|
-
|
|
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
|
-
- **
|
|
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 +
|
|
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 +
|
|
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.
|
|
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",
|
package/public/theme.css
CHANGED
|
@@ -189,6 +189,12 @@
|
|
|
189
189
|
--z-modal: 1050;
|
|
190
190
|
--z-popover: 1060;
|
|
191
191
|
--z-tooltip: 1070;
|
|
192
|
+
|
|
193
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
194
|
+
--page-hero-bg: light-dark(#f2f6fe, #121e36);
|
|
195
|
+
--page-hero-ink: light-dark(#0f172a, #f8fafc);
|
|
196
|
+
--page-band-bg: light-dark(#f7fafe, #111b31);
|
|
197
|
+
--page-band-ink: light-dark(#0f172a, #f8fafc);
|
|
192
198
|
}
|
|
193
199
|
:root[data-theme=boilerplate-dark] {
|
|
194
200
|
color-scheme: dark;
|
|
@@ -363,6 +369,12 @@
|
|
|
363
369
|
--space-7: calc(var(--space-unit) * 24);
|
|
364
370
|
--space-8: calc(var(--space-unit) * 32);
|
|
365
371
|
--space-9: calc(var(--space-unit) * 48);
|
|
372
|
+
|
|
373
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
374
|
+
--page-hero-bg: #121e36;
|
|
375
|
+
--page-hero-ink: #f8fafc;
|
|
376
|
+
--page-band-bg: #111b31;
|
|
377
|
+
--page-band-ink: #f8fafc;
|
|
366
378
|
}
|
|
367
379
|
:root[data-theme=boilerplate-light] {
|
|
368
380
|
color-scheme: light;
|
|
@@ -537,6 +549,12 @@
|
|
|
537
549
|
--space-7: calc(var(--space-unit) * 24);
|
|
538
550
|
--space-8: calc(var(--space-unit) * 32);
|
|
539
551
|
--space-9: calc(var(--space-unit) * 48);
|
|
552
|
+
|
|
553
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
554
|
+
--page-hero-bg: #f2f6fe;
|
|
555
|
+
--page-hero-ink: #0f172a;
|
|
556
|
+
--page-band-bg: #f7fafe;
|
|
557
|
+
--page-band-ink: #0f172a;
|
|
540
558
|
}
|
|
541
559
|
:root[data-theme=cupertino] {
|
|
542
560
|
color-scheme: light dark;
|
|
@@ -711,6 +729,12 @@
|
|
|
711
729
|
--input-radius: var(--r-sm);
|
|
712
730
|
--modal-radius: var(--r-lg);
|
|
713
731
|
--tooltip-radius: var(--r-sm);
|
|
732
|
+
|
|
733
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
734
|
+
--page-hero-bg: light-dark(#e6ecf3, #1e252c);
|
|
735
|
+
--page-hero-ink: light-dark(#1d1d1f, #f5f5f7);
|
|
736
|
+
--page-band-bg: light-dark(#ecf0f5, #1e2226);
|
|
737
|
+
--page-band-ink: light-dark(#1d1d1f, #f5f5f7);
|
|
714
738
|
}
|
|
715
739
|
:root[data-theme=cupertino-dark] {
|
|
716
740
|
color-scheme: dark;
|
|
@@ -902,6 +926,12 @@
|
|
|
902
926
|
--input-radius: var(--r-sm); /* 8px — text field */
|
|
903
927
|
--modal-radius: var(--r-lg); /* matches panel */
|
|
904
928
|
--tooltip-radius: var(--r-sm); /* bezel tooltip */
|
|
929
|
+
|
|
930
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
931
|
+
--page-hero-bg: #1e252c;
|
|
932
|
+
--page-hero-ink: #f5f5f7;
|
|
933
|
+
--page-band-bg: #1e2226;
|
|
934
|
+
--page-band-ink: #f5f5f7;
|
|
905
935
|
}
|
|
906
936
|
:root[data-theme=cupertino-light] {
|
|
907
937
|
color-scheme: light;
|
|
@@ -1109,6 +1139,12 @@
|
|
|
1109
1139
|
--input-radius: var(--r-sm); /* 8px — text field */
|
|
1110
1140
|
--modal-radius: var(--r-lg); /* matches panel */
|
|
1111
1141
|
--tooltip-radius: var(--r-sm); /* bezel tooltip */
|
|
1142
|
+
|
|
1143
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
1144
|
+
--page-hero-bg: #e6ecf3;
|
|
1145
|
+
--page-hero-ink: #1d1d1f;
|
|
1146
|
+
--page-band-bg: #ecf0f5;
|
|
1147
|
+
--page-band-ink: #1d1d1f;
|
|
1112
1148
|
}
|
|
1113
1149
|
:root[data-theme=glass] {
|
|
1114
1150
|
color-scheme: light dark;
|
|
@@ -1308,6 +1344,12 @@
|
|
|
1308
1344
|
--z-modal: 1050;
|
|
1309
1345
|
--z-popover: 1060;
|
|
1310
1346
|
--z-tooltip: 1070;
|
|
1347
|
+
|
|
1348
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
1349
|
+
--page-hero-bg: light-dark(#ebe5fd, #101828);
|
|
1350
|
+
--page-hero-ink: light-dark(#1d1d1f, #f0f4ff);
|
|
1351
|
+
--page-band-bg: light-dark(#eee9fe, #0e1422);
|
|
1352
|
+
--page-band-ink: light-dark(#1d1d1f, #f0f4ff);
|
|
1311
1353
|
}
|
|
1312
1354
|
:root[data-theme=glass-dark] {
|
|
1313
1355
|
color-scheme: dark;
|
|
@@ -1499,6 +1541,12 @@
|
|
|
1499
1541
|
--z-modal: 1050;
|
|
1500
1542
|
--z-popover: 1060;
|
|
1501
1543
|
--z-tooltip: 1070;
|
|
1544
|
+
|
|
1545
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
1546
|
+
--page-hero-bg: #101828;
|
|
1547
|
+
--page-hero-ink: #f0f4ff;
|
|
1548
|
+
--page-band-bg: #0e1422;
|
|
1549
|
+
--page-band-ink: #f0f4ff;
|
|
1502
1550
|
}
|
|
1503
1551
|
:root[data-theme=glass-light] {
|
|
1504
1552
|
color-scheme: light;
|
|
@@ -1701,6 +1749,12 @@
|
|
|
1701
1749
|
--z-modal: 1050;
|
|
1702
1750
|
--z-popover: 1060;
|
|
1703
1751
|
--z-tooltip: 1070;
|
|
1752
|
+
|
|
1753
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
1754
|
+
--page-hero-bg: #ebe5fd;
|
|
1755
|
+
--page-hero-ink: #1d1d1f;
|
|
1756
|
+
--page-band-bg: #eee9fe;
|
|
1757
|
+
--page-band-ink: #1d1d1f;
|
|
1704
1758
|
}
|
|
1705
1759
|
:root[data-theme=graphite] {
|
|
1706
1760
|
color-scheme: light dark;
|
|
@@ -1865,6 +1919,12 @@
|
|
|
1865
1919
|
--z-modal: 1050;
|
|
1866
1920
|
--z-popover: 1060;
|
|
1867
1921
|
--z-tooltip: 1070;
|
|
1922
|
+
|
|
1923
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
1924
|
+
--page-hero-bg: light-dark(#e8ebef, #1a212a);
|
|
1925
|
+
--page-hero-ink: light-dark(#1a1f26, #f5f5f7);
|
|
1926
|
+
--page-band-bg: light-dark(#eceff2, #1a1e24);
|
|
1927
|
+
--page-band-ink: light-dark(#1a1f26, #f5f5f7);
|
|
1868
1928
|
}
|
|
1869
1929
|
:root[data-theme=graphite-dark] {
|
|
1870
1930
|
color-scheme: dark;
|
|
@@ -2057,6 +2117,12 @@
|
|
|
2057
2117
|
--z-modal: 1050;
|
|
2058
2118
|
--z-popover: 1060;
|
|
2059
2119
|
--z-tooltip: 1070;
|
|
2120
|
+
|
|
2121
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
2122
|
+
--page-hero-bg: #1a212a;
|
|
2123
|
+
--page-hero-ink: #f5f5f7;
|
|
2124
|
+
--page-band-bg: #1a1e24;
|
|
2125
|
+
--page-band-ink: #f5f5f7;
|
|
2060
2126
|
}
|
|
2061
2127
|
:root[data-theme=graphite-light] {
|
|
2062
2128
|
color-scheme: light;
|
|
@@ -2239,6 +2305,12 @@
|
|
|
2239
2305
|
--z-modal: 1050;
|
|
2240
2306
|
--z-popover: 1060;
|
|
2241
2307
|
--z-tooltip: 1070;
|
|
2308
|
+
|
|
2309
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
2310
|
+
--page-hero-bg: #e8ebef;
|
|
2311
|
+
--page-hero-ink: #1a1f26;
|
|
2312
|
+
--page-band-bg: #eceff2;
|
|
2313
|
+
--page-band-ink: #1a1f26;
|
|
2242
2314
|
}
|
|
2243
2315
|
:root[data-theme=press] {
|
|
2244
2316
|
color-scheme: light dark;
|
|
@@ -2649,6 +2721,12 @@
|
|
|
2649
2721
|
--card-border: 1px solid var(--hair); /* thin rule instead */
|
|
2650
2722
|
--input-radius: var(--r-sm); /* 2px */
|
|
2651
2723
|
--modal-radius: var(--r-md); /* 3px */
|
|
2724
|
+
|
|
2725
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
2726
|
+
--page-hero-bg: #1c1c1c;
|
|
2727
|
+
--page-hero-ink: #fafaf7;
|
|
2728
|
+
--page-band-bg: #161616;
|
|
2729
|
+
--page-band-ink: #fafaf7;
|
|
2652
2730
|
}
|
|
2653
2731
|
:root[data-theme=press-light] {
|
|
2654
2732
|
color-scheme: light;
|
|
@@ -2859,6 +2937,12 @@
|
|
|
2859
2937
|
--card-border: 1px solid var(--hair); /* thin ink rule instead */
|
|
2860
2938
|
--input-radius: var(--r-sm); /* 2px — text field */
|
|
2861
2939
|
--modal-radius: var(--r-md); /* 3px — still tight */
|
|
2940
|
+
|
|
2941
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
2942
|
+
--page-hero-bg: #ededea;
|
|
2943
|
+
--page-hero-ink: #0a0a0a;
|
|
2944
|
+
--page-band-bg: #f2f2ef;
|
|
2945
|
+
--page-band-ink: #0a0a0a;
|
|
2862
2946
|
}
|
|
2863
2947
|
:root[data-theme=prism] {
|
|
2864
2948
|
color-scheme: light dark;
|
|
@@ -3027,6 +3111,12 @@
|
|
|
3027
3111
|
--card-border: 1px solid var(--hair);
|
|
3028
3112
|
--input-radius: var(--r-md);
|
|
3029
3113
|
--modal-radius: var(--r-lg);
|
|
3114
|
+
|
|
3115
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
3116
|
+
--page-hero-bg: light-dark(#f2f6fe, #0c1019);
|
|
3117
|
+
--page-hero-ink: light-dark(#09090b, #fafafa);
|
|
3118
|
+
--page-band-bg: light-dark(#f7fafe, #0b0d13);
|
|
3119
|
+
--page-band-ink: light-dark(#09090b, #fafafa);
|
|
3030
3120
|
}
|
|
3031
3121
|
:root[data-theme=prism-dark] {
|
|
3032
3122
|
color-scheme: dark;
|
|
@@ -3210,6 +3300,12 @@
|
|
|
3210
3300
|
--card-border: 1px solid var(--hair);
|
|
3211
3301
|
--input-radius: var(--r-md);
|
|
3212
3302
|
--modal-radius: var(--r-lg);
|
|
3303
|
+
|
|
3304
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
3305
|
+
--page-hero-bg: #0c1019;
|
|
3306
|
+
--page-hero-ink: #fafafa;
|
|
3307
|
+
--page-band-bg: #0b0d13;
|
|
3308
|
+
--page-band-ink: #fafafa;
|
|
3213
3309
|
}
|
|
3214
3310
|
:root[data-theme=prism-light] {
|
|
3215
3311
|
color-scheme: light;
|
|
@@ -3393,6 +3489,12 @@
|
|
|
3393
3489
|
--card-border: 1px solid var(--hair);
|
|
3394
3490
|
--input-radius: var(--r-md);
|
|
3395
3491
|
--modal-radius: var(--r-lg);
|
|
3492
|
+
|
|
3493
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
3494
|
+
--page-hero-bg: #f2f6fe;
|
|
3495
|
+
--page-hero-ink: #09090b;
|
|
3496
|
+
--page-band-bg: #f7fafe;
|
|
3497
|
+
--page-band-ink: #09090b;
|
|
3396
3498
|
}
|
|
3397
3499
|
:root[data-theme=sketchbook] {
|
|
3398
3500
|
color-scheme: light dark;
|
|
@@ -3554,6 +3656,12 @@
|
|
|
3554
3656
|
--z-modal: 1050;
|
|
3555
3657
|
--z-popover: 1060;
|
|
3556
3658
|
--z-tooltip: 1070;
|
|
3659
|
+
|
|
3660
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
3661
|
+
--page-hero-bg: light-dark(#eae8e2, #1f1f1f);
|
|
3662
|
+
--page-hero-ink: light-dark(#2a241e, #f4efe2);
|
|
3663
|
+
--page-band-bg: light-dark(#efede5, #1d1c1b);
|
|
3664
|
+
--page-band-ink: light-dark(#2a241e, #f4efe2);
|
|
3557
3665
|
}
|
|
3558
3666
|
:root[data-theme=sketchbook-dark] {
|
|
3559
3667
|
color-scheme: dark;
|
|
@@ -3736,6 +3844,12 @@
|
|
|
3736
3844
|
--z-modal: 1050;
|
|
3737
3845
|
--z-popover: 1060;
|
|
3738
3846
|
--z-tooltip: 1070;
|
|
3847
|
+
|
|
3848
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
3849
|
+
--page-hero-bg: #1f1f1f;
|
|
3850
|
+
--page-hero-ink: #f4efe2;
|
|
3851
|
+
--page-band-bg: #1d1c1b;
|
|
3852
|
+
--page-band-ink: #f4efe2;
|
|
3739
3853
|
}
|
|
3740
3854
|
:root[data-theme=sketchbook-light] {
|
|
3741
3855
|
color-scheme: light;
|
|
@@ -3927,6 +4041,12 @@
|
|
|
3927
4041
|
--space-7: calc(var(--space-unit) * 24);
|
|
3928
4042
|
--space-8: calc(var(--space-unit) * 32);
|
|
3929
4043
|
--space-9: calc(var(--space-unit) * 48);
|
|
4044
|
+
|
|
4045
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
4046
|
+
--page-hero-bg: #eae8e2;
|
|
4047
|
+
--page-hero-ink: #2a241e;
|
|
4048
|
+
--page-band-bg: #efede5;
|
|
4049
|
+
--page-band-ink: #2a241e;
|
|
3930
4050
|
}
|
|
3931
4051
|
:root[data-theme=terminal] {
|
|
3932
4052
|
color-scheme: dark;
|
|
@@ -4095,6 +4215,12 @@
|
|
|
4095
4215
|
--input-radius: 0;
|
|
4096
4216
|
--card-shadow: var(--glow-sm);
|
|
4097
4217
|
--card-border: 1px solid var(--ink-faint);
|
|
4218
|
+
|
|
4219
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
4220
|
+
--page-hero-bg: #111a19;
|
|
4221
|
+
--page-hero-ink: #4fe078;
|
|
4222
|
+
--page-band-bg: #0e1513;
|
|
4223
|
+
--page-band-ink: #4fe078;
|
|
4098
4224
|
}
|
|
4099
4225
|
:root[data-theme=terminal-dark] {
|
|
4100
4226
|
color-scheme: dark;
|
|
@@ -4298,6 +4424,12 @@
|
|
|
4298
4424
|
--input-radius: 0;
|
|
4299
4425
|
--card-shadow: var(--glow-sm);
|
|
4300
4426
|
--card-border: 1px solid var(--ink-faint);
|
|
4427
|
+
|
|
4428
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
4429
|
+
--page-hero-bg: #111a19;
|
|
4430
|
+
--page-hero-ink: #4fe078;
|
|
4431
|
+
--page-band-bg: #0e1513;
|
|
4432
|
+
--page-band-ink: #4fe078;
|
|
4301
4433
|
}
|
|
4302
4434
|
:root[data-theme=terminal-light] {
|
|
4303
4435
|
color-scheme: light;
|
|
@@ -4459,4 +4591,10 @@
|
|
|
4459
4591
|
--z-modal: 1050;
|
|
4460
4592
|
--z-popover: 1060;
|
|
4461
4593
|
--z-tooltip: 1070;
|
|
4594
|
+
|
|
4595
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
4596
|
+
--page-hero-bg: #dadfe4;
|
|
4597
|
+
--page-hero-ink: #1a1a1a;
|
|
4598
|
+
--page-band-bg: #e0e3e6;
|
|
4599
|
+
--page-band-ink: #1a1a1a;
|
|
4462
4600
|
}
|
|
@@ -162,4 +162,10 @@
|
|
|
162
162
|
--z-modal: 1050;
|
|
163
163
|
--z-popover: 1060;
|
|
164
164
|
--z-tooltip: 1070;
|
|
165
|
+
|
|
166
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
167
|
+
--page-hero-bg: light-dark(#f2f6fe, #121e36);
|
|
168
|
+
--page-hero-ink: light-dark(#0f172a, #f8fafc);
|
|
169
|
+
--page-band-bg: light-dark(#f7fafe, #111b31);
|
|
170
|
+
--page-band-ink: light-dark(#0f172a, #f8fafc);
|
|
165
171
|
}
|
|
@@ -172,4 +172,10 @@
|
|
|
172
172
|
--space-7: calc(var(--space-unit) * 24);
|
|
173
173
|
--space-8: calc(var(--space-unit) * 32);
|
|
174
174
|
--space-9: calc(var(--space-unit) * 48);
|
|
175
|
+
|
|
176
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
177
|
+
--page-hero-bg: #121e36;
|
|
178
|
+
--page-hero-ink: #f8fafc;
|
|
179
|
+
--page-band-bg: #111b31;
|
|
180
|
+
--page-band-ink: #f8fafc;
|
|
175
181
|
}
|
|
@@ -172,4 +172,10 @@
|
|
|
172
172
|
--space-7: calc(var(--space-unit) * 24);
|
|
173
173
|
--space-8: calc(var(--space-unit) * 32);
|
|
174
174
|
--space-9: calc(var(--space-unit) * 48);
|
|
175
|
+
|
|
176
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
177
|
+
--page-hero-bg: #f2f6fe;
|
|
178
|
+
--page-hero-ink: #0f172a;
|
|
179
|
+
--page-band-bg: #f7fafe;
|
|
180
|
+
--page-band-ink: #0f172a;
|
|
175
181
|
}
|
|
@@ -173,4 +173,10 @@
|
|
|
173
173
|
--input-radius: var(--r-sm);
|
|
174
174
|
--modal-radius: var(--r-lg);
|
|
175
175
|
--tooltip-radius: var(--r-sm);
|
|
176
|
+
|
|
177
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
178
|
+
--page-hero-bg: light-dark(#e6ecf3, #1e252c);
|
|
179
|
+
--page-hero-ink: light-dark(#1d1d1f, #f5f5f7);
|
|
180
|
+
--page-band-bg: light-dark(#ecf0f5, #1e2226);
|
|
181
|
+
--page-band-ink: light-dark(#1d1d1f, #f5f5f7);
|
|
176
182
|
}
|
|
@@ -208,4 +208,10 @@
|
|
|
208
208
|
--input-radius: var(--r-sm); /* 8px — text field */
|
|
209
209
|
--modal-radius: var(--r-lg); /* matches panel */
|
|
210
210
|
--tooltip-radius: var(--r-sm); /* bezel tooltip */
|
|
211
|
+
|
|
212
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
213
|
+
--page-hero-bg: #1e252c;
|
|
214
|
+
--page-hero-ink: #f5f5f7;
|
|
215
|
+
--page-band-bg: #1e2226;
|
|
216
|
+
--page-band-ink: #f5f5f7;
|
|
211
217
|
}
|
|
@@ -235,4 +235,10 @@
|
|
|
235
235
|
--input-radius: var(--r-sm); /* 8px — text field */
|
|
236
236
|
--modal-radius: var(--r-lg); /* matches panel */
|
|
237
237
|
--tooltip-radius: var(--r-sm); /* bezel tooltip */
|
|
238
|
+
|
|
239
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
240
|
+
--page-hero-bg: #e6ecf3;
|
|
241
|
+
--page-hero-ink: #1d1d1f;
|
|
242
|
+
--page-band-bg: #ecf0f5;
|
|
243
|
+
--page-band-ink: #1d1d1f;
|
|
238
244
|
}
|
|
@@ -198,4 +198,10 @@
|
|
|
198
198
|
--z-modal: 1050;
|
|
199
199
|
--z-popover: 1060;
|
|
200
200
|
--z-tooltip: 1070;
|
|
201
|
+
|
|
202
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
203
|
+
--page-hero-bg: light-dark(#ebe5fd, #101828);
|
|
204
|
+
--page-hero-ink: light-dark(#1d1d1f, #f0f4ff);
|
|
205
|
+
--page-band-bg: light-dark(#eee9fe, #0e1422);
|
|
206
|
+
--page-band-ink: light-dark(#1d1d1f, #f0f4ff);
|
|
201
207
|
}
|
|
@@ -209,4 +209,10 @@
|
|
|
209
209
|
--z-modal: 1050;
|
|
210
210
|
--z-popover: 1060;
|
|
211
211
|
--z-tooltip: 1070;
|
|
212
|
+
|
|
213
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
214
|
+
--page-hero-bg: #101828;
|
|
215
|
+
--page-hero-ink: #f0f4ff;
|
|
216
|
+
--page-band-bg: #0e1422;
|
|
217
|
+
--page-band-ink: #f0f4ff;
|
|
212
218
|
}
|
|
@@ -237,4 +237,10 @@
|
|
|
237
237
|
--z-modal: 1050;
|
|
238
238
|
--z-popover: 1060;
|
|
239
239
|
--z-tooltip: 1070;
|
|
240
|
+
|
|
241
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
242
|
+
--page-hero-bg: #ebe5fd;
|
|
243
|
+
--page-hero-ink: #1d1d1f;
|
|
244
|
+
--page-band-bg: #eee9fe;
|
|
245
|
+
--page-band-ink: #1d1d1f;
|
|
240
246
|
}
|
|
@@ -163,4 +163,10 @@
|
|
|
163
163
|
--z-modal: 1050;
|
|
164
164
|
--z-popover: 1060;
|
|
165
165
|
--z-tooltip: 1070;
|
|
166
|
+
|
|
167
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
168
|
+
--page-hero-bg: light-dark(#e8ebef, #1a212a);
|
|
169
|
+
--page-hero-ink: light-dark(#1a1f26, #f5f5f7);
|
|
170
|
+
--page-band-bg: light-dark(#eceff2, #1a1e24);
|
|
171
|
+
--page-band-ink: light-dark(#1a1f26, #f5f5f7);
|
|
166
172
|
}
|
|
@@ -231,4 +231,10 @@
|
|
|
231
231
|
--z-modal: 1050;
|
|
232
232
|
--z-popover: 1060;
|
|
233
233
|
--z-tooltip: 1070;
|
|
234
|
+
|
|
235
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
236
|
+
--page-hero-bg: #1a212a;
|
|
237
|
+
--page-hero-ink: #f5f5f7;
|
|
238
|
+
--page-band-bg: #1a1e24;
|
|
239
|
+
--page-band-ink: #f5f5f7;
|
|
234
240
|
}
|
|
@@ -199,4 +199,10 @@
|
|
|
199
199
|
--z-modal: 1050;
|
|
200
200
|
--z-popover: 1060;
|
|
201
201
|
--z-tooltip: 1070;
|
|
202
|
+
|
|
203
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
204
|
+
--page-hero-bg: #e8ebef;
|
|
205
|
+
--page-hero-ink: #1a1f26;
|
|
206
|
+
--page-band-bg: #eceff2;
|
|
207
|
+
--page-band-ink: #1a1f26;
|
|
202
208
|
}
|
|
@@ -218,4 +218,10 @@
|
|
|
218
218
|
--print-muted: #6B6963; /* warm editorial gray */
|
|
219
219
|
/* stylelint-enable no-invalid-position-declaration */
|
|
220
220
|
}
|
|
221
|
+
|
|
222
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
223
|
+
--page-hero-bg: light-dark(#ededea, #1c1c1c);
|
|
224
|
+
--page-hero-ink: light-dark(#0a0a0a, #fafaf7);
|
|
225
|
+
--page-band-bg: light-dark(#f2f2ef, #161616);
|
|
226
|
+
--page-band-ink: light-dark(#0a0a0a, #fafaf7);
|
|
221
227
|
}
|
|
@@ -207,4 +207,10 @@
|
|
|
207
207
|
--card-border: 1px solid var(--hair); /* thin rule instead */
|
|
208
208
|
--input-radius: var(--r-sm); /* 2px */
|
|
209
209
|
--modal-radius: var(--r-md); /* 3px */
|
|
210
|
+
|
|
211
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
212
|
+
--page-hero-bg: #1c1c1c;
|
|
213
|
+
--page-hero-ink: #fafaf7;
|
|
214
|
+
--page-band-bg: #161616;
|
|
215
|
+
--page-band-ink: #fafaf7;
|
|
210
216
|
}
|
|
@@ -243,4 +243,10 @@
|
|
|
243
243
|
--card-border: 1px solid var(--hair); /* thin ink rule instead */
|
|
244
244
|
--input-radius: var(--r-sm); /* 2px — text field */
|
|
245
245
|
--modal-radius: var(--r-md); /* 3px — still tight */
|
|
246
|
+
|
|
247
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
248
|
+
--page-hero-bg: #ededea;
|
|
249
|
+
--page-hero-ink: #0a0a0a;
|
|
250
|
+
--page-band-bg: #f2f2ef;
|
|
251
|
+
--page-band-ink: #0a0a0a;
|
|
246
252
|
}
|
|
@@ -167,4 +167,10 @@
|
|
|
167
167
|
--card-border: 1px solid var(--hair);
|
|
168
168
|
--input-radius: var(--r-md);
|
|
169
169
|
--modal-radius: var(--r-lg);
|
|
170
|
+
|
|
171
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
172
|
+
--page-hero-bg: light-dark(#f2f6fe, #0c1019);
|
|
173
|
+
--page-hero-ink: light-dark(#09090b, #fafafa);
|
|
174
|
+
--page-band-bg: light-dark(#f7fafe, #0b0d13);
|
|
175
|
+
--page-band-ink: light-dark(#09090b, #fafafa);
|
|
170
176
|
}
|
|
@@ -193,4 +193,10 @@
|
|
|
193
193
|
--card-border: 1px solid var(--hair);
|
|
194
194
|
--input-radius: var(--r-md);
|
|
195
195
|
--modal-radius: var(--r-lg);
|
|
196
|
+
|
|
197
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
198
|
+
--page-hero-bg: #0c1019;
|
|
199
|
+
--page-hero-ink: #fafafa;
|
|
200
|
+
--page-band-bg: #0b0d13;
|
|
201
|
+
--page-band-ink: #fafafa;
|
|
196
202
|
}
|
|
@@ -196,4 +196,10 @@
|
|
|
196
196
|
--card-border: 1px solid var(--hair);
|
|
197
197
|
--input-radius: var(--r-md);
|
|
198
198
|
--modal-radius: var(--r-lg);
|
|
199
|
+
|
|
200
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
201
|
+
--page-hero-bg: #f2f6fe;
|
|
202
|
+
--page-hero-ink: #09090b;
|
|
203
|
+
--page-band-bg: #f7fafe;
|
|
204
|
+
--page-band-ink: #09090b;
|
|
199
205
|
}
|
|
@@ -160,4 +160,10 @@
|
|
|
160
160
|
--z-modal: 1050;
|
|
161
161
|
--z-popover: 1060;
|
|
162
162
|
--z-tooltip: 1070;
|
|
163
|
+
|
|
164
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
165
|
+
--page-hero-bg: light-dark(#eae8e2, #1f1f1f);
|
|
166
|
+
--page-hero-ink: light-dark(#2a241e, #f4efe2);
|
|
167
|
+
--page-band-bg: light-dark(#efede5, #1d1c1b);
|
|
168
|
+
--page-band-ink: light-dark(#2a241e, #f4efe2);
|
|
163
169
|
}
|
|
@@ -202,4 +202,10 @@
|
|
|
202
202
|
--z-modal: 1050;
|
|
203
203
|
--z-popover: 1060;
|
|
204
204
|
--z-tooltip: 1070;
|
|
205
|
+
|
|
206
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
207
|
+
--page-hero-bg: #1f1f1f;
|
|
208
|
+
--page-hero-ink: #f4efe2;
|
|
209
|
+
--page-band-bg: #1d1c1b;
|
|
210
|
+
--page-band-ink: #f4efe2;
|
|
205
211
|
}
|
|
@@ -189,4 +189,10 @@
|
|
|
189
189
|
--space-7: calc(var(--space-unit) * 24);
|
|
190
190
|
--space-8: calc(var(--space-unit) * 32);
|
|
191
191
|
--space-9: calc(var(--space-unit) * 48);
|
|
192
|
+
|
|
193
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
194
|
+
--page-hero-bg: #eae8e2;
|
|
195
|
+
--page-hero-ink: #2a241e;
|
|
196
|
+
--page-band-bg: #efede5;
|
|
197
|
+
--page-band-ink: #2a241e;
|
|
192
198
|
}
|
|
@@ -167,4 +167,10 @@
|
|
|
167
167
|
--input-radius: 0;
|
|
168
168
|
--card-shadow: var(--glow-sm);
|
|
169
169
|
--card-border: 1px solid var(--ink-faint);
|
|
170
|
+
|
|
171
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
172
|
+
--page-hero-bg: #111a19;
|
|
173
|
+
--page-hero-ink: #4fe078;
|
|
174
|
+
--page-band-bg: #0e1513;
|
|
175
|
+
--page-band-ink: #4fe078;
|
|
170
176
|
}
|
|
@@ -237,4 +237,10 @@
|
|
|
237
237
|
--input-radius: 0;
|
|
238
238
|
--card-shadow: var(--glow-sm);
|
|
239
239
|
--card-border: 1px solid var(--ink-faint);
|
|
240
|
+
|
|
241
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
242
|
+
--page-hero-bg: #111a19;
|
|
243
|
+
--page-hero-ink: #4fe078;
|
|
244
|
+
--page-band-bg: #0e1513;
|
|
245
|
+
--page-band-ink: #4fe078;
|
|
240
246
|
}
|
|
@@ -160,4 +160,10 @@
|
|
|
160
160
|
--z-modal: 1050;
|
|
161
161
|
--z-popover: 1060;
|
|
162
162
|
--z-tooltip: 1070;
|
|
163
|
+
|
|
164
|
+
/* page surfaces — derived, see scripts/derive-page-surfaces.mjs */
|
|
165
|
+
--page-hero-bg: #dadfe4;
|
|
166
|
+
--page-hero-ink: #1a1a1a;
|
|
167
|
+
--page-band-bg: #e0e3e6;
|
|
168
|
+
--page-band-ink: #1a1a1a;
|
|
163
169
|
}
|
package/scripts/audit-pairs.json
CHANGED
|
@@ -1,25 +1,173 @@
|
|
|
1
1
|
[
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{
|
|
2
|
+
{
|
|
3
|
+
"fg": "--text-primary",
|
|
4
|
+
"bg": "--paper",
|
|
5
|
+
"required": 4.5,
|
|
6
|
+
"kind": "text",
|
|
7
|
+
"note": "primary body text on the page background"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"fg": "--text-secondary",
|
|
11
|
+
"bg": "--paper",
|
|
12
|
+
"required": 4.5,
|
|
13
|
+
"kind": "text",
|
|
14
|
+
"note": "secondary body text on the page background"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"fg": "--text-tertiary",
|
|
18
|
+
"bg": "--paper",
|
|
19
|
+
"required": 3,
|
|
20
|
+
"kind": "large-text",
|
|
21
|
+
"warnIfBelow": 4.5,
|
|
22
|
+
"note": "tertiary text - legal at large sizes; warn if used as body"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"fg": "--text-muted",
|
|
26
|
+
"bg": "--paper",
|
|
27
|
+
"required": 4.5,
|
|
28
|
+
"kind": "text",
|
|
29
|
+
"note": "muted UI text on the page background"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"fg": "--ink",
|
|
33
|
+
"bg": "--paper",
|
|
34
|
+
"required": 4.5,
|
|
35
|
+
"kind": "text",
|
|
36
|
+
"note": "native ink on native paper"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"fg": "--ink-soft",
|
|
40
|
+
"bg": "--paper",
|
|
41
|
+
"required": 4.5,
|
|
42
|
+
"kind": "text",
|
|
43
|
+
"note": "soft ink on native paper"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"fg": "--ink-faint",
|
|
47
|
+
"bg": "--paper",
|
|
48
|
+
"required": 3,
|
|
49
|
+
"kind": "large-text",
|
|
50
|
+
"warnIfBelow": 4.5,
|
|
51
|
+
"note": "faint ink - large/UI only; warn if used as body"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"fg": "--text-link",
|
|
55
|
+
"bg": "--paper",
|
|
56
|
+
"required": 4.5,
|
|
57
|
+
"kind": "text",
|
|
58
|
+
"note": "inline link color on the page background"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"fg": "--text-inverse",
|
|
62
|
+
"bg": "--action-primary-default",
|
|
63
|
+
"required": 4.5,
|
|
64
|
+
"kind": "text",
|
|
65
|
+
"note": "button label on the primary action surface"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"fg": "--text-inverse",
|
|
69
|
+
"bg": "--ai",
|
|
70
|
+
"required": 4.5,
|
|
71
|
+
"kind": "text",
|
|
72
|
+
"note": "inverse text on the AI/brand accent surface"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"fg": "--success-text",
|
|
76
|
+
"bg": "--success-subtle",
|
|
77
|
+
"required": 4.5,
|
|
78
|
+
"kind": "text",
|
|
79
|
+
"note": "success message text on its subtle background"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"fg": "--warning-text",
|
|
83
|
+
"bg": "--warning-subtle",
|
|
84
|
+
"required": 4.5,
|
|
85
|
+
"kind": "text",
|
|
86
|
+
"note": "warning message text on its subtle background"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"fg": "--error-text",
|
|
90
|
+
"bg": "--error-subtle",
|
|
91
|
+
"required": 4.5,
|
|
92
|
+
"kind": "text",
|
|
93
|
+
"note": "error message text on its subtle background"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"fg": "--info-text",
|
|
97
|
+
"bg": "--info-subtle",
|
|
98
|
+
"required": 4.5,
|
|
99
|
+
"kind": "text",
|
|
100
|
+
"note": "info message text on its subtle background"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"fg": "--border-default",
|
|
104
|
+
"bg": "--paper",
|
|
105
|
+
"required": 3,
|
|
106
|
+
"kind": "non-text",
|
|
107
|
+
"decorative": true,
|
|
108
|
+
"note": "default border against the page background - decorative; WCAG 2.2 SC 1.4.11 applies only to graphical objects essential for understanding content"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"fg": "--border-focus",
|
|
112
|
+
"bg": "--paper",
|
|
113
|
+
"required": 3,
|
|
114
|
+
"kind": "non-text",
|
|
115
|
+
"note": "focus ring against the page background"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"fg": "--shu",
|
|
119
|
+
"bg": "--paper",
|
|
120
|
+
"required": 3,
|
|
121
|
+
"kind": "non-text",
|
|
122
|
+
"note": "seal accent - must read as a UI mark on paper"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"fg": "--code-ink",
|
|
126
|
+
"bg": "--code-bg",
|
|
127
|
+
"required": 4.5,
|
|
128
|
+
"kind": "text",
|
|
129
|
+
"note": "default code text on the code surface"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"fg": "--code-muted",
|
|
133
|
+
"bg": "--code-bg",
|
|
134
|
+
"required": 4.5,
|
|
135
|
+
"kind": "text",
|
|
136
|
+
"note": "code comments on the code surface - read as prose, so full text contrast"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"fg": "--code-accent",
|
|
140
|
+
"bg": "--code-bg",
|
|
141
|
+
"required": 4.5,
|
|
142
|
+
"kind": "text",
|
|
143
|
+
"note": "keyword / accent token on the code surface"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"fg": "--code-blue",
|
|
147
|
+
"bg": "--code-bg",
|
|
148
|
+
"required": 4.5,
|
|
149
|
+
"kind": "text",
|
|
150
|
+
"note": "blue syntax token on the code surface"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"fg": "--code-green",
|
|
154
|
+
"bg": "--code-bg",
|
|
155
|
+
"required": 4.5,
|
|
156
|
+
"kind": "text",
|
|
157
|
+
"note": "green syntax token (strings) on the code surface"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"fg": "--page-hero-ink",
|
|
161
|
+
"bg": "--page-hero-bg",
|
|
162
|
+
"required": 4.5,
|
|
163
|
+
"kind": "text",
|
|
164
|
+
"note": "text on the hero page surface - graded only when the theme declares the slot"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"fg": "--page-band-ink",
|
|
168
|
+
"bg": "--page-band-bg",
|
|
169
|
+
"required": 4.5,
|
|
170
|
+
"kind": "text",
|
|
171
|
+
"note": "text on the band page surface - graded only when the theme declares the slot"
|
|
172
|
+
}
|
|
25
173
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"description": "Authoritative token contract for css-is-awesome themes. Every theme.css MUST declare every token in `required`. Tokens in `optional` are reported by the validator as info, never as failures
|
|
2
|
+
"version": "1.3",
|
|
3
|
+
"description": "Authoritative token contract for css-is-awesome themes. Every theme.css MUST declare every token in `required`. Tokens in `optional` are reported by the validator as info, never as failures — the library or the theme generator supplies a default. Source of truth is CONTRACT.md (human-readable) and public/theme.css (Sketchbook reference). Contract 1.3 (2026-09-24): the page-surfaces feature adds eight optional tokens for the hero and band surfaces, and --background-hero is deprecated in favour of --page-hero-bg (kept valid, removed no earlier than contract 2).",
|
|
4
4
|
"required": [
|
|
5
5
|
"--action-primary-active",
|
|
6
6
|
"--action-primary-default",
|
|
@@ -151,6 +151,14 @@
|
|
|
151
151
|
"--logo-monochrome",
|
|
152
152
|
"--logo-wordmark",
|
|
153
153
|
"--modal-radius",
|
|
154
|
+
"--page-band-bg",
|
|
155
|
+
"--page-band-image",
|
|
156
|
+
"--page-band-ink",
|
|
157
|
+
"--page-band-scrim",
|
|
158
|
+
"--page-hero-bg",
|
|
159
|
+
"--page-hero-image",
|
|
160
|
+
"--page-hero-ink",
|
|
161
|
+
"--page-hero-scrim",
|
|
154
162
|
"--print-ink",
|
|
155
163
|
"--print-line",
|
|
156
164
|
"--print-muted",
|
|
@@ -181,7 +189,7 @@
|
|
|
181
189
|
]
|
|
182
190
|
},
|
|
183
191
|
"spacing-aliases": {
|
|
184
|
-
"enables": "T-shirt spacing names (2xs
|
|
192
|
+
"enables": "T-shirt spacing names (2xs–xl) for consumer CSS that prefers them; the library reads the numbered scale, so these are pure aliases.",
|
|
185
193
|
"tokens": [
|
|
186
194
|
"--space-2xs",
|
|
187
195
|
"--space-xs",
|
|
@@ -236,7 +244,6 @@
|
|
|
236
244
|
"enables": "Extra background layers (elevated, hero, overlay, scrim) for themes that want more than the required surface set; each falls back to a required surface.",
|
|
237
245
|
"tokens": [
|
|
238
246
|
"--background-elevated",
|
|
239
|
-
"--background-hero",
|
|
240
247
|
"--background-overlay",
|
|
241
248
|
"--background-scrim"
|
|
242
249
|
]
|
|
@@ -264,6 +271,28 @@
|
|
|
264
271
|
"tokens": [
|
|
265
272
|
"--touch-target-min"
|
|
266
273
|
]
|
|
274
|
+
},
|
|
275
|
+
"page-surfaces": {
|
|
276
|
+
"enables": "Two page-level surfaces a theme owns outright: a hero for the front page and a band for section stripes and footers. Each carries a background colour, an optional gradient or url() image, an ink colour for text on it, and a scrim that keeps that text legible over an image. Applied only via cia.surface() or [data-surface] - declaring them changes nothing on its own.",
|
|
277
|
+
"tokens": [
|
|
278
|
+
"--page-hero-bg",
|
|
279
|
+
"--page-hero-image",
|
|
280
|
+
"--page-hero-ink",
|
|
281
|
+
"--page-hero-scrim",
|
|
282
|
+
"--page-band-bg",
|
|
283
|
+
"--page-band-image",
|
|
284
|
+
"--page-band-ink",
|
|
285
|
+
"--page-band-scrim",
|
|
286
|
+
"--background-hero"
|
|
287
|
+
]
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
"deprecated": {
|
|
291
|
+
"--background-hero": {
|
|
292
|
+
"replacedBy": "--page-hero-bg",
|
|
293
|
+
"since": "1.3",
|
|
294
|
+
"removeIn": "2",
|
|
295
|
+
"note": "Was never read by the library. --page-hero-bg falls back through it, so an existing declaration keeps working untouched."
|
|
267
296
|
}
|
|
268
297
|
}
|
|
269
298
|
}
|
package/scss/_layout.scss
CHANGED
|
@@ -595,3 +595,132 @@ $_flow: (
|
|
|
595
595
|
margin-inline-start: auto;
|
|
596
596
|
}
|
|
597
597
|
}
|
|
598
|
+
|
|
599
|
+
// ============================================================================
|
|
600
|
+
// PAGE SURFACES — hero + band
|
|
601
|
+
// ============================================================================
|
|
602
|
+
// Two page-level backgrounds a theme can own outright: `hero` for a landing
|
|
603
|
+
// page, `band` for a section stripe or a footer. Each slot carries four
|
|
604
|
+
// optional tokens — background colour, image, ink, scrim.
|
|
605
|
+
//
|
|
606
|
+
// NOTHING HERE RUNS UNTIL YOU ASK FOR IT. cia never applies a page surface
|
|
607
|
+
// automatically: not on `body`, not from a layout mixin, not from the reset.
|
|
608
|
+
// That guarantee is why adding these tokens to every shipped theme cannot
|
|
609
|
+
// change an existing consumer's page, and `tests/no-auto-surface.test.mjs`
|
|
610
|
+
// asserts it against the compiled bundles so it cannot be broken by accident.
|
|
611
|
+
//
|
|
612
|
+
// Every token falls back, so a theme that declares none of them still renders:
|
|
613
|
+
// background → the deprecated --background-hero, then the page surface
|
|
614
|
+
// ink → --text-primary
|
|
615
|
+
// image → none (and with no image, no scrim is drawn)
|
|
616
|
+
//
|
|
617
|
+
// The scrim is layered as a gradient in the SAME background-image as the
|
|
618
|
+
// image rather than as a pseudo-element or an extra wrapper, so `surface`
|
|
619
|
+
// works identically on <body> and on a <section>, and stacking context,
|
|
620
|
+
// overflow and child positioning are left alone.
|
|
621
|
+
|
|
622
|
+
$_surface-slots: (hero, band) !default;
|
|
623
|
+
|
|
624
|
+
@mixin surface($slot: hero, $image: null, $scrim: null) {
|
|
625
|
+
@if not list.index($_surface-slots, $slot) {
|
|
626
|
+
@error "surface(): unknown slot '#{$slot}'. Expected one of: hero, band.";
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
$bg: var(--page-#{$slot}-bg, var(--background-#{$slot}, var(--surface-default, var(--paper))));
|
|
630
|
+
$ink: var(--page-#{$slot}-ink, var(--text-primary, var(--ink)));
|
|
631
|
+
|
|
632
|
+
// The scrim only paints when there is an image UNDER it. Defaulting it to a
|
|
633
|
+
// colour would put a 50% black wash over every colour-only hero — which is
|
|
634
|
+
// both wrong and a silent visual change for anyone who sets just a colour.
|
|
635
|
+
//
|
|
636
|
+
// $image given → the caller has an image, so the scrim defaults to the
|
|
637
|
+
// 50% black that keeps text legible over a photo.
|
|
638
|
+
// $image omitted → the image comes from the token (or is absent), so the
|
|
639
|
+
// scrim defaults to `transparent` and the token carries
|
|
640
|
+
// the value. The theme editor writes a scrim whenever it
|
|
641
|
+
// writes an image, so the safe default still arrives.
|
|
642
|
+
$img: var(--page-#{$slot}-image, none);
|
|
643
|
+
$scrim-default: transparent;
|
|
644
|
+
@if $image {
|
|
645
|
+
$img: $image;
|
|
646
|
+
$scrim-default: rgb(0 0 0 / 0.5);
|
|
647
|
+
}
|
|
648
|
+
$scrim-color: var(--page-#{$slot}-scrim, #{$scrim-default});
|
|
649
|
+
@if $scrim {
|
|
650
|
+
$scrim-color: $scrim;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
background-color: #{$bg};
|
|
654
|
+
background-image: linear-gradient(#{$scrim-color}, #{$scrim-color}), #{$img};
|
|
655
|
+
background-size: cover;
|
|
656
|
+
background-position: center;
|
|
657
|
+
background-repeat: no-repeat;
|
|
658
|
+
color: #{$ink};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// The attribute form of the same thing, for consumers with no Sass build.
|
|
662
|
+
// Emitted only when this mixin is called — it is not part of the reset.
|
|
663
|
+
@mixin surface-attributes {
|
|
664
|
+
@each $slot in $_surface-slots {
|
|
665
|
+
[data-surface='#{$slot}'] {
|
|
666
|
+
@include surface($slot);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// ----------------------------------------------------------------------------
|
|
672
|
+
// WAVE DIVIDER — a curved edge between two sections, pure CSS
|
|
673
|
+
// ----------------------------------------------------------------------------
|
|
674
|
+
// Draws the curve with a radial-gradient mask on a ::before/::after, so there
|
|
675
|
+
// is no SVG file to host and the shape inherits whatever colour you give it.
|
|
676
|
+
// `$direction: down` curves the edge INTO the element (a valley at the top);
|
|
677
|
+
// `up` bulges it outward. `$flip: true` puts the wave on the bottom edge.
|
|
678
|
+
//
|
|
679
|
+
// .hero { @include cia.surface(hero); @include cia.wave-divider($height: 4rem); }
|
|
680
|
+
//
|
|
681
|
+
// The wave paints in `$color`, which defaults to the NEXT section's surface so
|
|
682
|
+
// the curve reads as that section rising into this one.
|
|
683
|
+
@mixin wave-divider(
|
|
684
|
+
$height: 3rem,
|
|
685
|
+
$color: var(--surface-default, var(--paper)),
|
|
686
|
+
$direction: down,
|
|
687
|
+
$flip: false,
|
|
688
|
+
$position: after
|
|
689
|
+
) {
|
|
690
|
+
@if $direction != down and $direction != up {
|
|
691
|
+
@error "wave-divider(): $direction must be `down` or `up`, got `#{$direction}`.";
|
|
692
|
+
}
|
|
693
|
+
@if $position != after and $position != before {
|
|
694
|
+
@error "wave-divider(): $position must be `after` or `before`, got `#{$position}`.";
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
position: relative;
|
|
698
|
+
isolation: isolate;
|
|
699
|
+
|
|
700
|
+
&::#{$position} {
|
|
701
|
+
content: '';
|
|
702
|
+
position: absolute;
|
|
703
|
+
inset-inline: 0;
|
|
704
|
+
block-size: $height;
|
|
705
|
+
pointer-events: none;
|
|
706
|
+
z-index: 1;
|
|
707
|
+
|
|
708
|
+
@if $flip {
|
|
709
|
+
inset-block-start: calc(100% - #{$height});
|
|
710
|
+
} @else {
|
|
711
|
+
inset-block-end: calc(100% - #{$height});
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// An ellipse wider than the box gives a shallow, natural curve rather
|
|
715
|
+
// than the circular arc a border-radius would produce.
|
|
716
|
+
@if $direction == down {
|
|
717
|
+
background: #{$color};
|
|
718
|
+
// stylelint-disable-next-line function-no-unknown
|
|
719
|
+
mask: radial-gradient(120% #{$height} at 50% 0%, transparent 99%, #000 100%);
|
|
720
|
+
} @else {
|
|
721
|
+
background: #{$color};
|
|
722
|
+
// stylelint-disable-next-line function-no-unknown
|
|
723
|
+
mask: radial-gradient(120% #{$height} at 50% 100%, #000 99%, transparent 100%);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|