gp-dimm-city 1.6.0 → 1.6.1

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,28 @@ cut a version that has no `## [X.Y.Z]` heading below.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.6.1] - 2026-10-12
11
+
12
+ ### Changed
13
+
14
+ - **Faction cards split across pages.** A `@faction` profile runs to half a page
15
+ or more; kept whole, a chapter of factions left half-empty pages. It now
16
+ splits between paragraphs like an entry; the name stays with its first lines,
17
+ and `.dc-avoid-split` on the marker keeps one whole.
18
+ - **The outcome ladder keeps its table's header.** The two header cells
19
+ (`Roll | Result`, `d20 | Repair Time`, …) now sit in the ladder's label bar
20
+ over the two columns, instead of being dropped for a fixed "Outcomes" label.
21
+ A table with an empty header, and `@outcome`, still say "Outcomes". The bar
22
+ is the same height, so no page moves.
23
+ - **ROLL THE DIE! is set in the text, not as a chip.** The phrase (and ROLL A
24
+ DIE!, ROLLS A DIE!, ROLLING THE DIE!) keeps the font and size of the text
25
+ around it and is bold, in a contrasting colour (`--dc-roll-the-die-color`,
26
+ default `--blood`), and underlined.
27
+
28
+ ### Removed
29
+
30
+ - `--dc-roll-the-die-border`: the phrase has no border any more.
31
+
10
32
  ## [1.6.0] - 2026-10-12
11
33
 
12
34
  ### Added
package/components.yaml CHANGED
@@ -511,7 +511,7 @@ components:
511
511
  recipe: "ROLL THE DIE! (automatic in markdown prose, uppercase only: ROLL|ROLLS|ROLLING + A|THE + DIE! — e.g. ROLL A DIE!, ROLLS A DIE!, ROLLING THE DIE!; code spans, raw HTML and headings are left alone)"
512
512
  emits: span.dc-roll-the-die
513
513
  css: styles/components/cards.css
514
- tokens: [--dc-roll-the-die-color, --dc-roll-the-die-border]
514
+ tokens: [--dc-roll-the-die-color]
515
515
  usage: ["ROLL THE DIE!", "ROLL A DIE!", "ROLLS A DIE!", "ROLLING THE DIE!"]
516
516
  breaks: none
517
517
  notes: "A plain inline box (stamped label look): its padding and border paint around the text without making the line taller, so a line with a chip is the same height as one without. It never wraps: a chip that would straddle a line end moves to the next line whole."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gp-dimm-city",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "Dimm City design system for Gutterpress: the markdown-it macros (@skill, @specialty, @learning-path, @callout, …), print stylesheets, design tokens, fonts and page templates the Dimm City TTRPG books are set in.",
5
5
  "type": "module",
6
6
  "main": "plugin.js",
package/plugin.js CHANGED
@@ -396,7 +396,8 @@ function parseBand(cell) {
396
396
  return lo <= hi ? [lo, hi] : null;
397
397
  }
398
398
 
