gp-dimm-city 1.6.2 → 1.6.3-alpha.2
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 +88 -0
- package/README.md +73 -5
- package/components.yaml +63 -22
- package/package.json +1 -1
- package/plugin.js +56 -8
- package/snippets/credits-page.md +1 -1
- package/snippets/intro-page.md +1 -1
- package/snippets/toc-page.md +1 -1
- package/styles/components/cards.css +10 -8
- package/styles/components/data.css +0 -5
- package/styles/components/entries.css +20 -0
- package/styles/components/images.css +0 -5
- package/styles/components/section.css +47 -13
- package/styles/dc-component-defaults.css +19 -0
- package/styles/dc-native.css +7 -5
- package/styles/page-templates.css +30 -10
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,94 @@ cut a version that has no `## [X.Y.Z]` heading below.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.6.3] - 2026-10-12
|
|
11
|
+
|
|
12
|
+
Content and markers by default, overrides when wanted: the defaults now do more,
|
|
13
|
+
so a book writes fewer `.dc-avoid-split`, `.dc-snug`, `{.dc-chevron}` and `gp-*`
|
|
14
|
+
classes, and every override that stays is documented and has a token a book can
|
|
15
|
+
set from its own CSS.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- **A creature stays whole by default.** An `@npc-stat` with no `####`, or one (a
|
|
20
|
+
species and its one variant), is one creature, read at one glance: it keeps its
|
|
21
|
+
padding inside its box and moves to the next page rather than splitting, as
|
|
22
|
+
`.dc-avoid-split` did. `.dc-avoid-split` on one is now redundant. A block with
|
|
23
|
+
two or more `####` entries is unchanged (it breaks between entries, never inside
|
|
24
|
+
one). `--dc-npc-stat-break-inside: auto` lets one split.
|
|
25
|
+
- **A catalog splits by default, and an explicit override still wins.** A
|
|
26
|
+
`@section catalog` reads its own token, `--dc-catalog-break-inside` (default
|
|
27
|
+
`auto`), because a run of entries kept whole leaves the foot of the page before
|
|
28
|
+
it blank. An author's `.dc-avoid-split` on it still keeps it whole, as it always
|
|
29
|
+
did, and so does `--dc-catalog-break-inside: avoid` from a book's CSS. A
|
|
30
|
+
container's `--dc-section-break-inside` does not reach a catalog.
|
|
31
|
+
- **Keeping a box whole is a token per component.** `--dc-section-break-inside`,
|
|
32
|
+
`--dc-catalog-break-inside`, `--dc-npc-stat-break-inside`,
|
|
33
|
+
`--dc-skill-card-break-inside` and `--dc-faction-break-inside` are declared at
|
|
34
|
+
`:root` (`avoid` or `auto`), and each component reads its own. `.dc-avoid-split`
|
|
35
|
+
is now a setter of them (and of `--dc-section-edge: 0px`, which keeps a whole
|
|
36
|
+
section's padding inside its box), so a book writes the same declarations for
|
|
37
|
+
one box from its own sheet (`#core-loop { --dc-section-break-inside: avoid;
|
|
38
|
+
--dc-section-edge: 0px; }`). A sheet that sets only the first still keeps the
|
|
39
|
+
section whole; the second keeps the pagination identical to the class. Sections,
|
|
40
|
+
skill cards and factions render as before. The skill card's `:not(.dc-avoid-split)`
|
|
41
|
+
guards on its keep-with-next chains are gone: a card kept whole is unaffected by
|
|
42
|
+
chains until it is taller than a page.
|
|
43
|
+
- **The space under paragraphs and list items is `--dc-flow-gap`.** `.dc-snug` is
|
|
44
|
+
now a setter of it (0.04in), and a book sets it on any box. Unset, each
|
|
45
|
+
component keeps its own spacing, so nothing changes until it is set. A
|
|
46
|
+
`revert-layer` fallback in the template layer hands the margin back to the
|
|
47
|
+
component while the token is unset.
|
|
48
|
+
- **Entry art has a default.** An image with no class inside a `@gear` entry
|
|
49
|
+
floats right at half the card (`--dc-entry-art-width`, 50%), as
|
|
50
|
+
`{.gp-right .gp-medium}` does. An image with no class on its own line under the
|
|
51
|
+
credits colophon is a band across the foot of the sheet, the page's full width
|
|
52
|
+
and `--dc-credits-art-height` (2.75in) tall, cropped to fit. Both read only an
|
|
53
|
+
image with no class, so a `gp-*` class an author writes still wins (the plugin's
|
|
54
|
+
layer outranks core's).
|
|
55
|
+
- **A front-matter title is a chevron by context.** The plugin writes `.dc-chevron`
|
|
56
|
+
on the `h1` straight under `@page intro`, `credits` and `contents`, so those
|
|
57
|
+
titles need no `{.dc-chevron}`; the class still works on any other heading and
|
|
58
|
+
is not doubled where it is written. The snippets for the three pages no longer
|
|
59
|
+
write it.
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- **A ladder table keeps what the author wrote on it.** `{#id .class}` after a
|
|
64
|
+
table of the five bands, outside a skill card and in one, was dropped with the
|
|
65
|
+
table; it now lands on the `.dc-outcomes` element, with any other attribute.
|
|
66
|
+
- **`@procedure` keeps the attributes on its line.** The wrapper renders nothing,
|
|
67
|
+
so `@procedure #steps .tight` lost its id and class; they now land on the list
|
|
68
|
+
(the first, when there are several, so an id stays unique).
|
|
69
|
+
|
|
70
|
+
### Removed
|
|
71
|
+
|
|
72
|
+
- **Two selectors that matched nothing in the design guide or either book:**
|
|
73
|
+
`.dc-skill-card:only-child` and `.dc-sidebar:empty`, and the
|
|
74
|
+
`.dc-card.dc-faction.dc-avoid-split` rule the faction token replaces. The 94
|
|
75
|
+
selectors that match nothing in the two books were checked against the design
|
|
76
|
+
guide too: 79 are documented there (`.dc-stat*`, `.dc-tape`, `.dc-spec-tweak`,
|
|
77
|
+
`.dc-npc-compact`, `.dc-img-float-*`, `.dc-sidebar`, the `@npc-stat` stat-line
|
|
78
|
+
rules and others), and the rest are element baselines, a rule a test asserts, or
|
|
79
|
+
the loose-list half of a live selector, so they stay (see
|
|
80
|
+
`docs/cleanup-backlog.md`).
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
|
|
84
|
+
- **README: "Author overrides".** One section for the supported overrides: core's
|
|
85
|
+
`gp-*` classes (a pointer to the Gutterpress guide), each plugin modifier with
|
|
86
|
+
what it does and the token that does the same from a book's CSS,
|
|
87
|
+
`@page-break`, `@columns`, `{#id}`, and the coming `[data-name]` hook. The
|
|
88
|
+
"what are you writing" tables no longer list `.dc-avoid-split`, `.dc-snug` or
|
|
89
|
+
`.dc-sidebar` as if ordinary content needed them, in the README and the design
|
|
90
|
+
guide.
|
|
91
|
+
- **The catalog names every class an author can write.** `components.yaml`:
|
|
92
|
+
`modifier:` takes a class or a list, `description:` is one line for every
|
|
93
|
+
modifier and author-facing class, and `.dc-h3` … `.dc-h6`, `.dc-chevron`,
|
|
94
|
+
`.dc-flush`, `.dc-spray`, `.dc-spec-tweak` / `.dc-no-top`, `.dc-sidebar` and the
|
|
95
|
+
image floats are entries with their modifier, for the app's completions. The
|
|
96
|
+
integrity test checks both.
|
|
97
|
+
|
|
10
98
|
## [1.6.2] - 2026-10-12
|
|
11
99
|
|
|
12
100
|
### Changed
|
package/README.md
CHANGED
|
@@ -46,7 +46,6 @@ package renders and prints; `docs/macros.md` is the full inventory and
|
|
|
46
46
|
| I am writing… | Use |
|
|
47
47
|
|---|---|
|
|
48
48
|
| Rules or reference text under a heading | `@section panel` |
|
|
49
|
-
| The same, kept on one page | `@section panel .dc-avoid-split` |
|
|
50
49
|
| Unboxed text that carries the accent rail | `@section flat` |
|
|
51
50
|
| A table or list to look up (prices, conditions, a menu of options) | `@section reference` |
|
|
52
51
|
| World or setting text | `@section lore` |
|
|
@@ -56,7 +55,6 @@ package renders and prints; `docs/macros.md` is the full inventory and
|
|
|
56
55
|
| A boxed note, warning, DM note, vibe, origin or visit | `@callout …` (`@dm-note`) |
|
|
57
56
|
| A worked example | `@callout example` |
|
|
58
57
|
| A box in one of three registers: panel, slate, shard | `@block …` |
|
|
59
|
-
| A callout floated beside the text | `@callout note .dc-sidebar` |
|
|
60
58
|
| Fiction, a chapter-opener story | `@fiction-excerpt` |
|
|
61
59
|
| A creature or NPC | `@npc-stat` (small ones: `@npc-stat compact`) |
|
|
62
60
|
| An organization: megacorp, cabal, cult, enforcers | `@faction megacorp`, `cabal`, `cult`, `enforcer` |
|
|
@@ -74,14 +72,16 @@ package renders and prints; `docs/macros.md` is the full inventory and
|
|
|
74
72
|
| The specialty catalog | `@card-grid` |
|
|
75
73
|
| A specialty, its learning paths and skill cards | `@specialty`, `@learning-path`, `@skill` |
|
|
76
74
|
| Grouping, with no styling | `@section` |
|
|
77
|
-
| A section that overflows by a line or two | add `.dc-snug` |
|
|
78
75
|
| Where it sits | `@page chapter-start`, `intro`, `credits`, `contents`, `citizen-file` (and core's `blank`, `full-bleed`); `@chapter rules`, `lore`, `citizen-file`, `specialty` |
|
|
79
76
|
|
|
80
77
|
The named components are also words on `@section` (`@npc-stat` is
|
|
81
78
|
`@section npc`, `@fiction-excerpt` is `@section fiction`); either spelling
|
|
82
79
|
renders the same. `reference`, `lore`, `dm` and `choose` are words only: panels
|
|
83
|
-
that say what kind of text they hold.
|
|
84
|
-
|
|
80
|
+
that say what kind of text they hold. Write the content and the marker that says
|
|
81
|
+
what it is: the defaults set how it looks and where it breaks (sections split
|
|
82
|
+
across pages, a catalog too, and a creature and a callout stay whole). A page
|
|
83
|
+
or chapter word draws no box of its own: it re-tunes the sections inside it. To
|
|
84
|
+
change how one block sits, see [Author overrides](#author-overrides).
|
|
85
85
|
|
|
86
86
|
Also in the box:
|
|
87
87
|
|
|
@@ -126,6 +126,66 @@ to lay down the front matter, and reach for *Skill*, *Learning Path* and
|
|
|
126
126
|
*Specialty* as you write. `page-rules.css` sets a Letter page with bleed; keep
|
|
127
127
|
the manifest's `page:` in step with it.
|
|
128
128
|
|
|
129
|
+
## Author overrides
|
|
130
|
+
|
|
131
|
+
A book's markdown holds the content and the markers that say what it is
|
|
132
|
+
(`@section panel`, `@npc-stat`, `@gear augment`); the defaults above make it
|
|
133
|
+
look right and break sensibly. None of what follows is needed for that. These
|
|
134
|
+
are the supported ways to change one block when the defaults do not suit it:
|
|
135
|
+
written in the markdown, or from the book's own CSS, with the same effect. They
|
|
136
|
+
are documented and kept; the defaults only make them needed less often.
|
|
137
|
+
|
|
138
|
+
**Core Gutterpress classes (`gp-*`).** Image placement and size (`.gp-left`,
|
|
139
|
+
`.gp-right`, `.gp-center`, `.gp-full`, `.gp-bleed`, `.gp-small`, `.gp-medium`,
|
|
140
|
+
`.gp-large`), pinning art to the page (`.gp-pin` with `.gp-top`, `.gp-bottom`,
|
|
141
|
+
`.gp-flush`, `.gp-behind`), wrapping text around a shape (`.gp-shape`) and the
|
|
142
|
+
fragmentation helpers (`.gp-no-break`, `.gp-break-before`) belong to Gutterpress,
|
|
143
|
+
not to this package. They are written as `{.gp-right
|
|
144
|
+
.gp-medium}` and are documented in the Gutterpress user guide
|
|
145
|
+
([Visual elements](https://github.com/dimm-city/gutterpress/blob/main/examples/gutterpress-user-guide/03-visual-elements.md)).
|
|
146
|
+
This package's defaults for art (below) read only an image with no class, so a
|
|
147
|
+
`gp-*` class always wins.
|
|
148
|
+
|
|
149
|
+
**Modifiers from this package.** Written after a marker (`@section panel
|
|
150
|
+
.dc-snug`) or in braces after an element (`## Title {.dc-h3}`). Each has a
|
|
151
|
+
matching setting for a book's CSS, so a book can do the same without a markdown
|
|
152
|
+
edit.
|
|
153
|
+
|
|
154
|
+
| Write | What it does | The same from a book's CSS |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| `.dc-avoid-split` on `@section`, `@skill`, `@faction` or `@npc-stat` | Keep that box on one page: it moves to the next page rather than splitting | `--dc-section-break-inside: avoid` with `--dc-section-edge: 0px` (a section), `--dc-skill-card-break-inside`, `--dc-faction-break-inside`, `--dc-npc-stat-break-inside` |
|
|
157
|
+
| `.dc-snug` on `@section` or `@page` | Tighten the space under paragraphs and list items, for one that overflows by a line or two | `--dc-flow-gap: 0.04in` |
|
|
158
|
+
| `.dc-h3` … `.dc-h6` on a heading or paragraph | Give it the look of that level without changing its place in the outline | none: a class only |
|
|
159
|
+
| `.dc-chevron` on a heading | Set it as a chevron banner (the title under `@page intro`, `credits` and `contents` already is one) | `--dc-chevron-bg`, `--dc-chevron-color`, `--dc-chevron-font-size` |
|
|
160
|
+
| `.dc-flush` | Run a tape, stat block, sticker chain, pull quote or `@outcome` edge to edge | none: a class only |
|
|
161
|
+
| `.dc-sidebar` on a callout | Float it right at about a third of the width, text wrapping on its left (`@callout note .dc-sidebar`) | none: a class only |
|
|
162
|
+
| `.dc-spray`, `.dc-spec-tweak`, `.dc-no-top`, `.dc-img-float-left`, `.dc-img-float-right` | Heading banners and an image float | none: classes only |
|
|
163
|
+
|
|
164
|
+
A catalog (`@section catalog`) splits across pages by default, since one kept
|
|
165
|
+
whole leaves the foot of the page before it blank; an explicit `.dc-avoid-split`
|
|
166
|
+
on it still keeps it whole, as does `--dc-catalog-break-inside: avoid` from a
|
|
167
|
+
book's CSS. An `@npc-stat` with at most one `####` is one creature and stays whole without
|
|
168
|
+
`.dc-avoid-split` (`--dc-npc-stat-break-inside: auto` lets one split). An image
|
|
169
|
+
with no class in a `@gear` entry floats right at half the card
|
|
170
|
+
(`--dc-entry-art-width`), and one on its own line under the credits colophon is
|
|
171
|
+
a band across the foot of the sheet (`--dc-credits-art-height`).
|
|
172
|
+
|
|
173
|
+
**Core markers and attributes.** `@page-break` starts a new page at that line;
|
|
174
|
+
`@columns 2` … `@end-columns` (one to five columns, and `@column-break` to move
|
|
175
|
+
to the next) is the one way to set text in columns. Both are Gutterpress's, not
|
|
176
|
+
this package's. `{#id}` (or `#id` on a marker line) names a block for a link and
|
|
177
|
+
for a book's CSS: `#core-loop { --dc-section-break-inside: avoid; }`. Written after
|
|
178
|
+
a table the package turns into an outcome ladder, or on an `@procedure` line, the
|
|
179
|
+
id and classes land on the ladder or the list.
|
|
180
|
+
|
|
181
|
+
**Coming: `[data-name]`.** Gutterpress will stamp a stable `data-name` on every
|
|
182
|
+
marker block, image and heading (from `name="…"`, then `label="…"`, then the
|
|
183
|
+
slug of its first heading, or the image's file name), so a book's CSS can tune
|
|
184
|
+
one block without touching the markdown:
|
|
185
|
+
`[data-name="core-loop"] { --dc-section-break-inside: avoid; }`. Until your
|
|
186
|
+
Gutterpress does, `name="…"` on a marker line writes it and `#id` works
|
|
187
|
+
everywhere.
|
|
188
|
+
|
|
129
189
|
## Your own CSS: the layer convention
|
|
130
190
|
|
|
131
191
|
List your sheets under `styles:` in the manifest. Gutterpress (0.11.0+) wraps
|
|
@@ -174,6 +234,14 @@ of every page). Public API for semver purposes: the macro vocabulary, the
|
|
|
174
234
|
classes and tokens marked `live` in `components.yaml`, the page templates, and
|
|
175
235
|
the layer names. `CHANGELOG.md` lists what each release changes.
|
|
176
236
|
|
|
237
|
+
### Moving from 1.6.2 or earlier
|
|
238
|
+
|
|
239
|
+
1.6.3 changes a default, so rebuild and compare:
|
|
240
|
+
|
|
241
|
+
- An `@npc-stat` with at most one `####` (one creature) stays whole. Add
|
|
242
|
+
`--dc-npc-stat-break-inside: auto` to let one split. A `.dc-avoid-split` on one
|
|
243
|
+
is now redundant.
|
|
244
|
+
|
|
177
245
|
### Moving from 1.6.1 or earlier
|
|
178
246
|
|
|
179
247
|
1.6.2 folds the item markers into `@gear` and gives the SPECS box one spelling.
|
package/components.yaml
CHANGED
|
@@ -16,8 +16,12 @@
|
|
|
16
16
|
# each exactly as written: "@npc-stat", "@section npc", "@page intro",
|
|
17
17
|
# "@chapter rules"; a retired entry lists the spellings that no longer
|
|
18
18
|
# work) · snippet (the file or files in snippets/ that insert it, by name
|
|
19
|
-
# without .md) · modifier (
|
|
20
|
-
#
|
|
19
|
+
# without .md) · modifier (the class, or list of classes, an author writes
|
|
20
|
+
# in `{…}` or after a marker to change a box without being a component:
|
|
21
|
+
# dc-avoid-split, dc-snug, dc-chevron, dc-h3…dc-h6; the app offers each as
|
|
22
|
+
# a completion) · description (one line, what an author gets from the
|
|
23
|
+
# class or word; every author-facing entry and every modifier has one) ·
|
|
24
|
+
# replaced_by (retired entries: what to
|
|
21
25
|
# write now) · recipe · emits (DOM strings, one or a list) · css
|
|
22
26
|
# (package-relative paths; required for live/unused, and at least one must
|
|
23
27
|
# style one of the entry's classes) · tokens (must be declared under
|
|
@@ -169,6 +173,7 @@ components:
|
|
|
169
173
|
- name: block-variants
|
|
170
174
|
status: live
|
|
171
175
|
origin: author
|
|
176
|
+
description: "The three looks of a @block: panel (HUD), slate (dark) and shard (zine)."
|
|
172
177
|
recipe: "@block panel | slate | shard"
|
|
173
178
|
emits: div.dc-block.dc-panel|.dc-slate|.dc-shard
|
|
174
179
|
css: styles/components/section.css
|
|
@@ -218,9 +223,9 @@ components:
|
|
|
218
223
|
recipe: "@gear [augment|treasure|vehicle|drug] #### Name … @end-gear (a @gear after a @gear closes the first)"
|
|
219
224
|
emits: div.dc-card.dc-entry.dc-gear
|
|
220
225
|
css: styles/components/entries.css
|
|
221
|
-
tokens: [--dc-entry-accent, --dc-entry-ink, --dc-entry-surface, --dc-entry-rail, --dc-entry-rule, --dc-entry-kind]
|
|
226
|
+
tokens: [--dc-entry-accent, --dc-entry-ink, --dc-entry-surface, --dc-entry-rail, --dc-entry-rule, --dc-entry-kind, --dc-entry-art-width]
|
|
222
227
|
breaks: "break-inside: avoid (via .dc-card)"
|
|
223
|
-
notes: "The item entry, and the one marker for every kind of item: bare `@gear` is general gear, and a bare word picks a kind (`augment`, `treasure`, `vehicle`, `drug`, the four entries below). A .dc-card of the entry family with an orange rail; the name (### or ####), the italic tagline paragraph and the bold price paragraph are picked out by shape. A `**SPECS:**` paragraph is a `@field specs`. Reports an entry with no name or with a second one, and a word that is not a kind (read as general gear). Not a section, so there is no `@section` word for it. A run of entries goes in a `@section catalog`; each kind is told apart by its rail colour and the small kind word over its name."
|
|
228
|
+
notes: "The item entry, and the one marker for every kind of item: bare `@gear` is general gear, and a bare word picks a kind (`augment`, `treasure`, `vehicle`, `drug`, the four entries below). A .dc-card of the entry family with an orange rail; the name (### or ####), the italic tagline paragraph and the bold price paragraph are picked out by shape. An image with no class in an entry is the item's picture: floated right at --dc-entry-art-width (half the card); a class the author writes (`{.gp-left .gp-large}`) places it instead. A `**SPECS:**` paragraph is a `@field specs`. Reports an entry with no name or with a second one, and a word that is not a kind (read as general gear). Not a section, so there is no `@section` word for it. A run of entries goes in a `@section catalog`; each kind is told apart by its rail colour and the small kind word over its name."
|
|
224
229
|
|
|
225
230
|
- name: augment
|
|
226
231
|
status: live
|
|
@@ -313,6 +318,7 @@ components:
|
|
|
313
318
|
- name: tape
|
|
314
319
|
status: live
|
|
315
320
|
origin: author
|
|
321
|
+
description: "A torn-tape divider with a label (raw HTML div)."
|
|
316
322
|
recipe: "<div class=\"dc-tape\">…</div> (add dc-flush to run edge to edge)"
|
|
317
323
|
emits: div.dc-tape
|
|
318
324
|
css: styles/components/chrome.css
|
|
@@ -352,7 +358,7 @@ components:
|
|
|
352
358
|
- --dc-outcome-name-color
|
|
353
359
|
- --dc-outcome-name-opacity
|
|
354
360
|
usage: ["| 20 |"]
|
|
355
|
-
breaks: "break-inside: avoid
|
|
361
|
+
breaks: "break-inside: avoid"
|
|
356
362
|
notes: "Declared marker; `flush` is its one variant (also writable .dc-flush). One row per `roll | name | text` line, coloured by position; a sixth row is a plain hit. Left open at the end of the file it warns (declared_marker_eof_close); a line that is not a row, a non-row block, or no rows at all is reported. The table form is recognised by its band values, not its headers: a table with any other set of bands (six bands, three, a split at 10) is a plain table, or an @roll-table. A table row's tier and name come from its band (20 crit, 11-19 hit, 6-10 hard choice, 2-5 miss, 1 catastrophe)."
|
|
357
363
|
|
|
358
364
|
- name: specialty
|
|
@@ -470,7 +476,8 @@ components:
|
|
|
470
476
|
- --dc-card-body-mark
|
|
471
477
|
- --dc-card-gap
|
|
472
478
|
- --dc-card-tab-shadow
|
|
473
|
-
|
|
479
|
+
- --dc-skill-card-break-inside
|
|
480
|
+
breaks: "splits across pages by default (a card is a third to half a page, so whole cards left pages one card deep); a split card never opens with only its tab, an ability row is never cut, a lead-in stays with what it introduces, and the last block stays with the one above it. {.dc-avoid-split} keeps one whole, as --dc-skill-card-break-inside: avoid does"
|
|
474
481
|
notes: "Declared marker. Every #### heading in one @skill is its own card, with the @skill line's classes and attributes. @end-skill closes only the skill, never the path around it. A ##### Outcomes sub-header is swallowed (the outcomes block carries its own label). Part of a card's body can sit in columns: wrap it in `@columns 2` … `@end-columns`; the run (and any `@column-break` in it) stays inside the card's .dc-card-inner, in place."
|
|
475
482
|
|
|
476
483
|
- name: skill-highlight
|
|
@@ -526,6 +533,8 @@ components:
|
|
|
526
533
|
- name: flush
|
|
527
534
|
status: live
|
|
528
535
|
origin: plugin
|
|
536
|
+
modifier: dc-flush
|
|
537
|
+
description: "Run a tape, stat block, sticker chain, pull quote or outcome ladder edge to edge, with no side margin."
|
|
529
538
|
recipe: "@outcome flush, > [!PULLQUOTE], or .dc-flush on raw .dc-tape / .dc-stat / .dc-stickers"
|
|
530
539
|
emits: .dc-flush (edge-to-edge modifier)
|
|
531
540
|
css: [styles/components/chrome.css, styles/components/data.css]
|
|
@@ -598,7 +607,8 @@ components:
|
|
|
598
607
|
- --dc-npc-stat-label-color
|
|
599
608
|
- --dc-npc-stat-rule
|
|
600
609
|
- --dc-npc-stat-rule-width
|
|
601
|
-
|
|
610
|
+
- --dc-npc-stat-break-inside
|
|
611
|
+
breaks: "a block with #### entries breaks between entries, never inside one (keep-with-next chain), whether the entries are direct children or sit in an @columns run inside it; a block with no ####, or one, is one creature and stays whole (--dc-npc-stat-break-inside: auto lets one split)"
|
|
602
612
|
|
|
603
613
|
- name: npc-stat-compact
|
|
604
614
|
status: live
|
|
@@ -630,9 +640,9 @@ components:
|
|
|
630
640
|
recipe: "@page credits"
|
|
631
641
|
emits: div.page.dc-page-credits
|
|
632
642
|
css: [styles/page-templates.css, styles/page-rules.css, styles/dc-native.css]
|
|
633
|
-
tokens: [--dc-intro-gap, --dc-intro-pad-bottom, --dc-section-gap, --dc-section-grow, --dc-section-drop]
|
|
643
|
+
tokens: [--dc-intro-gap, --dc-intro-pad-bottom, --dc-section-gap, --dc-section-grow, --dc-section-drop, --dc-credits-art-height]
|
|
634
644
|
breaks: "page: front-matter (no footer)"
|
|
635
|
-
notes: "The credits page: masthead, lede and colophon stacked flush. The colophon names go in `@columns 2` inside `@section flat`; the page sets the flat section's accent, drop, gap and grow by tokens."
|
|
645
|
+
notes: "The credits page: masthead, lede and colophon stacked flush. The title is a chevron banner by context, with no `{.dc-chevron}`. The colophon names go in `@columns 2` inside `@section flat`; the page sets the flat section's accent, drop, gap and grow by tokens. An image with no class on its own line under the colophon is the plate: a band across the foot of the sheet, --dc-credits-art-height tall, cropped to fit; a class the author writes places it instead."
|
|
636
646
|
|
|
637
647
|
- name: page-contents
|
|
638
648
|
status: live
|
|
@@ -644,7 +654,7 @@ components:
|
|
|
644
654
|
css: [styles/page-templates.css, styles/page-rules.css, styles/dc-native.css]
|
|
645
655
|
tokens: [--dc-toc-rail-y, --dc-toc-rail-x, --dc-toc-shadow, --dc-toc-badge, --dc-intro-gap, --dc-intro-pad-bottom]
|
|
646
656
|
breaks: "page: front-matter (no footer)"
|
|
647
|
-
notes: "The contents page: masthead, lede and the @toc card stacked flush. The page sets the card's rails, shadow and number-chip colour by tokens."
|
|
657
|
+
notes: "The contents page: masthead, lede and the @toc card stacked flush. The title is a chevron banner by context, with no `{.dc-chevron}`. The page sets the card's rails, shadow and number-chip colour by tokens."
|
|
648
658
|
|
|
649
659
|
- name: page-intro
|
|
650
660
|
status: live
|
|
@@ -656,7 +666,7 @@ components:
|
|
|
656
666
|
css: [styles/page-templates.css, styles/page-rules.css]
|
|
657
667
|
tokens: [--dc-intro-gap, --dc-intro-pad-bottom, --dc-chevron-bg, --dc-section-accent, --dc-section-drop]
|
|
658
668
|
breaks: "page: front-matter-intro (no footer, ordinary margins)"
|
|
659
|
-
notes: "The introduction: chevron, lede, then a `@section flat`. The page sets the lede's and the flat section's tokens."
|
|
669
|
+
notes: "The introduction: chevron, lede, then a `@section flat`. The title is a chevron banner by context, with no `{.dc-chevron}`. The page sets the lede's and the flat section's tokens."
|
|
660
670
|
|
|
661
671
|
# ── Chapter words: a register for the sections in the chapter ──────────
|
|
662
672
|
- name: chapter-rules
|
|
@@ -706,14 +716,19 @@ components:
|
|
|
706
716
|
- name: chevron
|
|
707
717
|
status: live
|
|
708
718
|
origin: author
|
|
719
|
+
modifier: dc-chevron
|
|
720
|
+
description: "Set a heading as a chevron banner (an h1 under @page intro, credits or contents already is one)."
|
|
709
721
|
recipe: "# Title {.dc-chevron} (the chapter-opener h1 gets the same treatment structurally)"
|
|
710
722
|
emits: h1.dc-chevron
|
|
711
723
|
css: [styles/components/chrome.css, styles/dc-native.css, styles/page-templates.css]
|
|
712
724
|
tokens: [--dc-chevron-bg, --dc-chevron-color, --dc-chevron-font-size]
|
|
725
|
+
notes: "The plugin writes the class on the h1 straight under @page intro, credits or contents, so a front-matter title needs none. It is the override for a heading anywhere else, and for a page that is not one of the three (a bare @page holding the introduction)."
|
|
713
726
|
|
|
714
727
|
- name: spray
|
|
715
728
|
status: live
|
|
716
729
|
origin: author
|
|
730
|
+
modifier: dc-spray
|
|
731
|
+
description: "Set a heading as a spray-paint banner."
|
|
717
732
|
recipe: "## Title {.dc-spray} (also emitted by @learning-path for its title)"
|
|
718
733
|
emits: ["h2.dc-spray (authored)", "h3.dc-spray (a @learning-path title)"]
|
|
719
734
|
css: [styles/components/chrome.css, styles/components/data.css]
|
|
@@ -723,6 +738,8 @@ components:
|
|
|
723
738
|
- name: spec-tweak
|
|
724
739
|
status: live
|
|
725
740
|
origin: author
|
|
741
|
+
modifier: [dc-spec-tweak, dc-no-top]
|
|
742
|
+
description: "Set a heading as a Spec Tweak title; .dc-no-top drops its top margin."
|
|
726
743
|
recipe: "### Title {.dc-spec-tweak [.dc-no-top]}"
|
|
727
744
|
emits: h3.dc-spec-tweak[.dc-no-top]
|
|
728
745
|
css: styles/components/chrome.css
|
|
@@ -730,6 +747,7 @@ components:
|
|
|
730
747
|
- name: classtag
|
|
731
748
|
status: live
|
|
732
749
|
origin: author
|
|
750
|
+
description: "A pill naming a specialty, with that specialty's colour dot (raw HTML span)."
|
|
733
751
|
recipe: "raw <span class=\"dc-classtag <specialty>\">"
|
|
734
752
|
emits: span.dc-classtag.<specialty>
|
|
735
753
|
css: styles/components/chrome.css
|
|
@@ -738,6 +756,7 @@ components:
|
|
|
738
756
|
- name: tag
|
|
739
757
|
status: live
|
|
740
758
|
origin: author
|
|
759
|
+
description: "A small keyword or cost label (raw HTML span)."
|
|
741
760
|
recipe: "raw <span class=\"dc-tag\">"
|
|
742
761
|
emits: span.dc-tag
|
|
743
762
|
css: styles/components/chrome.css
|
|
@@ -745,6 +764,7 @@ components:
|
|
|
745
764
|
- name: human-callout
|
|
746
765
|
status: live
|
|
747
766
|
origin: author
|
|
767
|
+
description: "A boxed NPC capsule, usually floated inside a .dc-sidebar (raw HTML div)."
|
|
748
768
|
recipe: "raw <div class=\"dc-sidebar\"><div class=\"dc-human-callout\">… (NPC sidebar)"
|
|
749
769
|
emits: div.dc-human-callout
|
|
750
770
|
css: styles/components/images.css
|
|
@@ -753,6 +773,7 @@ components:
|
|
|
753
773
|
- name: at-a-glance-card
|
|
754
774
|
status: live
|
|
755
775
|
origin: author
|
|
776
|
+
description: "A label-and-value card, three to a row inside @columns 3 (raw HTML div)."
|
|
756
777
|
recipe: "@columns 3 / raw <div class=\"dc-at-a-glance-card\"> × 3 / @end-columns"
|
|
757
778
|
emits: div.dc-at-a-glance-card
|
|
758
779
|
css: styles/components/data.css
|
|
@@ -760,6 +781,7 @@ components:
|
|
|
760
781
|
- name: stat-block
|
|
761
782
|
status: live
|
|
762
783
|
origin: author
|
|
784
|
+
description: "A four-cell stat grid with a name and a class line (raw HTML div; a creature's HP and Damage table is a stat strip instead)."
|
|
763
785
|
recipe: "raw <div class=\"dc-stat [dc-flush]\"> with .dc-stat-head, .dc-stat-grid cells and .dc-stat-line"
|
|
764
786
|
emits:
|
|
765
787
|
- div.dc-stat > div.dc-stat-head > span.dc-stat-name + span.dc-stat-class
|
|
@@ -772,26 +794,41 @@ components:
|
|
|
772
794
|
status: live
|
|
773
795
|
origin: author
|
|
774
796
|
modifier: dc-avoid-split
|
|
797
|
+
description: "Keep this section, skill card, faction or creature on one page: it moves to the next page rather than splitting."
|
|
775
798
|
snippet: avoid-split
|
|
776
|
-
recipe: "@section panel .dc-avoid-split | @skill .dc-avoid-split"
|
|
799
|
+
recipe: "@section panel .dc-avoid-split | @skill .dc-avoid-split | from a book's sheet: #id { --dc-section-break-inside: avoid; --dc-section-edge: 0px; }"
|
|
777
800
|
emits: .dc-avoid-split (on the section or skill card it is written on)
|
|
778
801
|
css: [styles/components/section.css, styles/components/cards.css]
|
|
779
|
-
|
|
780
|
-
|
|
802
|
+
tokens: [--dc-section-break-inside, --dc-section-edge, --dc-npc-stat-break-inside, --dc-skill-card-break-inside, --dc-faction-break-inside]
|
|
803
|
+
breaks: "break-inside: avoid. The class is a setter of the keep-whole tokens on the box it is written on, nothing more; a book writes the same declarations from its own sheet. A catalog splits by default, but the class keeps one whole (it sets --dc-catalog-break-inside: avoid)"
|
|
804
|
+
notes: "Replaces .dc-allow-split on sections and on skill cards. Avoid it on a section taller than a column inside @columns: it cannot split, and the facing column goes empty. On a skill card it costs a page of one card: use it for a card that must read as one object. A creature (an @npc-stat with at most one ####) needs none: it stays whole by default."
|
|
781
805
|
|
|
782
806
|
- name: snug
|
|
783
807
|
status: live
|
|
784
808
|
origin: author
|
|
785
809
|
modifier: dc-snug
|
|
810
|
+
description: "Tighten the space under paragraphs and list items in this section or page, for one that overflows by a line or two."
|
|
786
811
|
snippet: snug
|
|
787
|
-
recipe: "@section .dc-snug / @page .dc-snug"
|
|
812
|
+
recipe: "@section .dc-snug / @page .dc-snug | from a book's sheet: #id { --dc-flow-gap: 0.04in; }"
|
|
788
813
|
emits: .dc-snug (on the section or page it is written on)
|
|
789
814
|
css: styles/page-templates.css
|
|
790
|
-
|
|
815
|
+
tokens: [--dc-flow-gap]
|
|
816
|
+
notes: "A setter of --dc-flow-gap, the margin-bottom of a paragraph or list item inside it, to 0.04in. Unset, each component keeps its own spacing; set on a box or anything above it, it is the space under every paragraph and list item in it. Type size and leading are untouched."
|
|
817
|
+
|
|
818
|
+
- name: heading-look
|
|
819
|
+
status: live
|
|
820
|
+
origin: author
|
|
821
|
+
modifier: [dc-h3, dc-h4, dc-h5, dc-h6]
|
|
822
|
+
description: "Give a heading, or a paragraph, the look of a lower level without changing its place in the outline."
|
|
823
|
+
recipe: "## Useful Items {.dc-h3} | {.dc-h4} | {.dc-h5} | {.dc-h6}"
|
|
824
|
+
emits: .dc-h3 | .dc-h4 | .dc-h5 | .dc-h6 (on the heading or paragraph it is written on)
|
|
825
|
+
css: [styles/dc-core.css, styles/components/section.css]
|
|
826
|
+
notes: "A heading's level is its place in the outline and its look follows the level; the class sets the look of that level and the outline stays unbroken (`#` then `##`, never `#` then `###`). An `##` with .dc-h3 that opens a panel takes the subordinate title bar. On a paragraph it sets a line in heading type without adding it to the outline."
|
|
791
827
|
|
|
792
828
|
- name: full-page
|
|
793
829
|
status: live
|
|
794
830
|
origin: author
|
|
831
|
+
description: "A page that is one full-bleed plate, edge to edge (the same page as core's @page full-bleed)."
|
|
795
832
|
recipe: "@page .dc-full-page (core's @page full-bleed gets the same geometry and named page)"
|
|
796
833
|
emits: div.page.dc-full-page
|
|
797
834
|
css: [styles/page-templates.css, styles/page-rules.css, styles/dc-native.css]
|
|
@@ -801,6 +838,8 @@ components:
|
|
|
801
838
|
- name: img-float
|
|
802
839
|
status: live
|
|
803
840
|
origin: author
|
|
841
|
+
modifier: [dc-img-float-left, dc-img-float-right]
|
|
842
|
+
description: "Float an image to one side at 44% of the column, text wrapping beside it (core's .gp-left and .gp-right do the same)."
|
|
804
843
|
recipe: "{.dc-img-float-left|.dc-img-float-right}"
|
|
805
844
|
emits: img.dc-img-float-left|.dc-img-float-right
|
|
806
845
|
css: styles/components/images.css
|
|
@@ -822,8 +861,8 @@ components:
|
|
|
822
861
|
recipe: "@section panel … @end-section (or @section .dc-section-panel)"
|
|
823
862
|
emits: div.section.dc-section-panel
|
|
824
863
|
css: [styles/components/section.css, styles/dc-component-defaults.css]
|
|
825
|
-
tokens: [--dc-section-bg, --dc-section-accent, --dc-section-surface, --dc-section-shadow, --dc-section-clip, --dc-section-rail, --dc-section-gap, --dc-section-pad-top, --dc-section-pad-right, --dc-section-pad-bottom, --dc-section-pad-left]
|
|
826
|
-
breaks: "splits by default; add .dc-avoid-split to keep it whole"
|
|
864
|
+
tokens: [--dc-section-bg, --dc-section-accent, --dc-section-surface, --dc-section-shadow, --dc-section-clip, --dc-section-rail, --dc-section-gap, --dc-section-edge, --dc-section-break-inside, --dc-section-pad-top, --dc-section-pad-right, --dc-section-pad-bottom, --dc-section-pad-left]
|
|
865
|
+
breaks: "splits by default; add .dc-avoid-split to keep it whole (it sets --dc-section-break-inside: avoid and --dc-section-edge: 0px, which a book can set from its own sheet)"
|
|
827
866
|
notes: "The card: cream substrate, accent rail, clipped corner, shadow, and the first ## or ### as a title bar. @npc-stat, @citizen-walkthrough, @flaws, @ideals and @dreams are panels carrying their own class."
|
|
828
867
|
|
|
829
868
|
- name: section-catalog
|
|
@@ -834,8 +873,8 @@ components:
|
|
|
834
873
|
recipe: "@section catalog ## Title … @columns 2 @gear augment … @end-columns @end-section"
|
|
835
874
|
emits: div.section.dc-section-panel.dc-catalog
|
|
836
875
|
css: styles/components/entries.css
|
|
837
|
-
tokens: [--dc-entry-surface, --dc-entry-rail, --dc-entry-rule]
|
|
838
|
-
breaks: "a panel; its entries may split across a column or page (ruled, not boxed, so there is no frame to cut), the name keeps with what follows it"
|
|
876
|
+
tokens: [--dc-entry-surface, --dc-entry-rail, --dc-entry-rule, --dc-catalog-break-inside]
|
|
877
|
+
breaks: "a panel that splits by default (--dc-catalog-break-inside: auto); .dc-avoid-split, or --dc-catalog-break-inside: avoid, keeps one whole; its entries may split across a column or page (ruled, not boxed, so there is no frame to cut), the name keeps with what follows it"
|
|
839
878
|
notes: "A panel for a run of entries (@gear, of any kind). Its entries are ruled instead of boxed (and may split across columns, as the plain text they replace did): no card, no rail, a rule in the entry's own accent over each, so no `---` is needed between entries (a `---` left in draws nothing). Columns are core's: write `@columns 2` under the intro."
|
|
840
879
|
|
|
841
880
|
- name: section-flat
|
|
@@ -902,8 +941,8 @@ components:
|
|
|
902
941
|
recipe: "@faction [megacorp|cabal|cult|enforcer] [label=\"…\"] / #### Name / fields and prose … @end-faction"
|
|
903
942
|
emits: [div.dc-card.dc-faction.dc-faction-megacorp|.dc-faction-cabal|.dc-faction-cult|.dc-faction-enforcer, span.dc-faction-kind]
|
|
904
943
|
css: [styles/components/section.css]
|
|
905
|
-
tokens: [--dc-faction-accent, --dc-faction-badge-fg]
|
|
906
|
-
breaks: "break-inside:
|
|
944
|
+
tokens: [--dc-faction-accent, --dc-faction-badge-fg, --dc-faction-break-inside]
|
|
945
|
+
breaks: "splits between paragraphs by default (--dc-faction-break-inside: auto); .dc-avoid-split keeps one whole"
|
|
907
946
|
notes: "An organization's profile: a card whose rail and kind badge take the kind's colour (megacorp blue, cabal violet, cult blood, enforcer yellow). The kind is the bare word; the badge reads it unless label=\"…\" names its own; with neither there is no badge."
|
|
908
947
|
|
|
909
948
|
- name: stat-strip
|
|
@@ -919,6 +958,8 @@ components:
|
|
|
919
958
|
- name: sidebar-float
|
|
920
959
|
status: live
|
|
921
960
|
origin: author
|
|
961
|
+
modifier: dc-sidebar
|
|
962
|
+
description: "Float a callout to the right at about a third of the width, body text wrapping on its left."
|
|
922
963
|
recipe: "@callout note .dc-sidebar label=\"…\" (also raw <div class=\"dc-sidebar\"> around a human-callout)"
|
|
923
964
|
emits: .dc-sidebar (on the callout or div it is written on)
|
|
924
965
|
css: [styles/components/images.css]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gp-dimm-city",
|
|
3
|
-
"version": "1.6.2",
|
|
3
|
+
"version": "1.6.3-alpha.2",
|
|
4
4
|
"description": "Dimm City design system for Gutterpress: the markdown-it macros (@skill, @specialty, @learning-path, @callout, …), print stylesheets, design tokens, fonts and page templates the Dimm City TTRPG books are set in.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "plugin.js",
|
package/plugin.js
CHANGED
|
@@ -65,6 +65,10 @@
|
|
|
65
65
|
* `ROLL THE DIE!` (also ROLL A DIE!, ROLLS A DIE!, ROLLING THE DIE!)
|
|
66
66
|
* → span.dc-roll-the-die
|
|
67
67
|
* an image-only paragraph gets p.dc-img-wrapper
|
|
68
|
+
* the h1 under `@page intro | credits | contents` gets .dc-chevron
|
|
69
|
+
* a table of the five standard bands is the outcome ladder (it keeps the
|
|
70
|
+
* table's `{#id .class}`); `@procedure` keeps the
|
|
71
|
+
* attributes written on its line, on its list
|
|
68
72
|
*
|
|
69
73
|
* GFM ALERT SYNTAX:
|
|
70
74
|
* `> [!NOTE]` / `[!WARNING]` / `[!DM]` / `[!VIBE]` / `[!ORIGIN]` / `[!VISIT]`
|
|
@@ -419,9 +423,16 @@ function outcomeRowsHtml(rows, md, head = []) {
|
|
|
419
423
|
return html;
|
|
420
424
|
}
|
|
421
425
|
|
|
422
|
-
// A table of the five standard bands: tier and name come from the band.
|
|
423
|
-
|
|
424
|
-
|
|
426
|
+
// A table of the five standard bands: tier and name come from the band. The
|
|
427
|
+
// ladder replaces the table, so what the author wrote on the table (`{#id
|
|
428
|
+
// .class}`) and what the renderer threaded on it move to the ladder.
|
|
429
|
+
function buildLadderBlock({ head, rows }, md, table) {
|
|
430
|
+
const attrs = [['class', 'dc-outcomes']];
|
|
431
|
+
for (const [name, value] of table.attrs || []) {
|
|
432
|
+
if (name === 'class') attrs[0][1] += ' ' + value;
|
|
433
|
+
else attrs.push([name, value]);
|
|
434
|
+
}
|
|
435
|
+
return '<div' + md.renderer.renderAttrs({ attrs }) + '>\n' + outcomeRowsHtml(rows, md, head) + '</div>\n';
|
|
425
436
|
}
|
|
426
437
|
|
|
427
438
|
// Parse ability from list item - handles rendered HTML: "<strong>0 AP</strong> <em>Name:</em> Description"
|
|
@@ -575,8 +586,15 @@ function collectOrderedListItems(tokens, startIndex, md) {
|
|
|
575
586
|
return { items: items, endIndex: i };
|
|
576
587
|
}
|
|
577
588
|
|
|
578
|
-
|
|
579
|
-
|
|
589
|
+
// `attrs` are what the author wrote on the `@procedure` line: the wrapper
|
|
590
|
+
// renders nothing, so the list takes them.
|
|
591
|
+
function buildProcedureList(items, attrs, md) {
|
|
592
|
+
const list = [['class', 'dc-steps']];
|
|
593
|
+
for (const [name, value] of attrs) {
|
|
594
|
+
if (name === 'class') list[0][1] += ' ' + value;
|
|
595
|
+
else list.push([name, value]);
|
|
596
|
+
}
|
|
597
|
+
let html = '<ol' + md.renderer.renderAttrs({ attrs: list }) + '>\n';
|
|
580
598
|
items.forEach((itemHtml, idx) => {
|
|
581
599
|
const stepNo = String(idx + 1).padStart(2, '0');
|
|
582
600
|
html += ' <li><span class="dc-step-no">' + esc(stepNo) + '</span><span>' + itemHtml.trimEnd() + '</span></li>\n';
|
|
@@ -708,6 +726,31 @@ function dcImageParagraphs(state) {
|
|
|
708
726
|
}
|
|
709
727
|
}
|
|
710
728
|
|
|
729
|
+
// The title of a front-matter page is a chevron banner because of where it
|
|
730
|
+
// sits: the `h1` straight under `@page intro | credits | contents` is a
|
|
731
|
+
// `.dc-chevron`, so the author writes no `{.dc-chevron}`. The class stays
|
|
732
|
+
// available on any other heading.
|
|
733
|
+
const FRONT_MATTER_PAGES = ['dc-page-intro', 'dc-page-credits', 'dc-page-contents'];
|
|
734
|
+
|
|
735
|
+
function dcFrontMatterTitles(state) {
|
|
736
|
+
let front = false;
|
|
737
|
+
let depth = 0; // layout containers open inside the page: a heading in one is not the page's title
|
|
738
|
+
for (const tok of state.tokens) {
|
|
739
|
+
if (tok.type === 'layout_page_open') {
|
|
740
|
+
front = (tok.attrGet('class') || '').split(/\s+/).some((c) => FRONT_MATTER_PAGES.includes(c));
|
|
741
|
+
depth = 0;
|
|
742
|
+
} else if (tok.type === 'layout_page_close') {
|
|
743
|
+
front = false;
|
|
744
|
+
} else if (/^layout_.+_open$/.test(tok.type)) {
|
|
745
|
+
depth++;
|
|
746
|
+
} else if (/^layout_.+_close$/.test(tok.type)) {
|
|
747
|
+
depth--;
|
|
748
|
+
} else if (front && !depth && tok.type === 'heading_open' && tok.tag === 'h1') {
|
|
749
|
+
addTokenClass(tok, 'dc-chevron');
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
711
754
|
/**
|
|
712
755
|
* `data-position="odd|even"` on every @specialty-card, counted across the
|
|
713
756
|
* document in order so the card grid alternates its tilt/offset. The wrapper
|
|
@@ -991,7 +1034,7 @@ function dcSkillCards(state) {
|
|
|
991
1034
|
const tableTokens = collectTableTokens(content, i);
|
|
992
1035
|
const ladder = tok.meta?.rollTable ? null : ladderRows(readTable(tableTokens));
|
|
993
1036
|
if (ladder) {
|
|
994
|
-
emit(buildLadderBlock(ladder, md));
|
|
1037
|
+
emit(buildLadderBlock(ladder, md, tok));
|
|
995
1038
|
i = skipToTableClose(content, i);
|
|
996
1039
|
continue;
|
|
997
1040
|
}
|
|
@@ -1096,7 +1139,7 @@ function dcLadderTables(state) {
|
|
|
1096
1139
|
const tableTokens = collectTableTokens(tokens, i);
|
|
1097
1140
|
const ladder = ladderRows(readTable(tableTokens));
|
|
1098
1141
|
if (!ladder) continue;
|
|
1099
|
-
tokens.splice(i, tableTokens.length, makeToken('html_block', buildLadderBlock(ladder, state.md)));
|
|
1142
|
+
tokens.splice(i, tableTokens.length, makeToken('html_block', buildLadderBlock(ladder, state.md, tokens[i])));
|
|
1100
1143
|
}
|
|
1101
1144
|
}
|
|
1102
1145
|
|
|
@@ -1157,13 +1200,17 @@ function dcProcedures(state) {
|
|
|
1157
1200
|
const [open, close] = [run[0], run[run.length - 1]];
|
|
1158
1201
|
open.hidden = close.hidden = true;
|
|
1159
1202
|
const out = [];
|
|
1203
|
+
let attrs = open.attrs || []; // the first list takes them: an id stays unique
|
|
1160
1204
|
for (let i = 1; i < run.length - 1; i++) {
|
|
1161
1205
|
if (run[i].type !== 'ordered_list_open') {
|
|
1162
1206
|
out.push(run[i]);
|
|
1163
1207
|
continue;
|
|
1164
1208
|
}
|
|
1165
1209
|
const { items, endIndex } = collectOrderedListItems(run, i, state.md);
|
|
1166
|
-
if (items.length > 0)
|
|
1210
|
+
if (items.length > 0) {
|
|
1211
|
+
out.push(makeToken('html_block', buildProcedureList(items, attrs, state.md)));
|
|
1212
|
+
attrs = [];
|
|
1213
|
+
}
|
|
1167
1214
|
i = endIndex;
|
|
1168
1215
|
}
|
|
1169
1216
|
return [open, ...out, close];
|
|
@@ -1445,6 +1492,7 @@ export default function dimmCityPlugin(md, options = {}) {
|
|
|
1445
1492
|
// (p.dc-img-wrapper { padding:0; margin:0 }) lives in components/data.css.
|
|
1446
1493
|
// Per-page rules can further refine position via .page.my-class p.dc-img-wrapper.
|
|
1447
1494
|
md.core.ruler.push('dc_image_paragraphs', dcImageParagraphs);
|
|
1495
|
+
md.core.ruler.push('dc_front_matter_titles', dcFrontMatterTitles);
|
|
1448
1496
|
|
|
1449
1497
|
// Declared components. Callouts, cards, outcomes and procedures go first so
|
|
1450
1498
|
// one inside a skill is already rewritten when the skill's rule looks at it.
|
package/snippets/credits-page.md
CHANGED
package/snippets/intro-page.md
CHANGED
package/snippets/toc-page.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
--dc-card-tab-bg → tab background (default --ink-dark)
|
|
9
9
|
--dc-card-tab-title-color → tab title text color (default --paper-cream)
|
|
10
10
|
--dc-card-body-mark → decorative ::before mark color (default --crimson)
|
|
11
|
+
--dc-skill-card-break-inside → `avoid` keeps a card whole (default auto: it splits)
|
|
11
12
|
Specialty themes override these via .dc-specialty.<name> .dc-skill-card { }.
|
|
12
13
|
Adding a new specialty: copy a sibling block (.dc-specialty.augmerc .dc-skill-card)
|
|
13
14
|
and replace token values with the new specialty's --<name>-* aliases. */
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
overflow-x: clip;
|
|
36
37
|
/* A card splits across pages by default (its chains are below); the
|
|
37
38
|
`.dc-avoid-split` modifier keeps one whole. */
|
|
39
|
+
break-inside: var(--dc-skill-card-break-inside);
|
|
38
40
|
/* --dc-card-gap is the VISIBLE gap; the +6px clears chrome bleed on top of
|
|
39
41
|
it. Margin is layout space, but the shadow and outline pseudos paint
|
|
40
42
|
outside the border-box without affecting it: this card's hard poster
|
|
@@ -284,15 +286,15 @@
|
|
|
284
286
|
/* A card splits across pages by default: one is 30-50% of a page, so keeping
|
|
285
287
|
it whole left most specialty pages holding a single card and a third of the
|
|
286
288
|
sheet empty. `.dc-avoid-split` (a modifier on the `@skill` line, as on a
|
|
287
|
-
section) keeps one whole
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
289
|
+
section) keeps one whole, through `--dc-skill-card-break-inside`. Where it
|
|
290
|
+
may split, it splits at sensible places: the chains below. They stay on a
|
|
291
|
+
card that is kept whole, where they change nothing until it is taller than
|
|
292
|
+
a page. */
|
|
291
293
|
|
|
292
294
|
/* A card never opens with just its tab and a line or two at a page foot: its
|
|
293
295
|
first two blocks (the flavor line and a possibly one-line ability) stay with
|
|
294
296
|
the first two lines of what follows, or the card moves to the next page. */
|
|
295
|
-
.dc-skill-card
|
|
297
|
+
.dc-skill-card .dc-card-inner > :nth-child(-n+2) {
|
|
296
298
|
break-after: avoid;
|
|
297
299
|
}
|
|
298
300
|
|
|
@@ -316,14 +318,14 @@
|
|
|
316
318
|
`strong:only-child` also takes a paragraph whose only markup is one bold
|
|
317
319
|
run. A last child is left out: its break-after would pass up to the card
|
|
318
320
|
and glue the next path banner to it. */
|
|
319
|
-
.dc-skill-card
|
|
320
|
-
.dc-skill-card
|
|
321
|
+
.dc-skill-card .dc-card-inner > :is(.dc-ability, p:has(> strong:only-child)):not(:last-child),
|
|
322
|
+
.dc-skill-card .dc-card-inner > p:has(+ :is(ul, ol, table)) {
|
|
321
323
|
break-after: avoid;
|
|
322
324
|
}
|
|
323
325
|
|
|
324
326
|
/* The closing line of a card (a one-line sign-off, a trailing note) stays
|
|
325
327
|
with the block above it, so a continuation never opens with it alone. */
|
|
326
|
-
.dc-skill-card
|
|
328
|
+
.dc-skill-card .dc-card-inner > :last-child:not(:first-child) {
|
|
327
329
|
break-before: avoid;
|
|
328
330
|
}
|
|
329
331
|
|
|
@@ -775,11 +775,6 @@ table.dc-stat-strip {
|
|
|
775
775
|
break-before: avoid;
|
|
776
776
|
}
|
|
777
777
|
|
|
778
|
-
.dc-skill-card:only-child {
|
|
779
|
-
width: 100%;
|
|
780
|
-
max-width: 7.25in;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
778
|
/* .dc-img-wrapper: the plugin replaces p:has(img) with an explicit class */
|
|
784
779
|
p.dc-img-wrapper {
|
|
785
780
|
padding: 0;
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
--dc-entry-rail — width of the left rail (a catalog sets 0)
|
|
26
26
|
--dc-entry-rule — width of the top rule (a catalog sets it)
|
|
27
27
|
--dc-entry-kind — a quoted word printed small above the name, or `none`
|
|
28
|
+
--dc-entry-art-width — width of the item's picture, floated right (50%)
|
|
28
29
|
|
|
29
30
|
The labelled fields inside an entry (`@field`, `**SPECS:**`) are the last
|
|
30
31
|
section of this file; they work outside an entry as well.
|
|
@@ -75,6 +76,17 @@
|
|
|
75
76
|
margin: 0 0 var(--space-xs);
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
/* The item's picture: an image written in an entry with no class floats to the
|
|
80
|
+
right, `--dc-entry-art-width` of the card (half), and the text wraps on its
|
|
81
|
+
left. An image the author places with a class (core's `.gp-left`, `.gp-large`,
|
|
82
|
+
…) is left where they put it: this rule only reads an image with none. */
|
|
83
|
+
.dc-entry img:not([class]) {
|
|
84
|
+
float: right;
|
|
85
|
+
width: var(--dc-entry-art-width);
|
|
86
|
+
max-width: 100%;
|
|
87
|
+
margin: 0 0 1em 1em;
|
|
88
|
+
}
|
|
89
|
+
|
|
78
90
|
/* A `---` kept at the end of an entry would draw a rule inside the card. */
|
|
79
91
|
.dc-entry > hr:last-child {
|
|
80
92
|
display: none;
|
|
@@ -163,6 +175,14 @@
|
|
|
163
175
|
display: none;
|
|
164
176
|
}
|
|
165
177
|
|
|
178
|
+
/* A catalog is a run of entries that may run past a page, and kept whole it
|
|
179
|
+
leaves the foot of the page before it blank, so by default it splits.
|
|
180
|
+
`.dc-avoid-split`, or `--dc-catalog-break-inside: avoid` from a book's sheet,
|
|
181
|
+
keeps one whole. */
|
|
182
|
+
.dc-section-panel.dc-catalog {
|
|
183
|
+
--dc-section-break-inside: var(--dc-catalog-break-inside);
|
|
184
|
+
}
|
|
185
|
+
|
|
166
186
|
/* ═════════════════════════════════════════════════════════════════════════
|
|
167
187
|
FIELD — `@field <variant>`, and `**Label:** …` inside a card
|
|
168
188
|
═════════════════════════════════════════════════════════════════════════
|
|
@@ -12,9 +12,14 @@
|
|
|
12
12
|
npc, walkthrough, flaws, ideals, dreams = a panel plus the component class
|
|
13
13
|
fiction, cards = the component class alone
|
|
14
14
|
|
|
15
|
-
Sections split across pages by default. `.dc-avoid-split` keeps one whole
|
|
15
|
+
Sections split across pages by default. `.dc-avoid-split` keeps one whole,
|
|
16
|
+
by setting `--dc-section-break-inside` (below).
|
|
16
17
|
|
|
17
18
|
Public tokens (defaults declared in dc-component-defaults.css :root):
|
|
19
|
+
--dc-section-break-inside — `avoid` keeps a section whole, `auto` lets it
|
|
20
|
+
split. An `@npc-stat` with at most one `####` and a catalog
|
|
21
|
+
have their own (`--dc-npc-stat-break-inside`,
|
|
22
|
+
`--dc-catalog-break-inside`).
|
|
18
23
|
--dc-section-bg — panel / flat background surface
|
|
19
24
|
--dc-section-accent — rail and title-bar colour; the one accent knob
|
|
20
25
|
--dc-section-surface / --dc-section-shadow — `content` of the panel's
|
|
@@ -37,7 +42,11 @@
|
|
|
37
42
|
box-shadow, never as layout), and margin-bottom
|
|
38
43
|
grows by it. `.dc-avoid-split`
|
|
39
44
|
and every box that paints its own surface keep it
|
|
40
|
-
at 0px.
|
|
45
|
+
at 0px. A book that keeps one section whole from
|
|
46
|
+
its own sheet sets both
|
|
47
|
+
(`--dc-section-break-inside: avoid;
|
|
48
|
+
--dc-section-edge: 0px`): the first keeps the box
|
|
49
|
+
whole, the second keeps its padding inside it.
|
|
41
50
|
A variant or template owns its chrome by setting these on its own rule. */
|
|
42
51
|
|
|
43
52
|
/* Float containment. flow-root makes the box a block formatting context so
|
|
@@ -79,11 +88,29 @@
|
|
|
79
88
|
--dc-section-edge: var(--dc-section-pad-bottom);
|
|
80
89
|
}
|
|
81
90
|
|
|
82
|
-
/* Keep
|
|
83
|
-
|
|
84
|
-
.section.dc-avoid-split
|
|
85
|
-
|
|
91
|
+
/* Keep a section whole, or let it split: the token is the one setting.
|
|
92
|
+
`:where()` keeps this at zero specificity, so a rule on one kind of section
|
|
93
|
+
(a creature, below) outranks it. The bare `.section.dc-avoid-split` is the
|
|
94
|
+
one section with no variant class that still honours the modifier. */
|
|
95
|
+
:where(.dc-section-panel, .dc-section-flat, .dc-fiction-excerpt, .dc-card-grid, .section.dc-avoid-split) {
|
|
96
|
+
break-inside: var(--dc-section-break-inside);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* `.dc-avoid-split` keeps one box whole: it moves to the next page entirely if
|
|
100
|
+
it does not fit, and the dead zone at the foot of the previous page is the
|
|
101
|
+
price. It is a setter of the keep-whole tokens on what it is written on (a
|
|
102
|
+
section, a skill card, a faction, an `@npc-stat`), nothing more, so a book
|
|
103
|
+
can write the same declarations for one box from its own sheet. A section
|
|
104
|
+
that is whole keeps its padding inside the box (`--dc-section-edge`). A
|
|
105
|
+
catalog splits by default, but the class keeps one whole all the same: an
|
|
106
|
+
author's override wins over a default. */
|
|
107
|
+
.dc-avoid-split {
|
|
108
|
+
--dc-section-break-inside: avoid;
|
|
86
109
|
--dc-section-edge: 0px;
|
|
110
|
+
--dc-catalog-break-inside: avoid;
|
|
111
|
+
--dc-npc-stat-break-inside: avoid;
|
|
112
|
+
--dc-skill-card-break-inside: avoid;
|
|
113
|
+
--dc-faction-break-inside: avoid;
|
|
87
114
|
}
|
|
88
115
|
|
|
89
116
|
/* clip-path + left accent band on ::before.
|
|
@@ -561,7 +588,7 @@ h3 + .dc-section-panel {
|
|
|
561
588
|
first, floated to the right so the name and the text run beside it.
|
|
562
589
|
Splits across pages by default (see below).
|
|
563
590
|
Token contract: --dc-faction-accent (rail and badge fill),
|
|
564
|
-
--dc-faction-badge-fg (badge text). */
|
|
591
|
+
--dc-faction-badge-fg (badge text), --dc-faction-break-inside. */
|
|
565
592
|
.dc-card.dc-faction {
|
|
566
593
|
border-left-width: 5px;
|
|
567
594
|
border-left-color: var(--dc-faction-accent);
|
|
@@ -570,10 +597,7 @@ h3 + .dc-section-panel {
|
|
|
570
597
|
left half-empty pages through a chapter of factions. It splits between
|
|
571
598
|
paragraphs like an entry; the name keeps with its first lines (below), and
|
|
572
599
|
`.dc-avoid-split` on the marker keeps one whole. */
|
|
573
|
-
break-inside:
|
|
574
|
-
}
|
|
575
|
-
.dc-card.dc-faction.dc-avoid-split {
|
|
576
|
-
break-inside: avoid;
|
|
600
|
+
break-inside: var(--dc-faction-break-inside);
|
|
577
601
|
}
|
|
578
602
|
.dc-card.dc-faction > :is(h3, h4):first-of-type {
|
|
579
603
|
font-size: var(--fs-h4);
|
|
@@ -663,6 +687,7 @@ h3 + .dc-section-panel {
|
|
|
663
687
|
--dc-npc-stat-label-color → h5 subsection-label color (default --hud-blue-dark)
|
|
664
688
|
--dc-npc-stat-primary → primary stat-line color, e.g. "2 HP — 1 Damage" (default --hud-blue-dark)
|
|
665
689
|
--dc-npc-stat-secondary → secondary stat-line color (default --ink-smoke)
|
|
690
|
+
--dc-npc-stat-break-inside → `avoid` (default) keeps a block with no `####`, or one, whole
|
|
666
691
|
Override per chapter / per faction in the book's own sheet selector chains. */
|
|
667
692
|
/* Page breaks. A section splits across pages by default. A block with `####`
|
|
668
693
|
entries is a RUN of creatures: it may break between entries and never inside
|
|
@@ -672,8 +697,9 @@ h3 + .dc-section-panel {
|
|
|
672
697
|
an entry is itself unbreakable so a paragraph cannot split between columns.
|
|
673
698
|
Chromium keeps a chain together when it fits a page and lets it break only
|
|
674
699
|
when it cannot. The title bar (h3) and its intro chain on to the first entry,
|
|
675
|
-
so the bar is never alone at a page foot. A block with no `h4
|
|
676
|
-
creature (the bar names it)
|
|
700
|
+
so the bar is never alone at a page foot. A block with no `h4`, or one, is
|
|
701
|
+
ONE creature (the bar names it), read at one glance, so it stays whole:
|
|
702
|
+
`--dc-npc-stat-break-inside: auto` lets one split.
|
|
677
703
|
|
|
678
704
|
The entries are either direct children of the section (one column) or the
|
|
679
705
|
children of the `@columns` run inside it (`.gp-columns`); the rules below take
|
|
@@ -693,6 +719,14 @@ h3 + .dc-section-panel {
|
|
|
693
719
|
break-inside: avoid;
|
|
694
720
|
}
|
|
695
721
|
|
|
722
|
+
/* One creature, one glance: a block with no `####`, or with one (a species and
|
|
723
|
+
its one variant), stays whole, with its padding inside the box as
|
|
724
|
+
`.dc-avoid-split` leaves it. `h4 ~ h4` is a second entry beside the first. */
|
|
725
|
+
.dc-section-panel.dc-npc-stat:not(:has(h4 ~ h4)) {
|
|
726
|
+
break-inside: var(--dc-npc-stat-break-inside);
|
|
727
|
+
--dc-section-edge: 0px;
|
|
728
|
+
}
|
|
729
|
+
|
|
696
730
|
/* The `@columns` run of an entries block is glued to the bar and intro above it,
|
|
697
731
|
as a direct entry list is (the h3's own `break-after: avoid` plus the chain
|
|
698
732
|
above). Without this, Chromium can end a page with the bar and an EMPTY first
|
|
@@ -45,6 +45,21 @@
|
|
|
45
45
|
--dc-section-gap: 12pt;
|
|
46
46
|
--dc-section-grow: 0;
|
|
47
47
|
|
|
48
|
+
/* Keep whole, per component: `avoid` moves the box to the next page rather
|
|
49
|
+
than splitting it, `auto` lets it split. `.dc-avoid-split` sets all of
|
|
50
|
+
these to `avoid` on the box it is written on, and a book sets one the same
|
|
51
|
+
way from its own sheet (`#core-loop { --dc-section-break-inside: avoid; }`).
|
|
52
|
+
A custom property inherits, so one set on a container reaches what is
|
|
53
|
+
inside it. A section splits by default, and so does a catalog (it reads its
|
|
54
|
+
own token, so a container's `--dc-section-break-inside` does not keep a
|
|
55
|
+
catalog whole), and an `@npc-stat` with at most
|
|
56
|
+
one `####` is one creature and stays whole. */
|
|
57
|
+
--dc-section-break-inside: auto;
|
|
58
|
+
--dc-catalog-break-inside: auto;
|
|
59
|
+
--dc-npc-stat-break-inside: avoid;
|
|
60
|
+
--dc-skill-card-break-inside: auto;
|
|
61
|
+
--dc-faction-break-inside: auto;
|
|
62
|
+
|
|
48
63
|
/* ─── Component Public Token Defaults ────────────────────────────────────
|
|
49
64
|
The override surface for per-chapter and per-project theming. They live
|
|
50
65
|
on :root so the book's own sheet can override them at chapter-id scope
|
|
@@ -151,6 +166,10 @@
|
|
|
151
166
|
--dc-entry-rail: 3px; /* a catalog sets 0 */
|
|
152
167
|
--dc-entry-rule: 0px; /* a catalog sets it */
|
|
153
168
|
--dc-entry-kind: none; /* a quoted word over the name */
|
|
169
|
+
--dc-entry-art-width: 50%; /* the item's picture, floated right; a classed image is the author's */
|
|
170
|
+
|
|
171
|
+
/* credits page: the plate under the colophon (an image with no class) */
|
|
172
|
+
--dc-credits-art-height: 2.75in;
|
|
154
173
|
|
|
155
174
|
/* .dc-field public API (@field, and the **Label:** shortcut); each variant sets these on its own class */
|
|
156
175
|
--dc-field-accent: var(--ink-dark); /* rail and label chip */
|
package/styles/dc-native.css
CHANGED
|
@@ -229,11 +229,13 @@ figure {
|
|
|
229
229
|
initial value and what a column run gets; core has no sequential-fill
|
|
230
230
|
opt-in. */
|
|
231
231
|
|
|
232
|
-
/* ── 6. WALL ART placement is the
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
232
|
+
/* ── 6. WALL ART placement is the author's: core's gp-* classes, or the defaults ──
|
|
233
|
+
An image the author gives a class (core's `.gp-*`) is placed by that class,
|
|
234
|
+
and the plugin's defaults for art (an entry's picture, the credits plate)
|
|
235
|
+
read only an image with no class. A book's own sheet is unlayered, so a
|
|
236
|
+
position/float/margin declaration on a book class that the markdown also
|
|
237
|
+
pins beats `.gp-pin` at any specificity and silently DE-PINS whatever the
|
|
238
|
+
author asked for. */
|
|
237
239
|
|
|
238
240
|
/* ── 7. NO EMPTY FIRST FRAGMENTS on boxed callouts ─────────────────────────
|
|
239
241
|
Core's `break-after: avoid` on headings keeps a heading with the box that
|
|
@@ -115,12 +115,12 @@
|
|
|
115
115
|
visual contract for the two-page TOC + Credits frontmatter, written as:
|
|
116
116
|
|
|
117
117
|
@page contents
|
|
118
|
-
# Contents
|
|
118
|
+
# Contents
|
|
119
119
|
@lede ... @end-lede
|
|
120
120
|
@toc ... @end-toc
|
|
121
121
|
|
|
122
122
|
@page credits
|
|
123
|
-
# Credits
|
|
123
|
+
# Credits
|
|
124
124
|
@lede ... @end-lede
|
|
125
125
|
@section flat
|
|
126
126
|
@columns 2
|
|
@@ -331,6 +331,19 @@
|
|
|
331
331
|
line-height: 1.6;
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
/* The publisher's plate: a picture on its own line under the colophon, with no
|
|
335
|
+
class, is a band across the foot of the sheet. It is the page's full width
|
|
336
|
+
(the masthead's side pull, above), `--dc-credits-art-height` tall, and
|
|
337
|
+
cropped to fit. An image the author places with a class is left alone. */
|
|
338
|
+
.page.dc-page-credits > p > img:not([class]) {
|
|
339
|
+
display: block;
|
|
340
|
+
width: calc(100% + 1.25in);
|
|
341
|
+
max-width: none;
|
|
342
|
+
height: var(--dc-credits-art-height);
|
|
343
|
+
margin: 0 -0.625in;
|
|
344
|
+
object-fit: cover;
|
|
345
|
+
}
|
|
346
|
+
|
|
334
347
|
/* Chapter-start page: the h1 drops core's rule and gets headroom below the
|
|
335
348
|
page top. The title is never fragmented across sheets and stays with the
|
|
336
349
|
first block after it (a title wraps to several lines in the display face,
|
|
@@ -392,14 +405,21 @@
|
|
|
392
405
|
margin-top: 0;
|
|
393
406
|
}
|
|
394
407
|
|
|
395
|
-
/* ──
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
408
|
+
/* ── FLOW GAP — `--dc-flow-gap`, and `.dc-snug`, which sets it ───────────────
|
|
409
|
+
The space under a paragraph or list item. Unset, each keeps the spacing its
|
|
410
|
+
own component gives it; set (on a box, or on anything above it, from a
|
|
411
|
+
sheet or by `.dc-snug`), it is the space under every one of them in that
|
|
412
|
+
box. `.dc-snug` halves it, so a section or page
|
|
413
|
+
that overflows by a line or two fits; type size and leading are untouched.
|
|
414
|
+
Lives in dc.templates so it outranks the dc.components and dc.base
|
|
415
|
+
paragraph/list margins, and `revert-layer` hands the margin back to them
|
|
416
|
+
while the token is unset. The contents-page rows and the credits colophon,
|
|
417
|
+
which fix their own spacing here, outrank it. */
|
|
418
|
+
:is(p, li) {
|
|
419
|
+
margin-bottom: var(--dc-flow-gap, revert-layer);
|
|
420
|
+
}
|
|
421
|
+
.dc-snug {
|
|
422
|
+
--dc-flow-gap: 0.04in;
|
|
403
423
|
}
|
|
404
424
|
|
|
405
425
|
/* ── PAGE TEMPLATE: INTRO (chapter intro / narrative entry) ─────────────────
|