rikiki-deck 0.6.0 → 0.7.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.
Files changed (174) hide show
  1. package/.claude/skills/rikiki-debug/SKILL.md +17 -7
  2. package/.claude/skills/rikiki-deck/SKILL.md +362 -77
  3. package/.claude/skills/rikiki-theme/SKILL.md +1 -1
  4. package/README.md +69 -50
  5. package/bin/lib/assemble.mjs +154 -0
  6. package/bin/lib/box-geometry.mjs +66 -0
  7. package/bin/lib/browser.mjs +302 -0
  8. package/bin/lib/check-api.d.ts +28 -0
  9. package/bin/lib/check-api.mjs +6 -0
  10. package/bin/lib/check-plugins.mjs +228 -0
  11. package/bin/lib/check.mjs +1347 -0
  12. package/bin/lib/cli-error.mjs +26 -0
  13. package/bin/lib/component-deps.mjs +69 -0
  14. package/bin/lib/diff.mjs +275 -0
  15. package/bin/lib/export-pdf.mjs +65 -0
  16. package/bin/lib/graph-hit.mjs +86 -0
  17. package/bin/lib/inline.mjs +137 -39
  18. package/bin/lib/narrative.mjs +77 -0
  19. package/bin/lib/prune-icons.mjs +104 -0
  20. package/bin/lib/render.mjs +195 -0
  21. package/bin/lib/scan-external.mjs +126 -0
  22. package/bin/lib/starter.mjs +27 -14
  23. package/bin/lib/visual.mjs +120 -0
  24. package/bin/rikiki.mjs +420 -35
  25. package/dist/annotation-marks.d.ts +60 -0
  26. package/dist/annotation-marks.js +1 -0
  27. package/dist/bar-segments.d.ts +28 -0
  28. package/dist/bar-segments.js +1 -0
  29. package/dist/browser-location.d.ts +3 -0
  30. package/dist/browser-location.js +1 -0
  31. package/dist/cards-syntax.d.ts +31 -0
  32. package/dist/cards-syntax.js +6 -0
  33. package/dist/{plugins/click-stages.d.ts → click-stages.d.ts} +1 -1
  34. package/dist/deck-agenda.d.ts +25 -0
  35. package/dist/deck-agenda.js +6 -0
  36. package/dist/deck-annotate.d.ts +108 -0
  37. package/dist/deck-annotate.js +18 -0
  38. package/dist/deck-bar.d.ts +32 -0
  39. package/dist/deck-bar.js +19 -0
  40. package/dist/deck-bento.d.ts +38 -0
  41. package/dist/deck-bento.js +4 -0
  42. package/dist/{molecules/deck-callout.d.ts → deck-callout.d.ts} +2 -0
  43. package/dist/deck-callout.js +1 -1
  44. package/dist/deck-cell.d.ts +19 -0
  45. package/dist/deck-cell.js +1 -0
  46. package/dist/deck-checklist.d.ts +20 -0
  47. package/dist/deck-checklist.js +1 -0
  48. package/dist/{layouts/deck-cover.d.ts → deck-cover.d.ts} +8 -0
  49. package/dist/deck-cover.js +9 -6
  50. package/dist/deck-csv.d.ts +38 -0
  51. package/dist/deck-csv.js +15 -0
  52. package/dist/deck-feature-cards.js +2 -2
  53. package/dist/deck-feature.d.ts +18 -0
  54. package/dist/deck-feature.js +2 -2
  55. package/dist/deck-figure.d.ts +26 -0
  56. package/dist/deck-figure.js +8 -0
  57. package/dist/deck-fit.d.ts +14 -0
  58. package/dist/deck-fit.js +1 -0
  59. package/dist/deck-flow.d.ts +41 -0
  60. package/dist/deck-flow.js +7 -0
  61. package/dist/deck-graph.d.ts +92 -0
  62. package/dist/deck-graph.js +25 -0
  63. package/dist/deck-grid.js +1 -1
  64. package/dist/deck-icon.d.ts +20 -0
  65. package/dist/deck-icon.js +1 -0
  66. package/dist/{atoms/deck-kicker.d.ts → deck-kicker.d.ts} +5 -0
  67. package/dist/deck-kicker.js +1 -1
  68. package/dist/deck-kpi-grid.d.ts +26 -0
  69. package/dist/deck-kpi-grid.js +4 -0
  70. package/dist/deck-link.d.ts +21 -0
  71. package/dist/deck-link.js +1 -0
  72. package/dist/{molecules/deck-md.d.ts → deck-md.d.ts} +3 -0
  73. package/dist/deck-md.js +8 -3
  74. package/dist/deck-mermaid.js +15 -3
  75. package/dist/deck-outline.d.ts +50 -0
  76. package/dist/deck-outline.js +1 -0
  77. package/dist/deck-overview.js +53 -39
  78. package/dist/deck-persona.d.ts +31 -0
  79. package/dist/deck-persona.js +6 -0
  80. package/dist/deck-photo.js +1 -1
  81. package/dist/deck-point.d.ts +22 -0
  82. package/dist/deck-point.js +1 -0
  83. package/dist/deck-presenter.js +120 -48
  84. package/dist/deck-pull.d.ts +13 -0
  85. package/dist/deck-pull.js +1 -0
  86. package/dist/{atoms/deck-punch.d.ts → deck-punch.d.ts} +6 -0
  87. package/dist/deck-punch.js +1 -1
  88. package/dist/deck-quote.d.ts +28 -0
  89. package/dist/deck-quote.js +6 -0
  90. package/dist/{runtime/deck-root.d.ts → deck-root.d.ts} +88 -8
  91. package/dist/deck-root.js +17 -13
  92. package/dist/deck-section.js +2 -2
  93. package/dist/deck-source.d.ts +12 -0
  94. package/dist/deck-source.js +2 -0
  95. package/dist/deck-split.d.ts +30 -0
  96. package/dist/deck-split.js +5 -3
  97. package/dist/{molecules/deck-stat.d.ts → deck-stat.d.ts} +2 -0
  98. package/dist/deck-stat.js +2 -2
  99. package/dist/{molecules/deck-step-list.d.ts → deck-step-list.d.ts} +8 -0
  100. package/dist/deck-step-list.js +4 -2
  101. package/dist/deck-table.d.ts +26 -0
  102. package/dist/deck-table.js +1 -0
  103. package/dist/deck-takeaway.d.ts +18 -0
  104. package/dist/deck-takeaway.js +2 -2
  105. package/dist/deck-timeline.d.ts +37 -0
  106. package/dist/deck-timeline.js +5 -0
  107. package/dist/deck-transition.js +3 -3
  108. package/dist/deck-versus.d.ts +18 -0
  109. package/dist/deck-versus.js +9 -0
  110. package/dist/deep-link.d.ts +29 -0
  111. package/dist/deep-link.js +1 -0
  112. package/dist/escape-html.d.ts +3 -0
  113. package/dist/escape-html.js +1 -0
  114. package/dist/fit-controller.d.ts +27 -0
  115. package/dist/fit-controller.js +1 -0
  116. package/dist/graph-layout.d.ts +35 -0
  117. package/dist/graph-layout.js +1 -0
  118. package/dist/grid-tracks.d.ts +17 -0
  119. package/dist/grid-tracks.js +1 -0
  120. package/dist/icon-set.d.ts +6 -0
  121. package/dist/icon-set.js +1 -0
  122. package/dist/index.d.ts +37 -31
  123. package/dist/index.js +95 -49
  124. package/dist/keymap.d.ts +40 -0
  125. package/dist/keymap.js +1 -0
  126. package/dist/mouse-nav.d.ts +12 -0
  127. package/dist/mouse-nav.js +1 -0
  128. package/dist/navigation.d.ts +25 -0
  129. package/dist/navigation.js +1 -0
  130. package/dist/parse-csv.d.ts +9 -0
  131. package/dist/parse-csv.js +3 -0
  132. package/dist/shared-styles.js +1 -1
  133. package/dist/shiki.d.ts +8 -0
  134. package/dist/signature.d.ts +2 -0
  135. package/dist/signature.js +1 -0
  136. package/dist/slide-fill.d.ts +8 -0
  137. package/dist/slide-fill.js +1 -0
  138. package/dist/standalone.js +301 -169
  139. package/dist/vendor/THIRD-PARTY-NOTICES.txt +4347 -0
  140. package/dist/vendor/inventory.json +3029 -0
  141. package/dist/vendor/lit.js +62 -2
  142. package/dist/vendor/mermaid.min.js +95 -95
  143. package/dist/vendor/shiki.js +1 -57
  144. package/dist/viewport.d.ts +42 -0
  145. package/dist/viewport.js +1 -0
  146. package/docs/llms/rikiki-reference.md +955 -64
  147. package/docs/llms/rikiki-workflow.md +536 -0
  148. package/llms.txt +39 -12
  149. package/package.json +33 -12
  150. package/themes/rikiki.css +173 -47
  151. package/themes/siliceum.css +171 -51
  152. package/dist/layouts/deck-feature.d.ts +0 -11
  153. package/dist/layouts/deck-split.d.ts +0 -18
  154. package/dist/layouts/deck-takeaway.d.ts +0 -11
  155. package/dist/plugins/shiki.d.ts +0 -8
  156. /package/dist/{runtime/color.d.ts → color.d.ts} +0 -0
  157. /package/dist/{atoms/deck-badge.d.ts → deck-badge.d.ts} +0 -0
  158. /package/dist/{molecules/deck-card.d.ts → deck-card.d.ts} +0 -0
  159. /package/dist/{atoms/deck-code-highlighter.d.ts → deck-code-highlighter.d.ts} +0 -0
  160. /package/dist/{atoms/deck-code.d.ts → deck-code.d.ts} +0 -0
  161. /package/dist/{layouts/deck-feature-cards.d.ts → deck-feature-cards.d.ts} +0 -0
  162. /package/dist/{molecules/deck-grid.d.ts → deck-grid.d.ts} +0 -0
  163. /package/dist/{runtime/deck-help.d.ts → deck-help.d.ts} +0 -0
  164. /package/dist/{molecules/deck-mermaid.d.ts → deck-mermaid.d.ts} +0 -0
  165. /package/dist/{molecules/deck-metric.d.ts → deck-metric.d.ts} +0 -0
  166. /package/dist/{runtime/deck-notes.d.ts → deck-notes.d.ts} +0 -0
  167. /package/dist/{runtime/deck-overview.d.ts → deck-overview.d.ts} +0 -0
  168. /package/dist/{layouts/deck-photo.d.ts → deck-photo.d.ts} +0 -0
  169. /package/dist/{runtime/deck-presenter.d.ts → deck-presenter.d.ts} +0 -0
  170. /package/dist/{layouts/deck-section.d.ts → deck-section.d.ts} +0 -0
  171. /package/dist/{molecules/deck-shortcut.d.ts → deck-shortcut.d.ts} +0 -0
  172. /package/dist/{molecules/deck-stack.d.ts → deck-stack.d.ts} +0 -0
  173. /package/dist/{molecules/deck-tier-list.d.ts → deck-tier-list.d.ts} +0 -0
  174. /package/dist/{runtime/deck-transition.d.ts → deck-transition.d.ts} +0 -0
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "rikiki-deck",
3
- "version": "0.6.0",
3
+ "version": "0.7.2",
4
4
  "description": "A tiny Lit Web Components framework for technical presentations · zero-build for consumers, TypeScript for contributors.",
