@stnd/styles 0.5.1 → 0.5.3
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 +12 -0
- package/LICENSE +21 -0
- package/README.md +117 -21
- package/TOKENS.md +26 -4
- package/_standard-00-reset.scss +64 -5
- package/_standard-00-variables.scss +39 -11
- package/_standard-01-token.scss +324 -28
- package/_standard-02-color.scss +208 -86
- package/_standard-03-typography.scss +88 -121
- package/_standard-04-grid.scss +31 -30
- package/_standard-05-rhythm.scss +43 -0
- package/_standard-06-prose.scss +28 -40
- package/_standard-07-base.scss +44 -34
- package/_standard-08-media.scss +42 -29
- package/_standard-09-lists.scss +72 -17
- package/_standard-10-tables.scss +51 -3
- package/_standard-11-forms.scss +43 -10
- package/_standard-12-code.scss +84 -2
- package/_standard-13-components.scss +63 -33
- package/_standard-14-analog.scss +30 -4
- package/_standard-30-contrast.scss +20 -7
- package/_standard-31-print.scss +28 -1
- package/_standard-32-eink.scss +30 -3
- package/_standard-50-utilities.scss +39 -38
- package/_standard-99-debug.scss +25 -18
- package/obsidian.scss +5 -4
- package/package.json +5 -8
- package/standard.scss +11 -5
- package/dist/obsidian.css +0 -31
- package/dist/obsidian.css.map +0 -1
- package/dist/standard.css +0 -20
- package/dist/standard.css.map +0 -1
|
@@ -6,6 +6,27 @@
|
|
|
6
6
|
* @description Fine-art typography system using variable fonts, OpenType features,
|
|
7
7
|
* and mathematical scaling. Implements classical typography rules with modern web capabilities.
|
|
8
8
|
* Supports multiple font families, optical sizing, and locale-specific rules.
|
|
9
|
+
*
|
|
10
|
+
* @property --font-sans Sans-serif font stack (`"Inter", "Instrument Sans Variable", system-ui, -apple-system, sans-serif`).
|
|
11
|
+
* @property --font-serif Serif font stack (`"Source Serif 4", "Newsreader", "Instrument Serif", serif`).
|
|
12
|
+
* @property --font-monospace Monospace font stack (`"IBM Plex Mono", ui-monospace, monospace`).
|
|
13
|
+
* @property --font-text Semantic body font family (defaults to `--font-sans`).
|
|
14
|
+
* @property --font-header Semantic heading font family (defaults to `"Inter"`).
|
|
15
|
+
* @property --font-interface Semantic UI font family (defaults to `--font-sans`).
|
|
16
|
+
* @property --font-inter-feature OpenType stylistic feature set for Inter font.
|
|
17
|
+
* @property --font-instrument-feature OpenType stylistic feature set for Instrument Sans.
|
|
18
|
+
* @property --font-weight Normal text font weight (`400`).
|
|
19
|
+
* @property --font-weight-bold Bold text font weight (`600`).
|
|
20
|
+
* @property --font-header-weight Heading font weight anchor (`700`).
|
|
21
|
+
* @property --font-weight-h1 Level 1 heading weight.
|
|
22
|
+
* @property --font-weight-h2 Level 2 heading weight.
|
|
23
|
+
* @property --font-weight-h3 Level 3 heading weight.
|
|
24
|
+
* @property --font-weight-h4 Level 4 heading weight.
|
|
25
|
+
* @property --font-weight-h5 Level 5 heading weight.
|
|
26
|
+
* @property --font-weight-h6 Level 6 heading weight.
|
|
27
|
+
* @property --font-letter-spacing Body letter spacing default (`normal`).
|
|
28
|
+
* @property --font-header-letter-spacing Heading letter spacing default (`normal`).
|
|
29
|
+
* @property --list-indent Default list item indentation (`var(--space)`).
|
|
9
30
|
*/
|
|
10
31
|
|
|
11
32
|
#{$stnd-theme-scope} {
|
|
@@ -38,7 +59,11 @@
|
|
|
38
59
|
--font-weight-bold: 600;
|
|
39
60
|
--font-letter-spacing: normal;
|
|
40
61
|
--font-header-letter-spacing: normal;
|
|
41
|
-
|
|
62
|
+
/* Intentionally unset: leaving this undefined lets grid-line-height()'s
|
|
63
|
+
per-level $tightness (h1 1.05, h2/h3 1.15, h4-6 1.3) act as the real
|
|
64
|
+
default. A theme or note can still override by setting this explicitly —
|
|
65
|
+
but defining it here to a literal value would shadow every level's
|
|
66
|
+
tightness with the same number, which is the bug this avoids. */
|
|
42
67
|
--font-header-weight: 700;
|
|
43
68
|
|
|
44
69
|
/* Interface Tokens */
|
|
@@ -105,6 +130,11 @@ h6 {
|
|
|
105
130
|
max-width: 100%;
|
|
106
131
|
}
|
|
107
132
|
|
|
133
|
+
/* Fixed 2026-07-14 — the mixin's --target-lh now reads
|
|
134
|
+
--font-header-line-height as an override. The line-height set below
|
|
135
|
+
for h1/h2/h3 is still always overridden further down by
|
|
136
|
+
@include grid-line-height(...) (~line 393), which is what actually
|
|
137
|
+
controls heading line-height now. */
|
|
108
138
|
h1 {
|
|
109
139
|
font-weight: var(--font-weight-h1);
|
|
110
140
|
font-size: clamp(var(--size-xl), 5.5vw, var(--size-2xl));
|
|
@@ -141,7 +171,23 @@ h6 {
|
|
|
141
171
|
line-height: var(--line-height);
|
|
142
172
|
}
|
|
143
173
|
|
|
144
|
-
|
|
174
|
+
/**
|
|
175
|
+
* @component Typography Elements & Patterns
|
|
176
|
+
* @category Typography
|
|
177
|
+
* @description Headings, inline styling, small-caps overlines, keycaps, marks, and blockquotes.
|
|
178
|
+
*
|
|
179
|
+
* @property .overline Small-caps letterspaced kicker label with top border rule.
|
|
180
|
+
* @property .bold Strong bold text weight utility.
|
|
181
|
+
* @property .menu UI interface font role application.
|
|
182
|
+
* @property .ui UI interface font role application.
|
|
183
|
+
* @property .interface UI interface font role application.
|
|
184
|
+
* @property .font-interface Explicit interface font family utility.
|
|
185
|
+
* @property .font-mono Monospace font family utility.
|
|
186
|
+
* @property mark Highlight mark element with optical trim padding and theme tinting.
|
|
187
|
+
* @property kbd Keyboard keycap with raised shadow and monospace font.
|
|
188
|
+
* @property a:hover Color and underline accent transition for hyperlinks.
|
|
189
|
+
* @property a[target="_blank"] External link with automatic arrow indicator (`↗`).
|
|
190
|
+
*/
|
|
145
191
|
.overline {
|
|
146
192
|
font-variant-caps: small-caps;
|
|
147
193
|
letter-spacing: 0.04em;
|
|
@@ -226,67 +272,11 @@ pre,
|
|
|
226
272
|
font-variation-settings: var(--font-monospace-variation);
|
|
227
273
|
}
|
|
228
274
|
|
|
229
|
-
.stnd-code-block {
|
|
230
|
-
position: relative;
|
|
231
|
-
background: var(--color-surface-low);
|
|
232
|
-
border-radius: var(--radius-sm);
|
|
233
|
-
box-shadow: var(--shadow-inset), var(--shadow-ring);
|
|
234
|
-
transition: all var(--transition);
|
|
235
|
-
|
|
236
|
-
pre {
|
|
237
|
-
margin: 0 !important;
|
|
238
|
-
background: transparent !important;
|
|
239
|
-
box-shadow: none !important;
|
|
240
|
-
border: none !important;
|
|
241
|
-
padding: var(--space-d2);
|
|
242
|
-
overflow-x: auto;
|
|
243
|
-
position: static;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
&:hover .copy-button {
|
|
247
|
-
opacity: 1;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.copy-button {
|
|
252
|
-
position: absolute;
|
|
253
|
-
top: var(--leading);
|
|
254
|
-
right: var(--leading);
|
|
255
|
-
opacity: 0;
|
|
256
|
-
|
|
257
|
-
&:hover {
|
|
258
|
-
opacity: 1 !important;
|
|
259
|
-
color: var(--color-on-accent);
|
|
260
|
-
background-color: var(--color-accent);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
&.copied {
|
|
264
|
-
color: var(--color-success, #22c55e) !important;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
&.failed {
|
|
268
|
-
color: var(--color-error, #ef4444) !important;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
pre {
|
|
273
|
-
line-height: var(--line-height-compact);
|
|
274
|
-
|
|
275
|
-
code {
|
|
276
|
-
opacity: 0.75;
|
|
277
|
-
transition: opacity var(--transition);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
&:hover code {
|
|
281
|
-
opacity: 1;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
275
|
blockquote {
|
|
286
276
|
font-style: italic;
|
|
287
277
|
color: var(--color-muted);
|
|
288
278
|
padding: var(--space);
|
|
289
|
-
border-left: var(--stroke-width-
|
|
279
|
+
border-left: var(--stroke-width-lg, 2px) solid var(--color-border);
|
|
290
280
|
|
|
291
281
|
cite {
|
|
292
282
|
display: block;
|
|
@@ -295,7 +285,7 @@ blockquote {
|
|
|
295
285
|
}
|
|
296
286
|
}
|
|
297
287
|
|
|
298
|
-
/* Utilities */
|
|
288
|
+
/* Utilities & Inline Elements */
|
|
299
289
|
small {
|
|
300
290
|
font-size: var(--size-sm);
|
|
301
291
|
}
|
|
@@ -314,84 +304,61 @@ sup {
|
|
|
314
304
|
vertical-align: super;
|
|
315
305
|
}
|
|
316
306
|
|
|
307
|
+
/* Duplicate of the `em` rule at line 82 (same --color-italic), this copy
|
|
308
|
+
additionally sets font-style — harmless overlap, not a conflict. */
|
|
317
309
|
em {
|
|
318
310
|
color: var(--color-italic);
|
|
319
311
|
font-style: italic;
|
|
320
312
|
}
|
|
321
313
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
314
|
+
/* Mark highlighting */
|
|
315
|
+
mark {
|
|
316
|
+
background: oklch(from var(--color-yellow) l c h / 0.3);
|
|
317
|
+
color: color-mix(in oklch, var(--color-yellow) 30%, var(--color-foreground));
|
|
318
|
+
padding: var(--trim);
|
|
319
|
+
padding-top: 0.1em;
|
|
327
320
|
}
|
|
328
321
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
Slope: (Ratio - 1).
|
|
341
|
-
- Golden (0.618) -> steep slope (fast growth).
|
|
342
|
-
- Silver (0.414) -> moderate slope.
|
|
343
|
-
*/
|
|
344
|
-
--physics-slope: calc(var(--optical-ratio) - 1);
|
|
345
|
-
|
|
346
|
-
/* Growth Factor: How aggressive is the resizing?
|
|
347
|
-
We multiply the slope by 1vw to create a viewport-relative unit. */
|
|
348
|
-
--fluid-growth: calc(var(--physics-slope) * 0.8vw);
|
|
349
|
-
|
|
350
|
-
/* Tension Factor: How much do we tighten leading as we grow?
|
|
351
|
-
Higher ratios need more tension to keep large text readable. */
|
|
352
|
-
--fluid-tension: calc(var(--physics-slope) * 0.3vw);
|
|
353
|
-
|
|
354
|
-
/* ===== 3. FLUID TYPOGRAPHY =====
|
|
355
|
-
Base size starts at 1rem and grows according to the Physics Slope.
|
|
356
|
-
*/
|
|
357
|
-
--base-size: var(--font-text-size, 1rem);
|
|
358
|
-
|
|
359
|
-
--font-size: clamp(
|
|
360
|
-
var(--base-size),
|
|
361
|
-
calc(var(--base-size) + var(--fluid-growth)),
|
|
362
|
-
calc(var(--base-size) * 1.5)
|
|
363
|
-
);
|
|
364
|
-
|
|
365
|
-
/* ===== 4. FLUID LINE HEIGHT =====
|
|
366
|
-
This is the "Next Level" logic.
|
|
367
|
-
Start with the Optical Ratio as the base breathing room (in ems).
|
|
368
|
-
As the screen (and font) grows, SUBTRACT the Tension Factor.
|
|
369
|
-
|
|
370
|
-
Why? Large text (Desktop) needs TIGHTER leading than small text (Mobile).
|
|
371
|
-
A steep ratio (Golden) creates huge text, so it applies MORE tension.
|
|
372
|
-
*/
|
|
373
|
-
--line-height: clamp(
|
|
374
|
-
1.15,
|
|
375
|
-
calc(var(--optical-ratio) - (var(--fluid-tension) / 1vw)),
|
|
376
|
-
1.65
|
|
377
|
-
);
|
|
322
|
+
/* Keycaps */
|
|
323
|
+
kbd {
|
|
324
|
+
background-color: var(--color-surface);
|
|
325
|
+
background-image: var(--effect-grain);
|
|
326
|
+
border: none;
|
|
327
|
+
border-radius: var(--radius);
|
|
328
|
+
box-shadow: var(--shadow-raised);
|
|
329
|
+
padding: var(--space-d6) var(--space-d3);
|
|
330
|
+
font-family: var(--font-monospace);
|
|
331
|
+
font-size: var(--size-xs);
|
|
332
|
+
pointer-events: none;
|
|
378
333
|
}
|
|
379
334
|
|
|
380
|
-
|
|
335
|
+
/**
|
|
336
|
+
* @component Heading Rhythm & Grid Snapping
|
|
337
|
+
* @category Typography
|
|
338
|
+
* @description Half-baseline rhythm snapping mixin for heading hierarchy.
|
|
339
|
+
*
|
|
340
|
+
* @property @mixin grid-line-height Heading line-height mixin snapping leading to half-baseline rhythm increments.
|
|
341
|
+
*/
|
|
381
342
|
|
|
382
343
|
@mixin grid-line-height($tightness: 1.1) {
|
|
383
|
-
/* The "Target" is simply the font-size * tightness
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
344
|
+
/* The "Target" is simply the font-size * tightness, unless a note
|
|
345
|
+
overrides it via --font-header-line-height in frontmatter */
|
|
346
|
+
--target-lh: calc(1em * var(--font-header-line-height, #{$tightness}));
|
|
347
|
+
|
|
348
|
+
/* The Snap: force it to be a multiple of *half* a baseline, not a whole
|
|
349
|
+
one. Whole-baseline snapping wastes up to ~1 baseline in the worst case
|
|
350
|
+
(target just above a multiple) — brutal on smaller headings whose
|
|
351
|
+
font-size is close to or under one baseline (e.g. h2/h3). Half-baseline
|
|
352
|
+
halves that worst case while still landing on the page's rhythm every
|
|
353
|
+
two headings. */
|
|
354
|
+
line-height: round(up, var(--target-lh), calc(var(--baseline) / 2)) !important;
|
|
388
355
|
|
|
389
356
|
/* Why 'up'?
|
|
390
357
|
'nearest' might snap down and cause letters to clash.
|
|
391
358
|
'up' ensures we always have *at least* enough room. */
|
|
392
359
|
}
|
|
393
360
|
|
|
394
|
-
/* Usage in
|
|
361
|
+
/* Usage in Header sizes */
|
|
395
362
|
h1 {
|
|
396
363
|
/* Giant text needs very tight leading (1.05x), then snap up */
|
|
397
364
|
@include grid-line-height(1.05);
|
package/_standard-04-grid.scss
CHANGED
|
@@ -8,14 +8,18 @@
|
|
|
8
8
|
* asymmetric layouts, gap variants (compact/normal/wide), and responsive column changes.
|
|
9
9
|
* All gaps align to the vertical rhythm system.
|
|
10
10
|
*
|
|
11
|
-
* @
|
|
12
|
-
* @
|
|
13
|
-
* @
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
16
|
-
* @
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
11
|
+
* @property .grid 12-column Swiss-style responsive grid container with automatic column flow.
|
|
12
|
+
* @property .grid-row Grid container with row flow.
|
|
13
|
+
* @property .grid-{n} Explicit n-column grid container (1 to 12 columns).
|
|
14
|
+
* @property .col-{n} Column span modifiers (1 to 12 columns, direct children of .grid).
|
|
15
|
+
* @property .start-{n} Column start position (1 to 12).
|
|
16
|
+
* @property .grid.no-gap Removes grid row gap.
|
|
17
|
+
* @property .grid.compact Compact gap variant aligned to `--trim`.
|
|
18
|
+
* @property .grid.relaxed Relaxed gap variant aligned to `--space`.
|
|
19
|
+
* @property .sm:col-{n} Responsive column spans at mobile viewport (<=768px).
|
|
20
|
+
* @property .sm:grid-{n} Responsive column grid count at mobile viewport (<=768px).
|
|
21
|
+
* @property .lg:col-{n} Responsive column spans at desktop viewport (>=1024px).
|
|
22
|
+
* @property .lg:grid-{n} Responsive column grid count at desktop viewport (>=1024px).
|
|
19
23
|
*
|
|
20
24
|
* @example
|
|
21
25
|
* // Basic 12-column grid with equal width columns
|
|
@@ -28,8 +32,8 @@
|
|
|
28
32
|
*
|
|
29
33
|
* // Responsive grid layout
|
|
30
34
|
* <div class="grid">
|
|
31
|
-
* <div class="col-12 col-
|
|
32
|
-
* <div class="col-12 col-
|
|
35
|
+
* <div class="col-12 sm:col-6 lg:col-3">Card</div>
|
|
36
|
+
* <div class="col-12 sm:col-6 lg:col-3">Card</div>
|
|
33
37
|
* </div>
|
|
34
38
|
*
|
|
35
39
|
* // Main content + sidebar layout
|
|
@@ -47,10 +51,15 @@
|
|
|
47
51
|
Relies on logical properties and Harmony tokens: --base, calc(var(--space) / 4), --base-2, borders, etc.
|
|
48
52
|
*/
|
|
49
53
|
|
|
50
|
-
/*
|
|
51
|
-
.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
/* Fixed 2026-07-14 — was attribute selectors (order-dependent), now an
|
|
55
|
+
explicit selector list built once via $grid-selectors (order-independent). */
|
|
56
|
+
$grid-selectors: ".grid, .grid-row";
|
|
57
|
+
@for $i from 1 through 12 {
|
|
58
|
+
$grid-selectors: $grid-selectors + ", .grid-#{$i}";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Grid container. */
|
|
62
|
+
#{$grid-selectors} {
|
|
54
63
|
display: grid;
|
|
55
64
|
grid-auto-columns: 1fr;
|
|
56
65
|
grid-auto-flow: column;
|
|
@@ -58,8 +67,7 @@
|
|
|
58
67
|
row-gap: var(--gap);
|
|
59
68
|
}
|
|
60
69
|
|
|
61
|
-
|
|
62
|
-
[class^="grid-"] {
|
|
70
|
+
#{$grid-selectors} {
|
|
63
71
|
> * {
|
|
64
72
|
margin: 0;
|
|
65
73
|
}
|
|
@@ -73,25 +81,26 @@
|
|
|
73
81
|
/* TYPOGRAPHIC NUANCES */
|
|
74
82
|
/* =========================== */
|
|
75
83
|
|
|
76
|
-
|
|
84
|
+
#{$grid-selectors} > * {
|
|
77
85
|
min-width: 0;
|
|
78
86
|
/* ← Force items to shrink below content size */
|
|
79
87
|
margin-block: 0;
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
@media (max-width: #{$mobile}) {
|
|
83
|
-
|
|
91
|
+
#{$grid-selectors} > * {
|
|
84
92
|
min-width: 0;
|
|
85
93
|
}
|
|
86
94
|
}
|
|
87
95
|
|
|
88
|
-
|
|
96
|
+
#{$grid-selectors} {
|
|
89
97
|
.card {
|
|
90
98
|
margin: 0;
|
|
91
99
|
}
|
|
92
100
|
}
|
|
93
101
|
|
|
94
|
-
/* Gap variants aligned to rhythm
|
|
102
|
+
/* Gap variants aligned to rhythm — this is the LIVE definition (sets --gap,
|
|
103
|
+
the property actually consumed by column-gap/row-gap above). */
|
|
95
104
|
:is(.grid, [class^="grid-"]).compact {
|
|
96
105
|
--gap: var(--trim);
|
|
97
106
|
}
|
|
@@ -267,19 +276,11 @@ hr.col-row {
|
|
|
267
276
|
z-index: 1;
|
|
268
277
|
}
|
|
269
278
|
|
|
270
|
-
/* Row gap utilities for grid system */
|
|
279
|
+
/* Row gap utilities for grid system. */
|
|
271
280
|
.grid.no-gap {
|
|
272
281
|
row-gap: 0;
|
|
273
282
|
}
|
|
274
283
|
|
|
275
|
-
.grid.compact {
|
|
276
|
-
--grid-gap: var(--leading);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.grid.relaxed {
|
|
280
|
-
--grid-gap: var(--space-2);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
284
|
/* Common layout containers inherit rhythm to cascade deeper */
|
|
284
285
|
.box,
|
|
285
286
|
.grid > .col-1,
|
|
@@ -309,6 +310,6 @@ hr.col-row {
|
|
|
309
310
|
}
|
|
310
311
|
}
|
|
311
312
|
|
|
312
|
-
|
|
313
|
+
#{$grid-selectors} .container-hero {
|
|
313
314
|
margin-inline: 0;
|
|
314
315
|
}
|
package/_standard-05-rhythm.scss
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
@use "standard-00-variables" as *;
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @component Rhythm
|
|
5
|
+
* @category Layout
|
|
6
|
+
* @description Vertical rhythm for any container: apply `.rhythm` and its
|
|
7
|
+
* children get consistent `margin-block-start` spacing with no per-element
|
|
8
|
+
* classes, heavier before headings and around block-level elements
|
|
9
|
+
* (tables, blockquotes, figures — the tags this cascades to are declared
|
|
10
|
+
* once in `_standard-00-variables.scss`, not here). `.flex > *` is zeroed
|
|
11
|
+
* out automatically so rhythm margins never stack with flex `gap`.
|
|
12
|
+
*
|
|
13
|
+
* @property .rhythm The container class. Sets `display: flow-root` so child margins cannot collapse out of it.
|
|
14
|
+
* @property .no-rhythm Zeroes `margin-block-start` on every descendant — a subtree-wide rhythm opt-out.
|
|
15
|
+
* @property --gap-multiplicator Rhythm multiplier factor for block-level spacing and heading exceptions.
|
|
16
|
+
* @property .flex > * Zeroes `margin-block-start` for flex children so margins do not stack with flex gap.
|
|
17
|
+
*
|
|
18
|
+
* @example html - Turn any container into a rhythm block
|
|
19
|
+
* <article class="rhythm">
|
|
20
|
+
* <h2>Heading</h2>
|
|
21
|
+
* <p>Spaced automatically — no margin utility classes needed.</p>
|
|
22
|
+
* </article>
|
|
23
|
+
*/
|
|
24
|
+
|
|
3
25
|
/* ===== BULLETPROOF RHYTHM SYSTEM ===== */
|
|
4
26
|
/* Applied to any container — cascades to children via margin-block-start */
|
|
5
27
|
|
|
@@ -9,6 +31,24 @@
|
|
|
9
31
|
Think of it as "overflow: hidden" but without clipping content. */
|
|
10
32
|
display: flow-root;
|
|
11
33
|
|
|
34
|
+
/* Every selector below is wrapped in :where(), including .rhythm itself
|
|
35
|
+
— that's zero specificity everywhere, by design (easy for any other
|
|
36
|
+
rule to override). Which means SOURCE ORDER is the only tiebreaker
|
|
37
|
+
when more than one of these rules matches the same element (e.g. a
|
|
38
|
+
paragraph immediately before an h1 matches both the base 1x rule
|
|
39
|
+
below AND the heading exception further down — the exception wins
|
|
40
|
+
purely because it's declared later). Do not reorder this block
|
|
41
|
+
without checking every rule still resolves the way you expect. */
|
|
42
|
+
|
|
43
|
+
/* AUDIT FLAG (2026-07-14): this base rule has no `>` — it applies at
|
|
44
|
+
ANY nesting depth inside .rhythm, not just direct children. Every
|
|
45
|
+
other rule in this block (the double-tag 2x rule right below, and
|
|
46
|
+
all EXCEPTIONS) is `>`-scoped to direct children only. So a heading
|
|
47
|
+
nested two levels deep (inside a .callout, say) gets the base 1x
|
|
48
|
+
spacing but never the heading-specific 2x/3x exceptions a top-level
|
|
49
|
+
heading would get. Possibly intentional (exceptions are for
|
|
50
|
+
top-level document flow only) — flagging since the asymmetry itself
|
|
51
|
+
isn't declared anywhere, just falls out of one missing `>`. */
|
|
12
52
|
:where(:is(#{$rhythm-tags})) + :where(:is(#{$rhythm-tags})) {
|
|
13
53
|
margin-block-start: calc(var(--gap) * 1);
|
|
14
54
|
}
|
|
@@ -46,6 +86,9 @@
|
|
|
46
86
|
|
|
47
87
|
//*/
|
|
48
88
|
|
|
89
|
+
/* Flex children use `gap` for spacing, not margin (see cheat sheet:
|
|
90
|
+
"gap on the parent, not margin on children") — zero out any rhythm
|
|
91
|
+
margin that would otherwise stack with the flex gap. */
|
|
49
92
|
.flex > * {
|
|
50
93
|
margin-block-start: 0;
|
|
51
94
|
}
|
package/_standard-06-prose.scss
CHANGED
|
@@ -8,16 +8,20 @@
|
|
|
8
8
|
* responsive content columns for sidebars, accents, and featured content.
|
|
9
9
|
* Inspired by fine-art typography and classical book design principles.
|
|
10
10
|
*
|
|
11
|
-
* @
|
|
12
|
-
* @
|
|
13
|
-
* @
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
16
|
-
* @
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
19
|
-
* @
|
|
20
|
-
* @
|
|
11
|
+
* @property .prose Main article/content grid container for readable prose with named tracks.
|
|
12
|
+
* @property .prose.left Left-aligned prose variant hugging the left edge.
|
|
13
|
+
* @property .small Narrow sidebar breakout column track.
|
|
14
|
+
* @property .editorial Editorial column breakout track (`minmax(0, var(--space-2))`).
|
|
15
|
+
* @property .feature Feature callout breakout track (`minmax(0, var(--space-4))`).
|
|
16
|
+
* @property .hero Full-bleed viewport width hero track (`minmax(0, 1fr)`).
|
|
17
|
+
* @property .full Full viewport width breakout track.
|
|
18
|
+
* @property --line-width Active reading column measure.
|
|
19
|
+
* @property --line-width-xs Extra small reading measure (24rem / 384px).
|
|
20
|
+
* @property --line-width-sm Small reading measure (32rem / 512px).
|
|
21
|
+
* @property --line-width-md Medium reading measure (42rem / 672px) - default.
|
|
22
|
+
* @property --line-width-lg Large reading measure (50rem / 800px).
|
|
23
|
+
* @property --line-width-xl Extra large reading measure (60rem / 960px).
|
|
24
|
+
* @property --body-max-width Overall page max-width constraint (900px).
|
|
21
25
|
*
|
|
22
26
|
* @example
|
|
23
27
|
* // Standard article with proper reading width
|
|
@@ -75,7 +79,7 @@
|
|
|
75
79
|
transition: grid-template-columns var(--transition);
|
|
76
80
|
|
|
77
81
|
position: relative;
|
|
78
|
-
max-width: var(--
|
|
82
|
+
max-width: var(--body-max-width);
|
|
79
83
|
/*z-index: var(--z-base);*/
|
|
80
84
|
/* Default content positioning */
|
|
81
85
|
|
|
@@ -88,6 +92,13 @@
|
|
|
88
92
|
padding-inline var(--transition);
|
|
89
93
|
}
|
|
90
94
|
|
|
95
|
+
/* Astro islands render as <astro-island> with display:contents, so their
|
|
96
|
+
children — not the island — are the grid items and need placement too. */
|
|
97
|
+
> astro-island > * {
|
|
98
|
+
grid-column: content;
|
|
99
|
+
min-width: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
91
102
|
> .small,
|
|
92
103
|
> .container-small,
|
|
93
104
|
> .callout,
|
|
@@ -129,28 +140,6 @@
|
|
|
129
140
|
}
|
|
130
141
|
}
|
|
131
142
|
|
|
132
|
-
/* =========================== */
|
|
133
|
-
/* TYPOGRAPHIC NUANCES */
|
|
134
|
-
/* =========================== */
|
|
135
|
-
.video-container {
|
|
136
|
-
position: relative;
|
|
137
|
-
padding-bottom: 56.25%;
|
|
138
|
-
/* 16:9 aspect ratio */
|
|
139
|
-
height: 0;
|
|
140
|
-
overflow: hidden;
|
|
141
|
-
border-radius: var(--radius);
|
|
142
|
-
box-shadow: var(--shadow-raised);
|
|
143
|
-
|
|
144
|
-
iframe {
|
|
145
|
-
position: absolute;
|
|
146
|
-
top: 0;
|
|
147
|
-
left: 0;
|
|
148
|
-
width: 100%;
|
|
149
|
-
height: 100%;
|
|
150
|
-
border: 0;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
143
|
/* Image gallery layout */
|
|
155
144
|
&:not(.no-grid) {
|
|
156
145
|
p:has(img),
|
|
@@ -196,9 +185,6 @@
|
|
|
196
185
|
margin-inline: 0 !important;
|
|
197
186
|
}
|
|
198
187
|
|
|
199
|
-
/* Note: Page's main title h1:first-child retains spacing via direct child selector */
|
|
200
|
-
/* The > h1:first-child selector in h1 rule ensures it overrides rhythm's > * margin-reset */
|
|
201
|
-
|
|
202
188
|
/* Basic media styling */
|
|
203
189
|
img,
|
|
204
190
|
audio,
|
|
@@ -260,17 +246,19 @@
|
|
|
260
246
|
overflow-wrap: break-word;
|
|
261
247
|
}
|
|
262
248
|
|
|
249
|
+
/* Fixed 2026-07-14 — swapped undefined tokens for their real equivalents
|
|
250
|
+
(--color-muted, --color-accent, --color-surface-high). */
|
|
263
251
|
.mycelial-graft {
|
|
264
252
|
text-decoration: none;
|
|
265
|
-
border-bottom: 1px dotted var(--color-
|
|
253
|
+
border-bottom: 1px dotted var(--color-muted);
|
|
266
254
|
color: inherit;
|
|
267
255
|
cursor: help;
|
|
268
256
|
transition: all 0.2s ease;
|
|
269
257
|
|
|
270
258
|
&:hover {
|
|
271
|
-
color: var(--color-
|
|
272
|
-
border-bottom: 1px solid var(--color-
|
|
273
|
-
background-color: var(--color-surface-
|
|
259
|
+
color: var(--color-accent);
|
|
260
|
+
border-bottom: 1px solid var(--color-accent);
|
|
261
|
+
background-color: var(--color-surface-high);
|
|
274
262
|
}
|
|
275
263
|
}
|
|
276
264
|
}
|