gp-dimm-city 1.7.4 → 1.8.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,75 @@ cut a version that has no `## [X.Y.Z]` heading below.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.8.0] - 2026-10-15
11
+
12
+ ### Changed
13
+
14
+ - **Depth, recess and light, now that translucency prints.** Components get
15
+ a soft, translucent lift off the wall (`--shadow-lift`) under their hard
16
+ contact shadow: section panels (`--dc-section-lift`), path banners, skill
17
+ cards and specialty cards. The section's hard shadow and the skill-card and
18
+ `##` slip tape are translucent, so the brick reads through them. Recessed
19
+ things sink: the fiction excerpt's cavity and the `lore`/`dm`/`choose`
20
+ panels and title bars take a soft inset (`--shadow-press`). Title bands and
21
+ skill-card tabs carry a top gloss (`--light-gloss`). All of it is `box-shadow` and
22
+ gradients; a PDF/X build needs `pdfx.transparency: preserve-text`. A new
23
+ convention test allows `filter` only on a `::before`/`::after` layer:
24
+ Chromium prints the text of a filtered element as a picture.
25
+ - **A specialty card looks like its specialty's skill cards.** The card is
26
+ now that specialty's path banner as a sheet: the name on the specialty's
27
+ band colour, cut in the banner's title shape with its gloss and rule, and
28
+ a paper sheet with an ink outline in the banner's silhouette. The thick
29
+ top and left borders, the per-specialty card cut and the Augmerc override
30
+ are gone. Removed tokens: `--dc-specialty-card-border`,
31
+ `--dc-specialty-card-band-height`, `--dc-specialty-card-shadow`. New:
32
+ `--dc-specialty-card-band-bg`, `--dc-specialty-card-band-fg`,
33
+ `--dc-specialty-card-band-shape`, `--dc-specialty-card-pad-x`. A card's
34
+ portrait floats on its frame (the image wrapper) rather than on the image.
35
+ - **The specialty catalog spread closes each page with a full-width card.**
36
+ On `@page specialty-catalog`, Dualist spans both columns as the last row of
37
+ the left page and Generalist as the last row of the right page, whatever
38
+ order the book lists them in; the right page's other four cards are taller
39
+ with taller portraits. New tokens: `--dc-card-grid-item-span`,
40
+ `--dc-card-grid-item-order`, `--dc-card-grid-item-break`,
41
+ `--dc-card-grid-row-tall`, `--dc-card-grid-media-tall`,
42
+ `--dc-card-grid-media-wide`.
43
+
44
+ - **Needs Gutterpress 0.11.20-alpha.3 or later**, the first with PDF/X
45
+ `preserve-text`, which the translucent styles below print with. The
46
+ requirement is in `package.json`'s `engines.gutterpress`: a Gutterpress
47
+ that checks it (gutterpress#402) refuses to load this package and names the
48
+ version to update to. Older Gutterpress versions ignore the field.
49
+ - **Shadows and tints are translucent again, for books that opt in to
50
+ Gutterpress's `pdfx.transparency: preserve-text`** (Gutterpress #385). The
51
+ poster shadow (`--shadow-ink`, so the skill-card body shadow and the section
52
+ drop), the sticker and path-chip shadows, the rule divider, the spray smudge,
53
+ the pull-quote accent, and the AP-chip and outcome-key bevels are
54
+ `color-mix(…, transparent)` again instead of being pre-mixed onto one
55
+ surface, so a shadow on the brick wall darkens the brick instead of painting
56
+ a flat tone. The AP chip's soft `3px 3px 6px` shadow is back. Text colours
57
+ stay opaque: a translucent glyph prints fully opaque on a split page. The
58
+ wall tile stays opaque. `--wall-tone` is removed (nothing uses it). The
59
+ convention test *paint nothing transparent* becomes *keep text opaque*, and
60
+ its repeating-gradient check is kept as its own test.
61
+ - A book that keeps Gutterpress's default (`flatten-page`) and builds
62
+ PDF/X-1a gets more pages flattened to an image than with 1.7.2: set
63
+ `pdfx.transparency: preserve-text` in the book's manifest. Requires the
64
+ Gutterpress release that ships that option.
65
+ - **Lixdu is never faked bold.** Lixdu has one face, regular, but chapter
66
+ chips, folio chips, outcome rolls, block and card titles and headings asked
67
+ for a bold weight, so Chromium synthesized one, which prints as a Type 3
68
+ font that Gutterpress's PDF/X `preserve-text` split cannot keep. Every rule
69
+ that sets `--font-display` now sets `font-weight: 400` (a convention test
70
+ enforces it), and headings set `font-synthesis-weight: none` so `**bold**`
71
+ inside a heading prints in Lixdu's own stroke. That text is slightly thinner
72
+ than the synthetic bold.
73
+ - **A continuation card's tab draws its "continued" triangle** as a small
74
+ inline SVG in the title's colour, instead of a `▸` character. No Dimm City
75
+ font has that glyph, so Chromium borrowed one from a system font and printed
76
+ it as a Type 3 font; on the Field Guide that was the last one, and it made
77
+ its page fall back to whole-page flattening under `preserve-text`.
78
+
10
79
  ## [1.7.4] - 2026-10-15
11
80
 
12
81
  ### Changed
package/components.yaml CHANGED
@@ -423,7 +423,6 @@ components:
423
423
  - --dc-skill-body-shape
424
424
  - --dc-path-title-shape
425
425
  - --dc-path-shell-clip
426
- - --dc-specialty-card-shell-shape
427
426
  - --dc-specialty-intro-title-shape
428
427
  - --dc-specialty-intro-clip
429
428
  breaks: "none on the wrapper; children carry their own"
@@ -465,14 +464,16 @@ components:
465
464
  - styles/page-templates.css
466
465
  tokens:
467
466
  - --dc-specialty-card-bg
468
- - --dc-specialty-card-border
469
467
  - --dc-specialty-card-accent
470
468
  - --dc-specialty-card-fg
471
469
  - --dc-specialty-card-media-height
472
470
  - --dc-specialty-card-media-width
473
471
  - --dc-specialty-card-title-align
474
- - --dc-specialty-card-band-height
475
- - --dc-specialty-card-shadow
472
+ - --dc-specialty-card-band-bg
473
+ - --dc-specialty-card-band-fg
474
+ - --dc-specialty-card-band-shape
475
+ - --dc-specialty-card-shell-shape
476
+ - --dc-specialty-card-pad-x
476
477
  - --dc-specialty-card-title-color
477
478
  - --dc-specialty-card-display
478
479
  - --dc-specialty-card-media-order
@@ -648,8 +649,14 @@ components:
648
649
  - --dc-card-grid-item-display
649
650
  - --dc-card-grid-row
650
651
  - --dc-card-grid-gap
651
- breaks: "break-before: left (the spread opens on a left page, so its two pages face each other); the left page holds the title, the lede and four cards and the right page the other six (the row height, --dc-card-grid-row, sets the split)"
652
- notes: "The specialty catalog as a designed two-page spread: title and lede and the first four cards on the left, six cards on the right, in aligned rows of equal height (wrapped flex rows, not columns), each card a tall poster with its portrait on top. A location: it only sets tokens (the grid's flex layout, and the card's portrait, order, name size and index chip) and the page breaks. Whatever follows the grid starts on the next page: write a plain @page after @end-card-grid. The Variant Gallery's @card-grid, which sits on no such page, keeps the dense floated-thumbnail cards."
652
+ - --dc-card-grid-item-span
653
+ - --dc-card-grid-item-order
654
+ - --dc-card-grid-item-break
655
+ - --dc-card-grid-row-tall
656
+ - --dc-card-grid-media-tall
657
+ - --dc-card-grid-media-wide
658
+ breaks: "break-before: left (the spread opens on a left page, so its two pages face each other); the fifth card other than Dualist and Generalist opens the right page (--dc-card-grid-item-break: page)"
659
+ notes: "The specialty catalog as a designed two-page spread: title and lede and four cards on the left, four taller cards on the right, in aligned rows of equal height (wrapped flex rows, not columns), each card a poster with its portrait on top. Dualist and Generalist span both columns as the last row of the left and right page, as dense cards, whatever order the book lists them in. A location: it only sets tokens (the grid's flex layout, and the card's portrait, order, name size and index chip) and the page breaks. Whatever follows the grid starts on the next page: write a plain @page after @end-card-grid. The Variant Gallery's @card-grid, which sits on no such page, keeps the dense floated-thumbnail cards."
653
660
 
654
661
  - name: fiction-excerpt
655
662
  status: live
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gp-dimm-city",
3
- "version": "1.7.4",
3
+ "version": "1.8.0-alpha.2",
4
4
  "description": "Dimm City design system for Gutterpress: the markdown-it macros (@skill, @specialty, @learning-path, @callout, …), print stylesheets, design tokens, fonts and page templates the Dimm City TTRPG books are set in.",
5
5
  "type": "module",
6
6
  "main": "plugin.js",
@@ -73,6 +73,9 @@
73
73
  "gutterpress": "0.11.20-alpha.3",
74
74
  "markdown-it": "^14.1.0"
75
75
  },
76
+ "engines": {
77
+ "gutterpress": ">=0.11.20-alpha.3"
78
+ },
76
79
  "peerDependencies": {
77
80
  "markdown-it": ">=14"
78
81
  },
