gp-dimm-city 1.0.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/LICENSE +32 -0
  3. package/README.md +165 -0
  4. package/components.yaml +832 -0
  5. package/fonts/lixdu/LICENSE.txt +34 -0
  6. package/fonts/lixdu/lixdu.woff +0 -0
  7. package/fonts/titillium-web/OFL.txt +93 -0
  8. package/fonts/titillium-web/titillium-web-400-italic.ttf +0 -0
  9. package/fonts/titillium-web/titillium-web-400.ttf +0 -0
  10. package/fonts/titillium-web/titillium-web-600-italic.ttf +0 -0
  11. package/fonts/titillium-web/titillium-web-600.ttf +0 -0
  12. package/fonts/titillium-web/titillium-web-700-italic.ttf +0 -0
  13. package/fonts/titillium-web/titillium-web-700.ttf +0 -0
  14. package/fonts/tomorrow/OFL.txt +93 -0
  15. package/fonts/tomorrow/tomorrow-400-italic.ttf +0 -0
  16. package/fonts/tomorrow/tomorrow-400.ttf +0 -0
  17. package/fonts/tomorrow/tomorrow-500-italic.ttf +0 -0
  18. package/fonts/tomorrow/tomorrow-500.ttf +0 -0
  19. package/fonts/tomorrow/tomorrow-700-italic.ttf +0 -0
  20. package/fonts/tomorrow/tomorrow-700.ttf +0 -0
  21. package/images/brick-bg-01.png +0 -0
  22. package/package.json +78 -0
  23. package/plugin.js +2131 -0
  24. package/snippets/alert.md +2 -0
  25. package/snippets/block.md +5 -0
  26. package/snippets/callout.md +5 -0
  27. package/snippets/card.md +11 -0
  28. package/snippets/chapter-start-page.md +11 -0
  29. package/snippets/credits-page.md +13 -0
  30. package/snippets/definition.md +7 -0
  31. package/snippets/dm-note.md +5 -0
  32. package/snippets/gear.md +9 -0
  33. package/snippets/learning-path.md +10 -0
  34. package/snippets/lede.md +5 -0
  35. package/snippets/outcome.md +8 -0
  36. package/snippets/procedure.md +7 -0
  37. package/snippets/sidebar.md +7 -0
  38. package/snippets/skill.md +9 -0
  39. package/snippets/specialty-art.md +5 -0
  40. package/snippets/specialty-card.md +5 -0
  41. package/snippets/specialty.md +11 -0
  42. package/snippets/toc-page.md +15 -0
  43. package/styles/components/callouts.css +227 -0
  44. package/styles/components/cards.css +487 -0
  45. package/styles/components/chrome.css +483 -0
  46. package/styles/components/data.css +1026 -0
  47. package/styles/components/images.css +215 -0
  48. package/styles/components/section.css +1074 -0
  49. package/styles/components/specialty-identity.css +315 -0
  50. package/styles/components/specialty.css +273 -0
  51. package/styles/dc-component-defaults.css +214 -0
  52. package/styles/dc-core.css +268 -0
  53. package/styles/dc-fonts.css +107 -0
  54. package/styles/dc-identity.css +66 -0
  55. package/styles/dc-native.css +330 -0
  56. package/styles/dc-palette.css +198 -0
  57. package/styles/page-rules.css +207 -0
  58. package/styles/page-templates.css +636 -0
