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,315 @@
1
+ @layer dc.components {
2
+
3
+ /* ═══ SPECIALTY PARENT-CONTAINER VARIANTS ═══
4
+ Each .dc-specialty.<name> parent defines the FULL SHAPE FAMILY for that specialty
5
+ as CSS custom properties. All shape variables cascade to descendant components.
6
+ Component sub-blocks set only color/accent tokens.
7
+
8
+ Shape variable inventory (defined at parent, consumed by components):
9
+ --dc-skill-tab-shape → .dc-card-tab clip-path
10
+ --dc-skill-body-shape → .dc-card-body clip-path
11
+ --dc-path-title-shape → .dc-path-shell h2.dc-spray clip-path
12
+ --dc-path-shell-clip → .dc-path-shell clip-path
13
+ --dc-specialty-card-shell-shape → .dc-specialty-card clip-path
14
+ --dc-specialty-intro-title-shape → .dc-specialty-intro > h2 clip-path
15
+ --dc-specialty-intro-clip → .dc-specialty-intro clip-path
16
+
17
+ Title-covered corners (dc#28): the path-shell and specialty-intro ink
18
+ outlines are the panel polygon on a 2px-larger box, and the titles are
19
+ in-flow children with a clip of their own and no outline. A title cut
20
+ shallower than its panel's would reach past the outline un-inked, so the
21
+ panel cut EQUALS the title cut wherever the title covers the corner:
22
+ --dc-path-shell-clip == --dc-path-title-shape at top-left (the title
23
+ spans the shell minus its 12px padding-right, so it never reaches the
24
+ top-right corner, and a centre notch sits 6px left of the shell's);
25
+ --dc-specialty-intro-clip == --dc-specialty-intro-title-shape at both
26
+ top corners (the title spans the whole panel). */
27
+
28
+ /* ── Augmerc — cyber-augmentation, brand magenta + cyan accent, hex cuts ── */
29
+ /* ── Specialty identity + shape shared wiring (dc#38) ─────────────────────
30
+ Every .dc-specialty.<name> block below declares only its own identity
31
+ (--spec-accent/-mid/-dark, aliasing that specialty's own --<name>-accent/
32
+ -mid/-dark tokens) and its shape polygons. The four ONE-TIME wiring rules
33
+ here read --spec-* and apply it to every specialty's skill-card, path-
34
+ shell, specialty-intro and specialty-card — this is the pattern every
35
+ specialty followed identically (verified against all 10 blocks before
36
+ collapsing); a specialty needs its own extra override below ONLY where
37
+ its rendered value genuinely differs from this pattern (see the deltas
38
+ after augmerc/cybersurgeon/proxy/wirephreak/streetwarden/gutterdruid/
39
+ etherlock/generalist's blocks — technosorcerer and dualist need none).
40
+ Adding a new specialty: declare shape + --spec-accent/-mid/-dark in its
41
+ own .dc-specialty.<name> block; it gets correct skill-card/path-shell/
42
+ specialty-intro/specialty-card theming for free from these four rules. */
43
+ .dc-specialty .dc-skill-card {
44
+ --dc-card-accent: var(--spec-accent);
45
+ --dc-card-tab-bg: var(--spec-mid);
46
+ --dc-card-tab-title-color: var(--paper-cream);
47
+ }
48
+
49
+ .dc-specialty .dc-path-shell {
50
+ --dc-path-title-bg: var(--spec-dark);
51
+ --dc-path-accent: var(--spec-accent);
52
+ }
53
+
54
+ .dc-specialty .dc-specialty-intro {
55
+ --dc-specialty-intro-title-bg: var(--spec-dark);
56
+ --dc-specialty-intro-title-color: var(--paper-cream);
57
+ --dc-specialty-intro-bg: var(--paper-light);
58
+ }
59
+
60
+ .dc-specialty .dc-specialty-card {
61
+ --dc-specialty-card-bg: var(--paper-cream);
62
+ --dc-specialty-card-fg: var(--ink);
63
+ --dc-specialty-card-accent: var(--spec-mid);
64
+ --dc-specialty-card-border: var(--spec-mid);
65
+ --dc-specialty-card-title-color: var(--spec-dark);
66
+ }
67
+
68
+ /* ── Augmerc — cyber-augmentation, brand magenta + cyan accent, hex cuts ── */
69
+ .dc-specialty.augmerc {
70
+ --spec-accent: var(--augmerc-accent);
71
+ --spec-mid: var(--augmerc-mid);
72
+ --spec-dark: var(--augmerc-dark);
73
+ --dc-skill-tab-shape: polygon(14px 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%, 0 14px);
74
+ --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px));
75
+ /* Path title + shell clip-paths must AGREE at the top-right corner.
76
+ User feedback: "There's also a weird clipping issue in the top right
77
+ corner of biting distance similar to the OGMERK specialty intro."
78
+ Title is cut at 24px-from-right with 18px slope down. Shell is now
79
+ cut at the SAME 24px point so the title's TR cut sits flush against
80
+ the shell's TR cut instead of being exposed against a flat corner. */
81
+ --dc-path-title-shape: polygon(14px 0, calc(100% - 24px) 0, 100% 18px, 100% 100%, 0 100%, 0 14px);
82
+ --dc-path-shell-clip: polygon(14px 0, calc(100% - 24px) 0, 100% 18px, 100% calc(100% - 18px), calc(100% - 18px) 100%, 18px 100%, 0 calc(100% - 18px), 0 14px);
83
+ --dc-specialty-card-shell-shape: polygon(16px 0, 100% 0, 100% calc(100% - 16px), calc(100% - 16px) 100%, 0 100%, 0 16px);
84
+ /* Same fix on specialty-intro: intro-title is cut at 20px-from-right
85
+ with 16px slope. intro-clip now matches so the title's TR cut sits
86
+ flush against the container instead of being exposed against a
87
+ flat TR corner. */
88
+ --dc-specialty-intro-title-shape: polygon(14px 0, calc(100% - 20px) 0, 100% 16px, 100% 100%, 0 100%, 0 14px);
89
+ --dc-specialty-intro-clip: polygon(14px 0, calc(100% - 20px) 0, 100% 16px, 100% calc(100% - 18px), calc(100% - 18px) 100%, 0 100%, 0 14px);
90
+ }
91
+
92
+ /* Augmerc — paper poster with magenta ink. The specialty signature color
93
+ lives in the border + title, not the substrate — accent/border key on
94
+ the specialty's ACCENT token, not the shared --spec-mid pattern (a
95
+ genuine per-specialty delta, along with cybersurgeon below). Keeps the
96
+ card readable as a flyer pasted on the brick wall, not a painted plaque. */
97
+ .dc-specialty.augmerc .dc-specialty-card {
98
+ --dc-specialty-card-accent: var(--brand-magenta);
99
+ --dc-specialty-card-border: var(--brand-magenta);
100
+ --dc-specialty-card-shadow: inset 0 0 0 1.5pt var(--brand-magenta);
101
+ }
102
+
103
+ /* ── Cybersurgeon — precision surgical, silver, top-right diagonal ──────── */
104
+ .dc-specialty.cybersurgeon {
105
+ --spec-accent: var(--cybersurgeon-accent);
106
+ --spec-mid: var(--cybersurgeon-mid);
107
+ --spec-dark: var(--cybersurgeon-dark);
108
+ /* Tab diagonal capped at 18px — the 30px original exceeded the ~27px tab height,
109
+ making the polygon degenerate (right edge nearly invisible). */
110
+ --dc-skill-tab-shape: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%);
111
+ --dc-skill-body-shape: polygon(0 0, calc(100% - 28px) 0, 100% 28px, 100% 100%, 0 100%);
112
+ --dc-path-title-shape: polygon(0 0, calc(100% - 28px) 0, 100% 28px, 100% 100%, 0 100%);
113
+ --dc-path-shell-clip: polygon(0 0, calc(100% - 26px) 0, 100% 26px, 100% 100%, 0 100%);
114
+ --dc-specialty-card-shell-shape: polygon(0 0, calc(100% - 24px) 0, 100% 24px, 100% 100%, 0 100%);
115
+ --dc-specialty-intro-title-shape: polygon(0 0, calc(100% - 28px) 0, 100% 28px, 100% 100%, 0 100%);
116
+ --dc-specialty-intro-clip: polygon(0 0, calc(100% - 28px) 0, 100% 28px, 100% 100%, 0 100%);
117
+ }
118
+
119
+ /* Cybersurgeon — accent/border key on the shared HUD-blue chrome token,
120
+ not the specialty's own --spec-mid (a genuine delta; see augmerc above). */
121
+ .dc-specialty.cybersurgeon .dc-specialty-card {
122
+ --dc-specialty-card-accent: var(--hud-blue-dark);
123
+ --dc-specialty-card-border: var(--hud-blue-dark);
124
+ --dc-specialty-card-shadow: inset 0 0 0 1.5pt var(--hud-blue-dark);
125
+ }
126
+
127
+ /* ── Proxy — covert, orange, top-left step + diagonal bottom ────────────── */
128
+ .dc-specialty.proxy {
129
+ --spec-accent: var(--proxy-accent);
130
+ --spec-mid: var(--proxy-mid);
131
+ --spec-dark: var(--proxy-dark);
132
+ --dc-skill-tab-shape: polygon(0 18px, 18px 0, 100% 0, 100% 100%, 0 100%);
133
+ --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 36px), calc(100% - 52px) 100%, 0 100%);
134
+ --dc-path-title-shape: polygon(0 18px, 18px 0, 100% 0, 100% 100%, 0 100%);
135
+ --dc-path-shell-clip: polygon(0 18px, 18px 0, 100% 0, 100% calc(100% - 34px), calc(100% - 56px) 100%, 0 100%);
136
+ --dc-specialty-card-shell-shape: polygon(0 16px, 16px 0, 100% 0, 100% calc(100% - 24px), calc(100% - 36px) 100%, 0 100%);
137
+ --dc-specialty-intro-title-shape: polygon(0 18px, 18px 0, 100% 0, 100% 100%, 0 100%);
138
+ --dc-specialty-intro-clip: polygon(0 18px, 18px 0, 100% 0, 100% calc(100% - 36px), calc(100% - 56px) 100%, 0 100%);
139
+ }
140
+
141
+ .dc-specialty.proxy .dc-specialty-card {
142
+ --dc-specialty-card-bg: var(--paper-aged);
143
+ }
144
+
145
+ /* ── Wirephreak — hacker, magenta, asymmetric cross-cuts ───────────────── */
146
+ .dc-specialty.wirephreak {
147
+ --spec-accent: var(--wirephreak-accent);
148
+ --spec-mid: var(--wirephreak-mid);
149
+ --spec-dark: var(--wirephreak-dark);
150
+ --dc-skill-tab-shape: polygon(0 0, calc(100% - 24px) 0, 100% 24px, 100% 100%, 24px 100%, 0 calc(100% - 10px));
151
+ --dc-skill-body-shape: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 22px 100%, 0 calc(100% - 14px));
152
+ --dc-path-title-shape: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 0 100%);
153
+ --dc-path-shell-clip: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% calc(100% - 10px), calc(100% - 16px) 100%, 16px 100%, 0 calc(100% - 16px));
154
+ --dc-specialty-card-shell-shape: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 18px 100%, 0 calc(100% - 12px));
155
+ --dc-specialty-intro-title-shape: polygon(0 0, calc(100% - 24px) 0, 100% 24px, 100% 100%, 0 100%);
156
+ --dc-specialty-intro-clip: polygon(0 0, calc(100% - 24px) 0, 100% 24px, 100% calc(100% - 12px), calc(100% - 18px) 100%, 18px 100%, 0 calc(100% - 18px));
157
+ }
158
+
159
+ .dc-specialty.wirephreak .dc-specialty-card {
160
+ --dc-specialty-card-shadow: inset 0 0 0 1.5pt var(--wirephreak-mid);
161
+ }
162
+
163
+ /* ── Streetwarden — community defender, green, soft diamond cuts ──────── */
164
+ .dc-specialty.streetwarden {
165
+ --spec-accent: var(--streetwarden-accent);
166
+ --spec-mid: var(--streetwarden-mid);
167
+ --spec-dark: var(--streetwarden-dark);
168
+ --dc-skill-tab-shape: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
169
+ --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 18px), calc(100% - 22px) 100%, 22px 100%, 0 calc(100% - 18px));
170
+ --dc-path-title-shape: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
171
+ --dc-path-shell-clip: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% calc(100% - 20px), calc(100% - 28px) 100%, 28px 100%, 0 calc(100% - 20px));
172
+ --dc-specialty-card-shell-shape: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% calc(100% - 16px), calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 16px));
173
+ --dc-specialty-intro-title-shape: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%);
174
+ --dc-specialty-intro-clip: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% calc(100% - 20px), calc(100% - 28px) 100%, 28px 100%, 0 calc(100% - 20px));
175
+ }
176
+
177
+ .dc-specialty.streetwarden .dc-specialty-card {
178
+ --dc-specialty-card-bg: var(--paper-light);
179
+ }
180
+
181
+ /* ── Technosorcerer — arcane + tech, indigo, top-center gate notch ──────── */
182
+ .dc-specialty.technosorcerer {
183
+ --spec-accent: var(--technosorcerer-accent);
184
+ --spec-mid: var(--technosorcerer-mid);
185
+ --spec-dark: var(--technosorcerer-dark);
186
+ --dc-skill-tab-shape: polygon(0 0, calc(50% - 20px) 0, 50% 12px, calc(50% + 20px) 0, 100% 0, 100% 100%, 0 100%);
187
+ --dc-skill-body-shape: polygon(0 0, calc(50% - 18px) 0, 50% 10px, calc(50% + 18px) 0, 100% 0, 100% calc(100% - 20px), calc(100% - 24px) 100%, 24px 100%, 0 calc(100% - 20px));
188
+ --dc-path-title-shape: polygon(0 0, calc(50% - 22px) 0, 50% 12px, calc(50% + 22px) 0, 100% 0, 100% 100%, 0 100%);
189
+ /* The title's notch is centred 6px left of the shell's (see the header
190
+ note), so the visible gate is the shell's LEFT notch edge meeting the
191
+ title's RIGHT notch edge at (50% - 4.46px, 11.16px): the union the
192
+ drop-shadow used to outline. The shell traces that union so its outline
193
+ inks both edges of the gate. */
194
+ --dc-path-shell-clip: polygon(0 0, calc(50% - 22px) 0, calc(50% - 4.46px) 11.16px, calc(50% + 16px) 0, 100% 0, 100% calc(100% - 22px), calc(100% - 26px) 100%, 26px 100%, 0 calc(100% - 22px));
195
+ /* Specialty-card shell: rectangular top (tech-cluster register at grid
196
+ scale) with hex-cut bottom corners preserving the ritual-tech crossover
197
+ feel. The centre-notch lives on path-shell / specialty-intro only —
198
+ where it has the space to read as the runic-gate signature. At grid
199
+ density it collapsed into the magic cluster; rectangular top reads
200
+ tech immediately. */
201
+ --dc-specialty-card-shell-shape: polygon(0 0, 100% 0, 100% calc(100% - 16px), calc(100% - 22px) 100%, 22px 100%, 0 calc(100% - 16px));
202
+ --dc-specialty-intro-title-shape: polygon(0 0, calc(50% - 24px) 0, 50% 14px, calc(50% + 24px) 0, 100% 0, 100% 100%, 0 100%);
203
+ --dc-specialty-intro-clip: polygon(0 0, calc(50% - 24px) 0, 50% 14px, calc(50% + 24px) 0, 100% 0, 100% calc(100% - 32px), calc(100% - 56px) 100%, 0 100%);
204
+ }
205
+
206
+ /* TECHNOSORCERER title fix — "TECHNOSORCERER" is 14 chars and wraps mid-word
207
+ at card-grid scale ("TECHNOSORCERE / R" orphan). Tightened letter-spacing
208
+ keeps it on one line at the lixdu display size used in the card title.
209
+ (No specialty-card token delta: technosorcerer takes every default from
210
+ the shared wiring block above unchanged.) */
211
+ .dc-specialty.technosorcerer .dc-specialty-card h3 {
212
+ letter-spacing: -0.04em;
213
+ font-size: 1.05em;
214
+ }
215
+
216
+ /* ── Gutterdruid — street nature, amber-brown, center bottom pinch ──────── */
217
+ .dc-specialty.gutterdruid {
218
+ --spec-accent: var(--gutterdruid-accent);
219
+ --spec-mid: var(--gutterdruid-mid);
220
+ --spec-dark: var(--gutterdruid-dark);
221
+ --dc-skill-tab-shape: polygon(0 0, calc(50% - 20px) 0, 50% 12px, calc(50% + 20px) 0, 100% 0, 100% 100%, 0 100%);
222
+ --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 24px), calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 24px));
223
+ --dc-path-title-shape: polygon(0 0, calc(50% - 22px) 0, 50% 12px, calc(50% + 22px) 0, 100% 0, 100% 100%, 0 100%);
224
+ --dc-path-shell-clip: polygon(0 0, 100% 0, 100% calc(100% - 28px), calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 28px));
225
+ --dc-specialty-card-shell-shape: polygon(0 0, 100% 0, 100% calc(100% - 20px), calc(100% - 18px) 100%, 18px 100%, 0 calc(100% - 20px));
226
+ --dc-specialty-intro-title-shape: polygon(0 0, calc(50% - 22px) 0, 50% 12px, calc(50% + 22px) 0, 100% 0, 100% 100%, 0 100%);
227
+ --dc-specialty-intro-clip: polygon(0 0, 100% 0, 100% calc(100% - 28px), calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 28px));
228
+ }
229
+
230
+ .dc-specialty.gutterdruid .dc-specialty-card {
231
+ --dc-specialty-card-bg: var(--paper-aged);
232
+ }
233
+
234
+ /* ── Etherlock — ethereal, gold, parallelogram cross-cuts ──────────────── */
235
+ .dc-specialty.etherlock {
236
+ --spec-accent: var(--etherlock-accent);
237
+ --spec-mid: var(--etherlock-mid);
238
+ --spec-dark: var(--etherlock-dark);
239
+ --dc-skill-tab-shape: polygon(0 10px, 10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%);
240
+ --dc-skill-body-shape: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 18px 100%, 0 calc(100% - 20px));
241
+ --dc-path-title-shape: polygon(0 12px, 12px 0, 100% 0, 100% 100%, 0 100%);
242
+ --dc-path-shell-clip: polygon(0 12px, 12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 18px 100%, 0 calc(100% - 22px));
243
+ --dc-specialty-card-shell-shape: polygon(0 12px, 12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 16px 100%, 0 calc(100% - 18px));
244
+ --dc-specialty-intro-title-shape: polygon(0 14px, 14px 0, 100% 0, 100% 100%, 0 100%);
245
+ --dc-specialty-intro-clip: polygon(0 14px, 14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 18px) 100%, 20px 100%, 0 calc(100% - 24px));
246
+ }
247
+
248
+ .dc-specialty.etherlock .dc-specialty-card {
249
+ --dc-specialty-card-bg: var(--paper-aged);
250
+ }
251
+
252
+ /* ── Dualist — dual-class specialist, symmetric "two-sided" octagon shapes ─ */
253
+ .dc-specialty.dualist {
254
+ --spec-accent: var(--dualist-accent);
255
+ --spec-mid: var(--dualist-mid);
256
+ --spec-dark: var(--dualist-dark);
257
+ --dc-skill-tab-shape: polygon(10px 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%, 0 10px);
258
+ --dc-skill-body-shape: polygon(12px 0, calc(100% - 12px) 0, 100% 12px, 100% calc(100% - 12px), calc(100% - 12px) 100%, 12px 100%, 0 calc(100% - 12px), 0 12px);
259
+ --dc-path-title-shape: polygon(12px 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%, 0 12px);
260
+ --dc-path-shell-clip: polygon(12px 0, calc(100% - 14px) 0, 100% 14px, 100% calc(100% - 14px), calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px), 0 12px);
261
+ /* Dualist card shape: flat top + symmetric bottom point — crystal-facet
262
+ hint preserved on the bottom edge (the "refractive" bottom-pointed
263
+ drop), but a flat top so the colored header band renders as a clean
264
+ rectangle. Previous full-lozenge clipped the header band into a
265
+ triangle. */
266
+ --dc-specialty-card-shell-shape: polygon(0 0, 100% 0, 100% calc(100% - 22px), calc(100% - 20px) 100%, 50% calc(100% - 4px), 20px 100%, 0 calc(100% - 22px));
267
+ --dc-specialty-intro-title-shape: polygon(14px 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%, 0 14px);
268
+ --dc-specialty-intro-clip: polygon(14px 0, calc(100% - 14px) 0, 100% 14px, 100% calc(100% - 16px), calc(100% - 16px) 100%, 16px 100%, 0 calc(100% - 16px), 0 14px);
269
+ }
270
+ /* (No specialty-card token delta: dualist takes every default from the
271
+ shared wiring block above unchanged.) */
272
+
273
+ /* ── Generalist — jack-of-all-trades, soft chamfered rectangle (neutral) ─── */
274
+ .dc-specialty.generalist {
275
+ --spec-accent: var(--generalist-accent);
276
+ --spec-mid: var(--generalist-mid);
277
+ --spec-dark: var(--generalist-dark);
278
+ --dc-skill-tab-shape: polygon(4px 0, calc(100% - 4px) 0, 100% 4px, 100% 100%, 0 100%, 0 4px);
279
+ --dc-skill-body-shape: polygon(4px 0, calc(100% - 4px) 0, 100% 4px, 100% calc(100% - 4px), calc(100% - 4px) 100%, 4px 100%, 0 calc(100% - 4px), 0 4px);
280
+ --dc-path-title-shape: polygon(5px 0, calc(100% - 5px) 0, 100% 5px, 100% 100%, 0 100%, 0 5px);
281
+ --dc-path-shell-clip: polygon(5px 0, calc(100% - 6px) 0, 100% 6px, 100% calc(100% - 6px), calc(100% - 6px) 100%, 6px 100%, 0 calc(100% - 6px), 0 5px);
282
+ --dc-specialty-card-shell-shape: polygon(6px 0, calc(100% - 6px) 0, 100% 6px, 100% calc(100% - 6px), calc(100% - 6px) 100%, 6px 100%, 0 calc(100% - 6px), 0 6px);
283
+ --dc-specialty-intro-title-shape: polygon(6px 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 0 100%, 0 6px);
284
+ --dc-specialty-intro-clip: polygon(6px 0, calc(100% - 6px) 0, 100% 6px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 8px 100%, 0 calc(100% - 8px), 0 6px);
285
+ }
286
+
287
+ .dc-specialty.generalist .dc-specialty-card {
288
+ --dc-specialty-card-bg: var(--paper-light);
289
+ }
290
+
291
+ /* ───────── AP TAGS ───────── */
292
+
293
+ /* Standard action point — explicit class for documentation clarity */
294
+ .dc-ap.standard {
295
+ --dc-ap-bg: var(--hud-blue-dark);
296
+ }
297
+
298
+ /* Reduced-cost action */
299
+ .dc-ap.reduced {
300
+ --dc-ap-bg: var(--hud-blue-dim);
301
+ --dc-ap-fg: var(--ink);
302
+ }
303
+
304
+ /* Increased-cost action */
305
+ .dc-ap.increased {
306
+ --dc-ap-bg: var(--blood);
307
+ }
308
+
309
+ /* Special action — amber */
310
+ .dc-ap.special {
311
+ --dc-ap-bg: var(--amber);
312
+ --dc-ap-fg: var(--ink);
313
+ }
314
+
315
+ }
@@ -0,0 +1,273 @@
1
+ @layer dc.components {
2
+
3
+ /* ═══ LEARNING PATH + SPECIALTY INTRO + SPECIALTY CARD ═══ */
4
+
5
+ /* Token contract for .dc-specialty-intro:
6
+ --dc-specialty-intro-title-bg → title-tab background (default --hud-magenta)
7
+ --dc-specialty-intro-title-color → title-tab text color (default --bg)
8
+ --dc-specialty-intro-bg → body panel surface (default --paper-cream)
9
+ --dc-specialty-intro-title-shape → title-tab clip-path polygon
10
+ --dc-specialty-intro-clip → body shell clip-path polygon
11
+ Specialty themes override via .dc-specialty.<name> .dc-specialty-intro { }. */
12
+
13
+ /* ── Specialty intro shell + element overrides ────────────────────────── */
14
+ /* Token defaults for .dc-specialty-intro are declared in :root in dc-component-defaults.css.
15
+ Specialty contexts override via .dc-specialty.<name> .dc-specialty-intro { } above. */
16
+ .dc-specialty-intro {
17
+ /* NO clip-path here — surface + clip are on ::before, the ink outline on
18
+ ::after; an element with clip-path would clip both (dc#28). */
19
+ background: transparent;
20
+ padding: 1rem 1.25rem 0.75rem;
21
+ margin: 0;
22
+ /* The ink outline (::after) is a positioned box 2px past this panel on
23
+ every side, and a box past the page content box makes Chromium print
24
+ shrink-to-fit scale the whole book (the engine's width guard refuses
25
+ it). Clipping this panel's own horizontal overflow contains it — the
26
+ guard and Chromium both treat clipped overflow as contained — and it
27
+ changes nothing visible: the panel spans the page content box, so the
28
+ page already clipped the filter's rim at exactly these two edges. */
29
+ overflow-x: clip;
30
+ position: relative;
31
+ z-index: 1;
32
+ break-inside: avoid;
33
+ box-sizing: border-box;
34
+ border: none;
35
+ }
36
+
37
+ /* Substrate behind the content, not under a lift — same reasoning as
38
+ `.section::before`; see the containing-block note there. The host is
39
+ already a stacking context (`position: relative; z-index: 1`), so -1
40
+ stays inside this component. */
41
+ .dc-specialty-intro::before {
42
+ content: '';
43
+ position: absolute;
44
+ inset: 0;
45
+ background: var(--dc-specialty-intro-bg);
46
+ clip-path: var(--dc-specialty-intro-clip);
47
+ z-index: -1;
48
+ }
49
+
50
+ /* 2px ink outline: the shell shape on a box 2px larger on every side, filled
51
+ with ink, behind the surface. Replaces the 4-way drop-shadow(±2px) filter,
52
+ which rasterized the panel and its prose (dc#28). The title (h2) is an
53
+ in-flow child with its own clip and no outline of its own, so every intro
54
+ clip equals its title shape at both top corners (specialty-identity.css,
55
+ "Title-covered corners").
56
+ The box starts AT the panel's top and is translated up 2px, rather than
57
+ starting 2px above it: every field-guide intro opens its chapter at the
58
+ top of a page, and Chromium pushes a positioned box that would start
59
+ before the page's content area down to it — the whole outline landed 2px
60
+ low (measured in the PDF's clip polygons), thinning the top-corner rims
61
+ to half and hiding the technosorcerer gate's rim under the title. A
62
+ transform is applied at paint and does not take part in fragmentation. */
63
+ .dc-specialty-intro::after {
64
+ content: '';
65
+ position: absolute;
66
+ top: 0;
67
+ right: -2px;
68
+ bottom: -4px;
69
+ left: -2px;
70
+ transform: translateY(-2px);
71
+ background: var(--ink);
72
+ clip-path: var(--dc-specialty-intro-clip);
73
+ z-index: -2;
74
+ }
75
+
76
+ .dc-specialty-intro>h2:first-child {
77
+ font-size: 1.6rem;
78
+ color: var(--dc-specialty-intro-title-color);
79
+ letter-spacing: 0.04em;
80
+ line-height: 1;
81
+ background: var(--dc-specialty-intro-title-bg);
82
+ display: block;
83
+ padding: 0.6rem 1.25rem;
84
+ margin: -1rem -1.25rem 0.6rem -1.25rem;
85
+ clip-path: var(--dc-specialty-intro-title-shape);
86
+ border: none;
87
+ break-after: avoid;
88
+ }
89
+
90
+ .dc-specialty-intro>h3 {
91
+ /* --crimson on paper-cream = 4.03 (fails AA). --blood = 7.73:1.
92
+ The band is design: it reads as a hard-edged "wall object" and keeps
93
+ the h3 legible independent of the ::before pseudo-panel behind it. */
94
+ color: var(--blood);
95
+ background: var(--paper-cream);
96
+ letter-spacing: 0.05em;
97
+ font-size: 1rem;
98
+ margin-top: 0.6rem;
99
+ margin-bottom: 0.2rem;
100
+ padding: 0.15rem 0.4rem 0.25rem;
101
+ border-bottom: 2px solid var(--blood);
102
+ }
103
+
104
+ .dc-specialty-intro>p {
105
+ margin-block: 0.3rem;
106
+ font-size: 9.5pt;
107
+ line-height: 1.5;
108
+ }
109
+
110
+ .dc-specialty-intro>h2:first-child+p {
111
+ margin-top: 0.2rem;
112
+ }
113
+
114
+ .dc-specialty-intro>ul,
115
+ .dc-specialty-intro>ol {
116
+ margin-block: 0.45rem;
117
+ padding-left: 1.2rem;
118
+ }
119
+
120
+ .dc-specialty-intro> :last-child {
121
+ margin-bottom: 0;
122
+ }
123
+
124
+ /* ── Specialty section content (blockquote, h3 — component rules win for h2) ─── */
125
+ /* LIVE inside plugin-emitted specialty sections. */
126
+ .dc-specialty blockquote {
127
+ margin: 0.12in 0;
128
+ padding: 0.08in 0.12in;
129
+ }
130
+
131
+ /* LIVE inside plugin-emitted specialty sections. */
132
+ .dc-specialty h3 {
133
+ margin-top: 0.18in;
134
+ padding-top: 0.08in;
135
+ border-top: var(--bw-thin) solid var(--orange);
136
+ }
137
+
138
+ /* Token contract for .dc-specialty-card:
139
+ --dc-specialty-card-bg → card body background (default --paper-cream)
140
+ --dc-specialty-card-border → outer card border color (default --hud-blue)
141
+ --dc-specialty-card-accent → inner accent rule color (default --crimson)
142
+ --dc-specialty-card-fg → body text color (default --ink)
143
+ --dc-specialty-card-media-width → portrait image width (default 0.75in)
144
+ --dc-specialty-card-media-height → portrait image height (default 0.85in)
145
+ --dc-specialty-card-title-align → title text-align (default right)
146
+ --dc-specialty-card-shell-shape → outer clip-path polygon
147
+ --dc-specialty-card-shadow → box-shadow (default none) — future-tech-high
148
+ specialties opt into LED-rim inset highlight here
149
+ Specialty themes override via .dc-specialty.<name> .dc-specialty-card { }. */
150
+
151
+ /* ── Specialty card (.dc-specialty-card + descendants + nth-of-type(even)) */
152
+ /* Token defaults for .dc-specialty-card are declared in :root in dc-component-defaults.css.
153
+ Specialty contexts override via .dc-specialty.<name> .dc-specialty-card { } above. */
154
+ .dc-specialty-card {
155
+ /* Stack the optional per-specialty shadow on top of the universal
156
+ poster-wall shadow. The poster shadow pins the card to the brick
157
+ wall as a physical object (hard offset, no blur — "stuck on" not
158
+ "floating"). Specialty themes can add LED-rim insets via the
159
+ shadow token without losing the wall-pin. */
160
+ box-shadow: var(--dc-specialty-card-shadow), var(--shadow-poster);
161
+ /* Poster-header pattern: thick colored TOP border = the specialty's
162
+ header ribbon. paper-cream body below = the printed flyer substrate.
163
+ Title h3 + body content sit inside the padding box, naturally below
164
+ the border (which is part of the box model, not content area).
165
+ This puts the specialty signature in the band + title color + side
166
+ border — NOT in the card body. Reads as a printed poster pasted on
167
+ the brick wall, not a painted plaque. */
168
+ background: var(--dc-specialty-card-bg);
169
+ color: var(--dc-specialty-card-fg);
170
+ display: flow-root;
171
+ overflow: hidden;
172
+ line-height: var(--lh-tight);
173
+ /* --dc-card-gap is the VISIBLE gap; +4px clears this card's box-shadow
174
+ bleed (--shadow-poster paints below the border-box) plus the next
175
+ card's. Note .dc-card-grid below resets this to 0 — the grid packs
176
+ cards deliberately tight and owns its own spacing. */
177
+ margin: 0 0 calc(var(--dc-card-gap) + 4px) 0;
178
+ padding: 0.14in 0.18in 0.18in 0.18in;
179
+ position: relative;
180
+ break-inside: avoid;
181
+ border: 1.5pt solid var(--dc-specialty-card-border);
182
+ border-top: var(--dc-specialty-card-band-height) solid var(--dc-specialty-card-accent);
183
+ border-left: 3pt solid var(--dc-specialty-card-accent);
184
+ /* Top band gets a small chip cut at the upper-right to break the flat
185
+ rectangle reading. Per user feedback: "a little more clip path
186
+ treatments on the top border of the specialty cards." Per-specialty
187
+ overrides via --dc-specialty-card-shell-shape still take precedence;
188
+ the new default has a 12px chamfer at the top-right corner. */
189
+ clip-path: var(--dc-specialty-card-shell-shape);
190
+ }
191
+
192
+ /* Portrait image floated in specialty card. */
193
+ .dc-specialty-card img {
194
+ width: var(--dc-specialty-card-media-width);
195
+ height: var(--dc-specialty-card-media-height);
196
+ object-fit: cover;
197
+ border: none;
198
+ padding: 0;
199
+ box-sizing: border-box;
200
+ float: left;
201
+ margin: 0 0.14in 0.08in 0;
202
+ border-radius: 2px;
203
+ }
204
+
205
+ /* Specialty name heading — colored in the specialty's accent (the "ink"
206
+ on the paper-poster substrate). Each specialty's identity color shows
207
+ here, in the border, and in the body-accent rule — NOT in the card
208
+ background. The card itself stays paper-cream so the colored elements
209
+ read as ink on paper, not as a painted card. */
210
+ .dc-specialty-card h3 {
211
+ margin: 0;
212
+ font-size: 1.15em;
213
+ color: var(--dc-specialty-card-title-color);
214
+ text-align: var(--dc-specialty-card-title-align);
215
+ white-space: normal;
216
+ overflow-wrap: anywhere;
217
+ text-wrap: balance;
218
+ }
219
+
220
+ /* Subtitle tagline — the specialty's "archetype label" (e.g.,
221
+ "Cybernetic Commando", "Wold Witch"). This is the card's INTERIOR
222
+ visual beat per contest judge R9 ("each specialty card needs one
223
+ nail hole — a single strong visual beat inside the card body").
224
+ Mono-caps + tracked + accent-colored + bottom-rule gives the card
225
+ a typographic anchor below the title, lifting the interior from
226
+ "uniform cream surface" to a structured stat-block-like reading. */
227
+ .dc-specialty-card blockquote {
228
+ background: none;
229
+ border: none;
230
+ border-bottom: 0.75pt solid var(--dc-specialty-card-accent);
231
+ padding: 0 0.06in 0.03in;
232
+ margin: 0.02in 0 0.06in;
233
+ font-family: var(--font-mono);
234
+ font-size: 0.72em;
235
+ font-style: normal;
236
+ font-weight: 600;
237
+ letter-spacing: 0.12em;
238
+ text-transform: uppercase;
239
+ /* Use the dark variant for text (WCAG safe on cream); border stays
240
+ bright (graphic separation, not body-text rule). Falls back to the
241
+ accent for any specialty that hasn't defined its dark variant. */
242
+ color: var(--dc-specialty-card-title-color);
243
+ opacity: 1;
244
+ text-align: var(--dc-specialty-card-title-align);
245
+ white-space: normal;
246
+ overflow-wrap: anywhere;
247
+ }
248
+
249
+ /* Card body paragraph spacing. */
250
+ .dc-specialty-card p {
251
+ margin-top: 0.02in;
252
+ margin-bottom: 0;
253
+ line-height: 1.35;
254
+ color: var(--dc-specialty-card-fg);
255
+ overflow-wrap: anywhere;
256
+ }
257
+
258
+ /* Even cards flip the border accent to the right. data-position is emitted by
259
+ the plugin (specialtyCardCount resets per-specialty), which counts within a
260
+ specialty — :nth-of-type() would count within the DOM parent instead. */
261
+ .dc-specialty-card[data-position="even"] {
262
+ --dc-specialty-card-title-align: left;
263
+
264
+ border-left: 1.5px solid var(--dc-specialty-card-border);
265
+ border-right: var(--callout-border-width-small) solid var(--dc-specialty-card-accent);
266
+ }
267
+
268
+ .dc-specialty-card[data-position="even"] img {
269
+ float: right;
270
+ margin: 0 0 0.08in 0.14in;
271
+ }
272
+
273
+ }