package/plugin.js CHANGED
@@ -113,6 +113,13 @@
113
113
  * (@end-learning-path, a new @learning-path, @end-specialty, @page, EOF).
114
114
  */
115
115
 
116
+ // The "continued" mark on a continuation card's tab: a drawn triangle, not a
117
+ // ▸ character. No Dimm City font has that glyph, so Chromium borrowed one
118
+ // from a system font and printed it as a Type 3 font, which Gutterpress's
119
+ // PDF/X preserve-text split cannot keep. It takes the tab title's colour.
120
+ const CONTINUED_MARK =
121
+ '<svg class="dc-tab-cont-mark" viewBox="0 0 6 8" aria-hidden="true"><path d="M0 0 6 4 0 8z" fill="currentColor"/></svg>';
122
+
116
123
  function esc(s) {
117
124
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;')
118
125
  .replace(/>/g, '&gt;').replace(/"/g, '&quot;');
@@ -952,7 +959,7 @@ function dcSkillCards(state) {
952
959
  emit(
953
960
  cardOpen(true) +
954
961
  ' <div class="dc-card-tab dc-card-tab-cont">\n' +
955
- ' <span class="dc-tab-title">' + esc(title.name) + ' ▸</span>\n' +
962
+ ' <span class="dc-tab-title">' + esc(title.name) + ' ' + CONTINUED_MARK + '</span>\n' +
956
963
  (title.tier ? ' <span class="dc-tab-tier">' + esc(title.tier) + '</span>\n' : '') +
957
964
  ' </div>\n' +
958
965
  ' <div class="dc-card-body">\n' +
@@ -72,7 +72,7 @@
72
72
  /* 18px right and 16px left clear the deepest tab cut (a specialty's
73
73
  --dc-skill-tab-shape, at most 15px) by more than 2pt. */
74
74
  padding: 3px 18px 3px 16px;
75
- background: var(--dc-card-tab-bg);
75
+ background: var(--light-gloss), var(--dc-card-tab-bg);
76
76
  border: 2px solid var(--dc-card-accent);
77
77
  border-bottom: 0;
78
78
  margin-left: 10px;
@@ -158,6 +158,14 @@
158
158
  text-wrap: wrap;
159
159
  }
160
160
 
161
+ /* The continuation tab's mark (plugin.js CONTINUED_MARK), sized to the
162
+ title's cap height. */
163
+ .dc-tab-cont-mark {
164
+ width: 0.45em;
165
+ height: 0.6em;
166
+ vertical-align: baseline;
167
+ }
168
+
161
169
  /* The tier pill (AUG1.3) is the specialty's own: a chip of its bright signal
162
170
  colour (cream with a dark edge where the signal fails 4.5:1 for the type),
163
171
  set by the --dc-tier-* tokens the specialty wiring fills (specialty-identity.css).
@@ -209,6 +217,7 @@
209
217
  background: transparent;
210
218
  clip-path: none;
211
219
  padding: 0;
220
+ box-shadow: var(--shadow-lift);
212
221
  }
213
222
 
214
223
  .dc-skill-card > .dc-card-body > .dc-card-inner {
@@ -351,11 +360,10 @@
351
360
  right: 18px;
352
361
  width: 34px;
353
362
  height: 11px;
354
- /* A strip of masking tape holding the card to the wall: an opaque flat tint
355
- of the card's mark colour on paper-aged, with a hard edge line, slightly
356
- rotated. It was a 2px hairline at 15% mark colour, which read as a stray
357
- scratch rather than as a deliberate cue. */
358
- background: color-mix(in srgb, var(--dc-card-body-mark) 14%, var(--paper-aged));
363
+ /* A strip of masking tape holding the card to the wall: a translucent tint
364
+ of the card's mark colour on paper-aged, so the card edge and the wall
365
+ read through it, with a hard edge line, slightly rotated. */
366
+ background: color-mix(in srgb, color-mix(in srgb, var(--dc-card-body-mark) 14%, var(--paper-aged)) 78%, transparent);
359
367
  box-shadow: inset 0 -1px 0 var(--ink-dust);
360
368
  transform: rotate(3deg);
361
369
  z-index: 2;
@@ -456,8 +464,9 @@
456
464
  /* Layered shadow: an inset highlight plus a hard offset, so the chip reads
457
465
  as lifted off the card. */
458
466
  box-shadow:
459
- inset 0 1px 0 color-mix(in srgb, var(--paper-cream) 15%, var(--dc-ap-bg)),
460
- 2px 2px 0 color-mix(in srgb, var(--ink) 10%, var(--dc-card-surface));
467
+ inset 0 1px 0 color-mix(in srgb, var(--paper-cream) 15%, transparent),
468
+ 2px 2px 0 color-mix(in srgb, var(--ink) 10%, transparent),
469
+ 3px 3px 6px color-mix(in srgb, var(--ink) 8%, transparent);
461
470
  text-shadow: 0 1px 0 color-mix(in srgb, var(--ink) 20%, var(--dc-ap-bg));
462
471
  letter-spacing: 0.06em;
463
472
  flex-shrink: 0;
@@ -38,6 +38,7 @@
38
38
  warning). */
39
39
  .dc-chevron {
40
40
  font-family: var(--font-display);
41
+ font-weight: 400;
41
42
  font-size: var(--dc-chevron-font-size);
42
43
  letter-spacing: 0.06em;
43
44
  color: var(--dc-chevron-color);
@@ -92,6 +93,7 @@ h1.dc-chevron {
92
93
  standalone-tag cue.) */
93
94
  .dc-spray {
94
95
  font-family: var(--font-display);
96
+ font-weight: 400;
95
97
  font-size: 22px;
96
98
  color: var(--dc-spray-color);
97
99
  text-transform: uppercase;
@@ -139,7 +141,7 @@ h1.dc-chevron {
139
141
  left: 8%;
140
142
  width: 45%;
141
143
  height: 5px;
142
- background: color-mix(in srgb, var(--dc-spray-bg) 8%, var(--wall-tone));
144
+ background: color-mix(in srgb, var(--dc-spray-bg) 8%, transparent);
143
145
  }
144
146
 
145
147
 
@@ -170,7 +172,7 @@ h1.dc-chevron {
170
172
  transform: rotate(-0.5deg);
171
173
  text-transform: uppercase;
172
174
  letter-spacing: 0.03em;
173
- box-shadow: 2px 2px 0 color-mix(in srgb, var(--ink) 35%, var(--paper-cream));
175
+ box-shadow: 2px 2px 0 color-mix(in srgb, var(--ink) 35%, transparent);
174
176
  }
175
177
 
176
178
  .dc-sticker:nth-child(4n+3) {
@@ -209,7 +211,7 @@ h1.dc-chevron {
209
211
  vertical-align: middle;
210
212
  position: relative;
211
213
  top: -1px;
212
- box-shadow: 1px 2px 0 color-mix(in srgb, var(--ink) 30%, var(--dc-path-title-bg));
214
+ box-shadow: 1px 2px 0 color-mix(in srgb, var(--ink) 30%, transparent);
213
215
  }
214
216
 
215
217
  /* The gap between the sticker and the banner title. It is a real space
@@ -335,7 +337,7 @@ h1.dc-chevron {
335
337
  /* ── Rule divider (hr) ─────────────────────────────────────────── */
336
338
  hr {
337
339
  border: none;
338
- border-top: 1.5px solid color-mix(in srgb, var(--hud-magenta) 50%, var(--paper-cream));
340
+ border-top: 1.5px solid color-mix(in srgb, var(--hud-magenta) 50%, transparent);
339
341
  margin: var(--space-lg) 0;
340
342
  }
341
343
 
@@ -38,8 +38,10 @@
38
38
  padding-right: 0;
39
39
  position: relative;
40
40
  /* Both pseudos sit at negative z-index; this is the stacking context that
41
- keeps them behind THIS shell's content instead of behind the page. */
41
+ keeps them behind THIS shell's content instead of behind the page. It
42
+ paints its own soft lift first, under both. */
42
43
  isolation: isolate;
44
+ box-shadow: var(--shadow-lift);
43
45
  }
44
46
 
45
47
  /* Background + clip-path on ::before — the element itself stays unclipped so
@@ -109,7 +111,7 @@
109
111
  redrawn here. */
110
112
  .dc-path-shell>h3.dc-spray:first-child {
111
113
  color: var(--dc-path-title-color);
112
- background: var(--dc-path-title-bg);
114
+ background: var(--light-gloss), var(--dc-path-title-bg);
113
115
  clip-path: var(--dc-path-title-shape);
114
116
  /* the slanted rule (::after) overhangs the band by --dc-band-rule-bleed; the
115
117
  clip-path trims it on paper, this keeps it out of the page's scroll width
@@ -385,8 +387,8 @@
385
387
  var(--row-color, var(--ink)) 50%,
386
388
  color-mix(in srgb, var(--row-color, var(--ink)) 96%, var(--ink) 4%) 100%); /* PDF/X-1a: pre-composite to ~96% row colour + 4% ink; on the default --ink (#1e1d1c) */
387
389
  box-shadow:
388
- inset 0 1px 0 color-mix(in srgb, var(--paper-cream) 12%, var(--row-color, var(--ink))),
389
- inset 0 -1px 0 color-mix(in srgb, var(--ink) 18%, var(--row-color, var(--ink)));
390
+ inset 0 1px 0 color-mix(in srgb, var(--paper-cream) 12%, transparent),
391
+ inset 0 -1px 0 color-mix(in srgb, var(--ink) 18%, transparent);
390
392
  /* Use the token so .dc-outcome-row.hit (which sets --dc-outcome-key-color
391
393
  to --ink because the fungi-glow fill is too light for cream text: 1.24:1)
392
394
  propagates to the chip element itself, not just to its children. Default
@@ -419,7 +421,7 @@
419
421
  .dc-outcome-key .dc-outcome-roll {
420
422
  font-family: var(--font-display);
421
423
  font-size: 16px;
422
- font-weight: 700;
424
+ font-weight: 400;
423
425
  letter-spacing: 0.03em;
424
426
  color: var(--dc-outcome-key-color);
425
427
  display: block;
@@ -529,6 +531,7 @@
529
531
 
530
532
  .dc-roll-table-name {
531
533
  font-family: var(--font-display);
534
+ font-weight: 400;
532
535
  font-size: var(--fs-h5);
533
536
  letter-spacing: var(--ls-heading);
534
537
  text-transform: uppercase;
@@ -586,6 +589,7 @@
586
589
  top: -6px;
587
590
  left: 10px;
588
591
  font-family: var(--font-display);
592
+ font-weight: 400;
589
593
  font-size: 48px;
590
594
  color: color-mix(in srgb, var(--hud-magenta) 55%, var(--dc-pullquote-bg));
591
595
  line-height: 1;
@@ -724,6 +728,7 @@
724
728
  heading and a divider. A bold lead (`**Term** — gloss`) needs nothing. */
725
729
  .dc-definition-block > h4 {
726
730
  font-family: var(--font-display);
731
+ font-weight: 400;
727
732
  font-size: var(--fs-h5);
728
733
  font-style: normal;
729
734
  letter-spacing: var(--ls-heading);
@@ -825,6 +830,7 @@
825
830
 
826
831
  .dc-stat-cell-val {
827
832
  font-family: var(--font-display);
833
+ font-weight: 400;
828
834
  font-size: 26px;
829
835
  letter-spacing: 0.04em;
830
836
  color: var(--orange);
@@ -1053,6 +1059,7 @@ p.dc-img-wrapper {
1053
1059
  margin: 0;
1054
1060
  padding: 0 8px;
1055
1061
  font-family: var(--font-display);
1062
+ font-weight: 400;
1056
1063
  font-size: 24px;
1057
1064
  letter-spacing: 0.04em;
1058
1065
  line-height: 1.1;
@@ -119,6 +119,11 @@ div[class="section"] {
119
119
  .dc-section-panel {
120
120
  background: transparent;
121
121
  --dc-section-edge: var(--dc-section-pad-bottom);
122
+ /* The soft lift under the hung sheet (--shadow-lift, sized to include the
123
+ hanging edge). A host that is a stacking context paints it first, under
124
+ the surface and hard-shadow layers. Recessed kinds set its colour to
125
+ transparent: they are sunk into the wall, not hung on it. */
126
+ box-shadow: 3pt calc(7pt + var(--dc-section-edge)) 12pt -5pt var(--dc-section-lift);
122
127
  }
123
128
 
124
129
  /* Keep a section whole, or let it split: the token is the one setting.
@@ -220,8 +225,8 @@ div[class="section"] {
220
225
  left: 3px;
221
226
  right: -3px;
222
227
  bottom: 0;
223
- background: var(--ink-dark);
224
- box-shadow: 0 calc(3px + var(--dc-section-edge)) 0 0 var(--ink-dark);
228
+ background: var(--dc-section-hard-shadow);
229
+ box-shadow: 0 calc(3px + var(--dc-section-edge)) 0 0 var(--dc-section-hard-shadow);
225
230
  clip-path: polygon(
226
231
  var(--dc-section-cut-tl) 0,
227
232
  calc(100% - var(--dc-section-clip)) 0,
@@ -431,17 +436,23 @@ h3 + .dc-section-panel {
431
436
  :is(.dc-section-lore, .dc-section-dm) {
432
437
  --dc-section-recess:
433
438
  inset 0 var(--dc-section-recess-depth) 0 0 var(--dc-section-recess-shade),
439
+ inset 0 calc(var(--dc-section-recess-depth) + 6pt) 9pt -6pt var(--shadow-press),
434
440
  inset -2px 0 0 0 var(--dc-section-recess-lip);
435
441
  --dc-section-recess-foot: 2px;
436
442
  --dc-section-shadow: none;
443
+ --dc-section-lift: transparent;
437
444
  }
438
445
  .dc-section-choose {
439
446
  --dc-section-recess:
440
447
  inset 0 var(--dc-section-recess-depth) 0 0 var(--dc-section-recess-shade),
448
+ inset 0 calc(var(--dc-section-recess-depth) + 6pt) 9pt -6pt var(--shadow-press),
441
449
  inset -2px -2px 0 0 var(--dc-section-recess-lip);
450
+ --dc-section-lift: transparent;
442
451
  }
443
452
  :is(.dc-section-lore, .dc-section-dm) > :is(h2, h3):first-child {
444
- box-shadow: inset 0 var(--dc-section-recess-depth) 0 0 var(--dc-section-recess-shade);
453
+ box-shadow:
454
+ inset 0 var(--dc-section-recess-depth) 0 0 var(--dc-section-recess-shade),
455
+ inset 0 calc(var(--dc-section-recess-depth) + 6pt) 9pt -6pt var(--shadow-press);
445
456
  }
446
457
 
447
458
  /* ── lore — the world ─────────────────────────────────────────────────────────
@@ -722,7 +733,7 @@ h3 + .dc-section-panel {
722
733
  .dc-block-title {
723
734
  font-family: var(--font-display);
724
735
  font-size: var(--fs-h4);
725
- font-weight: var(--fw-bold);
736
+ font-weight: 400;
726
737
  letter-spacing: var(--ls-heading);
727
738
  text-transform: uppercase;
728
739
  line-height: 1.3;
@@ -871,7 +882,7 @@ h3 + .dc-section-panel {
871
882
  .dc-card-heading {
872
883
  font-family: var(--font-display);
873
884
  font-size: var(--fs-h4);
874
- font-weight: var(--fw-bold);
885
+ font-weight: 400;
875
886
  text-transform: uppercase;
876
887
  letter-spacing: var(--ls-heading);
877
888
  margin-bottom: var(--space-xs);
@@ -932,7 +943,7 @@ h3 + .dc-section-panel {
932
943
  margin-top: 0;
933
944
  font-family: var(--font-display);
934
945
  font-size: var(--fs-h4);
935
- font-weight: var(--fw-bold);
946
+ font-weight: 400;
936
947
  text-transform: uppercase;
937
948
  letter-spacing: var(--ls-heading);
938
949
  margin-bottom: var(--space-xs);
@@ -1467,12 +1478,13 @@ h3 + .dc-section-panel {
1467
1478
  --dc-specialty-card-media-width: 0.38in;
1468
1479
  --dc-specialty-card-name-size: 0.95em;
1469
1480
  /* Padding clears the deepest cut (14px) by 2pt: no glyph meets a corner. */
1470
- padding: 0.1in 0.14in 0.22in;
1481
+ --dc-specialty-card-pad-x: 0.14in;
1482
+ padding-bottom: 0.22in;
1471
1483
  margin: 0;
1472
1484
  }
1473
1485
  .dc-card-grid .dc-specialty-card img { margin-bottom: 0; }
1474
1486
  .dc-card-grid .dc-specialty-card p { line-height: 1.25; font-size: var(--fs-floor); }
1475
- .dc-card-grid .dc-specialty-card h3 { padding-top: 0; line-height: 1.3; }
1487
+ .dc-card-grid .dc-specialty-card h3 { line-height: 1.3; }
1476
1488
  .dc-card-grid .dc-specialty-card blockquote { font-size: var(--fs-floor); margin: 0; line-height: 1.3; }
1477
1489
 
1478
1490
 
@@ -1526,7 +1538,8 @@ h3 + .dc-section-panel {
1526
1538
  border-block: var(--dc-fiction-rule) solid var(--ink-dark);
1527
1539
  box-shadow:
1528
1540
  var(--dc-fiction-shadow),
1529
- inset var(--dc-fiction-depth) var(--dc-fiction-depth) 0 0 var(--dc-fiction-depth-bg);
1541
+ inset var(--dc-fiction-depth) var(--dc-fiction-depth) 0 0 var(--dc-fiction-depth-bg),
1542
+ inset calc(var(--dc-fiction-depth) + 5pt) calc(var(--dc-fiction-depth) + 5pt) 11pt -6pt var(--shadow-press);
1530
1543
  clip-path: var(--dc-fiction-shape);
1531
1544
  z-index: -1;
1532
1545
  }
@@ -9,9 +9,9 @@
9
9
  set per specialty --spec-edge-top, --spec-edge-rest (and --spec-edge-title
10
10
  where the band's foot is torn): the shell/intro/band
11
11
  silhouette; --dc-skill-tab-shape (.dc-card-tab),
12
- --dc-skill-body-shape (.dc-card-body),
13
- --dc-specialty-card-shell-shape (.dc-specialty-card)
14
- derived (wiring) --dc-path-shell-clip, --dc-path-title-shape,
12
+ --dc-skill-body-shape (.dc-card-body)
13
+ derived (wiring) --dc-path-shell-clip, --dc-path-title-shape (and the
14
+ specialty card's sheet and band, which are these two),
15
15
  --dc-specialty-intro-clip, --dc-specialty-intro-title-shape
16
16
 
17
17
  SHAPE LANGUAGE (silhouette = register): tech = crisp stair-steps and square
@@ -107,12 +107,17 @@
107
107
  --dc-specialty-intro-bg: var(--paper-light);
108
108
  }
109
109
 
110
+ /* The card is the path banner's family: the banner's silhouette for the
111
+ sheet, its colour and cut for the name band. */
110
112
  .dc-specialty .dc-specialty-card {
111
113
  --dc-accent-ink: var(--spec-ink);
112
114
  --dc-specialty-card-bg: var(--paper-cream);
113
115
  --dc-specialty-card-fg: var(--ink);
114
116
  --dc-specialty-card-accent: var(--spec-band);
115
- --dc-specialty-card-border: var(--spec-mid);
117
+ --dc-specialty-card-band-bg: var(--spec-band);
118
+ --dc-specialty-card-band-fg: var(--spec-on-band);
119
+ --dc-specialty-card-shell-shape: var(--dc-path-shell-clip);
120
+ --dc-specialty-card-band-shape: var(--dc-path-title-shape);
116
121
  --dc-specialty-card-title-color: var(--spec-dark);
117
122
  }
118
123
 
@@ -155,20 +160,9 @@
155
160
  --spec-edge-rest: 100% calc(100% - 12px), calc(100% - 8px) calc(100% - 12px), calc(100% - 8px) calc(100% - 8px), calc(100% - 16px) calc(100% - 8px), calc(100% - 16px) calc(100% - 4px), calc(100% - 24px) calc(100% - 4px), calc(100% - 24px) 100%, 10px 100%, 0 calc(100% - 10px);
156
161
  --dc-skill-tab-shape: polygon(0 8px, 8px 0, calc(100% - 15px) 0, calc(100% - 15px) 5px, calc(100% - 10px) 5px, calc(100% - 10px) 10px, calc(100% - 5px) 10px, calc(100% - 5px) 15px, 100% 15px, 100% 100%, 0 100%);
157
162
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 12px), calc(100% - 8px) calc(100% - 12px), calc(100% - 8px) calc(100% - 8px), calc(100% - 16px) calc(100% - 8px), calc(100% - 16px) calc(100% - 4px), calc(100% - 24px) calc(100% - 4px), calc(100% - 24px) 100%, 12px 100%, 0 calc(100% - 12px));
158
- --dc-specialty-card-shell-shape: polygon(0 12px, 12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 6px) calc(100% - 12px), calc(100% - 6px) calc(100% - 8px), calc(100% - 12px) calc(100% - 8px), calc(100% - 12px) calc(100% - 4px), calc(100% - 18px) calc(100% - 4px), calc(100% - 18px) 100%, 0 100%);
159
163
  --spec-media-shape: polygon(0 10px, 10px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 6px) calc(100% - 12px), calc(100% - 6px) calc(100% - 8px), calc(100% - 12px) calc(100% - 8px), calc(100% - 12px) calc(100% - 4px), calc(100% - 18px) calc(100% - 4px), calc(100% - 18px) 100%, 0 100%);
160
164
  }
161
165
 
162
- /* Augmerc — paper poster with magenta ink. The specialty signature color
163
- lives in the border + title, not the substrate — accent/border key on
164
- the specialty's ACCENT token, not the shared --spec-mid pattern (a
165
- genuine per-specialty delta, along with cybersurgeon below). Keeps the
166
- card readable as a flyer pasted on the brick wall, not a painted plaque. */
167
- .dc-specialty.augmerc .dc-specialty-card {
168
- --dc-specialty-card-accent: var(--brand-magenta);
169
- --dc-specialty-card-border: var(--brand-magenta);
170
- --dc-specialty-card-shadow: inset 0 0 0 1.5pt var(--brand-magenta);
171
- }
172
166
 
173
167
  /* ── Cybersurgeon — precision surgical, silver, top-right diagonal ──────── */
174
168
  .dc-specialty.cybersurgeon {
@@ -196,16 +190,9 @@
196
190
  --spec-edge-rest: 100% 100%, 20px 100%, 20px calc(100% - 9px), 0 calc(100% - 9px);
197
191
  --dc-skill-tab-shape: polygon(0 0, calc(100% - 18px) 0, calc(100% - 18px) 9px, 100% 9px, 100% 100%, 0 100%);
198
192
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 9px), calc(100% - 26px) calc(100% - 9px), calc(100% - 26px) 100%, 0 100%);
199
- --dc-specialty-card-shell-shape: polygon(0 0, calc(100% - 24px) 0, calc(100% - 24px) 9px, 100% 9px, 100% 100%, 16px 100%, 16px calc(100% - 9px), 0 calc(100% - 9px));
200
193
  --spec-media-shape: polygon(0 0, calc(100% - 22px) 0, calc(100% - 22px) 9px, 100% 9px, 100% calc(100% - 9px), calc(100% - 22px) calc(100% - 9px), calc(100% - 22px) 100%, 0 100%);
201
194
  }
202
195
 
203
- /* Cybersurgeon — the chrome band and steel frame come from the shared wiring;
204
- only the clinical inset frame is its own. */
205
- .dc-specialty.cybersurgeon .dc-specialty-card {
206
- --dc-specialty-card-shadow: inset 0 0 0 1.5pt var(--cybersurgeon-mid);
207
- }
208
-
209
196
  /* ── Technosorcerer — ritual on scrap, scorch orange, a burnt corner ──── */
210
197
  .dc-specialty.technosorcerer {
211
198
  --spec-accent: var(--technosorcerer-accent);
@@ -228,7 +215,6 @@
228
215
  --spec-edge-rest: 100% calc(100% - 22px), calc(100% - 4px) calc(100% - 17px), calc(100% - 2px) calc(100% - 11px), calc(100% - 13px) calc(100% - 9px), calc(100% - 17px) calc(100% - 3px), 100% 100%, calc(100% - 48px) 100%, 82% calc(100% - 6px), 69% calc(100% - 1px), 55% calc(100% - 7px), 41% calc(100% - 2px), 27% calc(100% - 7px), 14% calc(100% - 1px), 7% calc(100% - 4px), 0 100%, 0 calc(100% - 9px), 3px calc(100% - 14px);
229
216
  --dc-skill-tab-shape: polygon(0 14px, 14px 0, 38% 2px, 44% 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
230
217
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 20px), calc(100% - 5px) calc(100% - 15px), calc(100% - 4px) calc(100% - 9px), calc(100% - 17px) calc(100% - 8px), calc(100% - 24px) calc(100% - 2px), 100% 100%, calc(100% - 38px) 100%, 78% calc(100% - 5px), 62% calc(100% - 1px), 47% calc(100% - 6px), 31% calc(100% - 2px), 17% calc(100% - 6px), 8% calc(100% - 1px), 4px calc(100% - 3px), 0 100%, 0 calc(100% - 7px));
231
- --dc-specialty-card-shell-shape: polygon(0 14px, 14px 0, 100% 0, 100% calc(100% - 20px), calc(100% - 4px) calc(100% - 14px), calc(100% - 15px) calc(100% - 10px), calc(100% - 20px) calc(100% - 3px), 100% 100%, calc(100% - 34px) 100%, 70% calc(100% - 4px), 52% calc(100% - 1px), 33% calc(100% - 5px), 15% calc(100% - 1px), 6% calc(100% - 3px), 0 100%);
232
218
  --spec-edge-title: 100% calc(100% - 2px), 96% 100%, 91% calc(100% - 4px), 85% calc(100% - 1px), 79% calc(100% - 4px), 72% 100%, 65% calc(100% - 5px), 58% calc(100% - 1px), 50% calc(100% - 4px), 42% 100%, 35% calc(100% - 3px), 27% calc(100% - 1px), 20% calc(100% - 4px), 12% 100%, 6% calc(100% - 3px), 0 calc(100% - 1px);
233
219
  --spec-media-shape: polygon(0 14px, 14px 0, 100% 0, calc(100% - 2px) 40%, 100% 70%, 100% 100%, calc(100% - 20px) calc(100% - 3px), 86% calc(100% - 7px), 72% calc(100% - 2px), 58% calc(100% - 8px), 43% calc(100% - 3px), 29% calc(100% - 8px), 15% calc(100% - 2px), 6% calc(100% - 6px), 0 100%);
234
220
  }
@@ -261,14 +247,9 @@
261
247
  --spec-edge-rest: 100% calc(100% - 10px), calc(100% - 10px) 100%, 22px 100%, 22px calc(100% - 6px), 11px calc(100% - 6px), 11px calc(100% - 12px), 0 calc(100% - 12px);
262
248
  --dc-skill-tab-shape: polygon(0 0, calc(100% - 22px) 0, calc(100% - 22px) 10px, calc(100% - 11px) 10px, calc(100% - 11px) 20px, 100% 20px, 100% 100%, 0 100%);
263
249
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 22px 100%, 22px calc(100% - 6px), 11px calc(100% - 6px), 11px calc(100% - 12px), 0 calc(100% - 12px));
264
- --dc-specialty-card-shell-shape: polygon(0 0, calc(100% - 18px) 0, calc(100% - 18px) 6px, calc(100% - 9px) 6px, calc(100% - 9px) 12px, 100% 12px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 18px 100%, 18px calc(100% - 6px), 9px calc(100% - 6px), 9px calc(100% - 12px), 0 calc(100% - 12px));
265
250
  --spec-media-shape: polygon(0 0, calc(100% - 18px) 0, calc(100% - 18px) 6px, calc(100% - 9px) 6px, calc(100% - 9px) 12px, 100% 12px, 100% 100%, 18px 100%, 18px calc(100% - 6px), 9px calc(100% - 6px), 9px calc(100% - 12px), 0 calc(100% - 12px));