@@ -0,0 +1,1026 @@
1
+ @layer dc.components {
2
+
3
+ /* ── Learning path structural + path shell + title overrides ──────────── */
4
+ .dc-learning-path.dc-path-block {
5
+ --dc-path-accent: var(--crimson);
6
+ position: relative;
7
+ /* margin-bottom here is a no-op: .dc-path-block has no padding/border, so
8
+ this margin collapses with .dc-path-shell's own (larger) margin-bottom
9
+ below and never renders — every measured card-to-next-sibling gap in
10
+ the book is exactly the shell's 20px, never this 10px. The shell is
11
+ the value that actually controls spacing; see its comment. */
12
+ margin: 0 0 10px;
13
+ break-before: auto;
14
+ break-after: auto;
15
+ }
16
+
17
+ /* Token defaults for .dc-path-shell are declared in :root in dc-component-defaults.css.
18
+ Specialty contexts override via .dc-specialty.<name> .dc-path-shell { } above. */
19
+ .dc-path-shell {
20
+ /* Surface + clip-path are on ::before and the ink outline on ::after (the
21
+ two-pseudo pattern of .section, and of .dc-card-body inside a skill
22
+ card): an element with clip-path clips its own pseudos, so the outline
23
+ has to be a sibling layer of the clipped one. */
24
+ background: transparent;
25
+ /* --dc-card-gap is the VISIBLE gap; +4px clears chrome bleed on top of it
26
+ (this shell's ink outline paints 2px below its box — no poster-shadow
27
+ component here — and the next element's top ink-outline bleeds 2px up).
28
+ Unlike .dc-skill-card, no book-wide instance of this touching was found;
29
+ every live path→card seam already cleared, so this is added breathing
30
+ room rather than a defect fix. */
31
+ margin: 8px 8px calc(var(--dc-card-gap) + 4px);
32
+ padding-top: var(--dc-path-shell-padding-top);
33
+ padding-bottom: var(--dc-path-shell-padding-bottom);
34
+ /* Room for `.dc-spray::before`, the skewed tab pinned at `right: -8px` with
35
+ `width: 14px`. Without it that decoration escapes this shell (measured:
36
+ scrollWidth 394 vs clientWidth 384) and, with nothing clipping it, escapes
37
+ the document — at which point Chromium's native print widens its layout
38
+ past the page content box (696 -> 697 CSS px, read as an exact vector rect
39
+ out of the PDF). One pixel is enough to re-break a line: a paragraph sets
40
+ in 3 lines instead of 4 and the page count changes, while the on-screen
41
+ viewer keeps the spec-correct 696 and disagrees with the PDF.
42
+
43
+ This replaces a blanket `.chapter { overflow-x: clip }` that contained the
44
+ same overflow bluntly — and, as a side effect, clipped every full-bleed
45
+ plate back to the content box. Giving the decoration room keeps it fully
46
+ visible; clipping it here would work too but would cut the tab. */
47
+ padding-right: 12px;
48
+ position: relative;
49
+ /* Both pseudos sit at negative z-index; this is the stacking context that
50
+ keeps them behind THIS shell's content instead of behind the page. The
51
+ 4-way drop-shadow filter that used to be here supplied it implicitly —
52
+ and rasterized all 32 shells and their prose on every build (dc#28). */
53
+ isolation: isolate;
54
+ }
55
+
56
+ /* Background + clip-path on ::before — the element itself stays unclipped so
57
+ the ::after outline can reach outside the silhouette, same as .dc-skill-card.
58
+ Substrate behind the content, not under a lift — same reasoning as
59
+ `.section::before`; see the containing-block note there. The host is a
60
+ stacking context (isolation: isolate), so -1 stays inside this component. */
61
+ .dc-path-shell::before {
62
+ content: '';
63
+ position: absolute;
64
+ inset: 0;
65
+ background: linear-gradient(to right, var(--dc-path-accent) 4px, var(--paper-cream) 4px);
66
+ clip-path: var(--dc-path-shell-clip);
67
+ z-index: -1;
68
+ }
69
+
70
+ /* 2px ink outline: the shell shape on a box 2px larger on every side, filled
71
+ with ink, behind the surface. Replaces the 4-way drop-shadow(±2px) filter.
72
+ The title (h2.dc-spray) is an in-flow child with its own clip and no
73
+ outline of its own, so every shell cut equals its title cut at the corner
74
+ the title covers (specialty-identity.css, "Title-covered corners").
75
+ The box starts AT the shell's top and is translated up 2px: a shell that
76
+ opens a page (its top margin truncated at the break) would otherwise have
77
+ Chromium push the outline box down to the page's content area, 2px low —
78
+ see .dc-specialty-intro::after. */
79
+ .dc-path-shell::after {
80
+ content: '';
81
+ position: absolute;
82
+ top: 0;
83
+ right: -2px;
84
+ bottom: -4px;
85
+ left: -2px;
86
+ transform: translateY(-2px);
87
+ background: var(--ink);
88
+ clip-path: var(--dc-path-shell-clip);
89
+ z-index: -2;
90
+ }
91
+
92
+ /* Within a .dc-specialty parent (the canonical wrapper around path-shell +
93
+ skill cards), tighten path-shell padding tokens. Belongs here, not in
94
+ the book's own sheet — every DC project that uses the specialty system needs
95
+ this default. */
96
+ .dc-specialty .dc-path-shell {
97
+ --dc-path-shell-padding-top: 0;
98
+ --dc-path-shell-padding-bottom: 16px;
99
+ }
100
+
101
+ .dc-path-shell>h2.dc-spray {
102
+ width: stretch;
103
+ }
104
+
105
+ .dc-path-shell>h2.dc-spray:first-child {
106
+ color: var(--dc-path-title-color);
107
+ background: var(--dc-path-title-bg);
108
+ clip-path: var(--dc-path-title-shape);
109
+ margin-bottom: 12px;
110
+ padding: 10px 16px 12px;
111
+ font-size: 18px;
112
+ break-after: avoid;
113
+ border-bottom: none;
114
+ padding-bottom: 0;
115
+ }
116
+
117
+ .dc-path-shell>h2.dc-spray:first-child + * {
118
+ break-before: avoid;
119
+ }
120
+
121
+ .dc-path-shell>h2.dc-spray:first-child::before {
122
+ background: var(--dc-path-title-bg);
123
+ right: -5px;
124
+ }
125
+
126
+ .dc-path-shell>h2.dc-spray:first-child::after {
127
+ content: '';
128
+ position: absolute;
129
+ left: 0;
130
+ right: 0;
131
+ bottom: 0;
132
+ height: 3px;
133
+ background: var(--hud-magenta);
134
+ opacity: 1;
135
+ width: auto;
136
+ }
137
+
138
+ .dc-path-shell>p,
139
+ .dc-path-shell>div,
140
+ .dc-path-shell>div.dc-intro {
141
+ margin-inline: var(--space-sm);
142
+ padding-top: 6px;
143
+ padding-bottom: 6px;
144
+ }
145
+
146
+ /* ═══ OUTCOMES + STEPS + DISTANCE ═══ */
147
+
148
+ /* ── Procedure / numbered steps ───────────────────────────────────────── */
149
+ .dc-steps {
150
+ list-style: none;
151
+ padding: 0 0 0 12px;
152
+ margin: 8px 0;
153
+ border-left: 2px solid var(--hud-blue-dim);
154
+ break-inside: avoid;
155
+ }
156
+
157
+ .dc-steps>li {
158
+ display: grid;
159
+ grid-template-columns: 48px 1fr;
160
+ gap: 14px;
161
+ padding: 8px 0 8px 2px;
162
+ border-top: 1px dashed var(--paper-aged);
163
+ font-family: var(--font-body);
164
+ font-size: 9pt;
165
+ line-height: 1.5;
166
+ color: var(--ink);
167
+ align-items: baseline;
168
+ }
169
+
170
+ .dc-steps>li:first-child {
171
+ border-top: 0;
172
+ padding-top: 0;
173
+ }
174
+
175
+ .dc-steps>li::before {
176
+ content: none;
177
+ }
178
+
179
+ /* defang any inherited bullets */
180
+ .dc-steps .dc-step-no {
181
+ font-family: var(--font-mono);
182
+ font-weight: 700;
183
+ font-size: 13px;
184
+ letter-spacing: 2px;
185
+ color: var(--hud-blue-dark);
186
+ line-height: 1;
187
+ align-self: center;
188
+ }
189
+
190
+ .dc-steps li strong {
191
+ /* --crimson 4.03:1 on paper-cream → --blood 7.73:1 */
192
+ color: var(--blood);
193
+ font-weight: 700;
194
+ }
195
+
196
+ /* ── Outcome ladder ───────────────────────────────────────────────────────
197
+ Token contract:
198
+ --dc-outcomes-surface → body fill (default --paper-cream)
199
+ --dc-outcomes-border → outer frame color (default --ink)
200
+ --dc-outcomes-inner-border → inset hairline color (default --paper-aged)
201
+ --dc-outcomes-label-color → label text color (default --hud-blue)
202
+ --dc-outcomes-divider → label underline + row dividers (default --hud-blue-dim)
203
+ */
204
+ .dc-outcomes {
205
+ margin: 8px 0;
206
+ border: 2px solid var(--dc-outcomes-border);
207
+ background: var(--dc-outcomes-surface);
208
+ position: relative;
209
+ break-inside: avoid;
210
+ }
211
+
212
+ .dc-outcomes::after {
213
+ content: '';
214
+ position: absolute;
215
+ inset: 4px;
216
+ border: 1px solid var(--dc-outcomes-inner-border);
217
+ pointer-events: none;
218
+ }
219
+
220
+ .dc-outcomes-label {
221
+ font-family: var(--font-mono);
222
+ /* Bumped 8px → 10px and switched to ink-on-paper-aged chip styling
223
+ per user feedback: "The outcome header is kind of bland". Now
224
+ reads as a stamped header bar with its own surface rather than
225
+ a tiny label hovering above the chips. */
226
+ font-size: 10px;
227
+ font-weight: 700;
228
+ letter-spacing: 0.18em;
229
+ text-transform: uppercase;
230
+ color: var(--dc-outcomes-label-color);
231
+ background: var(--dc-outcomes-label-bg);
232
+ padding: 6px 14px 5px;
233
+ border-bottom: 2pt solid var(--dc-outcomes-divider);
234
+ position: relative;
235
+ z-index: 1;
236
+ }
237
+
238
+ .dc-outcome-row {
239
+ display: grid;
240
+ grid-template-columns: 130px 1fr;
241
+ gap: 0;
242
+ border-bottom: 1px solid var(--dc-outcomes-divider);
243
+ position: relative;
244
+ z-index: 1;
245
+ }
246
+
247
+ .dc-outcome-row:last-child {
248
+ border-bottom: 0;
249
+ }
250
+
251
+ .dc-outcome-key {
252
+ /* Inner top-highlight + bottom-shadow simulates ink density — the chip reads
253
+ as a "pressed-in" element rather than a flat color sticker. The 1px white
254
+ highlight at the top is the single most-recognisable signal designers use
255
+ to make a fill feel "lifted from above". */
256
+ background:
257
+ linear-gradient(180deg,
258
+ color-mix(in srgb, var(--row-color, var(--ink)) 92%, #fff 8%) 0%, /* PDF/X-1a: pre-composite to ~92% ink + 8% white; on --ink (#1a1512) → #2d2926; on Ingram submission replace with static opaque value in dc-tokens-print.css */
259
+ var(--row-color, var(--ink)) 50%,
260
+ color-mix(in srgb, var(--row-color, var(--ink)) 96%, #000 4%) 100%); /* PDF/X-1a: pre-composite to ~96% ink + 4% black; on --ink (#1a1512) → #191411; on Ingram submission replace with static opaque value in dc-tokens-print.css */
261
+ box-shadow:
262
+ inset 0 1px 0 rgba(255, 255, 255, 0.12),
263
+ inset 0 -1px 0 rgba(0, 0, 0, 0.18);
264
+ /* Use the token so .dc-outcome-row.hit (which sets --dc-outcome-key-color
265
+ to --ink because the fungi-glow fill is too light for cream text — was
266
+ 1.24:1) actually propagates to the chip element itself, not just to its
267
+ children. Default stays cream for the dark-fill outcomes (crit/miss/fail). */
268
+ color: var(--dc-outcome-key-color);
269
+ padding: 6px 10px;
270
+ display: flex;
271
+ flex-direction: column;
272
+ align-items: center;
273
+ justify-content: center;
274
+ gap: 3px;
275
+ }
276
+
277
+ .dc-outcome-name {
278
+ font-family: var(--font-mono);
279
+ font-size: 9px;
280
+ font-weight: 400;
281
+ letter-spacing: 0.10em;
282
+ text-transform: uppercase;
283
+ color: var(--dc-outcome-name-color);
284
+ opacity: var(--dc-outcome-name-opacity);
285
+ line-height: 1;
286
+ }
287
+
288
+ .dc-outcome-key .dc-outcome-roll {
289
+ font-family: var(--font-display);
290
+ font-size: 16px;
291
+ font-weight: 700;
292
+ letter-spacing: 0.03em;
293
+ color: var(--dc-outcome-key-color);
294
+ opacity: 1;
295
+ display: block;
296
+ line-height: 1;
297
+ white-space: nowrap;
298
+ order: -1;
299
+ }
300
+
301
+ .dc-outcome-text {
302
+ padding: 8px 12px;
303
+ font-family: var(--font-body);
304
+ font-size: 8.5pt;
305
+ line-height: 1.55;
306
+ color: var(--ink);
307
+ align-self: center;
308
+ /* Container rule tethers the result text to its row color — without it the
309
+ right-column text floats on plain paper-cream with no visual tie back to
310
+ the row band, reading as untether'd prose next to a designed table.
311
+ Reads `--row-color` which is set per-variant on .dc-outcome-row.X. */
312
+ border-left: 2px solid var(--row-color, var(--ink-dust));
313
+ }
314
+
315
+ /* ── Outcome row color modifiers ──────────────────────────────────────────
316
+ Creaturepunk pillar gradient across the 5-band outcome ladder:
317
+ crit → brand-magenta-deep (NEON peak, jewel-deep — paper-cream 6.21:1)
318
+ hit → fungi-glow + ink (FLUORESCENT FUNGI alive — ink-on-glow 12.24:1)
319
+ mixed → orange-deep (GUTTER warm, burnt-deep — paper-cream 5.25:1)
320
+ miss → rust (GUTTER deep — paper-cream 4.59:1)
321
+ fail → fungi-rot (FLUORESCENT FUNGI dark — paper-cream 8.73:1)
322
+ All four creaturepunk pillars present; all 5 rows clear WCAG AA 4.5:1
323
+ for 9px outcome-name and 12pt roll-number text.
324
+
325
+ The hit row uses --row-text-color override because fungi-glow is too
326
+ light to carry paper-cream text (1.13:1 fail). Bright row + dark text
327
+ preserves the bioluminescent signal while keeping labels press-legible. */
328
+ .dc-outcome-row.crit {
329
+ --row-color: var(--brand-magenta-deep);
330
+ }
331
+
332
+ .dc-outcome-row.hit {
333
+ --row-color: var(--fungi-glow);
334
+ --dc-outcome-name-color: var(--ink);
335
+ --dc-outcome-key-color: var(--ink);
336
+ }
337
+
338
+ .dc-outcome-row.mixed {
339
+ --row-color: var(--orange-deep);
340
+ }
341
+
342
+ .dc-outcome-row.miss {
343
+ /* --rust + cream = 4.48:1 (just under AA at small chip text). --blood
344
+ + cream = 7.73:1, safer at 9-10pt chip sizes. Still warm red, still
345
+ reads as "miss/fail" semantic. */
346
+ --row-color: var(--blood);
347
+ }
348
+
349
+ .dc-outcome-row.fail {
350
+ --row-color: var(--fungi-rot);
351
+ }
352
+
353
+ /* ── Distance tags (AP cost × distance block) ─────────────────────────── */
354
+ .dc-distance-tags {
355
+ display: flex;
356
+ flex-wrap: wrap;
357
+ gap: 6px;
358
+ margin: 10px 0;
359
+ }
360
+
361
+ /* Token contract for distance-tag pills:
362
+ --dc-dist-tag-surface → cell bg (default --paper-light)
363
+ --dc-dist-tag-border → cell border color (default --hud-blue-dim)
364
+ --dc-dist-ap-color → AP-cost number color (default --ink)
365
+ --dc-dist-name-color → distance-name caption color (default --hud-blue)
366
+ */
367
+ .dc-dist-tag {
368
+ display: inline-flex;
369
+ flex-direction: column;
370
+ align-items: center;
371
+ background: var(--dc-dist-tag-surface);
372
+ border: 1px solid var(--dc-dist-tag-border);
373
+ padding: 6px 10px;
374
+ min-width: 52px;
375
+ }
376
+
377
+ .dc-dist-ap {
378
+ font-family: var(--font-display);
379
+ font-size: 14px;
380
+ font-weight: 700;
381
+ color: var(--dc-dist-ap-color);
382
+ line-height: 1;
383
+ }
384
+
385
+ .dc-dist-name {
386
+ font-family: var(--font-mono);
387
+ font-size: 8px;
388
+ letter-spacing: 0.12em;
389
+ text-transform: uppercase;
390
+ color: var(--dc-dist-name-color);
391
+ margin-top: 3px;
392
+ }
393
+
394
+ /* ───────── LUCID / SURREAL ROLL VARIANTS ───────── */
395
+ .dc-roll-lucid,
396
+ .dc-roll-surreal {
397
+ font-family: var(--font-tab);
398
+ font-size: 0.75em;
399
+ font-weight: 600;
400
+ text-transform: uppercase;
401
+ letter-spacing: 0.06em;
402
+ }
403
+
404
+ /* --dc-roll-lucid-color (default --hud-blue-dark) */
405
+ .dc-roll-lucid {
406
+ color: var(--dc-roll-lucid-color);
407
+ }
408
+
409
+ .dc-roll-lucid::before {
410
+ content: '◈ ';
411
+ opacity: 1;
412
+ }
413
+
414
+ /* --dc-roll-surreal-color (default --hud-magenta) */
415
+ .dc-roll-surreal {
416
+ color: var(--dc-roll-surreal-color);
417
+ }
418
+
419
+ .dc-roll-surreal::before {
420
+ content: '∿ ';
421
+ opacity: 1;
422
+ }
423
+
424
+ /* ───────── PULL-QUOTE ───────── */
425
+ .dc-pullquote {
426
+ background: var(--dc-pullquote-bg);
427
+ border-left: 5px solid var(--dc-pullquote-accent);
428
+ border-right: 2px solid var(--dc-pullquote-accent-soft);
429
+ padding: 14px 20px 12px 28px;
430
+ position: relative;
431
+ font-family: var(--font-body);
432
+ font-style: italic;
433
+ font-size: var(--fs-h2);
434
+ line-height: 1.3;
435
+ color: var(--ink-dark);
436
+ letter-spacing: -0.01em;
437
+ margin: 18px 0;
438
+ break-inside: avoid;
439
+ }
440
+
441
+ .dc-pullquote::before {
442
+ /* User RE-REQUESTED these accent marks: "I noticed the accent marks
443
+ from the pull quote have disappeared. That was one of my favorite
444
+ accents. I don't know why that was removed." They were removed
445
+ earlier because of an over-decoration concern; turns out the user
446
+ wanted them. Restored. Tightened size slightly (was 56px, now 48px)
447
+ to reduce duplication with literal quotes in body text without
448
+ removing the accent entirely. */
449
+ content: '"';
450
+ position: absolute;
451
+ top: -6px;
452
+ left: 10px;
453
+ font-family: var(--font-display);
454
+ font-size: 48px;
455
+ color: var(--hud-magenta);
456
+ opacity: 0.55;
457
+ line-height: 1;
458
+ }
459
+
460
+ .dc-pullquote p {
461
+ margin: 0;
462
+ }
463
+
464
+ .dc-pullquote p+p {
465
+ margin-top: 10px;
466
+ }
467
+
468
+ /* ───────── PROSE PANEL BASE ───────── */
469
+ .dc-prose-panel {
470
+ padding: 10px 14px;
471
+ margin: 0.12in 0;
472
+ break-inside: avoid;
473
+ }
474
+
475
+ /* ───────── DEFINITION BLOCK ─────────
476
+ Token contract:
477
+ --dc-definition-block-surface → block background (default --surface-orange-tint)
478
+ --dc-definition-block-accent → left rail color (default --hud-blue-bright)
479
+ --dc-definition-block-accent-width → left rail weight (default 4px)
480
+ Per-section / per-column overrides set the tokens; they don't override
481
+ the properties directly. */
482
+ .dc-definition-block {
483
+ background: var(--dc-definition-block-surface);
484
+ border-left: var(--dc-definition-block-accent-width) solid var(--dc-definition-block-accent);
485
+ font-style: italic;
486
+ font-size: var(--fs-body);
487
+ line-height: var(--lh-normal);
488
+ color: var(--ink);
489
+ /* Added per user feedback: "text inside that section is pushed against
490
+ the left edge and potentially the right edge of the section." The
491
+ definition block had no internal padding so prose touched the box
492
+ edges. 9pt top/bottom + 12pt left/right gives prose breathing room
493
+ from the colored rail and right edge. */
494
+ padding: 9pt 12pt 9pt 14pt;
495
+ }
496
+
497
+ .dc-definition-block p {
498
+ margin: 0;
499
+ }
500
+
501
+ .dc-definition-block p+p {
502
+ margin-top: 6pt;
503
+ }
504
+
505
+ /* ───────── SIDEBAR BOX ─────────
506
+ Token contract:
507
+ --dc-sidebar-box-surface → background (default --paper-cream)
508
+ --dc-sidebar-box-border → frame border color (default --border-hairline)
509
+ --dc-sidebar-box-accent → left rail + heading + divider (default --hud-blue-dark)
510
+ --dc-sidebar-box-rail → left rail width (default 4px)
511
+ Override via the book's own sheet selector chain, e.g.:
512
+ .dc-danger .dc-sidebar-box { --dc-sidebar-box-accent: var(--blood); }
513
+ */
514
+ .dc-sidebar-box {
515
+ background: var(--dc-sidebar-box-surface);
516
+ border: 1.5px solid var(--dc-sidebar-box-border);
517
+ border-left: var(--dc-sidebar-box-rail) solid var(--dc-sidebar-box-accent);
518
+ }
519
+
520
+ /* Box heading — bold accent label above the internal divider */
521
+ .dc-sidebar-box>h3:first-child,
522
+ .dc-sidebar-box>h4:first-child {
523
+ font-size: var(--fs-h4);
524
+ letter-spacing: var(--ls-display);
525
+ color: var(--dc-sidebar-box-accent);
526
+ margin: 0 0 10px;
527
+ font-style: italic;
528
+ }
529
+
530
+ /* Internal dashed divider — separates the heading area from body content */
531
+ .dc-sidebar-box hr,
532
+ .dc-sidebar-box .dc-sidebar-box-divider {
533
+ border: none;
534
+ border-top: 1px dashed var(--dc-sidebar-box-accent);
535
+ margin: 7.5pt 0;
536
+ }
537
+
538
+ .dc-sidebar-box p {
539
+ margin: 0;
540
+ font-size: var(--fs-body-sm);
541
+ line-height: var(--lh-normal);
542
+ }
543
+
544
+ .dc-sidebar-box p+p {
545
+ margin-top: 6pt;
546
+ }
547
+
548
+ /* ───────── GEAR ENTRY — REMOVED 2026-08-21 ─────────
549
+ Two families of gear styling lived here and NEITHER could ever match:
550
+
551
+ .dc-gear-entry* — a manual-markup authoring path. No book
552
+ writes the class; it appears only in the
553
+ design guide's own documentation.
554
+ .section.dc-gear-list > .dc-card
555
+ — added 2026-06-21 to mirror the above for
556
+ the @gear macro, against a wrapper the
557
+ plugin does not emit. plugin.js
558
+ emits a bare `<div class="dc-card dc-gear">`
559
+ with no .section.dc-gear-list around it.
560
+
561
+ Net effect: `@gear` has always rendered as a plain .dc-card — no orange
562
+ left rule, no blood-red h3, no italic tagline — across all 48 uses. The
563
+ distinctive gear treatment is not "broken by a regression"; it never
564
+ printed.
565
+
566
+ To REVIVE it, style what the plugin actually emits (a design decision,
567
+ since it changes 48 cards):
568
+
569
+ .dc-card.dc-gear { margin: 0.1in 0; padding: 10pt 14pt;
570
+ background: var(--paper-light); border-left: 3pt solid var(--orange);
571
+ break-inside: avoid; }
572
+ .dc-card.dc-gear h3 { font-size: var(--fs-h4);
573
+ letter-spacing: var(--ls-display); color: var(--blood);
574
+ margin: 0 0 4px; break-after: avoid; }
575
+ .dc-card.dc-gear > p:first-of-type em:only-child,
576
+ .dc-card.dc-gear > p.dc-flavor:first-of-type { font-style: italic;
577
+ font-size: var(--fs-body-sm); color: var(--ink-smoke);
578
+ margin: 0 0 8px; display: block; }
579
+ ──────────────────────────────────────────────────────── */
580
+
581
+ /* ───────── STAT BLOCK (compact creature/NPC reference) ───────── */
582
+ .dc-stat {
583
+ background: var(--paper-cream);
584
+ border: 2px solid var(--ink);
585
+ padding: 14px 16px 16px;
586
+ position: relative;
587
+ margin: 18px 0;
588
+ break-inside: avoid;
589
+ }
590
+
591
+ .dc-stat::after {
592
+ content: '';
593
+ position: absolute;
594
+ inset: 4px;
595
+ border: 1px solid var(--paper-aged);
596
+ pointer-events: none;
597
+ }
598
+
599
+ .dc-stat-head {
600
+ display: flex;
601
+ justify-content: space-between;
602
+ align-items: baseline;
603
+ border-bottom: 2px solid var(--ink);
604
+ padding-bottom: 8px;
605
+ margin-bottom: 12px;
606
+ position: relative;
607
+ z-index: 1;
608
+ }
609
+
610
+ .dc-stat-name {
611
+ font-family: var(--font-tab);
612
+ font-size: 16px;
613
+ letter-spacing: 0.04em;
614
+ text-transform: uppercase;
615
+ color: var(--ink);
616
+ }
617
+
618
+ .dc-stat-class {
619
+ font-family: var(--font-mono);
620
+ font-size: 10px;
621
+ letter-spacing: 3px;
622
+ text-transform: uppercase;
623
+ color: var(--hud-blue);
624
+ }
625
+
626
+ .dc-stat-grid {
627
+ display: grid;
628
+ grid-template-columns: repeat(4, 1fr);
629
+ gap: 0;
630
+ margin-bottom: 10px;
631
+ position: relative;
632
+ z-index: 1;
633
+ }
634
+
635
+ .dc-stat-cell {
636
+ border-right: 1px dashed var(--paper-aged);
637
+ padding: 4px 8px 6px;
638
+ text-align: center;
639
+ display: flex;
640
+ flex-direction: column;
641
+ justify-content: center;
642
+ align-items: center;
643
+ gap: 2px;
644
+ }
645
+
646
+ .dc-stat-cell:last-child {
647
+ border-right: 0;
648
+ }
649
+
650
+ .dc-stat-cell-key {
651
+ font-family: var(--font-mono);
652
+ font-size: 9px;
653
+ letter-spacing: 3px;
654
+ text-transform: uppercase;
655
+ color: var(--hud-blue);
656
+ margin-bottom: 2px;
657
+ }
658
+
659
+ .dc-stat-cell-val {
660
+ font-family: var(--font-display);
661
+ font-size: 26px;
662
+ letter-spacing: 0.04em;
663
+ color: var(--orange);
664
+ line-height: 1;
665
+ min-width: 0;
666
+ overflow: hidden;
667
+ }
668
+
669
+ .dc-stat-line {
670
+ font-family: var(--font-body);
671
+ font-size: var(--fs-body-sm);
672
+ line-height: 1.45;
673
+ margin: 6px 0;
674
+ position: relative;
675
+ z-index: 1;
676
+ }
677
+
678
+ .dc-stat-line strong {
679
+ color: var(--crimson);
680
+ font-weight: 700;
681
+ }
682
+
683
+ /* ───────── TOC ───────── */
684
+ .dc-toc {
685
+ font-family: var(--font-body);
686
+ counter-reset: dc-toc;
687
+ /* Creaturepunk industrial card: paper substrate framed by rust strips
688
+ (top + bottom — "mechanical emphasis / AP / arrows" role per brand
689
+ guide) and hard --ink-dark side rails (heavy ink hard borders per
690
+ "Cards: Use hard borders and clipped corners"). The dual accent
691
+ stripes + ink side rails read as field-issued reference card, not
692
+ editorial design. Rubric: D9 brand identity per chapter, A2 token-
693
+ driven (per-project tints via tokens, not raw colors). */
694
+ background: var(--paper-cream);
695
+ padding: 0.18in 0.22in;
696
+ box-shadow: var(--shadow-poster);
697
+ border-top: 4pt solid var(--rust);
698
+ border-bottom: 4pt solid var(--rust);
699
+ border-left: 1.5pt solid var(--ink-dark);
700
+ border-right: 1.5pt solid var(--ink-dark);
701
+ }
702
+
703
+ .dc-toc ol {
704
+ list-style: none;
705
+ padding: 0;
706
+ margin: 0;
707
+ }
708
+
709
+ .dc-toc ol>li {
710
+ position: relative;
711
+ padding: 10px 4px 10px 56px;
712
+ border-bottom: 1px solid var(--hud-blue-dim);
713
+ counter-increment: dc-toc;
714
+ font-size: var(--fs-body-sm);
715
+ line-height: 1.4;
716
+ color: var(--ink-smoke);
717
+ font-style: italic;
718
+ list-style: none;
719
+ break-inside: avoid;
720
+ }
721
+
722
+ .dc-toc ol>li:last-child {
723
+ border-bottom: 0;
724
+ }
725
+
726
+ /* Number badge — reads as a stamped chip rather than plain mono text.
727
+ 42x22 boxed badge with rust fill + cream digits gives TOC entries a
728
+ designed start-of-row anchor instead of an underline-style number. */
729
+ .dc-toc ol>li::before {
730
+ content: counter(dc-toc, decimal-leading-zero);
731
+ position: absolute;
732
+ left: 0;
733
+ top: 10px;
734
+ width: 42px;
735
+ height: 22px;
736
+ display: flex;
737
+ align-items: center;
738
+ justify-content: center;
739
+ background: var(--rust);
740
+ color: var(--paper-cream);
741
+ font-family: var(--font-mono);
742
+ font-weight: 700;
743
+ font-size: 11px;
744
+ letter-spacing: 0.08em;
745
+ font-style: normal;
746
+ /* Small bottom-right corner cut so the badge reads as a stamp, not
747
+ a flat rectangle. */
748
+ clip-path: polygon(0 0, 100% 0, 100% calc(100% - 4px), calc(100% - 6px) 100%, 0 100%);
749
+ }
750
+
751
+ .dc-toc ol>li>strong {
752
+ color: var(--hud-blue-dark);
753
+ }
754
+
755
+ .dc-toc ol>li>a {
756
+ font-size: 15pt;
757
+ font-weight: 700;
758
+ letter-spacing: 0.03em;
759
+ color: var(--ink);
760
+ text-decoration: none;
761
+ border-bottom: 0;
762
+ font-style: normal;
763
+ }
764
+
765
+ .dc-toc ol>li>a::after {
766
+ content: ' p.' target-counter(attr(href), page);
767
+ font-family: var(--font-mono);
768
+ font-size: 10pt;
769
+ font-weight: 600;
770
+ letter-spacing: 1.5px;
771
+ color: var(--hud-blue);
772
+ font-style: normal;
773
+ margin-left: 0.6em;
774
+ white-space: nowrap;
775
+ }
776
+
777
+ .dc-toc-row {
778
+ display: flex;
779
+ align-items: baseline;
780
+ gap: 0;
781
+ padding: 10px 0;
782
+ border-bottom: 1px solid var(--hud-blue-dim);
783
+ }
784
+
785
+ .dc-toc .dc-toc-no {
786
+ font-family: var(--font-mono);
787
+ font-weight: 700;
788
+ font-size: 14px;
789
+ letter-spacing: 2px;
790
+ color: var(--hud-blue);
791
+ flex: 0 0 auto;
792
+ margin-right: 28px;
793
+ white-space: nowrap;
794
+ }
795
+
796
+ .dc-toc-title {
797
+ flex: 1 1 auto;
798
+ min-width: 0;
799
+ font-family: var(--font-body);
800
+ font-size: 13px;
801
+ font-weight: 600;
802
+ letter-spacing: 0.02em;
803
+ text-transform: none;
804
+ color: var(--ink);
805
+ }
806
+
807
+ .dc-toc-title small {
808
+ display: block;
809
+ font-family: var(--font-body);
810
+ font-size: var(--fs-body-sm);
811
+ font-style: italic;
812
+ letter-spacing: 0;
813
+ text-transform: none;
814
+ color: var(--ink-smoke);
815
+ margin-top: 2px;
816
+ }
817
+
818
+ .dc-toc-page {
819
+ flex: 0 0 auto;
820
+ margin-left: 18px;
821
+ font-family: var(--font-mono);
822
+ font-size: 11px;
823
+ letter-spacing: 2px;
824
+ color: var(--hud-blue);
825
+ font-weight: 600;
826
+ }
827
+
828
+ .dc-toc-page::before {
829
+ content: '— ';
830
+ color: var(--ink-dust);
831
+ font-weight: 400;
832
+ }
833
+
834
+ /* Cover-style chapter opener */
835
+ .dc-cover-page {
836
+ background: var(--hud-blue);
837
+ color: var(--paper-cream);
838
+ position: relative;
839
+ overflow: hidden;
840
+ }
841
+
842
+ .dc-cover-page .dc-cover-bg {
843
+ position: absolute;
844
+ inset: 0;
845
+ background:
846
+ radial-gradient(ellipse at 8% 10%, rgba(0, 0, 0, 0.55), transparent 62%),
847
+ radial-gradient(ellipse at 82% 88%, rgba(0, 0, 0, 0.30), transparent 55%),
848
+ radial-gradient(ellipse at 80% 18%, rgba(242, 77, 0, 0.14), transparent 50%),
849
+ radial-gradient(ellipse at 60% 55%, rgba(72, 164, 224, 0.16), transparent 60%),
850
+ var(--hud-blue);
851
+ }
852
+
853
+ .dc-cover-page .dc-cover-bg::after {
854
+ content: '';
855
+ position: absolute;
856
+ inset: 0;
857
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='4'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)' opacity='0.04'/%3E%3C/svg%3E");
858
+ }
859
+
860
+ /* HUD scanline overlay — horizontal lines at low opacity */
861
+ .dc-cover-page .dc-cover-bg::before {
862
+ content: '';
863
+ position: absolute;
864
+ inset: 0;
865
+ background-image: repeating-linear-gradient(to bottom,
866
+ transparent,
867
+ transparent 3px,
868
+ rgba(0, 0, 0, 0.04) 3px,
869
+ rgba(0, 0, 0, 0.04) 4px);
870
+ pointer-events: none;
871
+ }
872
+
873
+ .dc-cover-page>* {
874
+ position: relative;
875
+ z-index: 1;
876
+ }
877
+
878
+ .dc-cover-num {
879
+ font-family: var(--font-mono);
880
+ font-size: 11px;
881
+ letter-spacing: 6px;
882
+ text-transform: uppercase;
883
+ color: var(--hud-blue-dim);
884
+ margin-bottom: 18px;
885
+ }
886
+
887
+ .dc-cover-bigword {
888
+ font-family: var(--font-display);
889
+ /* Absolute, not vw: the cover word is sized against the sheet, and a
890
+ viewport unit in paged media has no stable meaning. */
891
+ font-size: 66pt;
892
+ line-height: 1.1;
893
+ letter-spacing: 0.06em;
894
+ text-transform: uppercase;
895
+ color: var(--orange);
896
+ margin: 0 0 16px;
897
+ word-break: break-word;
898
+ overflow-wrap: break-word;
899
+ }
900
+
901
+ .dc-cover-strap {
902
+ font-family: var(--font-body);
903
+ font-style: italic;
904
+ font-size: 14pt;
905
+ line-height: 1.4;
906
+ color: var(--paper-cream);
907
+ max-width: 24ch;
908
+ margin: 0 0 28px;
909
+ padding-left: 12px;
910
+ border-left: 3px solid var(--hud-magenta);
911
+ }
912
+
913
+ .dc-cover-meta-row {
914
+ display: grid;
915
+ grid-template-columns: repeat(3, 1fr);
916
+ gap: 14px;
917
+ margin-top: auto;
918
+ padding-top: 24px;
919
+ border-top: 1px solid var(--dc-cover-meta-border);
920
+ }
921
+
922
+ .dc-stat.dc-flush,
923
+ .dc-steps.dc-flush,
924
+ .dc-outcomes.dc-flush,
925
+ .dc-pullquote.dc-flush {
926
+ margin: 0;
927
+ }
928
+
929
+ /* Cover page layout override (flex column with more padding) */
930
+ .dc-cover-layout {
931
+ display: flex;
932
+ flex-direction: column;
933
+ padding: 60px 56px;
934
+ }
935
+
936
+ /* Cover body text */
937
+ .dc-cover-body {
938
+ font-family: var(--font-body);
939
+ font-size: var(--fs-body-xs);
940
+ line-height: 1.6;
941
+ color: var(--hud-blue-dim);
942
+ max-width: 46ch;
943
+ margin-bottom: auto;
944
+ }
945
+
946
+ /* When markdown wraps a list-item's text in a <p> (loose-list rendering),
947
+ the paragraph's block display + margins push the text below the marker.
948
+ Inline the paragraph so it flows directly after the bullet/number. */
949
+ .dc-skill-card li>p:only-child,
950
+ .dc-ability li>p:only-child {
951
+ display: inline;
952
+ margin: 0;
953
+ padding: 0;
954
+ }
955
+
956
+ .dc-card-body .dc-ability[data-ability-penultimate] {
957
+ break-after: avoid;
958
+ }
959
+
960
+ .dc-card-body .dc-ability[data-ability-last] {
961
+ break-before: avoid;
962
+ }
963
+
964
+ .dc-skill-card:only-child {
965
+ width: 100%;
966
+ max-width: 7.25in;
967
+ }
968
+
969
+ /* Universal card layout fixes — apply to any book using dc-skill-card. */
970
+
971
+ :is(.dc-skill-card, .dc-skill-card .dc-card-body) {
972
+ height: auto;
973
+ min-height: 0;
974
+ }
975
+
976
+ /* `.two-column-list` (this tombstone + the base one below + both real
977
+ rules in page-templates.css) is DELETED (2026-09-02) — 0 uses, 0
978
+ emissions; see page-templates.css's note at its old location. */
979
+
980
+ /* AP cell: prevent table-layout from over-allocating width to the cost
981
+ pill, which collapses the ability description column. */
982
+ .dc-ability ol li strong:first-of-type {
983
+ width: 1%;
984
+ white-space: nowrap;
985
+ word-break: keep-all;
986
+ overflow-wrap: normal;
987
+ }
988
+
989
+ /* .dc-img-wrapper: the plugin replaces p:has(img) with an explicit class */
990
+ p.dc-img-wrapper {
991
+ padding: 0;
992
+ margin: 0;
993
+ }
994
+
995
+ /* Native-print shrink-to-fit guard for content images. With `width: auto`,
996
+ an image's INTRINSIC width (these placards are 2000-3500px) feeds
997
+ Chromium's print preferred-width computation even though `max-width:
998
+ 100%` clamps the rendered box — and any preferred width past the page
999
+ content box makes native print scale the WHOLE book down (measured:
1000
+ `width: 100%` restores the uncompressed 79.7pt probe, `min-width: 0`
1001
+ alone does not). Scoped to UNCLASSED images in ANY paragraph wrapper (the bare markdown
1002
+ placards — including wrappers whose class the author set via attrs,
1003
+ which replaces dc-img-wrapper,
1004
+ which already render at container width, so this changes nothing
1005
+ visible): classed art images size themselves — some (fg-art-wall-feature,
1006
+ fg-art-vibe) derive width from an explicit height via aspect ratio, and a
1007
+ width here would distort them. `:where()` keeps specificity at (0,0,0)
1008
+ so any future contextual rule still wins. */
1009
+ :where(p) > :where(img:not([class])) {
1010
+ width: 100%;
1011
+ }
1012
+
1013
+ .dc-at-a-glance-cards {
1014
+ display: grid;
1015
+ grid-template-columns: repeat(3, 1fr);
1016
+ gap: 18px;
1017
+ margin: 0 0 18px;
1018
+ }
1019
+
1020
+ .dc-at-a-glance-card {
1021
+ background: var(--paper-light);
1022
+ border: 1px solid var(--paper-aged);
1023
+ padding: 14px 16px;
1024
+ }
1025
+
1026
+ }