You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,7 +25,7 @@ mCSS is a CSS framework (ITCSS-based) paired with an Astro documentation site, c
25
25
26
26
## CSS cascade layers are load-bearing
27
27
28
-
The framework uses native `@layer`; the layer name (declared in `src/styles/framework/mcss.css`) decides priority, and unlayered site CSS beats every layer. Import new framework files with `layer(<name>)`; never re-enable preset-env's `cascade-layers` polyfill in `postcss.config.cjs`. Always consult [agents/css.md](agents/css.md) before adding or moving CSS files.
28
+
The framework uses native `@layer`; the layer name (declared in `src/styles/framework/mcss.css`) decides priority, and unlayered site CSS beats every layer. Import new framework files with `layer(<name>)`, except `theme.*.css` files: those wrap themselves in `@layer theme` and are activated from the consumer entry (`_global.css`), never imported by `mcss.css`. Never re-enable preset-env's `cascade-layers` polyfill in `postcss.config.cjs`. Always consult [agents/css.md](agents/css.md) before adding or moving CSS files.
Copy file name to clipboardExpand all lines: DESIGN.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -137,7 +137,7 @@ components:
137
137
138
138
mCSS is a utility-conscious CSS framework and documentation site with an ITCSS cascade, compact component classes, and design tokens stored as CSS custom properties. The visual identity is clean, technical, and documentation-first: blue interaction color, cool neutral surfaces, dense spacing, rounded-but-not-pill shapes, and system typography that keeps pages fast and readable.
139
139
140
-
The canonical token sources are `src/styles/framework/settings.tokens.css` for raw scales and `src/styles/framework/settings.theme.default.css` for semantic theme and component defaults. This file translates those tokens into the DESIGN.md format for coding agents. When the CSS and this file disagree, the CSS source files win.
140
+
The canonical token sources are `src/styles/framework/settings.tokens.css` for raw scales and `src/styles/framework/settings.ui.css` for semantic aliases and component defaults (interface tokens). This file translates those tokens into the DESIGN.md format for coding agents. When the CSS and this file disagree, the CSS source files win.
141
141
142
142
## Colors
143
143
@@ -202,13 +202,13 @@ Buttons use `.button` or `.bt`, with variants such as `.bt-primary`, `.bt-outlin
202
202
203
203
Cards use `.card` with `.card-filled` and `.card-raised` variants. Keep internal spacing on `--card-spacing` and use `.card_header`, `.card_media`, `.card_content`, and `.card_actions` for composition.
204
204
205
-
Tags, notices, avatars, headers, footers, hero controls, and the read-progress bar all have semantic custom properties in `settings.theme.default.css`. When creating a new component, add semantic tokens there before using raw scale values inside component CSS.
205
+
Tags, notices, avatars, headers, footers, hero controls, and the read-progress bar all have semantic custom properties in `settings.ui.css`. When creating a new component, add interface tokens there before using raw scale values inside component CSS.
206
206
207
207
Class naming is BEM-like with mCSS separators: `.block`, `.block_element`, `.block-modifier`, and `.is-*` state classes composed inside the block.
208
208
209
209
## Do's and Don'ts
210
210
211
-
Do preserve the native cascade-layer setup: framework files import into named layers (`settings, base, elements, global, components, pages, helpers`) via `src/styles/framework/mcss.css`; site-only files import unlayered via `src/styles/_global.css`.
211
+
Do preserve the native cascade-layer setup: framework files import into named layers (`settings, base, elements, global, components, theme, helpers`) via `src/styles/framework/mcss.css`; site-only files import unlayered via `src/styles/_global.css`.
212
212
213
213
Do add new CSS files with the correct layer prefix, such as `component.name.css` or `help.name.css`, then import them with `layer(<name>)` in `framework/mcss.css` (framework) or plainly in `_global.css` (site).
Copy file name to clipboardExpand all lines: agents/components.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@
8
8
4.**Rest spread**: `{...rest}` on the root element so consumers can set any native attribute.
9
9
5.**`data-testid`**: accepted as a prop with a sensible per-component default.
10
10
6.**States vs modifiers**: runtime states are `.is-*` classes (`.is-active`, `.is-online`); build-time variants are block modifiers (`.card-filled`). Prefer styling ARIA attributes when one exists (`[aria-current]`, `[aria-disabled]`).
11
-
7.**Theme tokens**: every themable knob has a declared default in `settings.theme.default.css`; local-only custom properties use descriptive names (`--avatar-size`, not `--w`).
11
+
7.**Interface tokens**: every themable knob has a declared default in `settings.ui.css`; local-only custom properties use descriptive names (`--avatar-size`, not `--w`).
12
12
8.**Slots**: default slot for main content; named slots documented on the component's docs page.
13
13
9.**A11y**: keyboard operable, labelled, JS motion gated on `prefers-reduced-motion`, no live-region roles on static content.
The order runs **from default to deliberate**: `settings` through `components` are the framework's defaults, `theme` is a deliberate override of those defaults, helpers are the last word. (Not "generic to specific": a theme is broad in reach but late in intent, and intent decides cascade order.)
13
14
2.**Unlayered CSS beats every layer for normal declarations.** That's the consumer guarantee ("your CSS wins") and why site CSS is unlayered.
14
-
3.**Helpers are the exception: every helper declaration carries `!important`.** Important layered declarations beat unlayered CSS (the cascade inverts for important), so helpers win over site and consumer CSS too. They're element-level overrides, like inline styling. For important declarations layer order also inverts (earlier layer wins), which is why the reduced-motion block in `base.reset.css` still beats helpers.
15
-
4.`!important` is REQUIRED in every helper declaration and banned everywhere else in the framework, except the reduced-motion block in `base.reset.css` and third-party override files (see `site/external.astro.css`). `help.colors.css` and `help.spacing.css` get it from their generators.
16
-
5.`postcss.config.cjs` disables preset-env's `cascade-layers` polyfill. **Never remove that option** — the polyfill strips every `@layer` rule and silently replaces the cascade with specificity hacks. The browser floor is set in `.browserslistrc` (`defaults and supports css-cascade-layers`).
15
+
3.**The `theme` layer holds at most one active theme** (`theme.*.css`): token overrides plus optional skin rules. Theme files are self-layered (each wraps its own content in `@layer theme`) and are **never imported by `mcss.css`**; the consumer entry activates one (see `_global.css`). No theme = the default look. Unlayered consumer CSS still beats themes.
16
+
4.**Helpers are the exception: every helper declaration carries `!important`.** Important layered declarations beat unlayered CSS (the cascade inverts for important), so helpers win over site and consumer CSS too. They're element-level overrides, like inline styling. For important declarations layer order also inverts (earlier layer wins), which is why the reduced-motion block in `base.reset.css` still beats helpers.
17
+
5.`!important` is REQUIRED in every helper declaration and banned everywhere else in the framework, except the reduced-motion block in `base.reset.css` and third-party override files (see `site/external.astro.css`). `help.colors.css` and `help.spacing.css` get it from their generators.
18
+
6.`postcss.config.cjs` disables preset-env's `cascade-layers` polyfill. **Never remove that option** — the polyfill strips every `@layer` rule and silently replaces the cascade with specificity hacks. The browser floor is set in `.browserslistrc` (`defaults and supports css-cascade-layers`).
|pages|`page.*`| Page-specific styles that helpers may override |
29
+
|theme|`theme.*`| Swappable skins: token overrides + skin rules, self-layered via `@layer theme`, activated by the consumer entry (never by `mcss.css`)|
28
30
| helpers |`help.*`| Utility overrides (colors, spacing, typography), all `!important`: beats everything, including unlayered CSS |
29
31
30
-
Site-only files keep the same prefixes but live in `src/styles/site/` and import unlayered (`component.header.css`, `page.docs.css`, `external.astro.css`, `devtools.css`, …).
32
+
`page.*` is a file-naming convention only (page-specific styles, e.g. site `page.docs.css`); those files are plain unlayered consumer CSS, there is no `pages` layer.
33
+
34
+
Site-only files keep the same prefixes but live in `src/styles/site/` and import unlayered (`component.header.css`, `page.docs.css`, `external.astro.css`, …). Debug helpers (`help.devtools.css`: baseline overlay, `.dev-error` toast) are framework helpers, not site CSS: framework components reference them.
31
35
32
36
## Class Naming (BEM-like, different separators)
33
37
@@ -51,13 +55,14 @@ A selector must only contain classes from its own block. Never write a descendan
51
55
To style a component from outside:
52
56
53
57
-**Its root**: mix your own class onto the element in markup (`<Section class="home_section …">`) and style that class.
54
-
-**Its internals**: use the component's `<part>Class` props (`headerClass`, `titleClass`, …) to mix a class onto the part, or set the component's theme tokens on your own hook class. If neither exists yet, add the prop or token to the component. Do not reach in with a selector.
58
+
-**Its internals**: use the component's `<part>Class` props (`headerClass`, `titleClass`, …) to mix a class onto the part, or set the component's interface tokens on your own hook class. If neither exists yet, add the prop or token to the component. Do not reach in with a selector.
55
59
-**Bare HTML tags** (`.home_themer_formRow > button`), `.is-*` states, and ARIA attribute selectors are fine inside your own block.
56
60
-**Context blocks are not components**: a component may reference the environment it sits in (`@scope (.prose) to (.not-prose)` in `component.notice.css`, `:root.theme-dark`), but the context's own file must never name specific components (that's why `global.prose.css` lists only bare tags).
61
+
-**Theme files are the one sanctioned exception**: a `theme.*.css` file may select component classes from outside (`.card::after`, `.bt`) because a theme is by definition a skin over the whole system, versioned with the framework. Even there, prefer token overrides; reach for selectors only for what tokens can't express (pseudo-elements, `nth-child` rhythm, `text-decoration`).
57
62
58
63
### Token naming grammar
59
64
60
-
Theme tokens are the public API of every component; they follow `--component-part-property`, longhand, kebab-case:
65
+
Interface tokens (`settings.ui.css`) are the public API of every component; they follow `--component-part-property`, longhand, kebab-case:
- No abbreviations (`--card-bg-color` is legacy; new tokens spell out `background-color`), no camelCase, no underscores.
@@ -71,6 +76,7 @@ Never `transition: all` — it also transitions layout properties, so any late-a
71
76
72
77
-**One block per file.** Every block gets its own file named after it (`.featureItem` lives in `component.featureItem.css`, never inside `component.featureGrid.css`), even for small companion blocks (`component.fieldRow.css`, site `component.webring.css`).
73
78
- Framework file: create `src/styles/framework/<prefix>.<name>.css` and add `@import url(./<file>) layer(<layer>);` in the matching block of `framework/mcss.css`.
79
+
- Theme file: create `src/styles/framework/theme.<name>.css` wrapping its own content in `@layer theme { … }`; do NOT import it in `mcss.css` (the consumer entry activates it; the dist index lists it commented out).
74
80
- Site file: create `src/styles/site/<prefix>.<name>.css` and add a plain `@import` in `_global.css` (unlayered).
75
81
- Framework CSS must never reference site-only selectors (e.g. `.expressive-code`); the site file mirrors any shared pattern itself.
Copy file name to clipboardExpand all lines: agents/pitfalls.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,4 +14,4 @@ URLs for blog posts, docs, and component pages are derived from their file paths
14
14
15
15
## Theme Toggle
16
16
17
-
The light/dark toggle persists in **`localStorage`** (key `theme`). The inline script in `BaseLayout.astro` applies the class before paint to avoid FOUC; the toggle behavior itself lives in `ThemeToggle.astro` (self-contained; rendered twice, its module script runs once). Don't introduce a second theme mechanism.
17
+
The light/dark toggle persists in **`localStorage`** (key `theme`). The inline script in `BaseLayout.astro` applies the class before paint to avoid FOUC; the toggle behavior itself lives in `ThemeToggle.astro` (self-contained; rendered twice, its module script runs once). Don't introduce a second color-scheme mechanism. (Theme files, `theme.*.css`, are full skins and unrelated to the light/dark toggle.)
0 commit comments