266
251
  }
267
252
 
268
- .dc-specialty.wirephreak .dc-specialty-card {
269
- --dc-specialty-card-shadow: inset 0 0 0 1.5pt var(--wirephreak-mid);
270
- }
271
-
272
253
  /* ── Streetwarden — community defender, green, soft diamond cuts ──────── */
273
254
  .dc-specialty.streetwarden {
274
255
  --spec-accent: var(--streetwarden-accent);
@@ -293,7 +274,6 @@
293
274
  --spec-edge-rest: 100% calc(100% - 16px), calc(100% - 16px) 100%, 16px 100%, 0 calc(100% - 16px);
294
275
  --dc-skill-tab-shape: polygon(0 8px, 8px 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
295
276
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px));
296
- --dc-specialty-card-shell-shape: polygon(0 14px, 14px 0, calc(100% - 14px) 0, 100% 14px, 100% calc(100% - 14px), calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px));
297
277
  --spec-media-shape: polygon(0 14px, 14px 0, calc(100% - 14px) 0, 100% 14px, 100% calc(100% - 14px), calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px));
298
278
  }
299
279
 
@@ -324,7 +304,6 @@
324
304
  --spec-edge-rest: 100% calc(100% - 12px), calc(100% - 10px) calc(100% - 12px), calc(100% - 10px) calc(100% - 6px), calc(100% - 20px) calc(100% - 6px), calc(100% - 20px) 100%, 12px 100%, 0 calc(100% - 12px);