399
- // The ladder rows of a table, or null when it is not a ladder.
399
+ // The ladder of a table — its header cells and its rows — or null when it is
400
+ // not a ladder.
400
401
  function ladderRows(table) {
401
402
  const { head, rows } = table;
402
403
  if (head.length !== 2 || rows.length !== LADDER_BANDS_COUNT || rows.some((r) => r.length !== 2)) return null;
@@ -404,16 +405,23 @@ function ladderRows(table) {
404
405
  if (bands.some((b) => !b)) return null;
405
406
  const keys = bands.map(([lo, hi]) => (lo === hi ? String(lo) : lo + '-' + hi));
406
407
  if (new Set(keys).size !== LADDER_BANDS_COUNT || keys.some((k) => !Object.hasOwn(LADDER_TIER_OF_BAND, k))) return null;
407
- return rows.map((r, i) => {
408
- const tier = LADDER_TIER_OF_BAND[keys[i]];
409
- return { tier, name: OUTCOME_NAMES[tier], roll: keys[i].replace('-', '\u2013'), text: r[1].trim() };
410
- });
408
+ return {
409
+ head,
410
+ rows: rows.map((r, i) => {
411
+ const tier = LADDER_TIER_OF_BAND[keys[i]];
412
+ return { tier, name: OUTCOME_NAMES[tier], roll: keys[i].replace('-', '\u2013'), text: r[1].trim() };
413
+ }),
414
+ };
411
415
  }
412
416
 
413
417
  // The ladder's label bar and one row per `{ tier, name, roll, text }`; `text`
414
418
  // is markdown, so **bold** and ROLL THE DIE! render as they do anywhere else.
415
- function outcomeRowsHtml(rows, md) {
416
- let html = ' <div class="dc-outcomes-label">Outcomes</div>\n';
419
+ // A ladder made from a table keeps the table's header: its two cells sit in the
420
+ // label bar over the two columns. With no header text the bar says "Outcomes".
421
+ function outcomeRowsHtml(rows, md, head = []) {
422
+ let html = head.some((cell) => cell.trim())
423
+ ? ' <div class="dc-outcomes-label dc-outcomes-head">' + head.map((cell) => '<span>' + md.renderInline(cell.trim()) + '</span>').join('') + '</div>\n'
424
+ : ' <div class="dc-outcomes-label">Outcomes</div>\n';
417
425
  rows.forEach(({ tier, name, roll, text }) => {
418
426
  html += ' <div class="dc-outcome-row ' + tier + '">\n';
419
427
  html += ' <span class="dc-outcome-key tier-' + tier + '"><span class="dc-outcome-name">' + esc(name) + '</span><span class="dc-outcome-roll">' + esc(roll) + '</span></span>\n';
@@ -424,7 +432,7 @@ function outcomeRowsHtml(rows, md) {
424
432
  }
425
433
 
426
434
  // A table of the five standard bands: tier and name come from the band.
427
- function buildLadderBlock(rows, md, needsAvoid = true) {
435
+ function buildLadderBlock({ head, rows }, md, needsAvoid = true) {
428
436
  // data-break-inside="avoid" is added when the parent card can be split (is
429
437
  // not avoid-split) — the polyfill needs this to keep the
430
438
  // outcomes table together when the card itself isn't protected. When the card
@@ -433,7 +441,7 @@ function buildLadderBlock(rows, md, needsAvoid = true) {
433
441
  // by splitting the card at the outcomes boundary, leaving a headless
434
442
  // card-body on one page and the outcomes-only continuation on the next.
435
443
  const avoidAttr = needsAvoid ? ' data-break-inside="avoid"' : '';
436
- return '<div class="dc-outcomes"' + avoidAttr + '>\n' + outcomeRowsHtml(rows, md) + '</div>\n';
444
+ return '<div class="dc-outcomes"' + avoidAttr + '>\n' + outcomeRowsHtml(rows, md, head) + '</div>\n';
437
445
  }
438
446
 
439
447
  // Parse ability from list item - handles rendered HTML: "<strong>0 AP</strong> <em>Name:</em> Description"
@@ -440,35 +440,18 @@
440
440
  font-weight: 600;
441
441
  }
442
442
 
443
- /* ROLL THE DIE! emphasis chip — tokens: --dc-roll-the-die-color (text, default
444
- --blood), --dc-roll-the-die-border (default --hud-magenta).
445
- A stamped label for an instruction to act. It is a plain non-replaced
446
- `display: inline` box on purpose: an inline box's vertical padding, border
447
- and shadow paint around its text without adding to the line box, so a line
448
- holding a chip is exactly as tall as one without, and nothing around it
449
- moves. `line-height: 0` keeps the chip's own font from growing the line,
450
- the font is smaller than the body, and `white-space: nowrap` moves a chip that
451
- would straddle a line end to the next line whole (it still adds no height).
452
- `box-decoration-break: clone` keeps both edges if one ever does fragment.
453
- The fill is opaque paper, so contrast is fixed whatever it sits on: --blood on --paper-cream is 7.7:1
454
- (it failed at 2.64:1 on skill-card paper-aged as --crimson text). */
443
+ /* ROLL THE DIE! (and ROLL A DIE!, ROLLS A DIE!, ROLLING THE DIE!) — token:
444
+ --dc-roll-the-die-color (default --blood).
445
+ An instruction to act, set in the text around it: the same font and size as
446
+ the line it sits in, made bold, in a contrasting colour, and underlined in
447
+ that colour. It is plain inline text, so the line keeps its height. --blood
448
+ on --paper-cream is 7.7:1. */
455
449
  .dc-roll-the-die {
456
- display: inline;
457
- font-family: var(--font-display);
458
- font-size: 0.8em;
459
450
  font-weight: 700;
460
- line-height: 0;
461
- white-space: nowrap;
462
- letter-spacing: 0.06em;
463
- text-transform: uppercase;
464
451
  color: var(--dc-roll-the-die-color);
465
- background-color: var(--paper-cream);
466
- padding: 0.14em 0.35em;
467
- margin-inline: 0.05em;
468
- border: 1.5pt solid var(--dc-roll-the-die-border);
469
- border-bottom-width: 3pt;
470
- box-shadow: 1pt 1pt 0 var(--dc-roll-the-die-border);
471
- box-decoration-break: clone;
452
+ text-decoration: underline;
453
+ text-decoration-thickness: 1.5pt;
454
+ text-underline-offset: 0.15em;
472
455
  }
473
456
 
474
457
  /* ── AP base + author-facing variants ─────────────────────────────────── */
@@ -244,6 +244,23 @@
244
244
  z-index: 1;
245
245
  }
246
246
 
247
+ /* A ladder made from a table keeps the table's header: its two cells, in the
248
+ label bar, over the two columns of the rows below (same column widths and
249
+ text insets as .dc-outcome-key and .dc-outcome-text). */
250
+ .dc-outcomes-head {
251
+ display: flex;
252
+ padding-inline: 0;
253
+ }
254
+ .dc-outcomes-head > span:first-child {
255
+ flex: 0 0 130px;
256
+ box-sizing: border-box;
257
+ padding-inline: 10px;
258
+ text-align: center;
259
+ }
260
+ .dc-outcomes-head > span + span {
261
+ padding-inline: 12px;
262
+ }
263
+
247
264
  .dc-outcome-row {
248
265
  display: grid;
249
266
  grid-template-columns: 130px 1fr;
@@ -566,12 +566,21 @@ h3 + .dc-section-panel {
566
566
  A .dc-card whose rail and kind badge take the kind's colour. The name is the
567
567
  first heading (`####` as authored, or `###`); the badge is a span core puts
568
568
  first, floated to the right so the name and the text run beside it.
569
+ Splits across pages by default (see below).
569
570
  Token contract: --dc-faction-accent (rail and badge fill),
570
571
  --dc-faction-badge-fg (badge text). */
571
572
  .dc-card.dc-faction {
572
573
  border-left-width: 5px;
573
574
  border-left-color: var(--dc-faction-accent);
574
575
  padding: 10pt 14pt;
576
+ /* A profile runs to half a page or more; kept whole (.dc-card's default) it
577
+ left half-empty pages through a chapter of factions. It splits between
578
+ paragraphs like an entry; the name keeps with its first lines (below), and
579
+ `.dc-avoid-split` on the marker keeps one whole. */
580
+ break-inside: auto;
581
+ }
582
+ .dc-card.dc-faction.dc-avoid-split {
583
+ break-inside: avoid;
575
584
  }
576
585
  .dc-card.dc-faction > :is(h3, h4):first-of-type {
577
586
  font-size: var(--fs-h4);
@@ -225,7 +225,6 @@
225
225
  --dc-pullquote-bg: var(--concrete-pale);
226
226
 
227
227
  /* roll / die callout public API */
228
- --dc-roll-the-die-border: var(--hud-magenta);
229
228
  --dc-roll-the-die-color: var(--blood);
230
229
 
231
230
  /* .dc-skill-card extra public API (shape geometry) */