mote.css 0.7.0 → 0.9.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/CHANGELOG.md +136 -0
- package/README.md +15 -7
- package/mote.components.css +113 -4
- package/mote.css +36 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,140 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.9.0] - 2026-10-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`tests/fixture.html` — the regression fixture**: a self-checking page
|
|
13
|
+
loading the real committed stylesheets, with 54 assertions pinning the
|
|
14
|
+
principle invariants (two-tier gating, status inheritance, control
|
|
15
|
+
density, stack behavior, zebra-vs-`aria-current` order, skip-link states,
|
|
16
|
+
landmark styling, theme flip). Open it in any browser — the title shows
|
|
17
|
+
PASS or FAIL. Its first run caught two real bugs, both fixed in this
|
|
18
|
+
release.
|
|
19
|
+
- `tr[aria-current]` current-row treatment: accent-soft tint that reads
|
|
20
|
+
over zebra (same vocabulary as nav pills and pagination). The fixture
|
|
21
|
+
asserts it on both parities.
|
|
22
|
+
- `.mote-grid-sparse` is now standalone-complete (`display: grid` + gap) —
|
|
23
|
+
it was a columns-only modifier that silently rendered as a plain block
|
|
24
|
+
when used alone, as the README advertised it (fixture-caught).
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- **Badges never grow past body scale**: `font-size: min(0.8em, 0.8rem)` —
|
|
29
|
+
a pill inside a heading stays readable (three round-6 builds hit the old
|
|
30
|
+
heading-scale default), small contexts still scale down with the em side.
|
|
31
|
+
- **`.mote-stack` is now a real stack**: flex column with
|
|
32
|
+
`--mote-stack-gap` (default 1.25rem) and zeroed child margins, so the
|
|
33
|
+
name is honest for any content — form rhythm is designed, not `<p>`
|
|
34
|
+
margin luck. Field stretching and the 1em checkbox/radio exception are
|
|
35
|
+
unchanged. The sr-only control rule inside stacks was strengthened to
|
|
36
|
+
beat the checkbox width rule on specificity.
|
|
37
|
+
- **Header navs scroll instead of wrapping**: `body > header nav` /
|
|
38
|
+
`.mote-nav` pill rows stay one line at any width — a long section list
|
|
39
|
+
(the docs' own ten pills) scrolls inside the bar instead of pushing the
|
|
40
|
+
brand or the theme toggle to a second row. The scrollbar is hidden;
|
|
41
|
+
a hairline under the pills carries directional accent fades pinned to
|
|
42
|
+
the nav edges — they never float with scroll position. Pure CSS cannot
|
|
43
|
+
distinguish "at the start" from "nothing to scroll", so the fades key
|
|
44
|
+
off a `data-nav` attribute kept current by a seven-line documented
|
|
45
|
+
snippet (the theme-toggle precedent, including a webfont-load re-sync);
|
|
46
|
+
without it, the hairline and the
|
|
47
|
+
cut pill are the whole hint. Direction-agnostic snippet math; the
|
|
48
|
+
gradients flip under `[dir="rtl"]`.
|
|
49
|
+
- Tokenized the hardcoded paddings: `--mote-grid-gap` (1.25rem) and
|
|
50
|
+
`--mote-band-pad` (4rem) — thin strips and matched split rhythms no
|
|
51
|
+
longer need hand-copied values.
|
|
52
|
+
|
|
53
|
+
### Fixed (docs — round-6 build findings)
|
|
54
|
+
|
|
55
|
+
- Band placement warning: inside `main.mote-container` a band bleeds only
|
|
56
|
+
to the container edge — the docs now say so (the one round-6 trap that
|
|
57
|
+
actually broke a build mid-flight)
|
|
58
|
+
- `.mote-card` + `.mote-media` merge warning: the card's column direction
|
|
59
|
+
silently wins; nest instead.
|
|
60
|
+
- `aria-label` case-sensitivity warning on the semantic selectors.
|
|
61
|
+
- `.mote-num` widened: "table columns or any figure block".
|
|
62
|
+
- Media-object default alignment (`flex-start`) documented.
|
|
63
|
+
- Skip-link mechanism wording: clipped via `clip-path`, not `display: none`.
|
|
64
|
+
- Badge and stack paragraphs rewritten for the new behavior; note-width
|
|
65
|
+
recipe added; three new token rows.
|
|
66
|
+
- Six new pattern recipes: toolbar row, result rows, price line, post
|
|
67
|
+
actions, growing input, prominent search.
|
|
68
|
+
- **`demo.html` merged into the docs page as the Gallery section** (every
|
|
69
|
+
input type, footnoted table, sample output) and deleted — one canonical
|
|
70
|
+
page, no drift risk. README and in-page links updated.
|
|
71
|
+
|
|
72
|
+
### Evaluation
|
|
73
|
+
|
|
74
|
+
- Sixth round: ten agents built ten NEW page types (forum, product,
|
|
75
|
+
status, checkout, inbox, gallery, profile, FAQ, poll, playlist) against
|
|
76
|
+
v0.8.0. 10/10 would-use-again, zero rendering failures; every v0.8.0
|
|
77
|
+
fix verified load-bearing. Asymmetric grid splits stay page CSS by
|
|
78
|
+
design (documented, not a gap).
|
|
79
|
+
|
|
80
|
+
## [0.8.0] - 2026-10-22
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
|
|
84
|
+
- `.mote-band`: full-bleed tinted section — CTA bands, section dividers,
|
|
85
|
+
announcement strips. Opaque `color-mix()` (unlike `--mote-accent-soft`,
|
|
86
|
+
which is transparent and can vanish over dark backgrounds). Reads
|
|
87
|
+
`--mote-status`, so bands are content surfaces under the two-tier
|
|
88
|
+
principle.
|
|
89
|
+
- `.mote-skip-link`: sr-only until keyboard focus, then a fixed pill.
|
|
90
|
+
Split from `.mote-sr-only`, which is now pure hiding — using sr-only to
|
|
91
|
+
hide toggle radios made them pop a skip-link pill on focus.
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
|
|
95
|
+
- `.mote-card` normalizes `text-align: start` — form labels inside a card
|
|
96
|
+
read normally even when the card sits in a centered `.mote-hero`
|
|
97
|
+
(cards already zeroed first/last-child margins; this finishes the job).
|
|
98
|
+
- Page footer navs (`body > footer nav ul`) render as quiet wrapped rows —
|
|
99
|
+
no bullets — matching the header's semantic treatment. No class needed.
|
|
100
|
+
- File inputs use the density tokens (`--mote-control-pad`), so their
|
|
101
|
+
height matches sibling fields in a stack (was 41px vs 44px).
|
|
102
|
+
- Labels wrapping checkboxes/radios get `cursor: pointer` — the label is
|
|
103
|
+
the click target. Scoped via `label:has()`; text-input labels untouched.
|
|
104
|
+
|
|
105
|
+
### Fixed (docs — the bulk of this release, from a ten-agent build round)
|
|
106
|
+
|
|
107
|
+
- **Tokens reference**: new section listing every `--mote-*` knob — palette,
|
|
108
|
+
type/shape/motion, layout/density — including the actual
|
|
109
|
+
`--mote-accent-soft` definition (9% *transparent* mix) and a pointer to
|
|
110
|
+
`.mote-band` for opaque tints. Nav pill added.
|
|
111
|
+
- **Simple-page header snippet now shows the real composition**
|
|
112
|
+
(`.mote-container.mote-row` + `.mote-brand` + `.mote-push` inside the
|
|
113
|
+
header) — the old "no classes at all" snippet left the brand flush at
|
|
114
|
+
the viewport edge.
|
|
115
|
+
- **Notes and callouts** section: `.mote-note` (shipped since 0.3.0, never
|
|
116
|
+
documented as a concept) framed alongside the `blockquote` + status
|
|
117
|
+
quote treatment. Cross-linked from Blockquote and the consumer map.
|
|
118
|
+
- `.mote-num` documented (replaces the DIY `.num` page recipe);
|
|
119
|
+
`--mote-table-max` documented next to `.mote-table-scroll` (with the
|
|
120
|
+
sticky-engages-on-scroll note); `.mote-hero` + `--mote-hero-offset`
|
|
121
|
+
documented in Layout under "Hero and bands" — all previously findable
|
|
122
|
+
only by grepping the stylesheet.
|
|
123
|
+
- `.mote-card-media` documented (replaces the DIY `.card-media` recipe and
|
|
124
|
+
the false "cards don't ship this" claim); live band, hero and card-media
|
|
125
|
+
examples added.
|
|
126
|
+
- `--mote-rail-top`: docs now say it auto-derives from the sticky header —
|
|
127
|
+
set it only for wrapped shells (`.mote-header`).
|
|
128
|
+
- File-input treatment, badge context-scaling, and label-cursor behavior
|
|
129
|
+
documented.
|
|
130
|
+
- Seven new pattern recipes: login page, marketing hero (+ CTA band),
|
|
131
|
+
stat row, CSS-only billing toggle (with the sr-only-is-not-hiding
|
|
132
|
+
warning), display pull-quote, row hover, feedback row.
|
|
133
|
+
- Docs page gets a `.mote-skip-link` (dogfooding the new class).
|
|
134
|
+
|
|
135
|
+
### Evaluation
|
|
136
|
+
|
|
137
|
+
- Fifth round: ten agents each built a real page (pricing, blog, login,
|
|
138
|
+
404, settings, dashboard, KB, landing, release notes, contact) against
|
|
139
|
+
v0.7.0 and reported DX honestly. 10/10 would-use-again, zero rendering
|
|
140
|
+
failures; every change above traces to that round.
|
|
141
|
+
|
|
8
142
|
## [0.7.0] - 2026-10-21
|
|
9
143
|
|
|
10
144
|
### Changed
|
|
@@ -424,6 +558,8 @@ Components:
|
|
|
424
558
|
- Element gallery demo page (`demo.html`).
|
|
425
559
|
|
|
426
560
|
[0.3.0]: https://gitlab.com/abmach/mote/compare/v0.2.1...v0.3.0
|
|
561
|
+
[0.8.0]: https://gitlab.com/abmach/mote/compare/v0.7.0...v0.8.0
|
|
562
|
+
[0.9.0]: https://gitlab.com/abmach/mote/compare/v0.8.0...v0.9.0
|
|
427
563
|
[0.7.0]: https://gitlab.com/abmach/mote/compare/v0.6.1...v0.7.0
|
|
428
564
|
[0.6.1]: https://gitlab.com/abmach/mote/compare/v0.6.0...v0.6.1
|
|
429
565
|
[0.6.0]: https://gitlab.com/abmach/mote/compare/v0.5.1...v0.6.0
|
package/README.md
CHANGED
|
@@ -152,28 +152,34 @@ mote is class-optional by design — elements are styled from tags alone; these
|
|
|
152
152
|
| Ghost buttons | `.mote-ghost` — transparent fill; status tints from the button's own class (gated like solids) |
|
|
153
153
|
| Solid button on any element | `.mote-btn` — the full solid recipe for anchors, spans; status classes gated |
|
|
154
154
|
| Hero centering | `.mote-hero` — vertically centers content for error/login/empty-state pages |
|
|
155
|
+
| CTA bands | `.mote-band` — full-bleed tinted section; opaque in both themes, reads `--mote-status` |
|
|
155
156
|
| Card cover media | `.mote-card-media` — flush-top cover images with matched radius |
|
|
156
157
|
| Brand/wordmark | `.mote-brand` — quiet non-nav link for site headers |
|
|
157
158
|
| Media objects | `.mote-media` — avatar/icon beside body (flex, last child grows) |
|
|
158
159
|
| Display text | `.mote-display` — opt-in hero/error-code scale via `--mote-display` |
|
|
159
160
|
| Content rows | `.mote-row` + `.mote-push` — flex row, right-align helper |
|
|
160
|
-
|
|
|
161
|
+
| Stacks | `.mote-stack` — vertical rhythm with `--mote-stack-gap`; fields full width, checkboxes 1em, works on any content |
|
|
161
162
|
| Scrollable tables | `.mote-table-scroll` — sticky `thead`, no page scroll, no margin jump |
|
|
162
163
|
| Numeric columns | `.mote-num` — right-aligned tabular figures |
|
|
163
|
-
| Sparse grids | `.mote-grid-sparse` — auto-fit variant, collapses empty tracks |
|
|
164
|
+
| Sparse grids | `.mote-grid-sparse` — standalone auto-fit variant, collapses empty tracks |
|
|
164
165
|
| Pagination | `nav[aria-label="pagination"]` — semantic, no class |
|
|
165
166
|
| Table of contents | `nav[aria-label="toc"]` — semantic, no class |
|
|
166
|
-
|
|
|
167
|
-
|
|
|
167
|
+
| Current table row | `tr[aria-current]` — accent-tinted row, reads over zebra |
|
|
168
|
+
| Footer baseline | `body > footer` — semantic top-border + padding; its `nav` renders as a quiet wrapped row |
|
|
169
|
+
| Screen-reader helper | `.mote-sr-only` — pure hiding, never appears |
|
|
170
|
+
| Skip link | `.mote-skip-link` — sr-only until keyboard focus, then a fixed pill |
|
|
168
171
|
| Print helpers | `.mote-no-print` / `.mote-print-only` |
|
|
169
172
|
| Theme-switch guard | `.mote-theme-switch` — prevents Chromium stale-color bug on `data-theme` flips |
|
|
170
173
|
| Status inheritance control | `.mote-default` (force accent) · `.mote-reset` (clear inherited status) |
|
|
171
174
|
| Hero offset | `--mote-hero-offset` (default 12rem) — space for header/footer in `.mote-hero` |
|
|
172
175
|
| Table max height | `--mote-table-max` (default 60vh) — `.mote-table-scroll` panel cap |
|
|
176
|
+
| Stack gap | `--mote-stack-gap` (default 1.25rem) — `.mote-stack` vertical rhythm |
|
|
177
|
+
| Grid gap | `--mote-grid-gap` (default 1.25rem) — `.mote-grid` / `.mote-grid-sparse` |
|
|
178
|
+
| Band padding | `--mote-band-pad` (default 4rem) — `.mote-band`; 1rem for thin strips |
|
|
173
179
|
| Breadcrumbs | `nav[aria-label="breadcrumb"]` — semantic, no class |
|
|
174
180
|
| Card grids | `.mote-grid` — auto-fill columns from the container, no breakpoints |
|
|
175
|
-
| Cards | `.mote-card` |
|
|
176
|
-
| Badges | `.mote-badge` — gated: status from the badge's own class, never inherited |
|
|
181
|
+
| Cards | `.mote-card` — normalizes content: alignment reads start even inside centered regions |
|
|
182
|
+
| Badges | `.mote-badge` — gated: status from the badge's own class, never inherited; never grows past body scale |
|
|
177
183
|
| Avatars | `.mote-avatar` |
|
|
178
184
|
| Skeleton / spinner | `.mote-skeleton`, `.mote-spinner` |
|
|
179
185
|
| Tooltips | `[popover].mote-tooltip` + `popovertarget` button |
|
|
@@ -195,7 +201,9 @@ animations become instant, on older engines.
|
|
|
195
201
|
|
|
196
202
|
## Demo
|
|
197
203
|
|
|
198
|
-
Open [`
|
|
204
|
+
Open [`tests/fixture.html`](tests/fixture.html) in any browser for the regression checks — the title shows PASS or FAIL.
|
|
205
|
+
|
|
206
|
+
Open [`docs/index.html`](docs/index.html) for the full live documentation — it ends with a gallery of every styled element.
|
|
199
207
|
|
|
200
208
|
## License
|
|
201
209
|
|
package/mote.components.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* mote.components.css — opt-in components for mote.css.
|
|
3
|
-
* v0.
|
|
3
|
+
* v0.9.0 · MIT
|
|
4
4
|
* https://gitlab.com/abmach/mote · mirror: https://github.com/abmach/mote
|
|
5
5
|
*
|
|
6
6
|
* Requires mote.css loaded first (provides the --mote-* tokens).
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
border-radius: var(--mote-radius-lg);
|
|
24
24
|
background: color-mix(in oklab, var(--mote-surface) 55%, var(--mote-bg));
|
|
25
25
|
box-shadow: var(--mote-shadow-sm);
|
|
26
|
+
/* Cards normalize their content: alignment reads normally even when the
|
|
27
|
+
card sits inside a centered region (.mote-hero, centered sections). */
|
|
28
|
+
text-align: start;
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
:where(.mote-card) > :first-child {
|
|
@@ -33,6 +36,21 @@
|
|
|
33
36
|
margin-block-end: 0;
|
|
34
37
|
}
|
|
35
38
|
|
|
39
|
+
/* Band: a full-bleed tinted section — CTA bands, section dividers,
|
|
40
|
+
announcement strips. An opaque mix (unlike --mote-accent-soft, which is
|
|
41
|
+
transparent and can vanish over dark backgrounds), so it reads as a
|
|
42
|
+
deliberate section in both palettes. Content surfaces follow context:
|
|
43
|
+
a status class on an ancestor tints the band.
|
|
44
|
+
|
|
45
|
+
<section class="mote-band">
|
|
46
|
+
<div class="mote-container">…</div>
|
|
47
|
+
</section>
|
|
48
|
+
*/
|
|
49
|
+
.mote-band {
|
|
50
|
+
padding-block: var(--mote-band-pad, 4rem);
|
|
51
|
+
background: color-mix(in oklab, var(--mote-status, var(--mote-accent)) 12%, var(--mote-bg));
|
|
52
|
+
}
|
|
53
|
+
|
|
36
54
|
/* ---------------------------------------------------------------------------
|
|
37
55
|
* 2. Badges — .mote-badge + a status class from mote.css (optional)
|
|
38
56
|
*
|
|
@@ -48,7 +66,9 @@
|
|
|
48
66
|
display: inline-block;
|
|
49
67
|
padding: 0.1rem 0.6rem;
|
|
50
68
|
border-radius: 999px;
|
|
51
|
-
|
|
69
|
+
/* Never past body scale: 0.8em inside a heading balloons,
|
|
70
|
+
so clamp it — small contexts still scale down. */
|
|
71
|
+
font-size: min(0.8em, 0.8rem);
|
|
52
72
|
font-weight: 500;
|
|
53
73
|
line-height: 1.4;
|
|
54
74
|
background: var(--mote-accent-soft);
|
|
@@ -146,13 +166,89 @@ a:where(.mote-badge):hover {
|
|
|
146
166
|
padding-block: 0.7rem;
|
|
147
167
|
}
|
|
148
168
|
|
|
169
|
+
/* Long navs scroll inside the bar — they never wrap to a second line
|
|
170
|
+
or push the rest of the row (brand, toggle) off it. min-width lets
|
|
171
|
+
the nav yield space before the surrounding row needs to. */
|
|
172
|
+
:where(body > header nav, .mote-nav) {
|
|
173
|
+
/* basis 0 keeps the nav on the row's first line no matter how long
|
|
174
|
+
(line-breaking sees the unshrunk basis, so a content-sized basis
|
|
175
|
+
would push trailing controls to a second line); it then grows
|
|
176
|
+
into the free space and the pill row scrolls inside it. */
|
|
177
|
+
flex: 1 1 0%;
|
|
178
|
+
min-width: 0;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* Long navs: basis 0 keeps the nav on the row's first line no matter
|
|
182
|
+
how long (line-breaking sees the unshrunk basis, so a content-sized
|
|
183
|
+
basis would push trailing controls to a second line); it then grows
|
|
184
|
+
into the free space and the pill row scrolls inside it. The nav also
|
|
185
|
+
carries the hairline under the pills and hosts the fade pseudos. */
|
|
186
|
+
:where(body > header nav, .mote-nav) {
|
|
187
|
+
position: relative;
|
|
188
|
+
flex: 1 1 0%;
|
|
189
|
+
min-width: 0;
|
|
190
|
+
background:
|
|
191
|
+
linear-gradient(var(--mote-border), var(--mote-border)) left bottom / 100% 2px no-repeat;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Scroll hints: the hairline under the pills carries directional fades
|
|
195
|
+
that bloom toward whichever side holds more content. Pure CSS cannot
|
|
196
|
+
distinguish "scrolled to the start" from "nothing to scroll", so the
|
|
197
|
+
fades key off a data-nav attribute kept current by the seven-line
|
|
198
|
+
documented snippet (same opt-in pattern as the theme toggle).
|
|
199
|
+
Without it: the hairline and the cut pill are the whole hint.
|
|
200
|
+
The pseudos pin to the nav edges — the accent never floats inward,
|
|
201
|
+
whatever the scroll position. */
|
|
202
|
+
:where(body > header nav, .mote-nav)::before,
|
|
203
|
+
:where(body > header nav, .mote-nav)::after {
|
|
204
|
+
content: "";
|
|
205
|
+
position: absolute;
|
|
206
|
+
bottom: 0;
|
|
207
|
+
width: 4rem;
|
|
208
|
+
height: 2px;
|
|
209
|
+
opacity: 0;
|
|
210
|
+
transition: opacity var(--mote-transition);
|
|
211
|
+
pointer-events: none;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
:where(body > header nav, .mote-nav)::before {
|
|
215
|
+
inset-inline-start: 0;
|
|
216
|
+
background: linear-gradient(to left, transparent, color-mix(in oklab, var(--mote-accent) 55%, var(--mote-bg)) 40%);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
:where(body > header nav, .mote-nav)::after {
|
|
220
|
+
inset-inline-end: 0;
|
|
221
|
+
background: linear-gradient(to right, transparent, color-mix(in oklab, var(--mote-accent) 55%, var(--mote-bg)) 40%);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
:where(body > header nav[data-nav~="start"], nav.mote-nav[data-nav~="start"])::before,
|
|
225
|
+
:where(body > header nav[data-nav~="end"], nav.mote-nav[data-nav~="end"])::after {
|
|
226
|
+
opacity: 1;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* RTL: the logical anchors flip on their own; the gradients flip with them. */
|
|
230
|
+
[dir="rtl"] :where(body > header nav, .mote-nav)::before {
|
|
231
|
+
background: linear-gradient(to right, transparent, color-mix(in oklab, var(--mote-accent) 55%, var(--mote-bg)) 40%);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
[dir="rtl"] :where(body > header nav, .mote-nav)::after {
|
|
235
|
+
background: linear-gradient(to left, transparent, color-mix(in oklab, var(--mote-accent) 55%, var(--mote-bg)) 40%);
|
|
236
|
+
}
|
|
237
|
+
|
|
149
238
|
:where(body > header nav, .mote-nav) ul {
|
|
150
239
|
display: flex;
|
|
151
|
-
flex-wrap:
|
|
240
|
+
flex-wrap: nowrap;
|
|
152
241
|
gap: 0.25rem;
|
|
153
242
|
padding: 0;
|
|
154
243
|
margin: 0;
|
|
155
244
|
list-style: none;
|
|
245
|
+
overflow-x: auto;
|
|
246
|
+
overflow-y: hidden;
|
|
247
|
+
scrollbar-width: none;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
:where(body > header nav, .mote-nav) ul::-webkit-scrollbar {
|
|
251
|
+
display: none;
|
|
156
252
|
}
|
|
157
253
|
|
|
158
254
|
:where(body > header nav, .mote-nav) a {
|
|
@@ -303,6 +399,17 @@ nav[aria-label="toc"] a:hover {
|
|
|
303
399
|
border-block-start: var(--mote-border-width) solid var(--mote-border);
|
|
304
400
|
}
|
|
305
401
|
|
|
402
|
+
/* The page footer's nav is a quiet wrapped row — not pills like the
|
|
403
|
+
header. The landmark styles itself; no class needed. */
|
|
404
|
+
:where(body > footer, .mote-footer) nav ul {
|
|
405
|
+
display: flex;
|
|
406
|
+
flex-wrap: wrap;
|
|
407
|
+
gap: 0.35rem 1.25rem;
|
|
408
|
+
list-style: none;
|
|
409
|
+
margin: 0;
|
|
410
|
+
padding: 0;
|
|
411
|
+
}
|
|
412
|
+
|
|
306
413
|
/* ---------------------------------------------------------------------------
|
|
307
414
|
* 8. Popover surfaces — tooltips, menus, toasts
|
|
308
415
|
*
|
|
@@ -674,7 +781,7 @@ nav[aria-label="toc"] :is(h2, h3) {
|
|
|
674
781
|
Columns are computed from the container: as many as fit in 16rem. */
|
|
675
782
|
.mote-grid {
|
|
676
783
|
display: grid;
|
|
677
|
-
gap: 1.25rem;
|
|
784
|
+
gap: var(--mote-grid-gap, 1.25rem);
|
|
678
785
|
/* Density is a variable, not a class API: --mote-grid-min: 22rem
|
|
679
786
|
gives 3-wide pricing; 26rem gives 2-column content. */
|
|
680
787
|
grid-template-columns: repeat(auto-fill, minmax(min(var(--mote-grid-min, 16rem), 100%), 1fr));
|
|
@@ -682,5 +789,7 @@ nav[aria-label="toc"] :is(h2, h3) {
|
|
|
682
789
|
|
|
683
790
|
/* Sparse grids: collapse empty tracks (footers, short card rows) */
|
|
684
791
|
.mote-grid-sparse {
|
|
792
|
+
display: grid;
|
|
793
|
+
gap: var(--mote-grid-gap, 1.25rem);
|
|
685
794
|
grid-template-columns: repeat(auto-fit, minmax(min(var(--mote-grid-min, 16rem), 100%), 1fr));
|
|
686
795
|
}
|
package/mote.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* mote.css — a mote of styling for plain HTML.
|
|
3
|
-
* v0.
|
|
3
|
+
* v0.9.0 · MIT
|
|
4
4
|
* https://gitlab.com/abmach/mote · mirror: https://github.com/abmach/mote
|
|
5
5
|
*
|
|
6
6
|
* The smallest thing that can carry style:
|
|
@@ -396,6 +396,13 @@ tbody tr:nth-child(even) {
|
|
|
396
396
|
background: color-mix(in oklab, var(--mote-surface) 55%, transparent);
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
+
/* The current row — same aria-current vocabulary as nav pills and
|
|
400
|
+
pagination. Opt-in via the attribute; accent-soft reads over zebra
|
|
401
|
+
because this rule follows it in source order. */
|
|
402
|
+
tbody tr[aria-current] {
|
|
403
|
+
background: var(--mote-accent-soft);
|
|
404
|
+
}
|
|
405
|
+
|
|
399
406
|
/* ---------------------------------------------------------------------------
|
|
400
407
|
* 8. Forms & buttons
|
|
401
408
|
* ------------------------------------------------------------------------- */
|
|
@@ -406,6 +413,11 @@ label {
|
|
|
406
413
|
font-weight: 500;
|
|
407
414
|
}
|
|
408
415
|
|
|
416
|
+
/* A label that wraps a checkbox or radio is the click target itself */
|
|
417
|
+
:where(label:has(:is([type="checkbox"], [type="radio"]))) {
|
|
418
|
+
cursor: pointer;
|
|
419
|
+
}
|
|
420
|
+
|
|
409
421
|
fieldset {
|
|
410
422
|
padding: 1rem 1.2rem;
|
|
411
423
|
border: var(--mote-border-width) solid var(--mote-border);
|
|
@@ -473,7 +485,7 @@ select[multiple] {
|
|
|
473
485
|
}
|
|
474
486
|
|
|
475
487
|
[type="file"] {
|
|
476
|
-
padding: 0.
|
|
488
|
+
padding: var(--mote-control-pad, 0.5rem) var(--mote-control-pad-inline, 0.75rem);
|
|
477
489
|
background: none;
|
|
478
490
|
border-style: dashed;
|
|
479
491
|
}
|
|
@@ -679,8 +691,20 @@ progress, meter {
|
|
|
679
691
|
text-align: center;
|
|
680
692
|
}
|
|
681
693
|
|
|
682
|
-
/*
|
|
683
|
-
|
|
694
|
+
/* Stack: a vertical rhythm for forms and lists — gap drives the
|
|
695
|
+
spacing, children's block margins are zeroed, fields stretch full
|
|
696
|
+
width while checkboxes/radios stay at 1em. Works on any content;
|
|
697
|
+
--mote-stack-gap tunes it. */
|
|
698
|
+
.mote-stack {
|
|
699
|
+
display: flex;
|
|
700
|
+
flex-direction: column;
|
|
701
|
+
gap: var(--mote-stack-gap, 1.25rem);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.mote-stack > * {
|
|
705
|
+
margin-block: 0;
|
|
706
|
+
}
|
|
707
|
+
|
|
684
708
|
.mote-stack :is(input, select, textarea, progress, meter) {
|
|
685
709
|
width: 100%;
|
|
686
710
|
}
|
|
@@ -689,7 +713,7 @@ progress, meter {
|
|
|
689
713
|
width: 1em;
|
|
690
714
|
}
|
|
691
715
|
|
|
692
|
-
.mote-stack :is(input, select, textarea)
|
|
716
|
+
.mote-stack .mote-sr-only:is(input, select, textarea) {
|
|
693
717
|
width: 1px;
|
|
694
718
|
}
|
|
695
719
|
|
|
@@ -761,7 +785,8 @@ progress, meter {
|
|
|
761
785
|
font-variant-numeric: tabular-nums;
|
|
762
786
|
}
|
|
763
787
|
|
|
764
|
-
.mote-sr-only
|
|
788
|
+
.mote-sr-only,
|
|
789
|
+
.mote-skip-link {
|
|
765
790
|
position: absolute;
|
|
766
791
|
width: 1px;
|
|
767
792
|
height: 1px;
|
|
@@ -773,8 +798,11 @@ progress, meter {
|
|
|
773
798
|
border: 0;
|
|
774
799
|
}
|
|
775
800
|
|
|
776
|
-
/* Skip link: sr-only until focused, then a fixed pill
|
|
777
|
-
.mote-
|
|
801
|
+
/* Skip link: sr-only until focused, then a fixed pill.
|
|
802
|
+
Use .mote-skip-link for the accessibility skip link;
|
|
803
|
+
use plain .mote-sr-only to hide things that must never
|
|
804
|
+
appear (radios driving CSS toggles, visually hidden labels). */
|
|
805
|
+
.mote-skip-link:focus-visible {
|
|
778
806
|
position: fixed;
|
|
779
807
|
top: 1rem;
|
|
780
808
|
left: 1rem;
|