325
305
  --dc-skill-tab-shape: polygon(0 8px, 8px 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
326
306
  --dc-skill-body-shape: polygon(0 0, calc(50% - 18px) 0, 50% 6px, calc(50% + 18px) 0, 100% 0, 100% calc(100% - 12px), calc(100% - 10px) calc(100% - 12px), calc(100% - 10px) calc(100% - 6px), calc(100% - 20px) calc(100% - 6px), calc(100% - 20px) 100%, 12px 100%, 0 calc(100% - 12px));
327
- --dc-specialty-card-shell-shape: polygon(0 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px));
328
307
  --spec-media-shape: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 16px 100%, 16px calc(100% - 5px), 8px calc(100% - 5px), 8px calc(100% - 10px), 0 calc(100% - 10px));
329
308
  }
330
309
 
@@ -350,7 +329,6 @@
350
329
  --spec-edge-rest: calc(100% - 3px) 63%, calc(100% - 2px) 73%, calc(100% - 4px) 83%, 100% calc(100% - 10px), calc(100% - 10px) 100%, 85% calc(100% - 6px), 71% calc(100% - 6px), 57% calc(100% - 5px), 43% calc(100% - 5px), 29% calc(100% - 2px), 15% calc(100% - 2px), 12px 100%, 0 calc(100% - 12px), 4px 83%, 4px 73%, 0 63%;
