gp-dimm-city 1.0.0 → 1.1.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 +210 -1
- package/README.md +68 -38
- package/components.yaml +12 -3
- package/package.json +7 -3
- package/plugin.js +1 -1
- package/styles/components/callouts.css +4 -4
- package/styles/components/cards.css +14 -2
- package/styles/components/chrome.css +24 -1
- package/styles/components/data.css +4 -0
- package/styles/components/images.css +6 -4
- package/styles/components/section.css +27 -17
- package/styles/dc-component-defaults.css +4 -3
- package/styles/dc-fonts.css +19 -16
- package/styles/dc-native.css +68 -42
- package/styles/dc-palette.css +14 -1
- package/styles/page-rules.css +49 -4
- package/styles/page-templates.css +43 -18
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,216 @@ cut a version that has no `## [X.Y.Z]` heading below.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
## [1.
|
|
10
|
+
## [1.1.0] - 2026-10-07
|
|
11
|
+
|
|
12
|
+
**Layout note for books upgrading from 1.0.x:** the page margins now follow
|
|
13
|
+
DriveThruRPG's print specification (text at least 0.5in inside the trim),
|
|
14
|
+
which takes 0.25in off every page and reflows the whole book. Build and
|
|
15
|
+
review your book after upgrading; the Field Guide needed a short layout
|
|
16
|
+
pass (see `dc-op-manual`, branch `design/plugin-updates`). DriveThruRPG
|
|
17
|
+
books should also end with `@page .dc-printer-page` and set
|
|
18
|
+
`print: signature: 4` in `manifest.yaml`.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **`@page .dc-printer-page`**, a completely blank last page (no wall, no
|
|
23
|
+
footer). DriveThruRPG reserves a book's final page for printer
|
|
24
|
+
information: the interior must be one page short of its signature (4 for
|
|
25
|
+
US Letter) or end on a blank page. End the last chapter with this marker
|
|
26
|
+
and set `print: signature: 4` in the manifest — gutterpress pads with
|
|
27
|
+
blank pages to the next multiple of 4 — and the book always ends blank.
|
|
28
|
+
Verified in the Field Guide (228 content pages + 4 blank = 232).
|
|
29
|
+
- **Variant Gallery** (design guide chapter 11): every element with more than
|
|
30
|
+
one variant, its variants on one stage — all ten skill trees (each
|
|
31
|
+
specialty's first learning path with one skill card, Field Guide content
|
|
32
|
+
excerpted), the skill-card switches (tier override, both highlight forms,
|
|
33
|
+
two columns, outcome table), every AP chip, the ten specialty intros and
|
|
34
|
+
cards, class tags, alerts, blocks, choice cards, and the flush, heading,
|
|
35
|
+
section, sidebar and image-float variants.
|
|
36
|
+
- **The design guide lives here.** `design-guide/` is the Dimm City Design
|
|
37
|
+
Guide book, moved from `dimm-city/dc-op-manual`. Its manifest loads the
|
|
38
|
+
package from this checkout (`extensions: - ../`), so it documents and
|
|
39
|
+
renders the working copy: `npm run dev` previews it, `npm run build`
|
|
40
|
+
renders the PDF, and the test suite uses it as the fixture
|
|
41
|
+
(`test/design-guide.test.js`: every chapter renders clean, every macro and
|
|
42
|
+
alert type is demonstrated, and each chapter's HTML is snapshotted under
|
|
43
|
+
`test/__snapshots__/`). CI builds the PDF with the PR's plugin and CSS and
|
|
44
|
+
uploads it; the release workflow attaches it to the GitHub release; a
|
|
45
|
+
*Publish design guide* workflow deploys the HTML build to GitHub Pages.
|
|
46
|
+
- **`@glossary` is demonstrated** in the component gallery, which used raw
|
|
47
|
+
HTML for the term-list specimen before.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- **Page margins follow DriveThruRPG's print specification.** Its
|
|
52
|
+
[Quick Specifications for Print Books](https://help.drivethrupartners.com/hc/en-us/articles/12780800178583-Quick-Specifications-for-Print-Books)
|
|
53
|
+
require all text at least 0.5in inside the trim. The bleed (0.125in on
|
|
54
|
+
the three outside edges, none at the spine) and the outside and binding
|
|
55
|
+
margins already complied; the top did not (0.375in from the trim) and
|
|
56
|
+
neither did the footer chips (0.43in). Top margin 0.5in → 0.625in on the
|
|
57
|
+
sheet (0.5in from the trim); bottom 0.75in → 0.875in, as the new
|
|
58
|
+
`--bottom-margin` token, so the chips print 0.55in from the trim. The
|
|
59
|
+
"Citizen File" running head, which printed 0.1in from the trim, sits at
|
|
60
|
+
the foot of a 0.875in top margin. Footer chips re-homed by a `.gp-flush`
|
|
61
|
+
pin are top-aligned like native ones (gutterpress centres them, which put
|
|
62
|
+
them 0.24in from the trim). A card title too long for its card breaks
|
|
63
|
+
rather than running into the margin. **This reflows every book:** the
|
|
64
|
+
Field Guide goes from 221 to 238 pages and now has no text inside 0.5in
|
|
65
|
+
of the trim (it had 1,273 words on 204 pages); the design guide goes from
|
|
66
|
+
126 to 131.
|
|
67
|
+
- **Design guide: explainer pages print plain, specimens sit on the wall.**
|
|
68
|
+
Part 1 pages (and the Part 2 overview) are `@page .dg-doc`, a named page
|
|
69
|
+
with a white background and neutral headings, tables and contents, so guide
|
|
70
|
+
text can't be mistaken for a component. Each rendered result is wrapped in
|
|
71
|
+
a framed `.dg-stage` that carries the brick wall; whole-page specimens and
|
|
72
|
+
the Part 2 example pages keep the full brick page. Chapter ledes, the
|
|
73
|
+
contents lists, and the explainer notes and column panels that used
|
|
74
|
+
package components are now plain guide markup. All of this lives in
|
|
75
|
+
`design-guide/` (markdown and `styles/guide.css`); the package is unchanged.
|
|
76
|
+
- **Design guide: print-design review pass.** Readability and finish fixes
|
|
77
|
+
from a review against the print-quality rubrics, all in `design-guide/`:
|
|
78
|
+
- Code boxes are set in IBM Plex Mono (OFL, bundled in
|
|
79
|
+
`design-guide/fonts/ibm-plex-mono/`), 9pt on 1.4 leading, without the
|
|
80
|
+
doubled blank lines; fences of 20+ lines may split across pages.
|
|
81
|
+
- Guide text is capped at a 5.1in measure (about 65–70 characters) on 1.4
|
|
82
|
+
leading; tables are 10pt and may run across pages.
|
|
83
|
+
- Chapters open with a "Chapter N" label; H1 26pt, H3 13pt. Doc pages
|
|
84
|
+
carry a plain running foot (folio and chapter title); the contents list
|
|
85
|
+
has page numbers; Part 2 has a title page and E.1–E.6 chapter badges.
|
|
86
|
+
- YOU WRITE / RESULT labels are 8pt; YOU WRITE is cream on blood (7.7:1).
|
|
87
|
+
- Specimen stages stay whole unless marked `dg-tall`; prose specimens sit
|
|
88
|
+
on paper (`dg-on-paper`); two Do/Don't pairs (flavor in bold italic,
|
|
89
|
+
body text on bare wall).
|
|
90
|
+
- Typeface specimens for lixdu, Titillium Web and Tomorrow; palette
|
|
91
|
+
swatches are 1in and each carries a CMYK build from the CGATS21_CRPC1
|
|
92
|
+
profile (the hand-entered four-row CMYK table is replaced).
|
|
93
|
+
- Fixed: the type-scale table listed H1–H4 at stale sizes; the guide's
|
|
94
|
+
inline-code style leaked into the Part 2 examples (invisible text on a
|
|
95
|
+
dark callout), and its `hr` rule replaced the package's dashed rule in
|
|
96
|
+
the specimen; the inset-sidebar and art-plate specimens no longer leave
|
|
97
|
+
a RESULT tab stranded at a page foot.
|
|
98
|
+
- **Tests run against gutterpress 0.11.13** (devDependency, was 0.10.11).
|
|
99
|
+
- **`test/fixtures/all-macros.md` and its snapshot are gone**; the design
|
|
100
|
+
guide is the fixture. `npm run test:update-snapshot` is now bun's own
|
|
101
|
+
`--update-snapshots`; `scripts/update-snapshot.mjs` is removed.
|
|
102
|
+
|
|
103
|
+
### Fixed
|
|
104
|
+
|
|
105
|
+
- **No blank page after a two-column page that ends in a spanner.** A
|
|
106
|
+
`@page .gp-columns-2` page ending in a full-width section printed an
|
|
107
|
+
extra blank page under the DriveThruRPG margins (Field Guide: Quickstart
|
|
108
|
+
vs. Deep Dive): the section's bottom margin pushed the page box past its
|
|
109
|
+
one-sheet minimum. A multicol page's last child has no bottom margin.
|
|
110
|
+
Design guide unchanged; Field Guide loses the blank page.
|
|
111
|
+
- **The introduction page keeps the normal margins.** `.page-intro` shared
|
|
112
|
+
the `front-matter` named page with the Contents and Credits, whose side
|
|
113
|
+
and bottom margins are zeroed for their full-bleed masthead — so the
|
|
114
|
+
intro's chevron, lede and section sat flush on the sheet edge. It has its
|
|
115
|
+
own named page now, `front-matter-intro`: default margins, no footers.
|
|
116
|
+
The Field Guide writes its introduction as a plain `@page` and is
|
|
117
|
+
unaffected.
|
|
118
|
+
- **No more pages printed as images.** `filter: drop-shadow()` on the
|
|
119
|
+
intro page and on the labelled chapter-opener page made Chromium print
|
|
120
|
+
each of those pages as one 300ppi bitmap with a soft mask: no live text,
|
|
121
|
+
and a transparency mask PDF/X-1a forbids. Both shadows are vector now
|
|
122
|
+
(box-shadow on the lede, section and opener badge; the opener section's
|
|
123
|
+
own clipped `::after`). Design guide: 8 pages regain live text. The
|
|
124
|
+
Field Guide uses neither and is unaffected.
|
|
125
|
+
- **No hairline across the page after the credits.** The colophon fills to
|
|
126
|
+
the sheet's bottom edge, so its poster shadow's 3pt drop overflowed the
|
|
127
|
+
sheet and printed as a line across the top of the next page — over the
|
|
128
|
+
Field Guide's Contents masthead. The colophon keeps the shadow's side
|
|
129
|
+
offset and drops the downward one. (Clipping the page was rejected: it
|
|
130
|
+
would also clip a pinned or bleed plate.) Field Guide: p.2 loses the
|
|
131
|
+
line, and p.1 shows the colophon's side shadow starting level with its
|
|
132
|
+
top; nothing else changes.
|
|
133
|
+
- **Specialty art plates print full bleed.** The `.page` overflow guard
|
|
134
|
+
(page-templates.css) exempted pages holding `.gp-bleed`/`.gp-pin` art but
|
|
135
|
+
not `.dc-specialty-art` or `.dc-full-page`, so a plate on a page with no
|
|
136
|
+
other pinned art was cut at the text column — a 100pt strip of bare wall
|
|
137
|
+
down its outside edge (design guide p.45, p.105). The Field Guide's
|
|
138
|
+
plates were full width only because its specialty pages also carry
|
|
139
|
+
pinned art. Field Guide unchanged.
|
|
140
|
+
- **A long standalone banner title keeps its skew tab inside the margin.**
|
|
141
|
+
`.dc-spray`'s `::before` tab overhangs its right edge by 18px; a title
|
|
142
|
+
that filled its column pushed the tab past the margin, which is print
|
|
143
|
+
shrink-to-fit for the whole book once the page does not clip (found by
|
|
144
|
+
the build's width audit after the plate fix). Standalone banners cap at
|
|
145
|
+
the column less the tab; learning-path banners, which span their shell
|
|
146
|
+
with the tab pulled inside, are exempt. Field Guide unchanged.
|
|
147
|
+
- **A learning-path banner stays with its first card.** The shell is never
|
|
148
|
+
split and keeps with the next card, and the first path after a
|
|
149
|
+
specialty's art page drops its 8px top margin — moved into the package
|
|
150
|
+
from the Field Guide's own sheet, which measured both. Without them the
|
|
151
|
+
design guide printed the Biting Distance banner alone, with the edge of
|
|
152
|
+
the first card's tab at the page foot. The package's `break-before:
|
|
153
|
+
always` on `.dc-learning-path` is not a value Chromium supports and does
|
|
154
|
+
nothing; it is left as is (making it valid would put every path on a new
|
|
155
|
+
page). Field Guide unchanged.
|
|
156
|
+
- **A credits page that overflows no longer prints under the next page.**
|
|
157
|
+
`.page.page-credits` had an exact one-sheet `height`; when its colophon
|
|
158
|
+
did not fit, the colophon moved to a second sheet but the page box stayed
|
|
159
|
+
one sheet tall, so the following page started on that same sheet and was
|
|
160
|
+
painted over it (design guide: the Introduction over the colophon). It is
|
|
161
|
+
a `min-height` now: a page that fits is still exactly one sheet, so the
|
|
162
|
+
pinned plate still seats on the sheet edge, and the Field Guide renders
|
|
163
|
+
pixel-identical. The design guide's credits example also pins its plate
|
|
164
|
+
like the Field Guide's (`.gp-pin .gp-bottom .gp-full`) instead of placing
|
|
165
|
+
it in the colophon, which is what had made it overflow.
|
|
166
|
+
- **Variable AP chips print as variable.** The plugin emitted
|
|
167
|
+
`.dc-ap.variable` but the CSS only styled `.dc-ap.var`, and a `VAR AP`
|
|
168
|
+
cost got no variable class at all. Both spellings are styled now, and
|
|
169
|
+
`VAR` is detected alongside ranges and `X`. Visible change in the Field
|
|
170
|
+
Guide: 13 pages, each a range-cost chip (`2-X AP` and the like) turning
|
|
171
|
+
from standard blue to variable magenta; no layout change.
|
|
172
|
+
- **Short two-column runs no longer print full-page height.** `dc-native.css`
|
|
173
|
+
§10b set `column-fill: auto` on every `.gp-columns-*` run; with no fixed
|
|
174
|
+
height that fills the first column to the page foot, so a short column
|
|
175
|
+
panel became a full-height box with an empty right column, and a heading
|
|
176
|
+
above one was stranded alone when the box could not fit under it. The
|
|
177
|
+
rule is `balance` again, and the two per-shape `balance` exceptions it
|
|
178
|
+
made redundant are removed. A run that needs sequential fill opts in with
|
|
179
|
+
core's `.gp-columns-flow`. The Field Guide's 221 pages render
|
|
180
|
+
pixel-identical before and after.
|
|
181
|
+
- **A lede never splits** (`.dc-intro { break-inside: avoid }`), and the
|
|
182
|
+
section after a lede may start a new page. Core glues every section to
|
|
183
|
+
what precedes it, which chained heading → lede → section; when the section
|
|
184
|
+
could not fit, the lede split and painted an empty panel to the page foot.
|
|
185
|
+
- **`@sidebar .inset` with a single paragraph** set that paragraph in
|
|
186
|
+
centred display caps: the rail's closing-line rule matched it as the last
|
|
187
|
+
child. It now applies only from the second paragraph on. The inset rail
|
|
188
|
+
also keeps the sidebar's paper surface instead of a transparent one that
|
|
189
|
+
put its text on the brick wall.
|
|
190
|
+
- Two design guide chapters (`303`, `306`) closed `@procedure` on the line
|
|
191
|
+
right after a list item, which markdown folds into that item, so the
|
|
192
|
+
marker never closed and the chapter rendered with a layout warning.
|
|
193
|
+
|
|
194
|
+
## [1.0.1] - 2026-09-25
|
|
195
|
+
|
|
196
|
+
### Changed
|
|
197
|
+
|
|
198
|
+
- **The layer statement drops `book`**: `dc-fonts.css` now declares `@layer
|
|
199
|
+
dc.tokens, dc.base, dc.components, dc.templates, dc.pages;`. Gutterpress
|
|
200
|
+
0.11.0 wraps every extension's CSS in its own cascade layer (`@layer
|
|
201
|
+
ext.gp-dimm-city` for this package), so the package's own `dc.*` layers are
|
|
202
|
+
now sublayers nested inside that wrapper rather than top-level layers, and
|
|
203
|
+
a `book` sublayer declared here would only be reachable from inside this
|
|
204
|
+
package — a consuming book's separate `styles:` sheet can't nest into it.
|
|
205
|
+
Nothing in this package or any known consuming book ever put rules inside
|
|
206
|
+
`@layer book`, so there is no rendered change.
|
|
207
|
+
|
|
208
|
+
### Docs
|
|
209
|
+
|
|
210
|
+
- **README quick start now requires Gutterpress 0.11.0+** and drops the
|
|
211
|
+
`gutterpress ext remove ./extensions/clean-book` workaround: Gutterpress
|
|
212
|
+
now layers every extension's CSS itself (in `extensions:` list order), so
|
|
213
|
+
this package's rules can no longer be jumped by an unlayered starter look,
|
|
214
|
+
and `gutterpress new` no longer scaffolds one anyway. The "Your own CSS"
|
|
215
|
+
section no longer recommends wrapping book overrides in `@layer book` —
|
|
216
|
+
a book's own `styles:` sheets are unlayered by the engine and already beat
|
|
217
|
+
this whole package at any specificity.
|
|
218
|
+
|
|
219
|
+
## [1.0.0] - 2026-09-25
|
|
11
220
|
|
|
12
221
|
First release as a standalone package. Extracted from the private
|
|
13
222
|
`dimm-city/dc-op-manual` repository, where it lived at `dc-design-guide/` as a
|
package/README.md
CHANGED
|
@@ -67,20 +67,16 @@ byte for byte on every build.
|
|
|
67
67
|
|
|
68
68
|
## Quick start
|
|
69
69
|
|
|
70
|
+
Requires Gutterpress **0.11.0** or later — it wraps every extension's CSS in
|
|
71
|
+
its own cascade layer, so a book no longer needs a starter look removed
|
|
72
|
+
before this package can win the cascade.
|
|
73
|
+
|
|
70
74
|
```sh
|
|
71
75
|
gutterpress new "My Book" --preset dtrpg
|
|
72
|
-
gutterpress ext remove ./extensions/clean-book my-book && rm -r my-book/extensions
|
|
73
76
|
gutterpress ext add gp-dimm-city my-book
|
|
74
77
|
gutterpress preview my-book
|
|
75
78
|
```
|
|
76
79
|
|
|
77
|
-
The second line matters. `gutterpress new` gives every book a starter look
|
|
78
|
-
(`./extensions/clean-book`), and a look's CSS is unlayered, so it beats this
|
|
79
|
-
package's layered rules on anything the look styles — plain prose comes out in
|
|
80
|
-
the starter's serif instead of Titillium Web. This package *is* the look;
|
|
81
|
-
remove the starter before adding it. (In the app: Project settings → Look →
|
|
82
|
-
remove *Clean book*.)
|
|
83
|
-
|
|
84
80
|
Then insert the *Toc Page*, *Credits Page* and *Chapter Start Page* snippets
|
|
85
81
|
to lay down the front matter, and reach for *Skill*, *Learning Path* and
|
|
86
82
|
*Specialty* as you write. `page-rules.css` sets a Letter page with bleed; keep
|
|
@@ -88,34 +84,28 @@ the manifest's `page:` in step with it.
|
|
|
88
84
|
|
|
89
85
|
## Your own CSS: the layer convention
|
|
90
86
|
|
|
91
|
-
List your sheets under `styles:` in the manifest.
|
|
92
|
-
|
|
87
|
+
List your sheets under `styles:` in the manifest. Gutterpress (0.11.0+) wraps
|
|
88
|
+
this whole package in its own cascade layer, `@layer ext.gp-dimm-city`, and
|
|
89
|
+
keeps the book's own `styles:` unlayered — so anything you write there beats
|
|
90
|
+
every rule in this package at any specificity, with no layer of your own to
|
|
91
|
+
declare:
|
|
93
92
|
|
|
94
93
|
```css
|
|
95
|
-
|
|
96
|
-
#chapter-03 { --dc-section-accent: var(--hud-magenta); }
|
|
97
|
-
}
|
|
94
|
+
#chapter-03 { --dc-section-accent: var(--hud-magenta); }
|
|
98
95
|
```
|
|
99
96
|
|
|
100
|
-
The package
|
|
101
|
-
dc.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
— a book that must override it lists an **unlayered** sheet after the
|
|
106
|
-
extension; the last unlayered sheet wins.
|
|
107
|
-
- Do not invent layer names. A layer the package's statement does not name is
|
|
108
|
-
created where it is first used, which puts it *after* `book` and silently
|
|
109
|
-
above your own overrides.
|
|
97
|
+
The package's own sheets are layered internally (`@layer dc.tokens, dc.base,
|
|
98
|
+
dc.components, dc.templates, dc.pages`, nested inside `ext.gp-dimm-city`), and
|
|
99
|
+
`dc-native.css` stays last and unlayered within that internal stack — that's
|
|
100
|
+
a package-internal ordering concern, not something your book needs to work
|
|
101
|
+
around.
|
|
110
102
|
|
|
111
103
|
Never write bare `.dc-*` rules in a book to change a component; that fights
|
|
112
104
|
the package on every update. Reset the component's public tokens on a context
|
|
113
105
|
selector instead:
|
|
114
106
|
|
|
115
107
|
```css
|
|
116
|
-
|
|
117
|
-
.chapter-05 .dc-alert { --dc-alert-accent: var(--hud-blue); }
|
|
118
|
-
}
|
|
108
|
+
.chapter-05 .dc-alert { --dc-alert-accent: var(--hud-blue); }
|
|
119
109
|
```
|
|
120
110
|
|
|
121
111
|
The tokens each component exposes are listed under `tokens:` in
|
|
@@ -147,19 +137,59 @@ artwork and game text are not licensed by this package.
|
|
|
147
137
|
|
|
148
138
|
## Development
|
|
149
139
|
|
|
140
|
+
The short how-to is [docs/developing.md](./docs/developing.md): the edit → preview → test → release loop, in web-dev terms.
|
|
141
|
+
|
|
142
|
+
Everything you need to change the package and see the result is in this
|
|
143
|
+
repository: the plugin, the stylesheets, and `design-guide/` — the Dimm City
|
|
144
|
+
Design Guide, a Gutterpress book that documents every macro, token, component
|
|
145
|
+
and page template by rendering it. The guide's manifest loads the package from
|
|
146
|
+
this checkout (`extensions: - ../`), not from npm, so it is both the public
|
|
147
|
+
documentation and the test fixture: what it shows is what the working copy
|
|
148
|
+
renders.
|
|
149
|
+
|
|
150
150
|
```sh
|
|
151
151
|
bun install
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
npm run dev # live preview of the design guide, opens the browser
|
|
153
|
+
npm run build # lint + validate + render .build/design-guide.pdf (needs Chrome 148+)
|
|
154
|
+
npm run build:html # the guide as a static site, .build/design-guide-site/
|
|
155
|
+
bun test # plugin behaviour, design-guide render + snapshot, package, conventions
|
|
156
|
+
npm run test:update-snapshot # only when the plugin's output is meant to change
|
|
157
|
+
npm run pack:check # what npm would publish
|
|
155
158
|
```
|
|
156
159
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
`
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
The loop is the usual web one. `npm run dev` runs `gutterpress preview
|
|
161
|
+
design-guide`: edit `plugin.js`, a sheet under `styles/`, a font or the brick
|
|
162
|
+
tile, or any chapter of the guide, and the preview re-renders (the CLI lists
|
|
163
|
+
each watched file as it starts). The Gutterpress desktop app does the same —
|
|
164
|
+
open the `design-guide/` folder in it. `npm run build` is the PDF the
|
|
165
|
+
reader gets; it runs Gutterpress's print-safety lint and source/PDF
|
|
166
|
+
validation and fails on an error. Set `CHROMIUM_PATH` if your Chrome is not
|
|
167
|
+
on a standard path.
|
|
168
|
+
|
|
169
|
+
The tests (`bun test`) are the CI gate:
|
|
170
|
+
|
|
171
|
+
- `test/design-guide.test.js` — every chapter renders through Gutterpress's
|
|
172
|
+
pipeline with no layout warning and no marker left unrendered; every macro
|
|
173
|
+
and alert type the plugin handles appears in the guide; each chapter's HTML
|
|
174
|
+
matches `test/__snapshots__/`. A change to the plugin's output fails here
|
|
175
|
+
until you run `npm run test:update-snapshot` and review the snapshot diff
|
|
176
|
+
with the code.
|
|
177
|
+
- `test/plugin.test.js` — the loader contract and the behavioural edge cases.
|
|
178
|
+
- `test/package.test.js` — the tarball `npm publish` would ship: every
|
|
179
|
+
declared path, every `url()` asset, one licence per font directory, the
|
|
180
|
+
cascade contract.
|
|
181
|
+
- `test/conventions.test.js` — one prefix (`dc-`), no runtime imports, only
|
|
182
|
+
allow-listed core hooks.
|
|
183
|
+
|
|
184
|
+
CI (`.github/workflows/ci.yml`) runs the tests and then builds the design
|
|
185
|
+
guide PDF with the PR's plugin and CSS, uploaded as the `design-guide-pdf`
|
|
186
|
+
artifact — open it to see what a change did to every page. On `main`, the
|
|
187
|
+
*Publish design guide* workflow deploys the HTML build to GitHub Pages
|
|
188
|
+
(enable it once under Settings → Pages → Source: GitHub Actions).
|
|
189
|
+
|
|
190
|
+
`plugin.js` imports nothing at runtime — `gutterpress` is a devDependency used
|
|
191
|
+
by the tests (`gutterpress/render`) and by the scripts (the CLI). Releases are
|
|
192
|
+
cut from the *Release* workflow (version in; npm, GitHub release and the
|
|
193
|
+
design guide PDF out); it refuses a version with no `## [X.Y.Z]` heading in
|
|
194
|
+
`CHANGELOG.md`. Issues about the package — a macro, a sheet, a token, a font,
|
|
195
|
+
or a page of the guide — belong here.
|
package/components.yaml
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# WHAT THIS IS
|
|
5
5
|
# One entry per component: what an author writes, what lands in the HTML,
|
|
6
6
|
# which custom properties are public, how it fragments, and which stylesheet
|
|
7
|
-
# owns it. The Dimm City Design Guide (
|
|
7
|
+
# owns it. The Dimm City Design Guide (design-guide/ in this repo)
|
|
8
8
|
# explains and demonstrates the components; this file is the catalog of
|
|
9
9
|
# record. It is the file package.json declares as `gutterpress.components` —
|
|
10
10
|
# Gutterpress only checks that the file exists, so the schema below is this
|
|
@@ -389,13 +389,13 @@ components:
|
|
|
389
389
|
- name: ap-chip
|
|
390
390
|
status: live
|
|
391
391
|
origin: plugin
|
|
392
|
-
recipe: "1. **N AP** *Ability:* text (inside @skill; 0 AP → .free, ranges/X → .variable; also authored as raw <span class=\"dc-ap\">)"
|
|
392
|
+
recipe: "1. **N AP** *Ability:* text (inside @skill; 0 AP → .free, ranges/X/VAR → .variable; also authored as raw <span class=\"dc-ap\">)"
|
|
393
393
|
emits: span.dc-ap[.free|.variable]
|
|
394
394
|
css: [styles/components/cards.css, styles/components/specialty-identity.css]
|
|
395
395
|
tokens: [--dc-ap-bg, --dc-ap-fg, --dc-ap-border]
|
|
396
396
|
usage: [" AP**"]
|
|
397
397
|
breaks: none
|
|
398
|
-
notes: "
|
|
398
|
+
notes: "The plugin emits `variable`; the CSS styles both `.variable` and the raw spelling `.var`. `.standard/.reduced/.increased/.special` (specialty-identity.css) are never emitted, only authored raw — shown in the design guide's Variant Gallery."
|
|
399
399
|
|
|
400
400
|
- name: distance-tags
|
|
401
401
|
status: unused
|
|
@@ -667,6 +667,15 @@ components:
|
|
|
667
667
|
css: styles/page-rules.css
|
|
668
668
|
breaks: "page: clean"
|
|
669
669
|
|
|
670
|
+
- name: printer-page
|
|
671
|
+
status: live
|
|
672
|
+
origin: author
|
|
673
|
+
recipe: "@page .dc-printer-page (the last marker of a book's last chapter)"
|
|
674
|
+
emits: div.page.dc-printer-page
|
|
675
|
+
css: [styles/page-rules.css, styles/dc-native.css]
|
|
676
|
+
breaks: "page: printer-blank; break-before: page"
|
|
677
|
+
notes: "A completely blank final page — no wall, no footer — for DriveThruRPG's reserved printer page. With `print: signature: 4` in the manifest, gutterpress pads to the next multiple of 4, so the book always ends blank. Used by the Field Guide."
|
|
678
|
+
|
|
670
679
|
- name: cover-page
|
|
671
680
|
status: unused
|
|
672
681
|
origin: author
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gp-dimm-city",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
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",
|
|
@@ -59,12 +59,16 @@
|
|
|
59
59
|
"snippets": "snippets"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
|
+
"dev": "gutterpress preview design-guide --open",
|
|
63
|
+
"build": "gutterpress build design-guide --format pdf --out .build/design-guide.pdf",
|
|
64
|
+
"build:html": "gutterpress build design-guide --format html --out .build/design-guide-site",
|
|
65
|
+
"lint": "gutterpress lint design-guide",
|
|
62
66
|
"test": "bun test",
|
|
63
|
-
"test:update-snapshot": "bun
|
|
67
|
+
"test:update-snapshot": "bun test --update-snapshots",
|
|
64
68
|
"pack:check": "npm pack --dry-run"
|
|
65
69
|
},
|
|
66
70
|
"devDependencies": {
|
|
67
|
-
"gutterpress": "0.
|
|
71
|
+
"gutterpress": "0.11.13",
|
|
68
72
|
"markdown-it": "^14.1.0"
|
|
69
73
|
},
|
|
70
74
|
"peerDependencies": {
|
package/plugin.js
CHANGED
|
@@ -490,7 +490,7 @@ function parseAbilityFromListItem(html) {
|
|
|
490
490
|
// Determine AP class
|
|
491
491
|
let apClass = 'dc-ap';
|
|
492
492
|
if (apVal === '0 AP' || apVal === '0AP') apClass += ' free';
|
|
493
|
-
else if (apVal.includes('-') || apVal.toUpperCase()
|
|
493
|
+
else if (apVal.includes('-') || /X|VAR/.test(apVal.toUpperCase())) apClass += ' variable';
|
|
494
494
|
|
|
495
495
|
return {
|
|
496
496
|
apVal: apVal,
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
- :root token definitions (→ dc-component-defaults.css)
|
|
26
26
|
- @media screen rules (print-only project)
|
|
27
27
|
- Element selectors scoped to page/chapter context classes
|
|
28
|
-
(→ the book's own sheet (
|
|
28
|
+
(→ the book's own sheet (unlayered))
|
|
29
29
|
|
|
30
30
|
CORE CONSTRAINT — COMPONENT STYLE ISOLATION:
|
|
31
|
-
If a bare .dc-* rule needs different values in the book's own sheet (
|
|
31
|
+
If a bare .dc-* rule needs different values in the book's own sheet (unlayered), the
|
|
32
32
|
components/*.css value is WRONG — fix it here. The override files own
|
|
33
33
|
layout context only. Never split a component's appearance across files.
|
|
34
34
|
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
`var(--x, fallback)`. A token declared at :root needs no fallback, and
|
|
76
76
|
an inline fallback that duplicates the :root value is dead weight that
|
|
77
77
|
invites the two to drift (found and corrected during dc#34).
|
|
78
|
-
- Variants and contexts set tokens on ANCESTORS (the book's own sheet (
|
|
78
|
+
- Variants and contexts set tokens on ANCESTORS (the book's own sheet (unlayered)
|
|
79
79
|
chapter/page scopes) or on VARIANT CLASSES on the same element
|
|
80
80
|
(`.dc-ap.free`, `.dc-sidebar.inset`, `.dc-specialty.<name> .dc-X`) —
|
|
81
81
|
never by re-declaring the token on the base component selector itself.
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
|
|
93
93
|
/* ── Base shell — player-facing: pale cyan HUD panel, blue border ─────────── */
|
|
94
94
|
/* Token defaults for .dc-alert are declared in :root in dc-component-defaults.css.
|
|
95
|
-
Override at chapter-id scope in the book's own sheet (
|
|
95
|
+
Override at chapter-id scope in the book's own sheet (unlayered), or in variant rules below. */
|
|
96
96
|
.dc-alert {
|
|
97
97
|
background: var(--dc-alert-bg);
|
|
98
98
|
border-left: var(--dc-alert-border-width) solid var(--dc-alert-border);
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
6px. The old margin-bottom was exactly 6px, so it was entirely consumed
|
|
49
49
|
and consecutive cards rendered touching (screenshot-confirmed on the
|
|
50
50
|
Augmerc BODYCOVER/BLITZ seam). Same class of fix as .fg-art-portrait's
|
|
51
|
-
margin-bottom in the book's own sheet (
|
|
51
|
+
margin-bottom in the book's own sheet (unlayered). */
|
|
52
52
|
margin-bottom: calc(var(--dc-card-gap) + 6px);
|
|
53
53
|
max-width: 100%;
|
|
54
54
|
/* 4-way ink outline (2px on each side) + HARD offset poster shadow. The
|
|
@@ -480,8 +480,20 @@
|
|
|
480
480
|
--dc-ap-bg: var(--blood);
|
|
481
481
|
}
|
|
482
482
|
|
|
483
|
-
|
|
483
|
+
/* The plugin emits `.variable` (a range, X or VAR); `.var` is the raw
|
|
484
|
+
authored spelling. Only `.var` was styled, so plugin chips never showed
|
|
485
|
+
as variable. */
|
|
486
|
+
.dc-ap:is(.var, .variable) {
|
|
484
487
|
--dc-ap-bg: var(--hud-magenta);
|
|
485
488
|
}
|
|
486
489
|
|
|
490
|
+
/* A card title is a wide display word in a narrow box (a gear card in a
|
|
491
|
+
two-column run is ~3.4in). One that cannot fit ran past the card and into
|
|
492
|
+
the page margin — "ACCELERATOR" printed 0.41in from the trim, inside
|
|
493
|
+
DriveThruRPG's 0.5in text minimum. It now breaks, as a last resort; a
|
|
494
|
+
soft hyphen (­) in the source picks a better break. */
|
|
495
|
+
.dc-card :is(h2, h3, h4) {
|
|
496
|
+
overflow-wrap: break-word;
|
|
497
|
+
}
|
|
498
|
+
|
|
487
499
|
}
|
|
@@ -99,7 +99,7 @@ h1.dc-chevron {
|
|
|
99
99
|
line-height: 1.2;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
/* Front-matter chevron font-size overrides moved to the book's own sheet (
|
|
102
|
+
/* Front-matter chevron font-size overrides moved to the book's own sheet (unlayered) per A1
|
|
103
103
|
layer-ownership (page-context rules belong in the guide-specific override
|
|
104
104
|
file, not the portable component library). Three-judge gate iteration 3. */
|
|
105
105
|
|
|
@@ -130,6 +130,14 @@ h1.dc-chevron {
|
|
|
130
130
|
`isolation: isolate`, and with neither. */
|
|
131
131
|
clip-path: polygon(0 0, 100% 0, 100% 100%, 25px 100%, 0 calc(100% - 15px));
|
|
132
132
|
margin: 0;
|
|
133
|
+
/* Leave room for the ::before skew tab, which overhangs the right edge
|
|
134
|
+
(right: -8px, 14px wide, skewed): 18px measured. A long title that
|
|
135
|
+
filled its column pushed the tab past the margin — "What Makes a Good
|
|
136
|
+
Cross-Specialty Moment", scrollWidth 726px in a 708px column — which a
|
|
137
|
+
clipping .page hid, and which on a page that may not clip (one holding
|
|
138
|
+
plate or bleed art) is print shrink-to-fit for the whole book. Such a
|
|
139
|
+
title now wraps one tab-width earlier; shorter banners are untouched. */
|
|
140
|
+
max-width: calc(100% - 18px);
|
|
133
141
|
word-break: break-word;
|
|
134
142
|
overflow: visible;
|
|
135
143
|
}
|
|
@@ -329,6 +337,21 @@ h1.dc-chevron {
|
|
|
329
337
|
padding: 0 14px 10px 18px;
|
|
330
338
|
margin: 0 0 calc(0.1in + 3pt) 0;
|
|
331
339
|
box-shadow: var(--shadow-poster);
|
|
340
|
+
/* A lede is one to three short paragraphs: never split it. Split, its
|
|
341
|
+
panel painted on to the page foot with the last paragraph overleaf
|
|
342
|
+
(design guide p.82, "How Abilities Work"). */
|
|
343
|
+
break-inside: avoid;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Core glues every section to whatever precedes it (`:where(.section) >
|
|
347
|
+
:where(:first-child) { break-before: avoid }`), which chains heading →
|
|
348
|
+
lede → section into one unbreakable run. When that section cannot fit,
|
|
349
|
+
Chromium has to break inside the chain: it split the lede, or with the
|
|
350
|
+
lede kept whole, stranded the heading at the page foot. A lede stands on
|
|
351
|
+
its own, so the section after it may start a new page; the section's own
|
|
352
|
+
break-inside: avoid still moves it whole. */
|
|
353
|
+
.dc-intro + .section > :first-child {
|
|
354
|
+
break-before: auto;
|
|
332
355
|
}
|
|
333
356
|
|
|
334
357
|
/* ── Spec tweak section header ────────────────────────────────────────── */
|
|
@@ -100,6 +100,10 @@
|
|
|
100
100
|
|
|
101
101
|
.dc-path-shell>h2.dc-spray {
|
|
102
102
|
width: stretch;
|
|
103
|
+
/* A path banner spans its shell edge to edge, with its tab pulled inside
|
|
104
|
+
(`right: -5px` below): it takes none of the standalone banner's
|
|
105
|
+
tab allowance (chrome.css .dc-spray). */
|
|
106
|
+
max-width: none;
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
.dc-path-shell>h2.dc-spray:first-child {
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
`.page.page-sidebar` template in page-templates.css: a rail is meaningless
|
|
45
45
|
without a page that reserved room for it, and scoping it there means a
|
|
46
46
|
stray `@sidebar .inset` on an ordinary page stays a readable floated
|
|
47
|
-
sidebar instead of painting over the body text.
|
|
47
|
+
sidebar instead of painting over the body text. The rail keeps the
|
|
48
|
+
sidebar's paper surface: it was transparent, which put its text straight
|
|
49
|
+
on the brick wall. */
|
|
48
50
|
.dc-sidebar.inset {
|
|
49
|
-
--dc-sidebar-surface: transparent;
|
|
50
|
-
|
|
51
51
|
border-left: none;
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -102,7 +102,9 @@
|
|
|
102
102
|
padding: 0.06in 0.1in;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
/* The rail's closing line — only when it is not also the rail's only (first)
|
|
106
|
+
paragraph, or a one-paragraph rail sets its whole body in display caps. */
|
|
107
|
+
.dc-sidebar.inset>p:last-child:not(:first-of-type) {
|
|
106
108
|
margin-top: 0.1in;
|
|
107
109
|
margin-bottom: 0;
|
|
108
110
|
padding-top: 0.08in;
|
|
@@ -672,7 +672,7 @@ h3 + .section {
|
|
|
672
672
|
|
|
673
673
|
To tune the walkthrough's accent or substrate, override the existing
|
|
674
674
|
--dc-section-accent / --dc-section-bg custom properties at the chapter
|
|
675
|
-
id scope in the book's own sheet (
|
|
675
|
+
id scope in the book's own sheet (unlayered) — do NOT add bespoke rules here unless an
|
|
676
676
|
observed problem requires it.
|
|
677
677
|
|
|
678
678
|
OBSERVED PROBLEM (2026-05-25): When the walkthrough's first card uses
|
|
@@ -865,7 +865,7 @@ h3 + .section {
|
|
|
865
865
|
|
|
866
866
|
|
|
867
867
|
|
|
868
|
-
/* Per-book variant assignment lives in the book's own sheet (
|
|
868
|
+
/* Per-book variant assignment lives in the book's own sheet (unlayered) using natural
|
|
869
869
|
selector chains (chapter id → page template class → section component
|
|
870
870
|
class) that set component CSS custom properties. No utility-variant
|
|
871
871
|
classes here — that would force authors to re-type variant intent. */
|
|
@@ -940,16 +940,16 @@ h3 + .section {
|
|
|
940
940
|
border-top: 4pt solid var(--dc-chapter-opener-accent);
|
|
941
941
|
}
|
|
942
942
|
|
|
943
|
-
/*
|
|
944
|
-
`filter: drop-shadow()`
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
.chapter
|
|
952
|
-
|
|
943
|
+
/* Chapter-opener shadow — vector, per element. This was ONE
|
|
944
|
+
`filter: drop-shadow()` on the page wrapper; Chromium prints a filtered
|
|
945
|
+
subtree as a bitmap, so every opener page went to the PDF as a single
|
|
946
|
+
300ppi image with a transparency mask — no live text, and a soft mask
|
|
947
|
+
that PDF/X-1a forbids. The badge takes a box-shadow; the section's own
|
|
948
|
+
::after (below) draws its shadow on the same clipped silhouette as its
|
|
949
|
+
substrate, the way the base .section card does. The chevron sits inside
|
|
950
|
+
the section box, so the section's shadow covers it. */
|
|
951
|
+
.chapter-opener {
|
|
952
|
+
box-shadow: var(--dc-chapter-opener-shadow);
|
|
953
953
|
}
|
|
954
954
|
|
|
955
955
|
/* Section substrate for the chapter-opener intro section. Selector
|
|
@@ -988,11 +988,21 @@ h3 + .section {
|
|
|
988
988
|
);
|
|
989
989
|
}
|
|
990
990
|
|
|
991
|
-
/*
|
|
992
|
-
|
|
993
|
-
|
|
991
|
+
/* The chapter-opener section's shadow: the base ::after, offset like
|
|
992
|
+
--dc-chapter-opener-shadow and clipped to the same straight right edge
|
|
993
|
+
at the clip-tail as the substrate above. */
|
|
994
994
|
.chapter[data-chapter-label] > .page[data-page="intro"] > .section::after {
|
|
995
|
-
|
|
995
|
+
top: 4px;
|
|
996
|
+
left: 3px;
|
|
997
|
+
right: -3px;
|
|
998
|
+
bottom: -4px;
|
|
999
|
+
background: rgba(0, 0, 0, 0.28);
|
|
1000
|
+
clip-path: polygon(
|
|
1001
|
+
0 0,
|
|
1002
|
+
calc(100% - var(--dc-chapter-opener-clip-tail)) 0,
|
|
1003
|
+
calc(100% - var(--dc-chapter-opener-clip-tail)) 100%,
|
|
1004
|
+
0 100%
|
|
1005
|
+
);
|
|
996
1006
|
}
|
|
997
1007
|
|
|
998
1008
|
/* Auto-style the section's first h1 as a chevron banner — no markdown
|
|
@@ -1036,7 +1046,7 @@ h3 + .section {
|
|
|
1036
1046
|
declared in :root in dc-component-defaults.css — same values as before this moved
|
|
1037
1047
|
(the 3in art width: user feedback said the previous 1.85in "Lil Thump
|
|
1038
1048
|
placeholder image is too small... should take up more of the left side
|
|
1039
|
-
of the page"). Per-page/per-chapter variants override via the book's own sheet (
|
|
1049
|
+
of the page"). Per-page/per-chapter variants override via the book's own sheet (unlayered)
|
|
1040
1050
|
context selectors, e.g. `.page....chapter-01 .section.dc-fiction-excerpt`. */
|
|
1041
1051
|
.section.dc-fiction-excerpt {
|
|
1042
1052
|
background: var(--dc-fiction-bg);
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
:root { /* ── Section Component Public Tokens ────────────────────────────────────
|
|
4
4
|
Default theming for .section / @section macros. Chapter-scoped overrides
|
|
5
|
-
live in the book's own sheet (
|
|
5
|
+
live in the book's own sheet (unlayered — it wins over this whole package
|
|
6
|
+
regardless of specificity) and win via the parent-context cascade —
|
|
6
7
|
typically by applying a .dc-accent-X utility on @chapter / @section
|
|
7
8
|
(see components/*.css "ACCENT IDENTITY UTILITIES" section). */
|
|
8
9
|
--dc-section-bg: var(--paper-cream);
|
|
@@ -12,9 +13,9 @@
|
|
|
12
13
|
Override surface for per-chapter and per-project theming. These are the
|
|
13
14
|
defaults that were previously declared inside each component class rule.
|
|
14
15
|
Moving them to :root makes them visible to the theming system and lets
|
|
15
|
-
the book's own sheet
|
|
16
|
+
the book's own sheet override them at chapter-id scope instead of having to
|
|
16
17
|
write a full component selector chain.
|
|
17
|
-
Set them here; override at chapter id scope in the book's own sheet
|
|
18
|
+
Set them here; override at chapter id scope in the book's own sheet.
|
|
18
19
|
──────────────────────────────────────────────────────────────────────── */
|
|
19
20
|
|
|
20
21
|
/* .dc-alert public API */
|
package/styles/dc-fonts.css
CHANGED
|
@@ -15,29 +15,32 @@
|
|
|
15
15
|
- .page.* layout or column rules (→ page-templates.css)
|
|
16
16
|
- .dc-* component/utility styles (→ components/*.css / page-templates.css)
|
|
17
17
|
- Design tokens (→ dc-palette.css, dc-identity.css, dc-component-defaults.css)
|
|
18
|
-
- Anything a single book needs (→ that book's own sheet,
|
|
18
|
+
- Anything a single book needs (→ that book's own sheet, unlayered — no
|
|
19
|
+
`@layer` needed)
|
|
19
20
|
- @media screen rules (print-only project)
|
|
20
21
|
|
|
21
22
|
AGENT RULE: "Is this a token or a font?" — if NO, use another file.
|
|
22
23
|
|
|
23
24
|
──────────────────────────────────────────────────────────────────────── */
|
|
24
25
|
|
|
25
|
-
/*
|
|
26
|
-
first sheet the cascade sees — so layer order stops depending on the
|
|
27
|
-
manifest's file order.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
because it is LAST, and anything that must beat unlayered author CSS
|
|
32
|
-
cannot be layered (see docs/css-architecture.md).
|
|
26
|
+
/* Sublayer order for this package's OWN stack, declared here because this is
|
|
27
|
+
the first sheet the cascade sees — so layer order stops depending on the
|
|
28
|
+
manifest's file order. Gutterpress ≥0.11.0 wraps every extension's CSS in
|
|
29
|
+
`@layer ext.<name>` (this package is `ext.gp-dimm-city`), so this
|
|
30
|
+
statement declares sublayers nested inside that wrapper, not top-level
|
|
31
|
+
layers.
|
|
33
32
|
|
|
34
|
-
`
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
`dc-fonts.css` itself is deliberately NOT wrapped in a layer: @font-face
|
|
34
|
+
inside a layer is legal but pointless (font-family lookup is not a
|
|
35
|
+
cascade contest). `dc-native.css`, the last sheet in this package, is
|
|
36
|
+
ALSO deliberately unlayered — not because it is special, but because it
|
|
37
|
+
is LAST, and anything that must beat the other dc.* sublayers cannot
|
|
38
|
+
itself be layered. That ordering is internal to this package only: a
|
|
39
|
+
consuming book's own `styles:` sheets stay unlayered by the engine and
|
|
40
|
+
beat this whole `ext.gp-dimm-city` stack — dc-native.css included —
|
|
41
|
+
automatically, at any specificity, so a book needs no layer of its own to
|
|
42
|
+
win (see docs/css-architecture.md). */
|
|
43
|
+
@layer dc.tokens, dc.base, dc.components, dc.templates, dc.pages;
|
|
41
44
|
|
|
42
45
|
/* ── WEBFONTS (local) ─────────────────────────────────────────────────────── */
|
|
43
46
|
@font-face {
|
package/styles/dc-native.css
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
DC-NATIVE.CSS — engine-specific page chrome
|
|
3
3
|
=============================================================================
|
|
4
4
|
The LAST entry in package.json `gutterpress.styles`, and deliberately
|
|
5
|
-
unlayered
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
unlayered *within this package's own layer stack* — so it beats every
|
|
6
|
+
`dc.*` sublayer in this package, which is why it must stay last in the
|
|
7
|
+
array. Gutterpress ≥0.11.0 wraps the whole package in a layer of its own,
|
|
8
|
+
`ext.gp-dimm-city`, so from outside the package that unlayered status
|
|
9
|
+
doesn't matter: the book's own `styles:` sheets stay unlayered by the
|
|
10
|
+
engine and beat this whole file automatically, at any specificity, with
|
|
11
|
+
no unlayered-sheet trick required on the book's side.
|
|
8
12
|
|
|
9
13
|
Mechanics, each measured against Chromium 151 (gutterpress ENGINE.md §5/§8):
|
|
10
14
|
- ONE `@page { background }` rule paints the brick wall across the whole
|
|
@@ -38,6 +42,12 @@
|
|
|
38
42
|
background-blend-mode: multiply;
|
|
39
43
|
}
|
|
40
44
|
|
|
45
|
+
/* The printer page (page-rules.css) carries no wall: DriveThruRPG wants
|
|
46
|
+
the final page free of any page background. */
|
|
47
|
+
@page printer-blank {
|
|
48
|
+
background: none;
|
|
49
|
+
}
|
|
50
|
+
|
|
41
51
|
/* ── 3. FOLIO + CHAPTER STICKERS ────────────────────────────────────────────
|
|
42
52
|
Chrome for the chip content page-rules.css declares on @bottom-left /
|
|
43
53
|
@bottom-right. Sticker identity swaps by spread side in page-rules.css's
|
|
@@ -69,11 +79,20 @@
|
|
|
69
79
|
Shrinking the box no longer punches a hole in the margin band: §1's
|
|
70
80
|
`@page` background paints underneath, so the wall shows through the rest
|
|
71
81
|
of the slot on its own. */
|
|
82
|
+
/* `align-self: flex-start`: on a page whose footer band a `.gp-flush` pin
|
|
83
|
+
frees, gutterpress re-homes these chips into a flex slot the size of the
|
|
84
|
+
margin box, centred vertically (gutterpress-agent setFlushFurniture,
|
|
85
|
+
`align-items: center`), and copies these declarations onto the chip. A
|
|
86
|
+
native margin box anchors a fit-content chip at the TOP of the band;
|
|
87
|
+
centred, a re-homed chip printed 0.24in from the trim, against
|
|
88
|
+
DriveThruRPG's 0.5in text minimum (Field Guide p.9, p.10, p.16). The
|
|
89
|
+
declaration does nothing to a native margin box, which is not a flex item. */
|
|
72
90
|
@page :left {
|
|
73
91
|
@bottom-left {
|
|
74
92
|
/* folio sticker — civic register */
|
|
75
93
|
width: fit-content;
|
|
76
94
|
height: fit-content;
|
|
95
|
+
align-self: flex-start;
|
|
77
96
|
font-family: var(--font-mono);
|
|
78
97
|
font-size: 9pt;
|
|
79
98
|
font-weight: 700;
|
|
@@ -88,6 +107,7 @@
|
|
|
88
107
|
/* chapter sticker — stamped coupon */
|
|
89
108
|
width: fit-content;
|
|
90
109
|
height: fit-content;
|
|
110
|
+
align-self: flex-start;
|
|
91
111
|
font-family: var(--font-display);
|
|
92
112
|
font-size: 9pt;
|
|
93
113
|
font-weight: 700;
|
|
@@ -105,6 +125,7 @@
|
|
|
105
125
|
/* chapter sticker — stamped coupon */
|
|
106
126
|
width: fit-content;
|
|
107
127
|
height: fit-content;
|
|
128
|
+
align-self: flex-start;
|
|
108
129
|
font-family: var(--font-display);
|
|
109
130
|
font-size: 9pt;
|
|
110
131
|
font-weight: 700;
|
|
@@ -119,6 +140,7 @@
|
|
|
119
140
|
/* folio sticker — civic register */
|
|
120
141
|
width: fit-content;
|
|
121
142
|
height: fit-content;
|
|
143
|
+
align-self: flex-start;
|
|
122
144
|
font-family: var(--font-mono);
|
|
123
145
|
font-size: 9pt;
|
|
124
146
|
font-weight: 700;
|
|
@@ -179,14 +201,19 @@
|
|
|
179
201
|
padding-bottom: 0.75in;
|
|
180
202
|
}
|
|
181
203
|
/* Credits page as a full-height flex column so a pinned founders plate
|
|
182
|
-
(`.gp-pin .gp-bottom .gp-full`) seats on the sheet edge.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
204
|
+
(`.gp-pin .gp-bottom .gp-full`) seats on the sheet edge. Carried from the
|
|
205
|
+
field guide's native sheet in 1.0.0: every Dimm City book writes this page.
|
|
206
|
+
|
|
207
|
+
`min-height`, not `height`. A page whose credits fit is exactly one sheet
|
|
208
|
+
either way, so the pin still seats on the sheet edge. An exact `height`
|
|
209
|
+
broke the page whose credits do NOT fit: the colophon went to a second
|
|
210
|
+
sheet while the page box stayed one sheet tall, so the next page started
|
|
211
|
+
on that same second sheet and printed on top of it (design guide, the
|
|
212
|
+
Introduction over the credits colophon). */
|
|
186
213
|
.page.page-credits {
|
|
187
214
|
display: flex;
|
|
188
215
|
flex-direction: column;
|
|
189
|
-
height: var(--gp-content-h);
|
|
216
|
+
min-height: var(--gp-content-h);
|
|
190
217
|
padding-bottom: 0;
|
|
191
218
|
}
|
|
192
219
|
.page.page-credits .section.credits-colophon {
|
|
@@ -195,6 +222,14 @@
|
|
|
195
222
|
display: flex;
|
|
196
223
|
flex-direction: column;
|
|
197
224
|
margin-bottom: 0;
|
|
225
|
+
/* The colophon fills to the sheet's bottom edge (this template has no
|
|
226
|
+
bottom margin), so the poster shadow's 3pt drop landed past the sheet,
|
|
227
|
+
and Chromium printed that overflow as a hairline across the top of the
|
|
228
|
+
NEXT sheet — the Field Guide's Contents masthead, the design guide's
|
|
229
|
+
Introduction. The shadow keeps its side offset and loses the drop; the
|
|
230
|
+
colophon's foot sits under the pinned plate in any case. (Clipping the
|
|
231
|
+
page instead would also clip a pinned or bleed plate on it.) */
|
|
232
|
+
box-shadow: 2pt 0 0 rgba(0, 0, 0, 0.28);
|
|
198
233
|
}
|
|
199
234
|
/* The masthead escapes the padding back to the sheet edges — visible paint
|
|
200
235
|
inside the full-width content box. `margin-top: 0` is deliberate: a
|
|
@@ -246,44 +281,35 @@ figure {
|
|
|
246
281
|
value depends on whether the run fragments, and only the author knows).
|
|
247
282
|
page-templates.css used to answer `balance` for the whole book; under
|
|
248
283
|
native print the wrapper fragments across pages, and Chromium's
|
|
249
|
-
balance-in-fragmentation
|
|
250
|
-
column (measured: proof17 p12/p13)
|
|
251
|
-
|
|
284
|
+
balance-in-fragmentation left every non-final fragment with a dead right
|
|
285
|
+
column (measured: proof17 p12/p13), so this rule said `auto`.
|
|
286
|
+
|
|
287
|
+
It says `balance` again (2026-10). `auto` with no fixed height fills the
|
|
288
|
+
first column to the BOTTOM OF THE PAGE, so every short run — a column
|
|
289
|
+
panel, a pair of gear entries — printed as a full-height box with an
|
|
290
|
+
empty right column, and a heading above one was stranded alone on its
|
|
291
|
+
page when the full-height box could not fit under it (design guide
|
|
292
|
+
p.83, p.111). Measured against the change, under gutterpress 0.11.13:
|
|
293
|
+
the Field Guide's 221 pages render pixel-identical with `balance`, and
|
|
294
|
+
the design guide loses 6 pages of holes. A run that genuinely needs
|
|
295
|
+
sequential fill opts in with core's `.gp-columns-flow`. */
|
|
252
296
|
.gp-columns-2,
|
|
253
297
|
.gp-columns-3 {
|
|
254
|
-
column-fill:
|
|
298
|
+
column-fill: balance;
|
|
255
299
|
}
|
|
256
|
-
/*
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
p243's CORE ELEMENTS section, where the dc-alert callout is itself taller
|
|
262
|
-
than a column and MUST be allowed to fragment; see §13 below). A
|
|
263
|
-
`.section` that is ITSELF the multicol container is NOT reliably short —
|
|
264
|
-
CORE ELEMENTS is that same DOM shape (`.section.gp-columns-2`) and needs
|
|
265
|
-
`auto`, so shape alone can't tell "fits on one page" from "runs long".
|
|
300
|
+
/* The per-shape exceptions that used to follow — `.dc-citizen-walkthrough
|
|
301
|
+
.gp-columns-2` and `.page.gp-columns-2` set back to `balance` — are gone:
|
|
302
|
+
the rule above now says `balance` for every run. The Field Guide pages they
|
|
303
|
+
were measured on (p12/p13 "THE PACK SHOULD BE WEIRD", p243 CORE ELEMENTS,
|
|
304
|
+
p7 "Image Is Everything") are among the 221 that render pixel-identical. */
|
|
266
305
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
fragment, the compiler's own multicol-fragmentation check flags it and
|
|
275
|
-
tells the author to add column-fill: auto locally — not a silent trap.
|
|
276
|
-
|
|
277
|
-
(b) a PAGE that is itself the multicol container. A `.page` is one sheet by
|
|
278
|
-
construction, so its run does not fragment and balance is the correct
|
|
279
|
-
value. This carries forward the `.page.two-column { column-fill: balance }`
|
|
280
|
-
that page-templates.css used to win with on specificity alone (0-2-0 over
|
|
281
|
-
this file's 0-1-0); stating it here puts it next to the reasoning and the
|
|
282
|
-
measurements instead of leaving it to load order. Live user:
|
|
283
|
-
`@page .dc-citizen-file-page .gp-columns-2` in the design guide. */
|
|
284
|
-
.dc-citizen-walkthrough.gp-columns-2,
|
|
285
|
-
.page.gp-columns-2 {
|
|
286
|
-
column-fill: balance;
|
|
306
|
+
/* A PAGE that is itself the multicol container (`@page .gp-columns-2`) and
|
|
307
|
+
ends in a full-width spanner: the spanner's bottom margin pushed the page
|
|
308
|
+
box past its one-sheet minimum height, and the overflow printed as a blank
|
|
309
|
+
page (Field Guide: Quickstart vs. Deep Dive, after the DriveThruRPG
|
|
310
|
+
margins). A page's last child needs no bottom margin. */
|
|
311
|
+
.page:is(.gp-columns-2, .gp-columns-3) > :last-child {
|
|
312
|
+
margin-bottom: 0;
|
|
287
313
|
}
|
|
288
314
|
|
|
289
315
|
/* ── 12. WALL ART placement is the markdown's, via core's gp-* classes ──────
|
package/styles/dc-palette.css
CHANGED
|
@@ -123,7 +123,20 @@
|
|
|
123
123
|
--dc-card-gap: 0.15in; /* ~11pt */
|
|
124
124
|
|
|
125
125
|
--gutter: 0.15in; /* two-column structural gutter */
|
|
126
|
-
|
|
126
|
+
/* Page margins, measured from the SHEET edge. The sheet is the trim plus
|
|
127
|
+
DriveThruRPG's 0.125in bleed on the top, bottom and outside edge (none
|
|
128
|
+
at the spine), so each bleed-side margin is the trim distance + 0.125in.
|
|
129
|
+
DriveThruRPG "Quick Specifications for Print Books": all text at least
|
|
130
|
+
0.5in inside the page (trim) edge; non-bleeding art 0.25in from the
|
|
131
|
+
outside three edges and 0.5in from the binding edge.
|
|
132
|
+
top 0.625in = 0.5in from the trim (was 0.5in: 0.375in, out of spec)
|
|
133
|
+
bottom 0.875in = 0.75in from the trim (was 0.75in: the folio and
|
|
134
|
+
chapter chips sit in this band and printed 0.43in
|
|
135
|
+
from the trim, out of spec)
|
|
136
|
+
outside 0.625in = 0.5in from the trim
|
|
137
|
+
binding 0.75in = 0.75in from the spine (no bleed on that edge) */
|
|
138
|
+
--page-margin: 0.625in;
|
|
139
|
+
--bottom-margin: 0.875in;
|
|
127
140
|
--outer-margin: 0.625in; /* outer (non-binding) page margin */
|
|
128
141
|
--sidebar-width: 3.05in;
|
|
129
142
|
|
package/styles/page-rules.css
CHANGED
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
--page-height in dc-palette.css: change both together. */
|
|
57
57
|
@page {
|
|
58
58
|
size: 8.625in 11.25in;
|
|
59
|
-
margin: var(--page-margin) var(--outer-margin)
|
|
59
|
+
margin: var(--page-margin) var(--outer-margin) var(--bottom-margin);
|
|
60
60
|
background-color: var(--bg);
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -90,12 +90,26 @@
|
|
|
90
90
|
@bottom-right { content: none; }
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
.page.page-intro,
|
|
94
93
|
.page.page-toc,
|
|
95
94
|
.page.page-credits {
|
|
96
95
|
page: front-matter;
|
|
97
96
|
}
|
|
98
97
|
|
|
98
|
+
/* The introduction is front matter too — unnumbered — but it is not part
|
|
99
|
+
of the full-bleed masthead composite: its chevron, lede and section sit
|
|
100
|
+
inside the ordinary text column. It used to share `front-matter`, whose
|
|
101
|
+
zeroed side and bottom margins (dc-native.css §5) put the whole page
|
|
102
|
+
flush against the sheet edge. Its own name keeps the default margins and
|
|
103
|
+
drops only the footers. */
|
|
104
|
+
@page front-matter-intro {
|
|
105
|
+
@bottom-left { content: none; }
|
|
106
|
+
@bottom-right { content: none; }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.page.page-intro {
|
|
110
|
+
page: front-matter-intro;
|
|
111
|
+
}
|
|
112
|
+
|
|
99
113
|
/* ---------------------------------------------------------------------------
|
|
100
114
|
Chapter start — footers suppressed; the chevron banner IS the visual
|
|
101
115
|
identity. dc-native.css refills the two bottom boxes with the brick
|
|
@@ -137,6 +151,28 @@
|
|
|
137
151
|
@bottom-right { content: none; }
|
|
138
152
|
}
|
|
139
153
|
|
|
154
|
+
/* ---------------------------------------------------------------------------
|
|
155
|
+
Printer page — a completely blank last page. DriveThruRPG reserves a
|
|
156
|
+
book's final page for printer information: the interior must be one page
|
|
157
|
+
short of its signature (4 pages for US Letter), or end on a page "devoid
|
|
158
|
+
of page backgrounds, page numbers, etc." (Quick Specifications for Print
|
|
159
|
+
Books). End the last chapter with `@page .dc-printer-page` and set
|
|
160
|
+
`print: signature: 4` in the manifest: gutterpress pads with blank pages
|
|
161
|
+
to the next multiple of 4, so the book always ends blank whatever its
|
|
162
|
+
length. dc-native.css drops the wall on this page.
|
|
163
|
+
--------------------------------------------------------------------------- */
|
|
164
|
+
|
|
165
|
+
@page printer-blank {
|
|
166
|
+
@bottom-left { content: none; }
|
|
167
|
+
@bottom-right { content: none; }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.dc-printer-page {
|
|
171
|
+
page: printer-blank;
|
|
172
|
+
break-before: page;
|
|
173
|
+
height: var(--gp-content-h);
|
|
174
|
+
}
|
|
175
|
+
|
|
140
176
|
.dc-suppress-footer {
|
|
141
177
|
page: clean;
|
|
142
178
|
}
|
|
@@ -147,25 +183,34 @@
|
|
|
147
183
|
are left alone, so these pages keep the body footers.
|
|
148
184
|
--------------------------------------------------------------------------- */
|
|
149
185
|
|
|
186
|
+
/* The running head is TEXT, so DriveThruRPG wants it 0.5in inside the trim
|
|
187
|
+
— below the default top margin, whose whole band lies within 0.5in of
|
|
188
|
+
the trim. These pages carry a deeper top margin and set the head at the
|
|
189
|
+
foot of it: 0.875in from the sheet edge, head baseline ~0.7in, 0.58in
|
|
190
|
+
from the trim. (It printed at 0.1in from the trim.) */
|
|
150
191
|
@page citizen-file:right {
|
|
192
|
+
margin-top: 0.875in;
|
|
151
193
|
@top-right {
|
|
152
194
|
content: "Citizen File";
|
|
153
195
|
color: var(--amber);
|
|
154
196
|
font-family: var(--font-display);
|
|
155
197
|
letter-spacing: 0.1em;
|
|
156
198
|
font-size: 0.8em;
|
|
157
|
-
|
|
199
|
+
vertical-align: bottom;
|
|
200
|
+
padding-bottom: 0.08in;
|
|
158
201
|
}
|
|
159
202
|
}
|
|
160
203
|
|
|
161
204
|
@page citizen-file:left {
|
|
205
|
+
margin-top: 0.875in;
|
|
162
206
|
@top-left {
|
|
163
207
|
content: "Citizen File";
|
|
164
208
|
color: var(--amber);
|
|
165
209
|
font-family: var(--font-display);
|
|
166
210
|
letter-spacing: 0.1em;
|
|
167
211
|
font-size: 0.8em;
|
|
168
|
-
|
|
212
|
+
vertical-align: bottom;
|
|
213
|
+
padding-bottom: 0.08in;
|
|
169
214
|
}
|
|
170
215
|
}
|
|
171
216
|
|
|
@@ -102,8 +102,16 @@
|
|
|
102
102
|
|
|
103
103
|
/* The exception the guard above is scoped around: a page holding pinned or
|
|
104
104
|
bleed art must not clip it. `.gp-behind` is included because it is pinned
|
|
105
|
-
art by another name (a `.gp-pin` that paints under the text).
|
|
106
|
-
|
|
105
|
+
art by another name (a `.gp-pin` that paints under the text). The two
|
|
106
|
+
full-sheet plates are bleed art too: `.dc-specialty-art` and
|
|
107
|
+
`.dc-full-page` are sheet-wide on their zero-margin `full` page while the
|
|
108
|
+
`.page` around them keeps the body column's width, so the guard cut them
|
|
109
|
+
off at the column edge — a 100pt strip of bare wall down the outside of
|
|
110
|
+
every specialty plate on a page with no other pinned art (design guide
|
|
111
|
+
p.45, p.105). The Field Guide escaped only because its specialty pages
|
|
112
|
+
also carry pinned art. */
|
|
113
|
+
.page:is(:has(.gp-bleed), :has(.gp-pin), :has(.gp-behind),
|
|
114
|
+
:has(.dc-specialty-art), :has(.dc-full-page)) {
|
|
107
115
|
overflow-x: visible;
|
|
108
116
|
}
|
|
109
117
|
|
|
@@ -317,7 +325,7 @@
|
|
|
317
325
|
inside the composite.
|
|
318
326
|
|
|
319
327
|
This block is the SINGLE location where TOC and Credits styling lives —
|
|
320
|
-
do not split it across the book's own sheet
|
|
328
|
+
do not split it across the book's own sheet. */
|
|
321
329
|
|
|
322
330
|
/* Identity tokens for the spread. --dc-intro-accent / --dc-intro-bg feed
|
|
323
331
|
the .dc-intro component's gradient via its own var() fallback chain. */
|
|
@@ -537,6 +545,28 @@
|
|
|
537
545
|
break-inside: auto;
|
|
538
546
|
}
|
|
539
547
|
|
|
548
|
+
/* The learning-path BANNER (the shell: title, intro, sticker row) is never
|
|
549
|
+
split and stays on the page of the first card after it. Note the rule
|
|
550
|
+
above does NOT do this: Chromium does not support `break-before: always`
|
|
551
|
+
and drops the declaration (measured by the Field Guide). Targets the
|
|
552
|
+
shell, not .dc-learning-path, which usually also holds the path's cards.
|
|
553
|
+
Without it the design guide printed the Biting Distance banner alone on
|
|
554
|
+
a page, with the edge of the first card's tab at the page foot. Carried
|
|
555
|
+
from the Field Guide's own sheet, where it is measured; the Field Guide
|
|
556
|
+
renders pixel-identical with it here. */
|
|
557
|
+
.dc-specialty .dc-path-shell {
|
|
558
|
+
break-inside: avoid;
|
|
559
|
+
break-after: avoid;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/* A banner that opens a page sits flush with its top. Chromium drops the
|
|
563
|
+
shell's 8px top margin at every unforced break but keeps it after the
|
|
564
|
+
forced break that ends a specialty's art page — and those 8px were all
|
|
565
|
+
that kept the first card off its banner's page. */
|
|
566
|
+
.dc-specialty > .dc-learning-path:first-child > .dc-path-shell {
|
|
567
|
+
margin-top: 0;
|
|
568
|
+
}
|
|
569
|
+
|
|
540
570
|
/* ── PAGE TEMPLATE: INTRO (chapter intro / narrative entry) ─────────────────
|
|
541
571
|
KEEPS the default .dc-chevron heading styling (magenta banner with its
|
|
542
572
|
own bottom-right diagonal clip-path) — that's the established intro
|
|
@@ -552,21 +582,18 @@
|
|
|
552
582
|
- Section gets a clean paper-cream substrate with the same 4px
|
|
553
583
|
magenta left rail as the lede; rail runs continuously through
|
|
554
584
|
both.
|
|
555
|
-
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
MEMORY R8: composite shadows via filter:drop-shadow on the
|
|
562
|
-
common wrapper.
|
|
585
|
+
- Vector shadows, per element: the lede and section each carry
|
|
586
|
+
--shadow-poster; the clipped chevron carries none. This was ONE
|
|
587
|
+
`filter: drop-shadow()` on the .page wrapper, which Chromium
|
|
588
|
+
prints as a bitmap — the whole intro page went to the PDF as a
|
|
589
|
+
300ppi image with a soft mask (no live text; PDF/X-1a forbids the
|
|
590
|
+
mask).
|
|
563
591
|
|
|
564
592
|
--intro-accent is the single recolor knob, mirroring --frontmatter-
|
|
565
593
|
accent's role on the TOC/Credits template. */
|
|
566
594
|
.page.page-intro {
|
|
567
595
|
--intro-accent: var(--brand-magenta-deep);
|
|
568
596
|
--dc-intro-accent: var(--intro-accent);
|
|
569
|
-
filter: drop-shadow(var(--shadow-poster));
|
|
570
597
|
}
|
|
571
598
|
|
|
572
599
|
/* Chevron geometry on the standalone intro page. This page is NOT a
|
|
@@ -591,20 +618,18 @@
|
|
|
591
618
|
}
|
|
592
619
|
|
|
593
620
|
/* Lede flush-attaches to the chevron above; bottom margin zeroed so
|
|
594
|
-
the next sibling .section sits flush below.
|
|
595
|
-
|
|
621
|
+
the next sibling .section sits flush below. It keeps the component's
|
|
622
|
+
own --shadow-poster. */
|
|
596
623
|
.page.page-intro .dc-intro {
|
|
597
624
|
margin-bottom: 0;
|
|
598
625
|
padding-bottom: 0;
|
|
599
|
-
box-shadow: none;
|
|
600
626
|
}
|
|
601
627
|
.page.page-intro .dc-intro > :last-child {
|
|
602
628
|
margin-bottom: 0;
|
|
603
629
|
}
|
|
604
630
|
|
|
605
631
|
/* Section content — paper-cream substrate, magenta 4px left rail
|
|
606
|
-
continuing from the lede
|
|
607
|
-
the composite shadow. */
|
|
632
|
+
continuing from the lede, with the poster shadow. */
|
|
608
633
|
.page.page-intro > .section {
|
|
609
634
|
background: linear-gradient(
|
|
610
635
|
to right,
|
|
@@ -612,7 +637,7 @@
|
|
|
612
637
|
var(--paper-cream) 4px
|
|
613
638
|
);
|
|
614
639
|
padding: 0.18in 0.22in;
|
|
615
|
-
box-shadow:
|
|
640
|
+
box-shadow: var(--shadow-poster);
|
|
616
641
|
}
|
|
617
642
|
|
|
618
643
|
/* Suppress the .section base ::before (magenta gradient + 18px top-right
|