| 1 |
|
| 2 |
MNW global stylesheet. Charter: docs/design-system.md. |
| 3 |
|
| 4 |
THIS FILE IS ONE PART OF THE SHEET, AND HOLDS NO RULES. |
| 5 |
|
| 6 |
The sheet is written as `css/*.css` and joined by build.rs into |
| 7 |
`static/style.css`. Edit a part, never the output. What each part holds, and |
| 8 |
why contiguity is the guarantee: css/README.md. |
| 9 |
|
| 10 |
Build new features by COMPOSING these primitives, in this order of preference: |
| 11 |
|
| 12 |
1. Use a UTILITY class for one-off adjustments (.mb-section, .text-sm, .nowrap) |
| 13 |
2. Use a LAYOUT PRIMITIVE to position content (.container, .stack-row, .field-row, .list-row) |
| 14 |
3. Use a COMPONENT PRIMITIVE for a UI element (.card, .callout, .badge, .progress-bar, .empty-state, .input--sm, .small) |
| 15 |
4. Extend a primitive with a modifier (.card--bordered, .callout--warning, .stack-row--bordered) |
| 16 |
5. ONLY THEN consider a new class, and add it to the right section below |
| 17 |
|
| 18 |
A new class is a smell, not a goal. Before writing one: |
| 19 |
- grep this file for the visual shape you want; almost everything is here |
| 20 |
- if you can't find it, consider whether the shape belongs in the design system |
| 21 |
(then add it to the appropriate section here AND to docs/design-system.md) |
| 22 |
- page-scoped rules (`.foo-page .bar`) are a last resort, not a first move |
| 23 |
|
| 24 |
-------------------------------------------------------------------------- |
| 25 |
FILE STRUCTURE (search by section name for anchor) |
| 26 |
|
| 27 |
FOUNDATIONS (05-core.css) |
| 28 |
:root tokens (color, type, space, radius, shadow) |
| 29 |
Element base (h1/h2/h3, p, a, button, input, table) |
| 30 |
|
| 31 |
UTILITIES |
| 32 |
Spacing (.m-0, .mt-*, .mb-*, .ml-*, .my-*) |
| 33 |
Sizing (.col-*, .w-*, .maxw-*, .minw-*) |
| 34 |
Text (.text-sm, .text-xs, .text-center, .text-right, .fw-bold, |
| 35 |
.nowrap, .muted, .dimmed, .dimmer, .is-faded, .danger-text) |
| 36 |
State (.hidden, .is-selected, .is-active, .unstyled-link) |
| 37 |
Shapes (.square-cover, .scroll-x) |
| 38 |
|
| 39 |
LAYOUT PRIMITIVES (page-scaffolding shapes) |
| 40 |
.container (width set by body class) |
| 41 |
.stack-row + --bordered / --tight / --top (toolbar / header bar) |
| 42 |
.field-row + .form-group.is-grow (inline form row) |
| 43 |
.list-row + .list-row-title (vertical item list) |
| 44 |
.form-row (2-col grid form) |
| 45 |
.cover-row + .cover-thumb + .cover-empty (image picker) |
| 46 |
|
| 47 |
COMPONENT PRIMITIVES (reusable UI blocks) |
| 48 |
.content-section (light-bg page section box) |
| 49 |
.card / .card-muted / .card--bordered / .card--selectable |
| 50 |
.form-group / .form-section / details.form-section |
| 51 |
.section-header / .section-lead / .section-group-label |
| 52 |
.badge + data-tone (success/warning/danger) |
| 53 |
.callout + --danger / --warning / --solid-warning |
| 54 |
.banner + --info / --warning (full-bleed page-top notice) |
| 55 |
.alert + -note / -tip / -warning / -caution (left-border inline notice) |
| 56 |
.modal + .modal-overlay |
| 57 |
.empty-state + --compact / --chart / --lg |
| 58 |
.progress-bar-container + .progress-bar (--slim, --rounded, --highlight) |
| 59 |
.upload-status + -row + -msg.is-success / .is-error |
| 60 |
.field-status / .save-status + .success / .error / .saving |
| 61 |
.toast + .toast--success / --error / --warning |
| 62 |
.breadcrumb / .pagination |
| 63 |
.tabs + .tab.chosen (chosen is makeover's) |
| 64 |
|
| 65 |
CONTROL MODIFIERS (compose onto buttons/inputs) |
| 66 |
.small / .btn-compact / .btn-link / .btn-tiny (button sizes) |
| 67 |
.btn-danger / .saved (button intents) |
| 68 |
.input--xs / --sm / --mono / --upper / --numeric (input sizes/shapes) |
| 69 |
|
| 70 |
FEATURE SUBAPPS (their own CSS scope) |
| 71 |
.git-* (git source browser at /source/*) |
| 72 |
Pricing calculator on /pricing |
| 73 |
Markdown preview / docs-ui in /docs/* |
| 74 |
|
| 75 |
PAGE-SCOPED LAYOUTS (when truly page-specific) |
| 76 |
.item-page / .project-page / .article-page / .purchase-page / .cart-* / |
| 77 |
.library-page / .feed-page / .discover-page / .landing / .creators-page / |
| 78 |
.health-page / .import-page / .delete-account-page / .export-page / |
| 79 |
.receipt-page / .fan-plus-page / .stripe-disclaimer-page / .buy-page / |
| 80 |
.user-page / .collection-page / .changelog-page / .policy-page / |
| 81 |
.tag-tree-page / .project-blog-page / .project-paywall-page / |
| 82 |
.confirm-delete-page / .admin-page / .dashboard-page |
| 83 |
|
| 84 |
DASHBOARD TABS (one section per tab partial) |
| 85 |
Per-tab classes scoped under their canonical body class. Use modifier |
| 86 |
composition where possible; only add tab-specific rules when the shape |
| 87 |
genuinely diverges from a primitive. |
| 88 |
|
| 89 |
RESPONSIVE (@media at end of file) |
| 90 |
768px tablet |
| 91 |
480px phone |
| 92 |
|
| 93 |
-------------------------------------------------------------------------- |
| 94 |
When in doubt: read docs/design-system.md first. Update both files together |
| 95 |
when you add a primitive. |
| 96 |
============================================================================ |
| 97 |
|
| 98 |
|
| 99 |
faces are fetched by the generated `typography.css`: Quasi Mono and Quasi |
| 100 |
Body from makeover's house layer, and Young Serif from MNW's own override, |
| 101 |
declared in build.rs. What left first: four blocks for IBM Plex Mono and |
| 102 |
Lato, regular and bold, 101 KB of woff2 covering two weights, replaced by |
| 103 |
81 KB carrying the whole 200-800 axis. What left second: the Young Serif |
| 104 |
block that used to sit here, and the `--font-display` beside it. |
| 105 |
|
| 106 |
Young Serif is still the brand tier and still MNW's alone. That has not |
| 107 |
changed and is not what moved. What changed is that the exemption is a |
| 108 |
mechanism now rather than a gap in the vocabulary: the face is declared |
| 109 |
once, as an override of the `display` slot, and reads as one. |
| 110 |
|
| 111 |
|
| 112 |
|
| 113 |
_head_assets.html declares the order once, `@layer makeover, base, |
| 114 |
components, responsive`, and until now three of those four names were |
| 115 |
empty: this file adopted none of them, so 11,788 unlayered lines outranked |
| 116 |
every named layer by construction and the generated sheets lost every |
| 117 |
contest they entered. |
| 118 |
|
| 119 |
Adopting `components` changes no rendering today. `components` already sits |
| 120 |
after `makeover` in the declared order, so this file wins the same contests |
| 121 |
it was winning before; what changes is that it wins them by a stated rule |
| 122 |
rather than by being unlayered. wizard.css and media-player.css adopt the |
| 123 |
same layer, and they still beat this file on a tie because a layer resolves |
| 124 |
internally by source order and they load later. |
| 125 |
|
| 126 |
One thing stays OUT of the layer, deliberately: the theme block theming.rs |
| 127 |
injects into <head> is unlayered, which is load-bearing. An unlayered rule |
| 128 |
outranks every layer, so a creator's chosen theme keeps overriding this |
| 129 |
sheet's :root without needing to know the order. (The @font-face rules this |
| 130 |
used to name as the second exception left for typography.css.) |
| 131 |
|