351
330
  --dc-skill-tab-shape: polygon(0 7px, 7px 0, 40% 2px, 60% 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
352
331
  --dc-skill-body-shape: polygon(0 5px, 5px 0, 38% 0, 53% 1px, 69% 2px, 84% 1px, calc(100% - 6px) 0, 100% 6px, calc(100% - 1px) 22%, calc(100% - 1px) 50%, 100% 78%, 100% calc(100% - 10px), calc(100% - 10px) 100%, 85% calc(100% - 4px), 71% 100%, 57% 100%, 43% calc(100% - 6px), 29% calc(100% - 2px), 15% calc(100% - 6px), 12px 100%, 0 calc(100% - 12px), 1px 78%, 4px 50%, 3px 22%);
353
- --dc-specialty-card-shell-shape: polygon(0 7px, 7px 0, 18% 0, 40% 3px, 60% 0, 82% 3px, calc(100% - 7px) 0, 100% 7px, 100% 53%, calc(100% - 1px) 68%, calc(100% - 1px) 84%, 100% calc(100% - 10px), calc(100% - 10px) 100%, 84% calc(100% - 2px), 67% calc(100% - 1px), 50% calc(100% - 5px), 33% calc(100% - 1px), 16% calc(100% - 4px), 10px 100%, 0 calc(100% - 10px), 1px 84%, 0 68%, 2px 53%);
354
332
  --spec-edge-title: 100% calc(100% - 2px), 96% 100%, 91% calc(100% - 4px), 85% calc(100% - 1px), 79% calc(100% - 4px), 72% 100%, 65% calc(100% - 5px), 58% calc(100% - 1px), 50% calc(100% - 4px), 42% 100%, 35% calc(100% - 3px), 27% calc(100% - 1px), 20% calc(100% - 4px), 12% 100%, 6% calc(100% - 3px), 0 calc(100% - 1px);
355
333
  --spec-media-shape: polygon(0 8px, 8px 0, 16% 3px, 33% 2px, 50% 1px, 67% 1px, 84% 3px, calc(100% - 10px) 0, 100% 10px, 100% 18%, 100% 40%, calc(100% - 2px) 60%, calc(100% - 1px) 82%, 100% calc(100% - 12px), calc(100% - 12px) 100%, 85% calc(100% - 2px), 71% calc(100% - 3px), 57% calc(100% - 1px), 43% calc(100% - 5px), 29% calc(100% - 2px), 15% 100%, 9px 100%, 0 calc(100% - 9px), 0 82%, 4px 60%, 4px 40%, 3px 18%);
356
334
  }
@@ -381,7 +359,6 @@
381
359
  --spec-edge-rest: 100% calc(100% - 16px), calc(100% - 16px) 100%, 6px 100%, 0 calc(100% - 6px);
382
360
  --dc-skill-tab-shape: polygon(0 10px, 10px 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 0 100%);
383
361
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 16px), calc(100% - 16px) 100%, 8px 100%, 0 calc(100% - 8px));
384
- --dc-specialty-card-shell-shape: polygon(0 14px, 14px 0, calc(100% - 6px) 0, 100% 6px, 100% calc(100% - 14px), calc(100% - 14px) 100%, 6px 100%, 0 calc(100% - 6px));
385
362
  --spec-media-shape: polygon(0 14px, 14px 0, calc(100% - 6px) 0, 100% 6px, 100% calc(100% - 14px), calc(100% - 14px) 100%, 6px 100%, 0 calc(100% - 6px));
386
363
  }
387
364
 
@@ -411,7 +388,6 @@
411
388
  --spec-edge-rest: 100% calc(100% - 14px), calc(100% - 14px) 100%, calc(50% + 26px) 100%, 50% calc(100% - 7px), calc(50% - 26px) 100%, 14px 100%, 0 calc(100% - 14px);
412
389
  --dc-skill-tab-shape: polygon(0 10px, 10px 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
413
390
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, calc(50% + 24px) 100%, 50% calc(100% - 7px), calc(50% - 24px) 100%, 14px 100%, 0 calc(100% - 14px));
414
- --dc-specialty-card-shell-shape: polygon(0 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, calc(50% + 22px) 100%, 50% calc(100% - 5px), calc(50% - 22px) 100%, 14px 100%, 0 calc(100% - 14px));
415
391
  --spec-media-shape: polygon(0 12px, 12px 0, calc(100% - 12px) 0, 100% 12px, 100% calc(100% - 12px), calc(100% - 12px) 100%, 12px 100%, 0 calc(100% - 12px));
416
392
  }
417
393
 
@@ -437,7 +413,6 @@
437
413
  --spec-edge-rest: 100% calc(100% - 6px), calc(100% - 6px) 100%, 22px 100%, 0 calc(100% - 22px);
438
414
  --dc-skill-tab-shape: polygon(0 4px, 4px 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
439
415
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 18px 100%, 0 calc(100% - 18px));
440
- --dc-specialty-card-shell-shape: polygon(0 6px, 6px 0, calc(100% - 16px) 0, 100% 16px, 100% calc(100% - 6px), calc(100% - 6px) 100%, 16px 100%, 0 calc(100% - 16px));
441
416
  --spec-media-shape: polygon(0 5px, 5px 0, calc(100% - 18px) 0, 100% 18px, 100% calc(100% - 5px), calc(100% - 5px) 100%, 18px 100%, 0 calc(100% - 18px));
442
417
  }
443
418
 
@@ -174,67 +174,81 @@
174
174
  }
175
175
 
