max / makenotwork
3 files changed,
+41 insertions,
-21 deletions
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | | Type size | `--text-fine` / `--text-note` / `--text-body` / `--text-lead` / `--text-subhead` / `--text-head` / `--text-title` / `--text-display` / `--text-hero`, named for what the text is, not the size | `geometry.css` (generated by makeover-build) | | |
| 16 | 16 | | Spacing | `--gap-bound` / `--gap-peer` / `--gap-group` / `--gap-section` / `--gap-pane` / `--gap-page`, named for the relationship they express, not the size | `geometry.css` (generated by makeover-build) | | |
| 17 | 17 | | Radius | `--radius-sm` (4px, controls: buttons, inputs, chips, badges), `--radius-md` (0, containers: cards, panels, dropdowns), `--radius-round` (50%) | `style.css:216-222` | | |
| 18 | + | | Stacking | `--z-raised` / `--z-nav` / `--z-header` / `--z-dropdown` / `--z-picker` / `--z-context` / `--z-overlay` / `--z-modal` / `--z-toast` / `--z-banner` / `--z-skip-link`, in that order, named for what floats over what | `style.css:213-228` | | |
| 18 | 19 | | Shadow | Everyday depth: `--shadow-raised` (buttons, tabs), `--shadow-card` (cards, panels), `--shadow-inset` (inputs, recessed). All three alias the bevel pair `--bevel-raised` / `--bevel-inset` from `layout.css`, which makeover derives from each theme's own raised surface. Blurred (true elevation, floats over page): `--shadow-1` (subtle), `--shadow-2` (raised), `--shadow-3` (modal/overlay). | `style.css:224-243` | | |
| 19 | 20 | ||
| 20 | 21 | Pure `#000` and `#fff` are forbidden outside the token table. Bootstrap-derived yellows (`#fff3cd`, `#ffc107`) are forbidden. Use `--warning-bg` / `--warning-border`. | |
| @@ -178,10 +179,11 @@ | |||
| 178 | 179 | 7. **Destructive actions** use `.danger` button class plus the `confirm_dialog` macro. No bare destructive buttons. | |
| 179 | 180 | 8. **Spacing values come from `--gap-*` tokens.** Pick the one that names what the rule separates: `bound` inside a thing, `peer` between siblings, `group` between related controls, `section` between parts of a pane, `pane` between panes, `page` at page level. Raw values and off-scale values are bugs. The tokens are generated from makeover-geometry and shift under a coarse pointer, so a hardcoded value silently opts that rule out of touch density. | |
| 180 | 181 | 9. **Font sizes come from `--text-*` tokens.** Pick the one that names what the text is: `fine` for timestamps and badges, `note` for metadata and table cells, `body` for running copy, `lead` for emphasised copy and card titles, `subhead` / `head` / `title` for the three heading levels, `display` and `hero` above the hierarchy. Raw values and off-scale values are bugs, including a value that differs from a tier by a fraction of a pixel. Nothing sits below `fine`: text that should recede does it with colour or weight. | |
| 181 | - | 10. **Page-scoped CSS is a last resort.** Default to composing layout + component primitives. Page-scoped sections exist for genuinely page-specific layout (grids, long-form typography, marketing heroes), not for shapes that are cards or list rows in disguise. | |
| 182 | - | 11. **No bare `<h1>` / `<h2>` in templates.** Pick a heading class: `.brand-h1` (wordmark), `.page-title` (page h1), `.subtitle-h2` (page subtitle on auth/wizards), `.subsection-title` (default h2 inside dashboards/tabs/partials), or `.section-header` (prose sub-section with bottom border). Two exceptions, both because the heading classes are the wrong tool rather than because the rule is optional. **Prose containers** style their own descendant headings — `.doc-body`, `.article-body`, `.markdown-preview` — so a heading inside one stays bare whether the prose was rendered from markdown or hand-written in the template (`pages/economics.html`). **Standalone creator pages** (`templates/custom/*.html`, `templates/embed/*.html`) do not load `style.css` at all, so no heading class exists to pick. | |
| 183 | - | 12. **Button class is `.btn-primary` / `.btn-secondary` / `.btn-danger`.** Works on both `<button>` and `<a>` (the `<a><button>` antipattern is banned. Use `<a class="btn-primary">…</a>`). The bare `button.primary` shorthand has been retired. | |
| 184 | - | 13. **Class names use kebab-case only.** No BEM `__` separator (retired 2026-05-20, was 112 sites across 20 prefixes, now flattened to single-dash). Modifier `--` (e.g. `.card--bordered`) is still allowed. | |
| 182 | + | 10. **`z-index` values come from `--z-*` tokens.** Pick the one that names what the thing is, and read the block in `:root` to see what it will float over. A raw number is a bug: it is how the old range reached 10000, each new floating thing picking a value bigger than whatever it happened to need to beat. If nothing in the scale describes the new thing, add a step to the scale rather than a number to the rule. | |
| 183 | + | 11. **Page-scoped CSS is a last resort.** Default to composing layout + component primitives. Page-scoped sections exist for genuinely page-specific layout (grids, long-form typography, marketing heroes), not for shapes that are cards or list rows in disguise. | |
| 184 | + | 12. **No bare `<h1>` / `<h2>` in templates.** Pick a heading class: `.brand-h1` (wordmark), `.page-title` (page h1), `.subtitle-h2` (page subtitle on auth/wizards), `.subsection-title` (default h2 inside dashboards/tabs/partials), or `.section-header` (prose sub-section with bottom border). Two exceptions, both because the heading classes are the wrong tool rather than because the rule is optional. **Prose containers** style their own descendant headings — `.doc-body`, `.article-body`, `.markdown-preview` — so a heading inside one stays bare whether the prose was rendered from markdown or hand-written in the template (`pages/economics.html`). **Standalone creator pages** (`templates/custom/*.html`, `templates/embed/*.html`) do not load `style.css` at all, so no heading class exists to pick. | |
| 185 | + | 13. **Button class is `.btn-primary` / `.btn-secondary` / `.btn-danger`.** Works on both `<button>` and `<a>` (the `<a><button>` antipattern is banned. Use `<a class="btn-primary">…</a>`). The bare `button.primary` shorthand has been retired. | |
| 186 | + | 14. **Class names use kebab-case only.** No BEM `__` separator (retired 2026-05-20, was 112 sites across 20 prefixes, now flattened to single-dash). Modifier `--` (e.g. `.card--bordered`) is still allowed. | |
| 185 | 187 | ||
| 186 | 188 | ## How to extend | |
| 187 | 189 |
| @@ -211,6 +211,24 @@ | |||
| 211 | 211 | --radius-md: 0; /* containers: cards, panels, dropdowns */ | |
| 212 | 212 | --radius-round: 50%; | |
| 213 | 213 | ||
| 214 | + | /* Stacking order, named for what floats over what. Local rather than | |
| 215 | + | generated: this is a claim about MNW's own furniture, not an invariant | |
| 216 | + | like spacing. The numbers are spaced so a value can be slotted between | |
| 217 | + | two of them without renumbering, and nothing outside this block should | |
| 218 | + | write a z-index literal. Anything not listed here does not float. */ | |
| 219 | + | --z-raised: 1; /* lifted within the flow: a saved badge on a card */ | |
| 220 | + | --z-nav: 10; /* the nav panel that drops out of the mobile header */ | |
| 221 | + | --z-header: 11; /* the header's own toggle and search panel, both of | |
| 222 | + | which have to stay above the panel they open */ | |
| 223 | + | --z-dropdown: 20; /* menus and suggestion lists opened from a control */ | |
| 224 | + | --z-picker: 30; /* pickers that open over a dropdown */ | |
| 225 | + | --z-context: 40; /* right-click / overflow context menus */ | |
| 226 | + | --z-overlay: 50; /* full-page scrims */ | |
| 227 | + | --z-modal: 60; /* dialogs, above their scrim */ | |
| 228 | + | --z-toast: 70; /* transient messages, above a dialog */ | |
| 229 | + | --z-banner: 80; /* page-level interruptions, above everything */ | |
| 230 | + | --z-skip-link: 90; /* the keyboard escape hatch outranks all of it */ | |
| 231 | + | ||
| 214 | 232 | /* Shadow scale. | |
| 215 | 233 | --shadow-1/-2/-3 are blurred elevation (true floating: popovers, | |
| 216 | 234 | dropdowns, modals). --shadow-raised/-card/-inset are everyday depth, | |
| @@ -763,7 +781,7 @@ | |||
| 763 | 781 | position: absolute; | |
| 764 | 782 | top: 100%; | |
| 765 | 783 | right: 0; | |
| 766 | - | z-index: 10; | |
| 784 | + | z-index: var(--z-dropdown); | |
| 767 | 785 | background: var(--surface-page); | |
| 768 | 786 | border: 1px solid var(--border); | |
| 769 | 787 | min-width: 180px; | |
| @@ -4540,7 +4558,7 @@ | |||
| 4540 | 4558 | display: none; | |
| 4541 | 4559 | cursor: pointer; | |
| 4542 | 4560 | padding: var(--gap-peer); | |
| 4543 | - | z-index: 11; | |
| 4561 | + | z-index: var(--z-header); | |
| 4544 | 4562 | } | |
| 4545 | 4563 | ||
| 4546 | 4564 | .nav-toggle-label span { | |
| @@ -4698,7 +4716,7 @@ | |||
| 4698 | 4716 | font-family: var(--font-mono); | |
| 4699 | 4717 | padding: var(--gap-bound) var(--gap-peer); | |
| 4700 | 4718 | white-space: nowrap; | |
| 4701 | - | z-index: 10; | |
| 4719 | + | z-index: var(--z-dropdown); | |
| 4702 | 4720 | pointer-events: none; | |
| 4703 | 4721 | margin-bottom: var(--gap-bound); | |
| 4704 | 4722 | } | |
| @@ -4839,7 +4857,7 @@ | |||
| 4839 | 4857 | position: fixed; | |
| 4840 | 4858 | bottom: 1.5rem; | |
| 4841 | 4859 | right: 1.5rem; | |
| 4842 | - | z-index: 1000; | |
| 4860 | + | z-index: var(--z-toast); | |
| 4843 | 4861 | display: flex; | |
| 4844 | 4862 | flex-direction: column; | |
| 4845 | 4863 | gap: var(--gap-peer); | |
| @@ -4967,7 +4985,7 @@ | |||
| 4967 | 4985 | top: 0; | |
| 4968 | 4986 | left: 0; | |
| 4969 | 4987 | right: 0; | |
| 4970 | - | z-index: 10000; | |
| 4988 | + | z-index: var(--z-banner); | |
| 4971 | 4989 | padding: var(--gap-group) var(--gap-section); | |
| 4972 | 4990 | animation: banner-slide-down 0.3s ease-out; | |
| 4973 | 4991 | } | |
| @@ -5079,7 +5097,7 @@ | |||
| 5079 | 5097 | background: var(--primary-dark); | |
| 5080 | 5098 | color: var(--primary-light); | |
| 5081 | 5099 | padding: 8px; | |
| 5082 | - | z-index: 100; | |
| 5100 | + | z-index: var(--z-skip-link); | |
| 5083 | 5101 | transition: top 0.2s ease; | |
| 5084 | 5102 | } | |
| 5085 | 5103 | ||
| @@ -5165,7 +5183,7 @@ | |||
| 5165 | 5183 | display: flex; | |
| 5166 | 5184 | align-items: center; | |
| 5167 | 5185 | justify-content: center; | |
| 5168 | - | z-index: 1000; | |
| 5186 | + | z-index: var(--z-modal); | |
| 5169 | 5187 | } | |
| 5170 | 5188 | ||
| 5171 | 5189 | .modal { | |
| @@ -6629,7 +6647,7 @@ | |||
| 6629 | 6647 | border-top: none; | |
| 6630 | 6648 | max-height: 300px; | |
| 6631 | 6649 | overflow-y: auto; | |
| 6632 | - | z-index: 20; | |
| 6650 | + | z-index: var(--z-dropdown); | |
| 6633 | 6651 | box-shadow: 0 4px 8px rgba(0,0,0,0.08); | |
| 6634 | 6652 | } | |
| 6635 | 6653 | .docs-search-result { | |
| @@ -7253,7 +7271,7 @@ | |||
| 7253 | 7271 | padding: var(--gap-section) var(--gap-pane); | |
| 7254 | 7272 | background: var(--surface-page); | |
| 7255 | 7273 | border-bottom: 1px solid var(--border); | |
| 7256 | - | z-index: 11; | |
| 7274 | + | z-index: var(--z-header); | |
| 7257 | 7275 | } | |
| 7258 | 7276 | ||
| 7259 | 7277 | .site-header nav { | |
| @@ -7265,7 +7283,7 @@ | |||
| 7265 | 7283 | background: var(--surface-page); | |
| 7266 | 7284 | border-bottom: 1px solid var(--border); | |
| 7267 | 7285 | padding: var(--gap-section) var(--gap-pane); | |
| 7268 | - | z-index: 10; | |
| 7286 | + | z-index: var(--z-nav); | |
| 7269 | 7287 | } | |
| 7270 | 7288 | ||
| 7271 | 7289 | .site-header { | |
| @@ -7691,7 +7709,7 @@ | |||
| 7691 | 7709 | border-radius: 0 0 var(--radius-md) var(--radius-md); | |
| 7692 | 7710 | max-height: 200px; | |
| 7693 | 7711 | overflow-y: auto; | |
| 7694 | - | z-index: 10; | |
| 7712 | + | z-index: var(--z-dropdown); | |
| 7695 | 7713 | box-shadow: var(--shadow-2); | |
| 7696 | 7714 | } | |
| 7697 | 7715 | ||
| @@ -7805,7 +7823,7 @@ | |||
| 7805 | 7823 | ||
| 7806 | 7824 | .collection-picker-anchor { position: relative; } | |
| 7807 | 7825 | .collection-picker { | |
| 7808 | - | position: absolute; left: 0; right: 0; top: 100%; z-index: 50; | |
| 7826 | + | position: absolute; left: 0; right: 0; top: 100%; z-index: var(--z-picker); | |
| 7809 | 7827 | background: var(--surface-page); border: 1px solid var(--border); | |
| 7810 | 7828 | box-shadow: 0 2px 8px rgba(0,0,0,0.12); min-width: 220px; | |
| 7811 | 7829 | } | |
| @@ -7829,7 +7847,7 @@ | |||
| 7829 | 7847 | } | |
| 7830 | 7848 | .row-save:hover, .grid-card-save:hover { opacity: 1; } | |
| 7831 | 7849 | .grid-card-save { | |
| 7832 | - | position: absolute; top: 0.4rem; right: 0.4rem; z-index: 2; | |
| 7850 | + | position: absolute; top: 0.4rem; right: 0.4rem; z-index: var(--z-raised); | |
| 7833 | 7851 | background: var(--surface-page); border-radius: 3px; padding: var(--gap-bound) var(--gap-peer); | |
| 7834 | 7852 | box-shadow: 0 1px 3px rgba(0,0,0,0.15); opacity: 0; | |
| 7835 | 7853 | } | |
| @@ -7846,7 +7864,7 @@ | |||
| 7846 | 7864 | .search-wrapper { position: relative; flex: 1; min-width: 0; } | |
| 7847 | 7865 | .search-suggestions, | |
| 7848 | 7866 | .tag-suggest-list { | |
| 7849 | - | display: none; position: absolute; left: 0; right: 0; top: 100%; z-index: 50; | |
| 7867 | + | display: none; position: absolute; left: 0; right: 0; top: 100%; z-index: var(--z-picker); | |
| 7850 | 7868 | background: var(--surface-page); border: 1px solid var(--border); border-top: none; | |
| 7851 | 7869 | box-shadow: 0 4px 12px rgba(0,0,0,0.1); max-height: 280px; overflow-y: auto; | |
| 7852 | 7870 | } | |
| @@ -8414,7 +8432,7 @@ | |||
| 8414 | 8432 | .tag-search-wrap { position: relative; } | |
| 8415 | 8433 | .tag-suggestions { | |
| 8416 | 8434 | position: absolute; | |
| 8417 | - | z-index: 10; | |
| 8435 | + | z-index: var(--z-dropdown); | |
| 8418 | 8436 | background: var(--surface-sunken); | |
| 8419 | 8437 | border: 1px solid var(--border); | |
| 8420 | 8438 | width: 100%; | |
| @@ -10491,7 +10509,7 @@ | |||
| 10491 | 10509 | border: 1px solid var(--border); | |
| 10492 | 10510 | box-shadow: var(--shadow-2); | |
| 10493 | 10511 | min-width: 160px; | |
| 10494 | - | z-index: 100; | |
| 10512 | + | z-index: var(--z-context); | |
| 10495 | 10513 | } | |
| 10496 | 10514 | .context-menu.open { display: block; } | |
| 10497 | 10515 | .context-menu-item { |
| @@ -162,7 +162,7 @@ | |||
| 162 | 162 | border-radius: 0 0 4px 4px; | |
| 163 | 163 | max-height: 200px; | |
| 164 | 164 | overflow-y: auto; | |
| 165 | - | z-index: 10; | |
| 165 | + | z-index: var(--z-dropdown); | |
| 166 | 166 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
| 167 | 167 | } | |
| 168 | 168 |