5
- "author": "Cédric Chariere Fiedler <cedric@siliceum.com>",
5
+ "author": "Cédric Chariere Fiedler <chariere.fiedler.cedric@gmail.com>",
6
6
  "homepage": "https://rikiki.tordu-jardin.fr",
7
7
  "repository": {
8
8
  "type": "git",
@@ -13,12 +13,16 @@
13
13
  },
14
14
  "type": "module",
15
15
  "bin": {
16
- "rikiki": "./bin/rikiki.mjs"
16
+ "rikiki": "bin/rikiki.mjs"
17
17
  },
18
18
  "main": "./dist/index.js",
19
19
  "module": "./dist/index.js",
20
20
  "types": "./dist/index.d.ts",
21
21
  "exports": {
22
+ "./check-api": {
23
+ "types": "./bin/lib/check-api.d.ts",
24
+ "import": "./bin/lib/check-api.mjs"
25
+ },
22
26
  ".": {
23
27
  "types": "./dist/index.d.ts",
24
28
  "import": "./dist/index.js"
@@ -32,6 +36,7 @@
32
36
  "files": [
33
37
  "dist",
34
38
  "bin",
39
+ "!bin/**/*.test.mjs",
35
40
  "tokens.css",
36
41
  "themes",
37
42
  "fonts",
@@ -43,35 +48,43 @@
43
48
  ".claude/skills/rikiki-debug"
44
49
  ],
45
50
  "scripts": {
46
- "build": "node build-vendor.mjs && node build.mjs && node build-standalone.mjs && tsc --emitDeclarationOnly -p tsconfig.build.json",
51
+ "build": "node build-vendor.mjs && node build.mjs && node build-standalone.mjs && node build-types.mjs",
47
52
  "vendor": "node build-vendor.mjs",
48
53
  "watch": "node build.mjs --watch",
49
54
  "typecheck": "tsc --noEmit",
50
55
  "clean": "rm -rf dist",
51
56
  "bundle": "node bundle.mjs",
52
- "deck": "node build/vite-deck.mjs",
53
- "deck:example": "node build/vite-deck.mjs decks/example/deck.config.js",
57
+ "examples": "node scripts/rebuild-examples.mjs",
58
+ "readme": "node scripts/build-readme.mjs",
59
+ "deck": "node bin/rikiki.mjs assemble",
60
+ "deck:example": "node bin/rikiki.mjs assemble decks/example/deck.config.js",
54
61
  "test": "vitest run",
55
62
  "test:e2e": "playwright test",
56
63
  "test:smoke": "playwright test --grep @smoke",
57
- "lint": "biome check src scripts",
58
- "format": "biome format --write src scripts",
64
+ "release:smoke": "node scripts/release-smoke.mjs",
65
+ "lint": "biome check src scripts tools",
66
+ "format": "biome format --write src scripts tools",
59
67
  "bump": "node scripts/bump-version.mjs",
68
+ "new:component": "node scripts/new-component.mjs",
60
69
  "prepublishOnly": "npm run build && npm test"
61
70
  },
62
71
  "devDependencies": {
72
+ "@axe-core/playwright": "^4.13.0",
63
73
  "@biomejs/biome": "^2.4.16",
64
74
  "@playwright/test": "^1.60.0",
65
75
  "esbuild": "^0.24.0",
66
76
  "lit": "^3.3.3",
67
77
  "marked": "^12.0.2",
68
- "mermaid": "^10.9.6",
78
+ "mermaid": "^10.9.8",
79
+ "rolldown": "^1.1.1",
69
80
  "shiki": "^1.24.0",
70
81
  "typescript": "^5.6.0",
71
82
  "vitest": "^2.1.0"
72
83
  },
73
84
  "peerDependencies": {
74
- "lit": "^3.3.3"
85
+ "lit": "^3.3.3",
86
+ "playwright": "^1.60.0",
87
+ "rolldown": "^1.1.1"
75
88
  },
76
89
  "keywords": [
77
90
  "lit",
@@ -82,7 +95,15 @@
82
95
  "rikiki"
83
96
  ],
84
97
  "license": "MIT",
85
- "dependencies": {
86
- "rolldown": "^1.1.1"
98
+ "peerDependenciesMeta": {
99
+ "rolldown": {
100
+ "optional": true
101
+ },
102
+ "playwright": {
103
+ "optional": true
104
+ }
105
+ },
106
+ "engines": {
107
+ "node": "^20.19.0 || >=22.12.0"
87
108
  }
88
109
  }
package/themes/rikiki.css CHANGED
@@ -37,6 +37,9 @@
37
37
 
38
38
  --rik-palette-mango-700: #b65820;
39
39
  --rik-palette-mango-500: #f07020;
40
+ /* The -100 step is the status FILL, and a fill has to be seen: measured
41
+ against the page it must clear a CIE76 delta E of 10, which lands every
42
+ hue at an alpha of 0.18. Enforced by scripts/theme-contrast.test.mjs. */
40
43
  --rik-palette-mango-200: rgba(240, 112, 32, 0.50);
41
44
  --rik-palette-mango-100: rgba(240, 112, 32, 0.18);
42
45
  --rik-palette-mango-50: rgba(240, 112, 32, 0.06);
@@ -80,7 +83,9 @@
80
83
  /* Text */
81
84
  --rik-text-default: var(--rik-palette-ink-900);
82
85
  --rik-text-default--muted: var(--rik-palette-ink-700);
83
- --rik-text-default--faint: var(--rik-palette-ink-500);
86
+ /* Text-grade · ink-500 measured 4.30:1 on the page, under AA body text.
87
+ Measured, not eyeballed · scripts/theme-contrast.test.mjs re-checks it. */
88
+ --rik-text-default--faint: #75706c;
84
89
  --rik-text-inverse: var(--rik-palette-night-100);
85
90
  --rik-text-inverse--muted: rgba(232, 228, 240, 0.72);
86
91
  --rik-text-inverse--faint: rgba(232, 228, 240, 0.55);
@@ -96,7 +101,8 @@
96
101
  --rik-accent--soft: var(--rik-palette-mango-100);
97
102
  --rik-accent--faint: var(--rik-palette-mango-50);
98
103
  --rik-accent--strong: var(--rik-palette-mango-700);
99
- --rik-accent__on: var(--rik-palette-paper-0);
104
+ /* Dark on accent · paper-0 on mango-500 measured 2.98:1. ink-900 gives 5.09. */
105
+ --rik-accent__on: var(--rik-palette-ink-900);
100
106
 
101
107
  /* Status · success */
102
108
  --rik-status-success: var(--rik-palette-helico-500);
@@ -116,7 +122,7 @@
116
122
  /* Status · info (low-emphasis accent variant) */
117
123
  --rik-status-info: var(--rik-palette-mango-500);
118
124
  --rik-status-info__text: var(--rik-palette-mango-700);
119
- --rik-status-info__bg: var(--rik-palette-mango-50);
125
+ --rik-status-info__bg: var(--rik-palette-mango-100);
120
126
  --rik-status-info__bg--mid: rgba(240, 112, 32, 0.12);
121
127
  --rik-status-info__bg--strong: rgba(240, 112, 32, 0.20);
122
128
  --rik-status-info__border: var(--rik-palette-mango-200);
@@ -134,7 +140,7 @@
134
140
  --rik-focus-ring--width: 2px;
135
141
  --rik-focus-ring--offset: 2px;
136
142
 
137
- /* Link · mango-500 on paper is 3.2:1 (fails WCAG AA for body text).
143
+ /* Link · mango-500 on paper is 2.81:1 (fails WCAG AA for body text).
138
144
  Default link uses mango-700 (≥4.5:1); hover bumps to the brighter
139
145
  accent for visual feedback. */
140
146
  --rik-link: var(--rik-accent--strong);
@@ -150,6 +156,23 @@
150
156
  --rik-decor-lime: var(--rik-palette-lime-500);
151
157
  --rik-decor-canary: var(--rik-palette-canary-500);
152
158
 
159
+ /* Default vertical distribution of a slide body · a per-slide `spread`
160
+ attribute overrides it. Density is usually a per-slide judgement, which is
161
+ why this is a theme default and not a deck-level attribute. */
162
+
163
+ /* Text-grade tone companions · the plain tones are surface/decoration colors
164
+ and several of them sit under WCAG AA on the page. Anything that renders
165
+ TEXT in a tone (deck-punch, deck-stat) must route here instead.
166
+ Measured, not eyeballed · src/shared/contrast.test.ts fails if a value
167
+ drifts under the large-text threshold. */
168
+ --rik-status-success__text: #00a282;
169
+ --rik-status-warn__text: var(--rik-palette-warm-500);
170
+ --rik-status-danger__text: var(--rik-palette-ember-500);
171
+ --rik-accent__text: #e66b1f;
172
+ --rik-decor-orchid__text: var(--rik-palette-orchid-500);
173
+ --rik-decor-lime__text: #7a9a20;
174
+ --rik-decor-canary__text: #00a281;
175
+
153
176
  /* Elevation */
154
177
  --rik-elevation-1: 0 1px 2px rgba(6, 8, 15, 0.04);
155
178
  --rik-elevation-2: 0 1px 3px rgba(6, 8, 15, 0.06), 0 4px 12px rgba(6, 8, 15, 0.06);
@@ -192,17 +215,31 @@
192
215
  --rik-text-3xl: 3.815rem; /* 1.25^6 */
193
216
  --rik-text-4xl: 4.768rem; /* 1.25^7 */
194
217
 
195
- /* Legacy names · kept aligned to the new scale.
218
+ /* Semantic sizes · the roles, mapped onto the raw scale above.
219
+ The step between a statement and the reading size is the one axis ADR-002
220
+ leaves free, and it used to be spent on nothing: a slide title was 1.56x
221
+ the body, which is not two sizes but one size in two weights, and it is
222
+ why the decks read flat from the back of a room. The title is 2.44x now
223
+ and a chapter title 3.05x, both held under the clipping budget that
224
+ e2e/slide-budget.spec.ts measures.
225
+
226
+ Legacy names · kept aligned to the new scale.
196
227
  Fixed in 2026-05-20: --rik-font-size-mega was smaller than -big · the
197
228
  order is now monotonic (strong < big < mega < hook < stat). */
198
- --rik-font-size-xs: var(--rik-text-2xs);
199
- --rik-font-size-sm: var(--rik-text-xs);
229
+ /* Both of these used to sit under the legibility floor · the 8H rule puts
230
+ the smallest readable text at 1/50 of the screen height, which is 21.6px
231
+ on the 1080 canvas, and they resolved to 16.2px (1/66) and 20.3px (1/53).
232
+ A size nobody in the room can read is not a quiet tier, it is a tier that
233
+ is not there, and it was the size the micro-label tier lived at.
234
+ scripts/type-scale.test.mjs holds the floor now. */
235
+ --rik-font-size-xs: var(--rik-text-sm);
236
+ --rik-font-size-sm: var(--rik-text-sm);
200
237
  --rik-font-size-body: var(--rik-text-base); /* ≈32px · sized for projection */
201
238
  --rik-font-size-lead: var(--rik-text-md);
202
239
  --rik-font-size-h2: var(--rik-text-md);
203
- --rik-font-size-h1: var(--rik-text-lg);
204
- --rik-font-size-section: var(--rik-text-lg);
205
- --rik-font-size-display: var(--rik-text-xl);
240
+ --rik-font-size-h1: var(--rik-text-2xl);
241
+ --rik-font-size-section: var(--rik-text-3xl);
242
+ --rik-font-size-display: var(--rik-text-2xl);
206
243
  --rik-font-size-mono: 0.88rem;
207
244
  --rik-font-size-mono-sm: var(--rik-text-xs);
208
245
 
@@ -247,6 +284,16 @@
247
284
  --rik-slide-padding-x: 4rem;
248
285
  --rik-title-block: 4.5rem;
249
286
 
287
+ /* Slide-title voice · the four values the two shipped themes disagreed on,
288
+ each of them written twice in a light-DOM rule the other theme copied and
289
+ edited. A theme carries VALUES; the rule that consumes them is written
290
+ once. scripts/theme-parity.test.mjs keeps the two files structurally
291
+ identical so the next divergence cannot be silent. */
292
+ --rik-title-weight: 800;
293
+ --rik-title-tracking: -0.025em;
294
+ --rik-title-leading: 1.1;
295
+ --rik-rule-weight: 4px;
296
+
250
297
  /* Code surface + syntax (BEM elements under "code") */
251
298
  --rik-code__bg: #0f0f10;
252
299
  --rik-code__border: #232325;
@@ -275,43 +322,55 @@
275
322
  /* ────────────────────────────────────────────────────────────────
276
323
  Minimal reset (don't override the padding of slotted components)
277
324
  ──────────────────────────────────────────────────────────────── */
278
- *, *::before, *::after { box-sizing: border-box; }
279
- body, h1, h2, h3, h4, p, ul, ol, li, blockquote, pre, table, td, th,
280
- figure, dl, dd { margin: 0; padding: 0; }
325
+ /* Scoped to the deck subtree · a host page that imports this theme to show an
326
+ embedded deck keeps its own box model and its own heading margins. */
327
+ deck-root, deck-root *, deck-root *::before, deck-root *::after { box-sizing: border-box; }
328
+ deck-root h1, deck-root h2, deck-root h3, deck-root h4, deck-root p,
329
+ deck-root ul, deck-root ol, deck-root li, deck-root blockquote, deck-root pre,
330
+ deck-root table, deck-root td, deck-root th, deck-root figure,
331
+ deck-root dl, deck-root dd { margin: 0; padding: 0; }
281
332
  /* The rem baseline and the no-scroll reset are injected globally by deck-root
282
333
  (theme-independent · see _injectGlobals). The theme only owns the page surface
283
334
  and the type below. */
284
- html, body { background: var(--rik-surface-page); }
285
- body { font-family: var(--rik-font-sans); color: var(--rik-text-default); }
335
+ /* Page surface · only when the deck IS the page. An embedded deck must not
336
+ repaint the document around it. */
337
+ html:has(> body > deck-root), html:has(> body > deck-root) body {
338
+ background: var(--rik-surface-page);
339
+ }
340
+ html:has(> body > deck-root) body {
341
+ margin: 0;
342
+ font-family: var(--rik-font-sans);
343
+ color: var(--rik-text-default);
344
+ }
286
345
 
287
346
  ::selection { background: var(--rik-selection__bg); color: var(--rik-selection__text); }
288
347
 
289
348
  /* ────────────────────────────────────────────────────────────────
290
349
  Light-DOM helpers (apply to slotted children of deck-* hosts)
291
350
  ──────────────────────────────────────────────────────────────── */
292
- .accent { color: var(--rik-accent); }
293
- .accent-danger { color: var(--rik-status-danger); }
294
- .accent-warn { color: var(--rik-status-warn); }
295
- .accent-success { color: var(--rik-status-success); }
296
- .accent-orchid { color: var(--rik-decor-orchid); }
297
- .accent-lime { color: var(--rik-decor-lime); }
298
-
299
- .sub {
351
+ deck-root .accent { color: var(--rik-accent); }
352
+ deck-root .accent-danger { color: var(--rik-status-danger); }
353
+ deck-root .accent-warn { color: var(--rik-status-warn); }
354
+ deck-root .accent-success { color: var(--rik-status-success); }
355
+ deck-root .accent-orchid { color: var(--rik-decor-orchid); }
356
+ deck-root .accent-lime { color: var(--rik-decor-lime); }
357
+
358
+ deck-root .sub {
300
359
  font-size: var(--rik-font-size-h2);
301
360
  color: var(--rik-text-inverse--muted);
302
361
  line-height: 1.45;
303
362
  max-width: 60ch;
304
363
  }
305
- .display {
364
+ deck-root .display {
306
365
  font-family: var(--rik-font-display);
307
366
  font-size: clamp(3rem, 7cqw, 5.5rem);
308
367
  font-weight: 900;
309
368
  line-height: 1.05;
310
369
  letter-spacing: -0.03em;
311
370
  }
312
- .display.danger { color: var(--rik-status-danger); }
313
- .caption.on-dark { color: var(--rik-text-inverse--muted); font-size: var(--rik-font-size-lead); }
314
- .lead {
371
+ deck-root .display.danger { color: var(--rik-status-danger); }
372
+ deck-root .caption.on-dark { color: var(--rik-text-inverse--muted); font-size: var(--rik-font-size-lead); }
373
+ deck-root .lead {
315
374
  font-size: var(--rik-font-size-lead);
316
375
  color: var(--rik-text-default--faint);
317
376
  line-height: 1.5;
@@ -321,20 +380,20 @@ body { font-family: var(--rik-font-sans); color: var(--rik-text-default); }
321
380
  /* Slide titles (h1 in light DOM, slotted) */
322
381
  deck-feature > h1,
323
382
  deck-split > h1,
324
- deck-feature-cards > h1 {
383
+ deck-root deck-feature-cards > h1 {
325
384
  font-family: var(--rik-font-display);
326
385
  font-size: var(--rik-font-size-h1);
327
- font-weight: 800;
386
+ font-weight: var(--rik-title-weight);
328
387
  color: var(--rik-text-default);
329
- letter-spacing: -0.025em;
330
- line-height: 1.1;
388
+ letter-spacing: var(--rik-title-tracking);
389
+ line-height: var(--rik-title-leading);
331
390
  margin-bottom: var(--rik-space-4);
332
391
  padding-bottom: var(--rik-space-2);
333
- border-bottom: 4px solid var(--rik-accent);
392
+ border-bottom: var(--rik-rule-weight) solid var(--rik-accent);
334
393
  display: inline-block;
335
394
  align-self: flex-start;
336
395
  }
337
- deck-cover > h1 {
396
+ deck-root deck-cover > h1 {
338
397
  font-family: var(--rik-font-display);
339
398
  font-size: clamp(3.6rem, 9cqw, 8.5rem);
340
399
  font-weight: 900;
@@ -343,7 +402,7 @@ deck-cover > h1 {
343
402
  letter-spacing: -0.035em;
344
403
  margin-bottom: var(--rik-space-4);
345
404
  }
346
- deck-section > h1 {
405
+ deck-root deck-section > h1 {
347
406
  font-family: var(--rik-font-display);
348
407
  font-size: var(--rik-font-size-section);
349
408
  font-weight: 900;
@@ -353,14 +412,14 @@ deck-section > h1 {
353
412
  max-width: 18ch;
354
413
  text-align: center;
355
414
  }
356
- deck-section > h1 em {
415
+ deck-root deck-section > h1 em {
357
416
  color: var(--rik-text-inverse--muted);
358
417
  font-style: normal;
359
418
  font-weight: 700;
360
419
  }
361
420
 
362
421
  /* Slotted sub-headings */
363
- deck-cover > .sub, deck-cover > p.sub {
422
+ deck-root deck-cover > .sub, deck-root deck-cover > p.sub {
364
423
  display: block;
365
424
  font-size: var(--rik-font-size-h2);
366
425
  color: var(--rik-text-inverse--muted);
@@ -371,7 +430,7 @@ deck-cover > .sub, deck-cover > p.sub {
371
430
 
372
431
  deck-feature > .lead,
373
432
  deck-split > .lead,
374
- deck-feature-cards > .lead {
433
+ deck-root deck-feature-cards > .lead {
375
434
  display: block;
376
435
  font-size: var(--rik-font-size-lead);
377
436
  color: var(--rik-text-default--faint);
@@ -381,7 +440,7 @@ deck-feature-cards > .lead {
381
440
  }
382
441
 
383
442
  /* Inline code in light DOM (slotted) */
384
- deck-feature code, deck-split code, deck-feature-cards code, deck-md code {
443
+ deck-root deck-feature code, deck-root deck-split code, deck-root deck-feature-cards code, deck-root deck-md code {
385
444
  font-family: var(--rik-font-mono);
386
445
  font-size: var(--rik-font-size-mono-sm);
387
446
  background: var(--rik-surface-tint);
@@ -389,17 +448,17 @@ deck-feature code, deck-split code, deck-feature-cards code, deck-md code {
389
448
  border-radius: var(--rik-radius-sm);
390
449
  color: var(--rik-text-default);
391
450
  }
392
- deck-code code { all: unset; }
451
+ deck-root deck-code code { all: unset; }
393
452
 
394
453
  /* Light-DOM utility blocks */
395
- .card-text {
454
+ deck-root .card-text {
396
455
  font-size: var(--rik-font-size-body);
397
456
  color: var(--rik-text-default--muted);
398
457
  line-height: 1.55;
399
458
  margin: 0;
400
459
  }
401
460
 
402
- table.dense {
461
+ deck-root table.dense {
403
462
  width: 100%;
404
463
  border-collapse: separate;
405
464
  border-spacing: 0;
@@ -410,7 +469,7 @@ table.dense {
410
469
  background: var(--rik-surface-raised--strong);
411
470
  box-shadow: var(--rik-elevation-2);
412
471
  }
413
- table.dense th {
472
+ deck-root table.dense th {
414
473
  text-align: left;
415
474
  padding: 10px var(--rik-space-3);
416
475
  color: var(--rik-text-default--faint);
@@ -421,13 +480,80 @@ table.dense th {
421
480
  border-bottom: 1px solid var(--rik-border-default);
422
481
  background: var(--rik-surface-sunken);
423
482
  }
424
- table.dense td {
483
+ deck-root table.dense td {
425
484
  padding: 10px var(--rik-space-3);
426
485
  border-bottom: 1px solid var(--rik-border-default);
427
486
  color: var(--rik-text-default--muted);
428
487
  line-height: 1.4;
429
488
  }
430
- table.dense tr:last-child td { border-bottom: none; }
431
- table.dense td.ok { color: var(--rik-status-success); font-weight: 700; }
432
- table.dense td.no { color: var(--rik-status-danger); }
433
- table.dense td.meh { color: var(--rik-status-warn); }
489
+ deck-root table.dense tr:last-child td { border-bottom: none; }
490
+ deck-root table.dense td.ok { color: var(--rik-status-success); font-weight: 700; }
491
+ deck-root table.dense td.no { color: var(--rik-status-danger); }
492
+ deck-root table.dense td.meh { color: var(--rik-status-warn); }
493
+
494
+ /* deck-table · the table stays in the author's light DOM, so its rules live
495
+ here rather than in a shadow root. Scoped to the deck subtree like every
496
+ other helper.
497
+
498
+ The look is the extras direction applied to data (docs/design/adr-002): the
499
+ header is told apart by weight and one rule, rows by hairlines, and nothing
500
+ is filled except the single row that matters. A pale tint reads as nothing at projection distance
501
+ (the raised surface sits at 1.10 contrast against the page), so emphasis is
502
+ the inverse surface · a dark band across the row. */
503
+ deck-root table[data-rik-table] {
504
+ width: 100%;
505
+ border-collapse: collapse;
506
+ font-variant-numeric: tabular-nums;
507
+ }
508
+ deck-root table[data-rik-table] thead th {
509
+ text-align: left;
510
+ font-weight: 700;
511
+ color: var(--rik-text-default--muted);
512
+ padding: 0 var(--rik-space-4) var(--rik-space-2);
513
+ border-bottom: 2px solid var(--rik-accent);
514
+ }
515
+ deck-root table[data-rik-table] tbody td {
516
+ padding: var(--rik-space-3) var(--rik-space-4);
517
+ border-bottom: 1px solid var(--rik-border-default);
518
+ color: var(--rik-text-default);
519
+ line-height: 1.35;
520
+ }
521
+ deck-root table[data-rik-table] tbody tr:last-child td { border-bottom: none; }
522
+
523
+ /* The emphasised row · one dark band, the only filled thing on the slide. */
524
+ deck-root table[data-rik-table] tr[data-mark] > td {
525
+ background: var(--deck-table-mark-bg, var(--rik-surface-inverse));
526
+ color: var(--deck-table-mark-color, var(--rik-text-inverse));
527
+ border-bottom-color: var(--deck-table-mark-bg, var(--rik-surface-inverse));
528
+ font-weight: 700;
529
+ }
530
+ deck-root table[data-rik-table] tr[data-mark] > td:first-child {
531
+ border-radius: var(--rik-radius-sm) 0 0 var(--rik-radius-sm);
532
+ }
533
+ deck-root table[data-rik-table] tr[data-mark] > td:last-child {
534
+ border-radius: 0 var(--rik-radius-sm) var(--rik-radius-sm) 0;
535
+ }
536
+
537
+ /* The emphasised column · colour and weight, never a second fill · two
538
+ overlapping tints is how a table stops having a hierarchy at all. */
539
+ deck-root table[data-rik-table] td[data-mark],
540
+ deck-root table[data-rik-table] th[data-mark] {
541
+ color: var(--deck-table-col-color, var(--rik-accent__text));
542
+ font-weight: 700;
543
+ }
544
+ deck-root table[data-rik-table] tr[data-mark] > td[data-mark] {
545
+ color: var(--deck-table-col-on-mark, var(--rik-accent));
546
+ }
547
+
548
+ deck-root table[data-rik-table] tr[data-pending] {
549
+ /* Hidden but still occupying its row · a table that grows makes the slide
550
+ jump under the audience. */
551
+ visibility: hidden;
552
+ }
553
+ @media print {
554
+ deck-root table[data-rik-table] tr[data-pending] { visibility: visible; }
555
+ deck-root table[data-rik-table] tr[data-mark] > td {
556
+ -webkit-print-color-adjust: exact;
557
+ print-color-adjust: exact;
558
+ }
559
+ }