176
176
  /* Token contract for .dc-specialty-card:
177
- --dc-specialty-card-bg → card body background (default --paper-cream)
178
- --dc-specialty-card-border → outer card border color (default --hud-blue)
179
- --dc-specialty-card-accent → inner accent rule color (default --crimson)
177
+ --dc-specialty-card-bg → the sheet's paper (default --paper-cream)
178
+ --dc-specialty-card-accent → the tagline's rule (default --crimson)
180
179
  --dc-specialty-card-fg → body text color (default --ink)
180
+ --dc-specialty-card-band-bg / -fg → the name band and the type on it
181
181
  --dc-specialty-card-media-width → portrait image width (default 0.75in)
182
182
  --dc-specialty-card-media-height → portrait image height (default 0.85in)
183
- --dc-specialty-card-title-align → title text-align (default right)
184
- --dc-specialty-card-shell-shape → outer clip-path polygon
185
- --dc-specialty-card-shadow → box-shadow (default none) — future-tech-high
186
- specialties opt into LED-rim inset highlight here
187
- Specialty themes override via .dc-specialty.<name> .dc-specialty-card { }. */
183
+ --dc-specialty-card-title-align → tagline text-align (default right)
184
+ --dc-specialty-card-shell-shape → the sheet's silhouette (clip-path)
185
+ --dc-specialty-card-band-shape → the band's silhouette (clip-path)
186
+ Inside a .dc-specialty the wiring (specialty-identity.css) sets them from
187
+ the specialty: the sheet is cut like its path banner, and the band is the
188
+ banner's own colour and cut, so a card reads as the same family as that
189
+ specialty's skill cards. */
188
190
 
189
191
  /* ── Specialty card (.dc-specialty-card + descendants + nth-of-type(even)) */
190
192
  /* Token defaults for .dc-specialty-card are declared in :root in dc-component-defaults.css.
191
193
  Specialty contexts override via .dc-specialty.<name> .dc-specialty-card { } above. */
194
+ /* The path banner's construction (data.css .dc-path-shell): the element is
195
+ unclipped, the paper is ::before cut to the silhouette, a 2px ink outline is
196
+ ::after (the silhouette on a box 2px larger), and the name is a band clipped
197
+ to the banner's own cut. Its soft lift is this element's box-shadow, which
198
+ paints first in its own stacking context, under both layers; it is pulled in
199
+ (negative spread) so it never shows past a cut corner. */
192
200
  .dc-specialty-card {
193
- /* Only the optional per-specialty inset shadow (LED rim) is declared:
194
- clip-path below clips this element's own outer box-shadow, so a
195
- --shadow-poster layer here would never paint. */
196
- box-shadow: var(--dc-specialty-card-shadow);
197
- /* Poster-header pattern: thick colored TOP border = the specialty's
198
- header ribbon. paper-cream body below = the printed flyer substrate.
199
- Title h3 + body content sit inside the padding box, naturally below
200
- the border (which is part of the box model, not content area).
201
- This puts the specialty signature in the band + title color + side
202
- border — NOT in the card body. Reads as a printed poster pasted on
203
- the brick wall, not a painted plaque. */
204
- background: var(--dc-specialty-card-bg);
201
+ box-shadow: var(--shadow-lift);
205
202
  color: var(--dc-specialty-card-fg);
206
203
  /* flow-root for the dense card; flex (a column) for the poster card of the
207
- specialty-catalog page, where the portrait is ordered above the name. */
204
+ specialty-catalog page, where the portrait sits under the band. */
208
205
  display: var(--dc-specialty-card-display);
209
206
  flex-direction: column;
210
- overflow: hidden;
211
207
  line-height: var(--lh-tight);
212
208
  /* Card spacing: --dc-card-gap plus 4px (layout, not shadow clearance).
213
209
  .dc-card-grid resets this to 0 — the grid packs cards deliberately tight
214
210
  and owns its own spacing. */
215
211
  margin: 0 0 calc(var(--dc-card-gap) + 4px) 0;
216
- padding: 0.14in 0.18in 0.18in 0.18in;
212
+ /* Top: the outline's 2px rim; the band starts under it and reaches out
213
+ through the side padding to the sheet's edges. */
214
+ padding: 2px var(--dc-specialty-card-pad-x) 0.18in;
217
215
  position: relative;
216
+ isolation: isolate;
218
217
  break-inside: avoid;
219
- border: 1.5pt solid var(--dc-specialty-card-border);
220
- border-top: var(--dc-specialty-card-band-height) solid var(--dc-specialty-card-accent);
221
- border-left: 3pt solid var(--dc-specialty-card-accent);
222
- /* The top band gets a small chip cut at the upper-right to break the flat
223
- rectangle reading. Per-specialty --dc-specialty-card-shell-shape takes
224
- precedence over the default 12px chamfer at the top-right corner. */
218
+ }
219
+
220
+ .dc-specialty-card::before {
221
+ content: '';
222
+ position: absolute;
223
+ inset: 2px 0 0;
224
+ background: var(--dc-specialty-card-bg);
225
225
  clip-path: var(--dc-specialty-card-shell-shape);
226
+ z-index: -1;
227
+ }
228
+
229
+ .dc-specialty-card::after {
230
+ content: '';
231
+ position: absolute;
232
+ top: 0;
233
+ right: -2px;
234
+ bottom: -2px;
235
+ left: -2px;
236
+ background: var(--ink);
237
+ clip-path: var(--dc-specialty-card-shell-shape);
238
+ z-index: -2;
226
239
  }
227
240
 
228
241
  /* Portrait. By default a small image floated beside the text (the dense
229
242
  card); the specialty-catalog page sets the tokens for a full-width frame
230
- above the name. The wrapper (the paragraph the image sits in) is the frame:
243
+ above the name. The wrapper (the paragraph the image sits in) is the frame, and it is what floats:
231
244
  an ink mat (--dc-specialty-card-media-mat, 0 by default) clipped to the
232
245
  specialty's own cut (--dc-specialty-card-media-shape), over a paper-aged
233
246
  field, so it reads whether the picture loads or the field is empty. */
234
247
  .dc-specialty-card .dc-img-wrapper {
235
248
  order: var(--dc-specialty-card-media-order);
236
249
  position: relative;
237
- margin: 0;
250
+ float: var(--dc-specialty-card-media-float);
251
+ margin: var(--dc-specialty-card-media-margin);
238
252
  padding: var(--dc-specialty-card-media-mat);
239
253
  background: var(--ink);
240
254
  clip-path: var(--dc-specialty-card-media-shape);
@@ -248,8 +262,7 @@
248
262
  border: none;
249
263
  padding: 0;
250
264
  box-sizing: border-box;
251
- float: var(--dc-specialty-card-media-float);
252
- margin: var(--dc-specialty-card-media-margin);
265
+ margin: 0;
253
266
  border-radius: 2px;
254
267
  background: var(--paper-aged);
255
268
  color: var(--ink);
@@ -280,18 +293,23 @@
280
293
  here, in the border, and in the body-accent rule — NOT in the card
281
294
  background. The card itself stays paper-cream so the colored elements
282
295
  read as ink on paper, not as a painted card. */
296
+ /* The name is the specialty's band, as on its path banner: the banner's fill,
297
+ type colour and cut, spanning the sheet edge to edge, its padding the
298
+ deepest cut plus 2pt (data.css, the path banner). First in the poster card
299
+ too: the portrait sits under it. */
283
300
  .dc-specialty-card h3 {
284
- margin: 0;
285
- /* In the poster card (a flex column) the slack of a row's shorter card goes
286
- above the name, between the portrait and the text, so the type block sits
287
- at the foot with no dead cream under the pitch; in the dense card an auto
288
- top margin is 0. */
289
- margin-top: auto;
290
- padding-top: 0;
301
+ order: -2;
302
+ position: relative;
303
+ margin: 0 calc(-1 * var(--dc-specialty-card-pad-x)) 0.1in;
304
+ padding: 12px 28px 7px 20px;
291
305
  border-top: 0;
306
+ background: var(--light-gloss), var(--dc-specialty-card-band-bg);
307
+ box-shadow: var(--dc-band-rim);
308
+ clip-path: var(--dc-specialty-card-band-shape);
309
+ overflow: clip;
292
310
  font-size: var(--dc-specialty-card-name-size);
293
- color: var(--dc-specialty-card-title-color);
294
- text-align: var(--dc-specialty-card-title-align);
311
+ color: var(--dc-specialty-card-band-fg);
312
+ text-align: left;
295
313
  /* A specialty's name is one word and sets on one line: a long one
296
314
  ("TECHNOSORCERER") broke mid-word and orphaned its last letter. The
297
315
  display face is tracked tighter instead (technosorcerer, the longest,
@@ -301,6 +319,22 @@
301
319
  overflow-wrap: normal;
302
320
  }
303
321
 
322
+ /* The band's rule, as under the path banner: the register (LED dots, hazard
323
+ tape, a solid bar) from the --dc-band-* tokens the specialty sets. */
324
+ .dc-specialty-card h3::after {
325
+ content: '';
326
+ position: absolute;
327
+ left: calc(-1 * var(--dc-band-rule-bleed));
328
+ right: calc(-1 * var(--dc-band-rule-bleed));
329
+ bottom: 0;
330
+ height: var(--dc-band-rule-h);
331
+ box-sizing: border-box;
332
+ background: var(--dc-band-rule);
333
+ border-top: var(--dc-band-tick-w) var(--dc-band-tick-style) var(--dc-band-tick);
334
+ box-shadow: var(--dc-band-reg);
335
+ transform: skewX(var(--dc-band-rule-skew));
336
+ }
337
+
304
338
  /* Subtitle tagline — the specialty's "archetype label" (e.g.,
305
339
  "Cybernetic Commando", "Wold Witch"). It is the card's one interior visual
306
340
  beat: mono-caps + tracked + accent-colored + bottom-rule gives the card a
@@ -311,7 +345,11 @@
311
345
  border: none;
312
346
  border-bottom: 0.75pt solid var(--dc-specialty-card-accent);
313
347
  padding: 0 0.06in 0.03in;
314
- margin: 0.02in 0 0.06in;
348
+ /* In the poster card (a flex column) the slack of a row's shorter card goes
349
+ above the tagline, between the portrait and the text, so the type block
350
+ sits at the foot with no dead paper under the pitch; in the dense card an
351
+ auto top margin is 0. */
352
+ margin: auto 0 0.06in;
315
353
  font-family: var(--font-mono);
316
354
  font-size: var(--fs-floor);
317
355
  font-style: normal;
@@ -336,17 +374,14 @@
336
374
  overflow-wrap: anywhere;
337
375
  }
338
376
 
339
- /* Even cards flip the border accent to the right. data-position is emitted by
340
- the plugin (dcSpecialtyCardPositions), which counts every specialty card
341
- in the document — :nth-of-type() would count within the DOM parent instead. */
377
+ /* Even cards float the portrait right. data-position is emitted by the plugin
378
+ (dcSpecialtyCardPositions), which counts every specialty card in the
379
+ document — :nth-of-type() would count within the DOM parent instead. */
342
380
  .dc-specialty-card[data-position="even"] {
343
381
  --dc-specialty-card-title-align: left;
344
-
345
- border-left: 1.5pt solid var(--dc-specialty-card-border);
346
- border-right: var(--callout-border-width-small) solid var(--dc-specialty-card-accent);
347
382
  }
348
383
 
349
- .dc-specialty-card[data-position="even"] img {
384
+ .dc-specialty-card[data-position="even"] .dc-img-wrapper {
350
385
  float: var(--dc-specialty-card-media-float-even);
351
386
  margin: var(--dc-specialty-card-media-margin-even);
352
387
  }
@@ -367,11 +402,16 @@
367
402
  counter-reset: dc-specialty;
368
403
  }
369
404
 
405
+ /* A card spans one column or both (--dc-card-grid-item-span, 1 or 2); a page
406
+ may reorder the cards (--dc-card-grid-item-order) and break before one
407
+ (--dc-card-grid-item-break). */
370
408
  .dc-card-grid .dc-specialty {
371
409
  display: var(--dc-card-grid-item-display);
372
410
  flex-direction: column;
373
- flex: 0 0 calc(50% - var(--gp-column-gap) / 2);
411
+ flex: 0 0 calc(50% * var(--dc-card-grid-item-span) + (var(--dc-card-grid-item-span) - 2) * var(--gp-column-gap) / 2);
374
412
  min-height: var(--dc-card-grid-row);
413
+ order: var(--dc-card-grid-item-order);
414
+ break-before: var(--dc-card-grid-item-break);
375
415
  }
376
416
 
377
417
  .dc-card-grid .dc-specialty-card {
@@ -47,6 +47,8 @@
47
47
  --dc-section-recess-shade: var(--ink-dark);
48
48
  --dc-section-recess-lip: var(--paper-cream);
49
49
  --dc-section-recess-foot: 0px; /* how far the sheet's hanging edge stops short of the lip */
50
+ --dc-section-lift: var(--shadow-soft); /* the soft lift's colour; transparent on a recessed kind */
51
+ --dc-section-hard-shadow: color-mix(in srgb, var(--ink-dark) 82%, transparent); /* the hard offset copy; translucent, so the brick reads through */
50
52
  --dc-section-top: 0px; /* extra padding on top inside the box: a kind that draws a tab (dm) reserves its height here */
51
53
  --dc-section-shadow-y: 0px; /* the shadow layer's extra offset: a kind with its own polygon adds it to both layers' foot */
52
54
  --dc-section-ink-mix: 72%; /* --dc-accent-ink of a panel: the accent mixed this far with --dc-section-ink-tone */
@@ -186,13 +188,14 @@
186
188
 
187
189
  /* .dc-specialty-card public API */
188
190
  --dc-specialty-card-bg: var(--paper-cream);
189
- --dc-specialty-card-border: var(--hud-blue);
190
191
  --dc-specialty-card-accent: var(--crimson);
191
192
  --dc-specialty-card-fg: var(--ink);
192
193
  --dc-specialty-card-media-height: 0.85in;
193
194
  --dc-specialty-card-media-width: 0.75in;
194
195
  --dc-specialty-card-title-align: right;
195
- --dc-specialty-card-band-height: 16pt;
196
+ --dc-specialty-card-band-bg: var(--dc-specialty-card-accent);
197
+ --dc-specialty-card-band-fg: var(--paper-cream);
198
+ --dc-specialty-card-pad-x: 0.18in; /* side padding; the name band reaches out through it */
196
199
  /* The card's layout. Defaults are the dense catalog card (a small portrait
197
200
  floated beside the text, the grid in columns); the specialty-catalog page
198
201
  sets them for the tall poster card in a grid of equal rows. */
@@ -209,6 +212,12 @@
209
212
  --dc-card-grid-display: block; /* flex: aligned rows, two cards across */
210
213
  --dc-card-grid-item-display: block; /* flex (a column): the card fills its row */
211
214
  --dc-card-grid-row: 0; /* the least height of a row */
215
+ --dc-card-grid-item-span: 1; /* 2: the card spans both columns */
216
+ --dc-card-grid-item-order: 0; /* flex order: a page may reorder the cards */
217
+ --dc-card-grid-item-break: auto; /* page: the card opens a page */
218
+ --dc-card-grid-row-tall: 0; /* a page's taller rows (the catalog's right page) */
219
+ --dc-card-grid-media-tall: 1in; /* their portraits */
220
+ --dc-card-grid-media-wide: 1in; /* the portrait of a card spanning both columns */
212
221
  --dc-card-grid-gap: 0.16in;
213
222
 
214
223
  /* .dc-block public API */
@@ -414,7 +423,7 @@
414
423
 
415
424
  /* .dc-pullquote public API */
416
425
  --dc-pullquote-accent: var(--hud-magenta);
417
- --dc-pullquote-accent-soft: color-mix(in srgb, var(--tint-magenta-rose) 15%, var(--dc-pullquote-bg));
426
+ --dc-pullquote-accent-soft: color-mix(in srgb, var(--tint-magenta-rose) 15%, transparent);
418
427
  --dc-pullquote-bg: var(--concrete-pale);
419
428
 
420
429
  /* The text-safe ink of whatever component the prose sits in: ROLL THE DIE!
@@ -427,8 +436,9 @@
427
436
  --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 28px), calc(100% - 44px) 100%, 0 100%);
428
437
  --dc-skill-tab-shape: polygon(0 0, calc(100% - 18px) 0, 100% 100%, 0 100%);
429
438
 
430
- /* .dc-specialty-card extra public API (shadow + shape + title) */
431
- --dc-specialty-card-shadow: none;
439
+ /* .dc-specialty-card extra public API (shapes + title). Inside a
440
+ .dc-specialty both shapes are the specialty's path-banner cuts. */
441
+ --dc-specialty-card-band-shape: none;
432
442
  --dc-specialty-card-shell-shape: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% calc(100% - 18px), calc(100% - 24px) 100%, 0 100%);
433
443
  --dc-specialty-card-title-color: var(--dc-specialty-card-accent);
434
444
 
@@ -77,6 +77,10 @@ body {
77
77
  h1, h2, h3, h4, h5, h6,
78
78
  .dc-h3, .dc-h4, .dc-h5, .dc-h6 {
79
79
  font-family: var(--font-display);
80
+ font-weight: 400;
81
+ /* `**bold**` in a heading asks for a bolder Lixdu, which has none: print it
82
+ in Lixdu's own stroke rather than a synthetic (Type 3) bold. */
83
+ font-synthesis-weight: none;
80
84
  letter-spacing: var(--ls-display);
81
85
  line-height: var(--lh-tight);
82
86
  text-transform: uppercase;
@@ -90,7 +94,6 @@ h1, h2, h3, h4, h5, h6,
90
94
  /* H1 — magenta neon authority: chapter openers, page-level titles. */
91
95
  h1 {
92
96
  font-size: var(--fs-h1);
93
- font-weight: var(--fw-bold);
94
97
  letter-spacing: 0.2em;
95
98
  margin-bottom: 0.75em;
96
99
  color: var(--hud-magenta);
@@ -116,7 +119,6 @@ h6, .dc-h6 { font-size: var(--fs-h6); margin-top: 0; color: var(--ink-dust); let
116
119
  /* What h1/h2 add that no lower look has: clear it when a look class is on
117
120
  one of those tags. */
118
121
  .dc-h3, .dc-h4, .dc-h5, .dc-h6 {
119
- font-weight: var(--fw-bold);
120
122
  margin-bottom: 0.5em;
121
123
  border-bottom: 0;
122
124
  padding-bottom: 0;
@@ -134,7 +134,7 @@
134
134
  line-height: 1;
135
135
  font-family: var(--font-display);
136
136
  font-size: var(--fs-floor);
137
- font-weight: 700;
137
+ font-weight: 400;
138
138
  letter-spacing: 0.06em;
139
139
  text-transform: uppercase;
140
140
  padding: 2px calc(8px - 0.06em) 0 8px;
@@ -157,7 +157,7 @@
157
157
  line-height: 1;
158
158
  font-family: var(--font-display);
159
159
  font-size: var(--fs-floor);
160
- font-weight: 700;
160
+ font-weight: 400;
161
161
  letter-spacing: 0.06em;
162
162
  text-transform: uppercase;
163
163
  padding: 2px calc(8px - 0.06em) 0 8px;
@@ -207,7 +207,7 @@
207
207
  line-height: 1;
208
208
  font-family: var(--font-display);
209
209
  font-size: var(--fs-floor);
210
- font-weight: 700;
210
+ font-weight: 400;
211
211
  letter-spacing: 0.1em;
212
212
  text-transform: uppercase;
213
213
  padding: 2px calc(9px - 0.1em) 0 9px;
@@ -227,7 +227,7 @@
227
227
  line-height: 1;
228
228
  font-family: var(--font-display);
229
229
  font-size: var(--fs-floor);
230
- font-weight: 700;
230
+ font-weight: 400;
231
231
  letter-spacing: 0.1em;
232
232
  text-transform: uppercase;
233
233
  padding: 2px calc(9px - 0.1em) 0 9px;
@@ -12,15 +12,30 @@
12
12
  --paper-light: #e2ded7; /* slightly darker grey alternate surface — for layered paper / secondary panels · TAC 32% (C10 M9 Y13 K0) */
13
13
  --paper-aged: #c8c2b8; /* weathered grey — decay register, dust + age · TAC 66% (C21 M20 Y26 K0) */
14
14
  --paper-stain: #b0a89c; /* deep stain — dark inset wells, smoke-grey · TAC 99% (C32 M30 Y37 K0) */
15
- /* Poster-wall shadow — hard offset, no blur. Pins paper-register
16
- components to the wall as physical objects, "stuck on the wall"
17
- rather than "embedded in the page." */
18
- /* The wall's average colour (mean of images/brick-wall.png). Shadows and
19
- tints that land on the wall pre-composite against it: PDF/X-1a carries
20
- no transparency (see docs/print-transparency-inventory.md). */
21
- --wall-tone: #c1beb8; /* TAC 70% (C24 M21 Y25 K0) */
22
- --shadow-ink: color-mix(in srgb, var(--ink) 28%, var(--wall-tone)); /* opaque ink-on-wall shadow colour */
23
- --shadow-poster: 2pt 3pt 0 var(--shadow-ink);
15
+ /* Poster-wall shadow — a hard offset that pins paper-register components to
16
+ the wall as physical objects ("stuck on the wall", not "embedded in the
17
+ page"), over a soft lift (below).
18
+ Translucent, so the wall's texture darkens under it. A PDF/X build
19
+ flattens the pages that use transparency and keeps their text live
20
+ (Gutterpress #385; see docs/print-transparency-inventory.md). */
21
+ --shadow-ink: color-mix(in srgb, var(--ink) 28%, transparent);
22
+ /* Depth (PDF/X preserve-text keeps text live over soft effects; see
23
+ docs/constitution.md §II "Depth"). Anything hung on the wall casts two
24
+ shadows: the hard contact edge (--shadow-ink, offset, no blur) that pins it
25
+ like a poster, and a soft ambient lift under it. The lift is pulled in
26
+ (negative spread), so it never shows past a clipped corner and only its
27
+ falloff reaches the wall. Blur comes only from box-shadow or a blurred
28
+ empty layer, never from `filter` on anything that holds text: Chromium
29
+ prints a filtered subtree, text included, as a picture. */
30
+ --shadow-soft: color-mix(in srgb, var(--ink) 34%, transparent);
31
+ --shadow-lift: 3pt 7pt 12pt -5pt var(--shadow-soft);
32
+ --shadow-poster: 2pt 3pt 0 var(--shadow-ink), var(--shadow-lift);
33
+ /* Recess: the soft falloff under a hard cast-shadow band, for anything sunk
34
+ into the wall (the fiction cavity, the lore/dm/choose sheets). */
35
+ --shadow-press: color-mix(in srgb, var(--ink-dark) 42%, transparent);
36
+ /* Light: a soft highlight across the top of a digital-display fill (a band,
37
+ a tab, a chip): the LED panel's sheen, layered over its colour. */
38
+ --light-gloss: linear-gradient(to bottom, color-mix(in srgb, var(--paper-cream) 30%, transparent), transparent 62%);
24
39
 
25
40
  /* ── Ink & Text — warm sepia drift, not neutral gray ───────────────────
26
41
  TAC figures in this file are MEASURED, not estimated: a swatch PDF
@@ -82,6 +97,10 @@
82
97
  --tint-hud-teal: #2a6a8a;/* TAC 175% (C85 M52 Y31 K8) */
83
98
 
84
99
  /* ── Type Families ────────────────────────────────────────────────────── */
100
+ /* Lixdu has one face, regular. Every rule that sets --font-display sets
101
+ font-weight: 400 (a test enforces it): a bold weight makes Chromium
102
+ synthesize a bold, which prints as a Type 3 font that Gutterpress's
103
+ PDF/X preserve-text split cannot keep (gutterpress#385). */
85
104
  --font-display: 'lixdu', 'Tomorrow', sans-serif;
86
105
  --font-tab: 'Tomorrow', 'lixdu', sans-serif;
87
106
  --font-body: 'Titillium Web', Georgia, sans-serif;
@@ -217,7 +217,7 @@
217
217
  border-bottom: 4px solid var(--frontmatter-accent);
218
218
  font-size: 26pt;
219
219
  letter-spacing: 0.32em;
220
- font-weight: 700;
220
+ font-weight: 400;
221
221
  }
222
222
 
223
223
  /* Lede flush-attaches to the masthead and passes straight into the next
@@ -458,7 +458,7 @@
458
458
  right: 0.5in;
459
459
  width: 0.42in;
460
460
  height: 11px;
461
- background: var(--dc-page-slip-tape);
461
+ background: color-mix(in srgb, var(--dc-page-slip-tape) 78%, transparent);
462
462
  border: 1px solid var(--dc-page-slip-edge);
463
463
  border-width: 1px 0;
464
464
  rotate: -2.5deg;
@@ -553,6 +553,9 @@
553
553
  --dc-card-grid-display: flex;
554
554
  --dc-card-grid-item-display: flex;
555
555
  --dc-card-grid-row: 3.05in;
556
+ --dc-card-grid-row-tall: 4.45in; /* the right page's rows */
557
+ --dc-card-grid-media-tall: 2.35in; /* their portraits */
558
+ --dc-card-grid-media-wide: 0.75in; /* the portrait of a card that spans both columns */
556
559
  --dc-card-grid-gap: 0.12in;
557
560
  --dc-intro-size: var(--fs-body-sm); /* the lede at body size, so the left page holds two rows of cards */
558
561
  }
@@ -573,6 +576,48 @@
573
576
  --dc-specialty-card-title-align: left;
574
577
  }
575
578
 
579
+ /* Dualist and Generalist, the two specialties built from the others, close the
580
+ spread: each spans both columns as the last row, Dualist under the left
581
+ page's four cards and Generalist under the right page's, whatever order the
582
+ book lists them in. The fifth of the other cards opens the right page, and
583
+ that page's rows are taller (it has no title or lede above them), with
584
+ taller portraits, so Generalist closes the page at its foot. */
585
+ .dc-page-specialty-catalog .dc-card-grid .dc-specialty:nth-child(-n + 4 of :not(.dualist, .generalist)) {
586
+ --dc-card-grid-item-order: 1;
587
+ }
588
+ .dc-page-specialty-catalog .dc-card-grid .dc-specialty:nth-child(n + 5 of :not(.dualist, .generalist)) {
589
+ --dc-card-grid-item-order: 3;
590
+ --dc-card-grid-row: var(--dc-card-grid-row-tall);
591
+ }
592
+ .dc-page-specialty-catalog .dc-card-grid .dc-specialty:nth-child(5 of :not(.dualist, .generalist)) {
593
+ --dc-card-grid-item-break: page;
594
+ }
595
+ .dc-page-specialty-catalog .dc-card-grid .dc-specialty:nth-child(n + 5 of :not(.dualist, .generalist)) > .dc-specialty-card {
596
+ --dc-specialty-card-media-height: var(--dc-card-grid-media-tall);
597
+ }
598
+ .dc-page-specialty-catalog .dc-card-grid .dc-specialty:is(.dualist, .generalist) {
599
+ --dc-card-grid-item-span: 2;
600
+ --dc-card-grid-row: 0;
601
+ }
602
+ .dc-page-specialty-catalog .dc-card-grid .dc-specialty.dualist {
603
+ --dc-card-grid-item-order: 2;
604
+ }
605
+ .dc-page-specialty-catalog .dc-card-grid .dc-specialty.generalist {
606
+ --dc-card-grid-item-order: 4;
607
+ }
608
+ /* A full-width card is the dense card again: the band on top, the portrait
609
+ floated left of the tagline and pitch. */
610
+ .dc-page-specialty-catalog .dc-card-grid :is(.dualist, .generalist) > .dc-specialty-card {
611
+ --dc-specialty-card-display: flow-root;
612
+ --dc-specialty-card-media-order: 0;
613
+ --dc-specialty-card-media-float: left;
614
+ --dc-specialty-card-media-float-even: left;
615
+ --dc-specialty-card-media-margin: 0 0.18in 0.06in 0;
616
+ --dc-specialty-card-media-margin-even: 0 0.18in 0.06in 0;
617
+ --dc-specialty-card-media-width: 2.4in;
618
+ --dc-specialty-card-media-height: var(--dc-card-grid-media-wide);
619
+ }
620
+
576
621
  /* A tape divider (`.dc-tape`: the MASTERS strip between creature blocks, a
577
622
  section break) never ends a page: it travels with what follows it. */
578
623
  .dc-tape {