@troshab/slidev-theme-troshab 0.1.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 (168) hide show
  1. package/CLAUDE.md +537 -0
  2. package/LICENSE +134 -0
  3. package/README.md +168 -0
  4. package/SKILL.md +414 -0
  5. package/components/AnimatedCounter.vue +35 -0
  6. package/components/Background.vue +204 -0
  7. package/components/Callout.vue +135 -0
  8. package/components/Card.vue +75 -0
  9. package/components/CardGrid.vue +67 -0
  10. package/components/CaseStudy.vue +66 -0
  11. package/components/CodeDiff.vue +229 -0
  12. package/components/CodeHighlight.vue +337 -0
  13. package/components/ColorSwatch.vue +114 -0
  14. package/components/Confetti.vue +292 -0
  15. package/components/Conversation.vue +405 -0
  16. package/components/Countdown.vue +476 -0
  17. package/components/Definition.vue +59 -0
  18. package/components/DeviceMockup.vue +392 -0
  19. package/components/Funnel.vue +87 -0
  20. package/components/Icon.vue +73 -0
  21. package/components/Iframe.vue +38 -0
  22. package/components/Image.vue +69 -0
  23. package/components/ImageCompare.vue +436 -0
  24. package/components/MatrixGrid.vue +85 -0
  25. package/components/MermaidChart.vue +299 -0
  26. package/components/Metric.vue +161 -0
  27. package/components/PersonCard.vue +165 -0
  28. package/components/PricingTable.vue +144 -0
  29. package/components/Progress.vue +100 -0
  30. package/components/Pyramid.vue +81 -0
  31. package/components/QRCode.vue +137 -0
  32. package/components/QuoteBlock.vue +101 -0
  33. package/components/SpeechBubble.vue +169 -0
  34. package/components/Stepper.vue +542 -0
  35. package/components/StyledList.vue +156 -0
  36. package/components/StyledText.vue +275 -0
  37. package/components/SwotGrid.vue +99 -0
  38. package/components/Tags.vue +20 -0
  39. package/components/Testimonial.vue +243 -0
  40. package/components/Typewriter.vue +181 -0
  41. package/components_base/AnimatedCounter.vue +208 -0
  42. package/components_base/CodeHighlight.vue +364 -0
  43. package/composables/useColors.ts +101 -0
  44. package/composables/useShiki.ts +81 -0
  45. package/example_content.md +371 -0
  46. package/example_dark.md +10 -0
  47. package/example_slides/001-cover.md +15 -0
  48. package/example_slides/002-agenda.md +25 -0
  49. package/example_slides/003-section-layouts.md +14 -0
  50. package/example_slides/004-fullscreen-centered.md +7 -0
  51. package/example_slides/005-fullscreen-align-bottom.md +14 -0
  52. package/example_slides/006-fullscreen-no-padding.md +14 -0
  53. package/example_slides/007-fullscreen-bg-image-dark.md +13 -0
  54. package/example_slides/008-fullscreen-bg-image-light.md +13 -0
  55. package/example_slides/009-fullscreen-bg-gradient.md +15 -0
  56. package/example_slides/010-fullscreen-bg-color.md +13 -0
  57. package/example_slides/011-split-basic.md +17 -0
  58. package/example_slides/012-split-image-text.md +18 -0
  59. package/example_slides/013-split-contrast.md +22 -0
  60. package/example_slides/014-columns-basic.md +13 -0
  61. package/example_slides/015-columns-two.md +26 -0
  62. package/example_slides/016-columns-ratios.md +22 -0
  63. package/example_slides/017-columns-three.md +31 -0
  64. package/example_slides/018-columns-four.md +22 -0
  65. package/example_slides/019-columns-alignment.md +23 -0
  66. package/example_slides/020-columns-styled.md +21 -0
  67. package/example_slides/021-footnote-prop.md +16 -0
  68. package/example_slides/022-iframe-fullscreen.md +8 -0
  69. package/example_slides/023-iframe-split.md +18 -0
  70. package/example_slides/024-section-components.md +14 -0
  71. package/example_slides/025-styled-text.md +9 -0
  72. package/example_slides/026-styled-text.md +15 -0
  73. package/example_slides/027-text-formatting.md +28 -0
  74. package/example_slides/028-text-spoiler.md +15 -0
  75. package/example_slides/029-icon-component.md +47 -0
  76. package/example_slides/030-metric-component.md +29 -0
  77. package/example_slides/031-person-card.md +33 -0
  78. package/example_slides/032-styled-list.md +50 -0
  79. package/example_slides/033-color-swatch.md +35 -0
  80. package/example_slides/034-code-highlight.md +9 -0
  81. package/example_slides/035-iframe-component.md +9 -0
  82. package/example_slides/036-callout.md +15 -0
  83. package/example_slides/037-card-grid.md +27 -0
  84. package/example_slides/038-stepper-variants.md +18 -0
  85. package/example_slides/039-stepper-clicks.md +49 -0
  86. package/example_slides/040-stepper-interactive.md +28 -0
  87. package/example_slides/041-tags-progress.md +21 -0
  88. package/example_slides/042-speech-bubble.md +30 -0
  89. package/example_slides/043-conversation.md +13 -0
  90. package/example_slides/044-device-iphone.md +26 -0
  91. package/example_slides/045-device-browser.md +7 -0
  92. package/example_slides/046-qrcode.md +26 -0
  93. package/example_slides/047-countdown.md +14 -0
  94. package/example_slides/048-typewriter.md +8 -0
  95. package/example_slides/049-confetti.md +16 -0
  96. package/example_slides/050-image-compare.md +13 -0
  97. package/example_slides/051-code-diff.md +24 -0
  98. package/example_slides/052-quote-block.md +8 -0
  99. package/example_slides/053-testimonial.md +26 -0
  100. package/example_slides/054-testimonial-featured.md +16 -0
  101. package/example_slides/055-funnel.md +12 -0
  102. package/example_slides/056-pyramid.md +13 -0
  103. package/example_slides/057-pricing-table.md +9 -0
  104. package/example_slides/058-swot-grid.md +12 -0
  105. package/example_slides/059-matrix-grid.md +12 -0
  106. package/example_slides/060-case-study.md +11 -0
  107. package/example_slides/061-definition.md +15 -0
  108. package/example_slides/062-mermaid-intro.md +34 -0
  109. package/example_slides/063-mermaid-flowchart.md +19 -0
  110. package/example_slides/064-mermaid-sequence.md +17 -0
  111. package/example_slides/065-mermaid-xy-chart.md +16 -0
  112. package/example_slides/066-mermaid-pie.md +17 -0
  113. package/example_slides/067-mermaid-class.md +19 -0
  114. package/example_slides/068-mermaid-state.md +19 -0
  115. package/example_slides/069-mermaid-er.md +22 -0
  116. package/example_slides/070-mermaid-gantt.md +24 -0
  117. package/example_slides/071-mermaid-timeline.md +17 -0
  118. package/example_slides/072-mermaid-mindmap.md +21 -0
  119. package/example_slides/073-mermaid-gitgraph.md +20 -0
  120. package/example_slides/074-mermaid-split.md +30 -0
  121. package/example_slides/075-mermaid-columns.md +32 -0
  122. package/example_slides/076-section-addons.md +14 -0
  123. package/example_slides/077-asciinema.md +27 -0
  124. package/example_slides/078-fancyarrow.md +31 -0
  125. package/example_slides/079-fancyarrow-demo.md +23 -0
  126. package/example_slides/080-section-theme.md +14 -0
  127. package/example_slides/081-color-architecture.md +22 -0
  128. package/example_slides/082-semantic-text-colors.md +25 -0
  129. package/example_slides/083-typography.md +16 -0
  130. package/example_slides/084-typography-rationale.md +22 -0
  131. package/example_slides/085-icons.md +24 -0
  132. package/example_slides/086-tables.md +14 -0
  133. package/example_slides/087-code-blocks.md +18 -0
  134. package/example_slides/088-motion-modes.md +35 -0
  135. package/example_slides/089-slide-transitions.md +31 -0
  136. package/example_slides/090-v-click-reveals.md +40 -0
  137. package/example_slides/091-accessibility.md +27 -0
  138. package/example_slides/092-safe-zone.md +17 -0
  139. package/example_slides/093-questions.md +8 -0
  140. package/example_white.md +10 -0
  141. package/fonts/IBMPlexMono-Medium.woff2 +1449 -0
  142. package/fonts/IBMPlexMono-Regular.woff2 +1449 -0
  143. package/fonts/IBMPlexSans-Bold.woff2 +1449 -0
  144. package/fonts/IBMPlexSans-Medium.woff2 +1449 -0
  145. package/fonts/IBMPlexSans-Regular.woff2 +1449 -0
  146. package/fonts/IBMPlexSans-SemiBold.woff2 +1449 -0
  147. package/fonts/LICENSE.txt +93 -0
  148. package/layouts/slide.vue +251 -0
  149. package/package.json +62 -0
  150. package/public/avatars/alice.png +0 -0
  151. package/public/avatars/bob.png +0 -0
  152. package/public/avatars/carol.png +0 -0
  153. package/scripts/chart-audit.mjs +216 -0
  154. package/scripts/contrast-audit.mjs +299 -0
  155. package/scripts/generate-palette.mjs +395 -0
  156. package/scripts/integrity-audit.mjs +357 -0
  157. package/scripts/shared/css-utils.mjs +216 -0
  158. package/scripts/shiki-audit.mjs +300 -0
  159. package/scripts/typography-audit.mjs +300 -0
  160. package/setup/main.ts +107 -0
  161. package/setup/mermaid.ts +237 -0
  162. package/setup/shiki.ts +40 -0
  163. package/snippets/demo.ts +26 -0
  164. package/styles/base.css +1053 -0
  165. package/styles/colors.css +422 -0
  166. package/styles/index.css +12 -0
  167. package/styles/motion.css +486 -0
  168. package/uno.config.ts +67 -0
@@ -0,0 +1,1053 @@
1
+ /* ============================================
2
+ slidev-theme-troshab — Typography & Base Styles
3
+ ============================================
4
+
5
+ Dyslexia-friendly defaults based on:
6
+ - British Dyslexia Association guidelines
7
+ - WCAG 2.1 accessibility standards
8
+ - ISO 9241 display ergonomics
9
+ ============================================ */
10
+
11
+ /* Import color system */
12
+ @import './colors.css';
13
+
14
+ /* ============================================
15
+ 1. @font-face — IBM Plex (local)
16
+ ============================================ */
17
+
18
+ @font-face {
19
+ font-family: 'IBM Plex Sans';
20
+ src: url('../fonts/IBMPlexSans-Regular.woff2') format('woff2');
21
+ font-weight: 400;
22
+ font-style: normal;
23
+ font-display: swap;
24
+ }
25
+
26
+ @font-face {
27
+ font-family: 'IBM Plex Sans';
28
+ src: url('../fonts/IBMPlexSans-Medium.woff2') format('woff2');
29
+ font-weight: 500;
30
+ font-style: normal;
31
+ font-display: swap;
32
+ }
33
+
34
+ @font-face {
35
+ font-family: 'IBM Plex Sans';
36
+ src: url('../fonts/IBMPlexSans-SemiBold.woff2') format('woff2');
37
+ font-weight: 600;
38
+ font-style: normal;
39
+ font-display: swap;
40
+ }
41
+
42
+ @font-face {
43
+ font-family: 'IBM Plex Sans';
44
+ src: url('../fonts/IBMPlexSans-Bold.woff2') format('woff2');
45
+ font-weight: 700;
46
+ font-style: normal;
47
+ font-display: swap;
48
+ }
49
+
50
+ @font-face {
51
+ font-family: 'IBM Plex Mono';
52
+ src: url('../fonts/IBMPlexMono-Regular.woff2') format('woff2');
53
+ font-weight: 400;
54
+ font-style: normal;
55
+ font-display: swap;
56
+ }
57
+
58
+ @font-face {
59
+ font-family: 'IBM Plex Mono';
60
+ src: url('../fonts/IBMPlexMono-Medium.woff2') format('woff2');
61
+ font-weight: 500;
62
+ font-style: normal;
63
+ font-display: swap;
64
+ }
65
+
66
+ /* ============================================
67
+ 2. CSS Custom Properties (Typography & Layout)
68
+ Note: Colors are defined in colors.css
69
+ ============================================ */
70
+
71
+ :root {
72
+ /* --- Fonts --- */
73
+ --font-sans: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
74
+ --font-mono: 'IBM Plex Mono', 'Consolas', 'Monaco', monospace;
75
+
76
+ /* --- Typography Scale (3 main + 1 small) ---
77
+ h1 = 57px, h2 = 43px (also h3), body = 24px, small = 18px.
78
+ */
79
+ --font-size-h1: 3.5625rem; /* 57px */
80
+ --font-size-h2: 2.6875rem; /* 43px */
81
+ --font-size-base: 1.5rem; /* 24px — body text */
82
+ --font-size-small: 1.125rem; /* 18px — captions, labels, code */
83
+
84
+ /* --- Font Weights --- */
85
+ --font-weight-normal: 400;
86
+ --font-weight-medium: 500;
87
+ --font-weight-semibold: 600;
88
+ --font-weight-bold: 700;
89
+
90
+ /* --- Line Heights (role-based) --- */
91
+ --line-height-heading: 1.15; /* tight for 1-2 line headings */
92
+ --line-height-body: 1.35; /* slides with short text blocks */
93
+ --line-height-reading: 1.5; /* longer paragraphs, BDA recommended */
94
+ --line-height-list: 1.4;
95
+ --line-height-code: 1.4;
96
+
97
+ /* --- Letter & Word Spacing (dyslexia-friendly) ---
98
+ Zorzi et al. (2012, PNAS): letter-spacing reduces crowding.
99
+ BDA 2018: word/letter ratio >= 3.5x. Ours: 4.0x (above minimum). */
100
+ --letter-spacing-body: 0.02em;
101
+ --word-spacing-body: 0.08em;
102
+ --letter-spacing-heading: 0.01em;
103
+
104
+ /* --- Spacing System (8-point grid) ---
105
+ Based on 8px base unit for visual rhythm.
106
+ Fibonacci extras: 13px, 21px for special cases.
107
+ */
108
+ --space-xs: 0.5rem; /* 8px — tight gaps */
109
+ --space-sm: 1rem; /* 16px — default gap */
110
+ --space-md: 1.5rem; /* 24px — section gaps */
111
+ --space-lg: 2rem; /* 32px — large gaps */
112
+ --space-xl: 3rem; /* 48px — section padding */
113
+ --space-2xl: 4rem; /* 64px — major sections */
114
+
115
+ /* Fibonacci extras */
116
+ --space-fib-sm: 0.8125rem; /* 13px */
117
+ --space-fib-md: 1.3125rem; /* 21px */
118
+
119
+ /* Legacy spacing aliases */
120
+ --paragraph-spacing: 0.75em;
121
+ --list-item-spacing: 0.25em;
122
+ --heading-spacing: 1.5em;
123
+
124
+ /* --- Measure (line length) --- */
125
+ --measure: 65ch;
126
+ --measure-narrow: 45ch;
127
+
128
+ /* --- Layout --- */
129
+ --slide-padding: var(--space-lg);
130
+ --slide-gap: var(--space-sm);
131
+
132
+ /* --- Safe-zone for projectors/TV overscan (5% default) --- */
133
+ --safe-inset-x: 5%;
134
+ --safe-inset-y: 5%;
135
+ }
136
+
137
+ /* ============================================
138
+ 3. Slidev Overrides
139
+ ============================================ */
140
+
141
+ /* Override Slidev's scoped bg-white/bg-dark on .slidev-slide-content[data-v-*] */
142
+ .slidev-slide-content {
143
+ background-color: var(--color-bg) !important;
144
+ }
145
+
146
+ /* ============================================
147
+ 4. Base Typography
148
+ ============================================ */
149
+
150
+ .slidev-layout {
151
+ font-family: var(--font-sans);
152
+ font-size: var(--font-size-base);
153
+ font-weight: var(--font-weight-normal);
154
+ line-height: var(--line-height-body);
155
+ letter-spacing: var(--letter-spacing-body);
156
+ word-spacing: var(--word-spacing-body);
157
+ color: var(--color-text);
158
+ padding: var(--safe-inset-y) var(--safe-inset-x);
159
+ height: 100%;
160
+ width: 100%;
161
+ }
162
+
163
+ /* --- Paragraphs --- */
164
+ .slidev-layout p {
165
+ margin-block: var(--paragraph-spacing);
166
+ max-width: var(--measure);
167
+ text-align: left;
168
+ }
169
+
170
+ /* --- Headings --- */
171
+ .slidev-layout h1,
172
+ .slidev-layout h2,
173
+ .slidev-layout h3,
174
+ .slidev-layout h4 {
175
+ line-height: var(--line-height-heading);
176
+ letter-spacing: var(--letter-spacing-heading);
177
+ word-spacing: normal;
178
+ font-style: normal;
179
+ text-transform: none;
180
+ }
181
+
182
+ .slidev-layout h1 {
183
+ font-size: var(--font-size-h1);
184
+ font-weight: var(--font-weight-bold);
185
+ line-height: var(--line-height-heading);
186
+ margin-block-end: var(--space-sm);
187
+ }
188
+
189
+ .slidev-layout h2 {
190
+ font-size: var(--font-size-h2);
191
+ font-weight: var(--font-weight-semibold);
192
+ line-height: var(--line-height-heading);
193
+ margin-block-start: var(--space-lg);
194
+ margin-block-end: var(--space-sm);
195
+ opacity: 0.9;
196
+ }
197
+
198
+ .slidev-layout h3 {
199
+ font-size: var(--font-size-h2);
200
+ font-weight: var(--font-weight-medium);
201
+ line-height: var(--line-height-heading);
202
+ margin-block-start: var(--space-md);
203
+ margin-block-end: var(--space-xs);
204
+ }
205
+
206
+ /* Remove margin from first heading in slide */
207
+ .slidev-layout > h1:first-child,
208
+ .slidev-layout > h2:first-child,
209
+ .slidev-layout > h3:first-child {
210
+ margin-block-start: 0;
211
+ }
212
+
213
+ /* --- Lists --- */
214
+ .slidev-layout ul,
215
+ .slidev-layout ol {
216
+ margin-block: var(--paragraph-spacing);
217
+ margin-inline-start: 1.5em;
218
+ line-height: var(--line-height-list);
219
+ text-align: left;
220
+ max-width: var(--measure);
221
+ }
222
+
223
+ .slidev-layout li {
224
+ margin-block: var(--list-item-spacing);
225
+ }
226
+
227
+ .slidev-layout ul {
228
+ list-style-type: disc;
229
+ }
230
+
231
+ .slidev-layout ol {
232
+ list-style-type: decimal;
233
+ }
234
+
235
+ /* Nested lists */
236
+ .slidev-layout ul ul,
237
+ .slidev-layout ol ol,
238
+ .slidev-layout ul ol,
239
+ .slidev-layout ol ul {
240
+ margin-block: 0.25em;
241
+ }
242
+
243
+ /* --- Strong/Bold --- */
244
+ .slidev-layout strong,
245
+ .slidev-layout b {
246
+ font-weight: var(--font-weight-semibold);
247
+ }
248
+
249
+ /* --- Emphasis (minimal italic usage) --- */
250
+ .slidev-layout em,
251
+ .slidev-layout i {
252
+ /* Italic only for book titles, foreign terms — not for emphasis */
253
+ font-style: italic;
254
+ }
255
+
256
+ /* --- Links --- */
257
+ .slidev-layout a {
258
+ color: var(--color-primary);
259
+ text-decoration: underline;
260
+ text-underline-offset: 0.15em;
261
+ }
262
+
263
+ /* ============================================
264
+ 4. Code & Monospace
265
+ ============================================ */
266
+
267
+ .slidev-layout pre,
268
+ .slidev-layout code {
269
+ font-family: var(--font-mono);
270
+ font-size: var(--font-size-small);
271
+ line-height: var(--line-height-code);
272
+ font-variant-ligatures: none;
273
+ font-variant-numeric: tabular-nums;
274
+ letter-spacing: 0;
275
+ word-spacing: normal;
276
+ }
277
+
278
+ .slidev-layout pre {
279
+ border-radius: 0.5rem;
280
+ margin-top: 1rem;
281
+ margin-bottom: 1rem;
282
+ white-space: pre-wrap;
283
+ overflow-wrap: break-word;
284
+ }
285
+
286
+ /* Hide Slidev's built-in copy button on code blocks */
287
+ .slidev-code-copy {
288
+ display: none;
289
+ }
290
+
291
+ /* Border only on native Shiki code blocks (not on pre inside CodeHighlight/CodeDiff) */
292
+ .slidev-layout pre.slidev-code {
293
+ border: 1px solid var(--color-border);
294
+ }
295
+
296
+ /* Reset .slidev-layout pre overrides for CodeHighlight/CodeDiff inner pre */
297
+ .code-hl pre,
298
+ .code-diff pre {
299
+ margin: 0;
300
+ border-radius: 0;
301
+ border: none;
302
+ }
303
+
304
+ /* Language label bar above code blocks (via Shiki transformer data-lang attribute) */
305
+ .slidev-layout pre[data-lang] {
306
+ position: relative;
307
+ /* Override Slidev's --slidev-code-padding (applied with !important) to make room for the label */
308
+ --slidev-code-padding: 2.25rem 8px 8px 8px;
309
+ }
310
+
311
+ .slidev-layout pre[data-lang]::before {
312
+ content: attr(data-lang);
313
+ position: absolute;
314
+ top: 0;
315
+ left: 0;
316
+ right: 0;
317
+ padding: 0.25rem 0.75rem;
318
+ font-family: var(--font-mono);
319
+ font-size: 0.8em;
320
+ font-weight: var(--font-weight-medium);
321
+ text-transform: uppercase;
322
+ letter-spacing: 0.05em;
323
+ color: var(--color-text-tertiary);
324
+ border-bottom: 1px solid var(--color-border);
325
+ background: var(--shiki-color-background, var(--color-bg-muted));
326
+ border-radius: 0.5rem 0.5rem 0 0;
327
+ }
328
+
329
+ .slidev-layout code {
330
+ padding-left: 0.375rem;
331
+ padding-right: 0.375rem;
332
+ padding-top: 0.125rem;
333
+ padding-bottom: 0.125rem;
334
+ border-radius: 0.25rem;
335
+ background-color: var(--color-bg-muted);
336
+ }
337
+
338
+ .slidev-layout pre code {
339
+ padding: 0;
340
+ background-color: transparent;
341
+ }
342
+
343
+ /* ============================================
344
+ 5. Tables
345
+ ============================================ */
346
+
347
+ .slidev-layout table {
348
+ width: 100%;
349
+ margin-top: 1rem;
350
+ margin-bottom: 1rem;
351
+ border-collapse: collapse;
352
+ font-variant-numeric: tabular-nums;
353
+ }
354
+
355
+ .slidev-layout th,
356
+ .slidev-layout td {
357
+ padding-left: 1rem;
358
+ padding-right: 1rem;
359
+ padding-top: 0.5rem;
360
+ padding-bottom: 0.5rem;
361
+ border: 1px solid var(--color-border);
362
+ text-align: left;
363
+ }
364
+
365
+ .slidev-layout th {
366
+ background-color: var(--color-bg-muted);
367
+ font-weight: var(--font-weight-semibold);
368
+ }
369
+
370
+ /* ============================================
371
+ 6. Blockquotes
372
+ ============================================ */
373
+
374
+ .slidev-layout blockquote {
375
+ padding-left: 1rem;
376
+ margin-top: 1rem;
377
+ margin-bottom: 1rem;
378
+ border-left: 4px solid var(--color-border-strong);
379
+ color: var(--color-text-secondary);
380
+ font-style: normal; /* No italic for readability */
381
+ max-width: var(--measure);
382
+ }
383
+
384
+ /* ============================================
385
+ 7. Layout Styles — slide (universal layout)
386
+ ============================================ */
387
+
388
+ /* --- 7a. Fullscreen Mode --- */
389
+ .slide-fullscreen {
390
+ display: flex;
391
+ flex-direction: column;
392
+ height: 100%;
393
+ width: 100%;
394
+ position: relative;
395
+ }
396
+
397
+ .slide-no-padding {
398
+ padding: 0;
399
+ }
400
+
401
+ .slidev-layout.slide-no-padding {
402
+ padding: 0;
403
+ }
404
+
405
+ /* Background layer (edge-to-edge, behind content) */
406
+ .slide-bg {
407
+ position: absolute;
408
+ inset: 0;
409
+ z-index: 0;
410
+ overflow: hidden;
411
+ }
412
+
413
+ /* Auto-sizing for media in bg slots */
414
+ .slide-bg img, .slide-bg video { width: 100%; height: 100%; object-fit: cover; display: block; }
415
+ .slide-bg iframe { width: 100%; height: 100%; border: 0; }
416
+ .slide-bg > div { width: 100%; height: 100%; }
417
+ .slide-bg > p { margin: 0; height: 100%; }
418
+ .slide-bg > p > img { width: 100%; height: 100%; object-fit: cover; display: block; }
419
+
420
+ .slide-content {
421
+ position: relative;
422
+ z-index: 2;
423
+ width: 100%;
424
+ height: 100%;
425
+ display: flex;
426
+ flex-direction: column;
427
+ }
428
+
429
+ /* Center-aligned content: headings and paragraphs follow */
430
+ .slide-content h1,
431
+ .slide-content h2,
432
+ .slide-content p { text-align: inherit; }
433
+
434
+ /* Overlay text: invariant (always light text on dark overlay, regardless of theme) */
435
+ .slide-fullscreen .slide-bg:has(.bg-overlay-dark) ~ .slide-content {
436
+ color: var(--color-drac-fg-50);
437
+ text-shadow: 0 2px 4px color-mix(in srgb, var(--color-black) 30%, transparent);
438
+ }
439
+
440
+ .slide-fullscreen .slide-bg:has(.bg-overlay-dark) ~ .slide-content h1,
441
+ .slide-fullscreen .slide-bg:has(.bg-overlay-dark) ~ .slide-content h2,
442
+ .slide-fullscreen .slide-bg:has(.bg-overlay-dark) ~ .slide-content h3,
443
+ .slide-fullscreen .slide-bg:has(.bg-overlay-dark) ~ .slide-content p {
444
+ color: inherit;
445
+ text-shadow: inherit;
446
+ }
447
+
448
+ .slide-fullscreen .slide-bg:has(.bg-overlay-light) ~ .slide-content {
449
+ color: var(--color-drac-fg-900);
450
+ }
451
+
452
+ .slide-fullscreen .slide-bg:has(.bg-overlay-light) ~ .slide-content h1,
453
+ .slide-fullscreen .slide-bg:has(.bg-overlay-light) ~ .slide-content h2,
454
+ .slide-fullscreen .slide-bg:has(.bg-overlay-light) ~ .slide-content h3,
455
+ .slide-fullscreen .slide-bg:has(.bg-overlay-light) ~ .slide-content p {
456
+ color: inherit;
457
+ }
458
+
459
+ /* Background utility classes (for use in ::bg:: / ::left-bg:: / ::right-bg:: slots) */
460
+ .bg-primary { background-color: var(--color-primary); }
461
+ .bg-success { background-color: var(--color-success); }
462
+ .bg-warning { background-color: var(--color-warning); }
463
+ .bg-danger { background-color: var(--color-danger); }
464
+ .bg-info { background-color: var(--color-info); }
465
+ .bg-soft { background-color: var(--color-bg-soft); }
466
+ .bg-muted { background-color: var(--color-bg-muted); }
467
+ .bg-gradient { background: var(--gradient-primary); }
468
+ .bg-gradient-section { background: var(--gradient-section); }
469
+
470
+ /* --- Colored background auto text color (fullscreen) --- */
471
+ .slide-fullscreen .slide-bg:has(.bg-primary) ~ .slide-content { color: var(--color-primary-foreground); }
472
+ .slide-fullscreen .slide-bg:has(.bg-success) ~ .slide-content { color: var(--color-success-foreground); }
473
+ .slide-fullscreen .slide-bg:has(.bg-warning) ~ .slide-content { color: var(--color-warning-foreground); }
474
+ .slide-fullscreen .slide-bg:has(.bg-danger) ~ .slide-content { color: var(--color-danger-foreground); }
475
+ .slide-fullscreen .slide-bg:has(.bg-info) ~ .slide-content { color: var(--color-info-foreground); }
476
+
477
+ /* soft/muted are light surfaces in both themes — keep default text */
478
+ .slide-fullscreen .slide-bg:has(.bg-soft) ~ .slide-content { color: var(--color-text); }
479
+ .slide-fullscreen .slide-bg:has(.bg-muted) ~ .slide-content { color: var(--color-text); }
480
+
481
+ /* Headings inherit adjusted color (fullscreen) */
482
+ .slide-fullscreen .slide-bg:has(.bg-primary) ~ .slide-content h1,
483
+ .slide-fullscreen .slide-bg:has(.bg-primary) ~ .slide-content h2,
484
+ .slide-fullscreen .slide-bg:has(.bg-primary) ~ .slide-content h3,
485
+ .slide-fullscreen .slide-bg:has(.bg-primary) ~ .slide-content p,
486
+ .slide-fullscreen .slide-bg:has(.bg-success) ~ .slide-content h1,
487
+ .slide-fullscreen .slide-bg:has(.bg-success) ~ .slide-content h2,
488
+ .slide-fullscreen .slide-bg:has(.bg-success) ~ .slide-content h3,
489
+ .slide-fullscreen .slide-bg:has(.bg-success) ~ .slide-content p,
490
+ .slide-fullscreen .slide-bg:has(.bg-warning) ~ .slide-content h1,
491
+ .slide-fullscreen .slide-bg:has(.bg-warning) ~ .slide-content h2,
492
+ .slide-fullscreen .slide-bg:has(.bg-warning) ~ .slide-content h3,
493
+ .slide-fullscreen .slide-bg:has(.bg-warning) ~ .slide-content p,
494
+ .slide-fullscreen .slide-bg:has(.bg-danger) ~ .slide-content h1,
495
+ .slide-fullscreen .slide-bg:has(.bg-danger) ~ .slide-content h2,
496
+ .slide-fullscreen .slide-bg:has(.bg-danger) ~ .slide-content h3,
497
+ .slide-fullscreen .slide-bg:has(.bg-danger) ~ .slide-content p,
498
+ .slide-fullscreen .slide-bg:has(.bg-info) ~ .slide-content h1,
499
+ .slide-fullscreen .slide-bg:has(.bg-info) ~ .slide-content h2,
500
+ .slide-fullscreen .slide-bg:has(.bg-info) ~ .slide-content h3,
501
+ .slide-fullscreen .slide-bg:has(.bg-info) ~ .slide-content p { color: inherit; }
502
+
503
+ /* --- Colored background auto text color (split panels) --- */
504
+ .slide-panel .slide-bg:has(.bg-primary) ~ .slide-panel-content { color: var(--color-primary-foreground); }
505
+ .slide-panel .slide-bg:has(.bg-success) ~ .slide-panel-content { color: var(--color-success-foreground); }
506
+ .slide-panel .slide-bg:has(.bg-warning) ~ .slide-panel-content { color: var(--color-warning-foreground); }
507
+ .slide-panel .slide-bg:has(.bg-danger) ~ .slide-panel-content { color: var(--color-danger-foreground); }
508
+ .slide-panel .slide-bg:has(.bg-info) ~ .slide-panel-content { color: var(--color-info-foreground); }
509
+
510
+ .slide-panel .slide-bg:has(.bg-soft) ~ .slide-panel-content { color: var(--color-text); }
511
+ .slide-panel .slide-bg:has(.bg-muted) ~ .slide-panel-content { color: var(--color-text); }
512
+
513
+ /* Split panel headings inherit */
514
+ .slide-panel .slide-bg:has(.bg-primary) ~ .slide-panel-content h1,
515
+ .slide-panel .slide-bg:has(.bg-primary) ~ .slide-panel-content h2,
516
+ .slide-panel .slide-bg:has(.bg-primary) ~ .slide-panel-content h3,
517
+ .slide-panel .slide-bg:has(.bg-primary) ~ .slide-panel-content p,
518
+ .slide-panel .slide-bg:has(.bg-success) ~ .slide-panel-content h1,
519
+ .slide-panel .slide-bg:has(.bg-success) ~ .slide-panel-content h2,
520
+ .slide-panel .slide-bg:has(.bg-success) ~ .slide-panel-content h3,
521
+ .slide-panel .slide-bg:has(.bg-success) ~ .slide-panel-content p,
522
+ .slide-panel .slide-bg:has(.bg-warning) ~ .slide-panel-content h1,
523
+ .slide-panel .slide-bg:has(.bg-warning) ~ .slide-panel-content h2,
524
+ .slide-panel .slide-bg:has(.bg-warning) ~ .slide-panel-content h3,
525
+ .slide-panel .slide-bg:has(.bg-warning) ~ .slide-panel-content p,
526
+ .slide-panel .slide-bg:has(.bg-danger) ~ .slide-panel-content h1,
527
+ .slide-panel .slide-bg:has(.bg-danger) ~ .slide-panel-content h2,
528
+ .slide-panel .slide-bg:has(.bg-danger) ~ .slide-panel-content h3,
529
+ .slide-panel .slide-bg:has(.bg-danger) ~ .slide-panel-content p,
530
+ .slide-panel .slide-bg:has(.bg-info) ~ .slide-panel-content h1,
531
+ .slide-panel .slide-bg:has(.bg-info) ~ .slide-panel-content h2,
532
+ .slide-panel .slide-bg:has(.bg-info) ~ .slide-panel-content h3,
533
+ .slide-panel .slide-bg:has(.bg-info) ~ .slide-panel-content p { color: inherit; }
534
+
535
+ /* bgOverlay detection for split panels */
536
+ .slide-panel .slide-bg:has(.bg-overlay-dark) ~ .slide-panel-content { color: var(--color-drac-fg-50); text-shadow: 0 2px 4px color-mix(in srgb, var(--color-black) 30%, transparent); }
537
+ .slide-panel .slide-bg:has(.bg-overlay-dark) ~ .slide-panel-content h1,
538
+ .slide-panel .slide-bg:has(.bg-overlay-dark) ~ .slide-panel-content h2,
539
+ .slide-panel .slide-bg:has(.bg-overlay-dark) ~ .slide-panel-content h3,
540
+ .slide-panel .slide-bg:has(.bg-overlay-dark) ~ .slide-panel-content p { color: inherit; text-shadow: inherit; }
541
+ .slide-panel .slide-bg:has(.bg-overlay-light) ~ .slide-panel-content { color: var(--color-drac-fg-900); }
542
+ .slide-panel .slide-bg:has(.bg-overlay-light) ~ .slide-panel-content h1,
543
+ .slide-panel .slide-bg:has(.bg-overlay-light) ~ .slide-panel-content h2,
544
+ .slide-panel .slide-bg:has(.bg-overlay-light) ~ .slide-panel-content h3,
545
+ .slide-panel .slide-bg:has(.bg-overlay-light) ~ .slide-panel-content p { color: inherit; }
546
+
547
+ /* --- 7b. Columns Mode --- */
548
+ .slide-columns {
549
+ display: flex;
550
+ flex-direction: column;
551
+ height: 100%;
552
+ }
553
+
554
+ .slide-title {
555
+ margin-bottom: var(--space-sm);
556
+ }
557
+
558
+ .slide-title h1,
559
+ .slide-title h2 {
560
+ margin-bottom: 0;
561
+ }
562
+
563
+ /* Footnote variant: pushes hr to bottom */
564
+ .slide-footnote .slide-single {
565
+ display: flex;
566
+ flex-direction: column;
567
+ }
568
+
569
+ .slide-footnote .slide-single hr {
570
+ margin-top: auto;
571
+ border: none;
572
+ border-top: 1px solid var(--color-border);
573
+ width: 100%;
574
+ }
575
+
576
+ .slide-footnote .slide-single hr ~ ol,
577
+ .slide-footnote .slide-single hr ~ p {
578
+ font-size: var(--font-size-small);
579
+ color: var(--color-text-secondary);
580
+ line-height: var(--line-height-reading);
581
+ }
582
+
583
+ .slide-footnote .slide-single hr ~ ol {
584
+ margin-inline-start: 1em;
585
+ }
586
+
587
+ .slide-subtitle {
588
+ margin-bottom: var(--space-sm);
589
+ color: var(--color-text-secondary);
590
+ }
591
+
592
+ .slide-single {
593
+ display: flex;
594
+ flex-direction: column;
595
+ flex: 1;
596
+ overflow: auto;
597
+ min-height: 0;
598
+ }
599
+
600
+ .slide-grid {
601
+ display: flex;
602
+ flex: 1;
603
+ min-height: 0;
604
+ }
605
+
606
+ .slide-col {
607
+ overflow: hidden;
608
+ display: flex;
609
+ flex-direction: column;
610
+ min-width: 0;
611
+ }
612
+
613
+ .slide-col p,
614
+ .slide-col ul {
615
+ max-width: var(--measure-narrow);
616
+ }
617
+
618
+ .slide-col-title {
619
+ padding-bottom: var(--space-sm);
620
+ margin-bottom: var(--space-sm);
621
+ border-bottom: 2px solid var(--color-border);
622
+ }
623
+
624
+ .slide-col-title h3 {
625
+ margin: 0;
626
+ }
627
+
628
+ .slide-col-body {
629
+ flex: 1;
630
+ }
631
+
632
+ /* Per-column backgrounds */
633
+ .slide-col-bg-soft { background: var(--color-bg-soft); border-radius: 0.5rem; padding: 1rem; }
634
+ .slide-col-bg-muted { background: var(--color-bg-muted); border-radius: 0.5rem; padding: 1rem; }
635
+ .slide-col-bg-primary { background: var(--color-primary); color: var(--color-primary-foreground); border-radius: 0.5rem; padding: 1rem; }
636
+ .slide-col-bg-success { background: var(--color-success); color: var(--color-success-foreground); border-radius: 0.5rem; padding: 1rem; }
637
+ .slide-col-bg-warning { background: var(--color-warning); color: var(--color-warning-foreground); border-radius: 0.5rem; padding: 1rem; }
638
+ .slide-col-bg-danger { background: var(--color-danger); color: var(--color-danger-foreground); border-radius: 0.5rem; padding: 1rem; }
639
+ .slide-col-bg-info { background: var(--color-info); color: var(--color-info-foreground); border-radius: 0.5rem; padding: 1rem; }
640
+
641
+ .slide-col-bg-primary h1, .slide-col-bg-primary h2, .slide-col-bg-primary h3,
642
+ .slide-col-bg-success h1, .slide-col-bg-success h2, .slide-col-bg-success h3,
643
+ .slide-col-bg-warning h1, .slide-col-bg-warning h2, .slide-col-bg-warning h3,
644
+ .slide-col-bg-danger h1, .slide-col-bg-danger h2, .slide-col-bg-danger h3,
645
+ .slide-col-bg-info h1, .slide-col-bg-info h2, .slide-col-bg-info h3 { color: inherit; }
646
+
647
+ /* Per-column border */
648
+ .slide-col-border { border: 1px solid var(--color-border); border-radius: 0.5rem; padding: 1rem; }
649
+
650
+ /* --- 7c. Split Mode --- */
651
+ .slide-split {
652
+ display: grid;
653
+ height: 100%;
654
+ width: 100%;
655
+ padding: 0;
656
+ position: relative;
657
+ }
658
+
659
+ .slidev-layout.slide-split {
660
+ padding: 0;
661
+ }
662
+
663
+ .slide-panel {
664
+ position: relative;
665
+ overflow: hidden;
666
+ }
667
+
668
+ .slide-panel-bg-only {
669
+ display: flex;
670
+ }
671
+
672
+ .slide-panel-bg-only .slide-bg {
673
+ position: relative;
674
+ width: 100%;
675
+ height: 100%;
676
+ }
677
+
678
+ .slide-panel-content {
679
+ padding: var(--safe-inset-y) var(--safe-inset-x);
680
+ overflow: auto;
681
+ display: flex;
682
+ flex-direction: column;
683
+ justify-content: center;
684
+ position: relative;
685
+ z-index: 2;
686
+ height: 100%;
687
+ }
688
+
689
+ /* When panel has both bg and content, overlay content on bg */
690
+ .slide-panel:not(.slide-panel-bg-only) .slide-bg {
691
+ position: absolute;
692
+ inset: 0;
693
+ z-index: 0;
694
+ }
695
+
696
+ /* --- 7d. Footer (all modes) --- */
697
+ .slide-footer {
698
+ padding: var(--space-xs) var(--safe-inset-x);
699
+ font-size: var(--font-size-small);
700
+ color: var(--color-text-tertiary);
701
+ margin-top: auto;
702
+ position: relative;
703
+ z-index: 2;
704
+ border-top: 1px solid var(--color-border);
705
+ }
706
+
707
+ /* In padded layouts (columns, fullscreen), extend footer to full slide width */
708
+ .slide-columns > .slide-footer,
709
+ .slide-fullscreen:not(.slide-no-padding) > .slide-footer {
710
+ margin-left: calc(var(--safe-inset-x) * -1);
711
+ margin-right: calc(var(--safe-inset-x) * -1);
712
+ }
713
+
714
+ /* ============================================
715
+ 8. Component Styles
716
+ ============================================ */
717
+
718
+ /* Tags component */
719
+ .tags-container {
720
+ display: flex;
721
+ flex-wrap: wrap;
722
+ gap: 0.5rem;
723
+ margin-top: 1rem;
724
+ margin-bottom: 1rem;
725
+ }
726
+
727
+ .tag {
728
+ padding-left: 0.75rem;
729
+ padding-right: 0.75rem;
730
+ padding-top: 0.25rem;
731
+ padding-bottom: 0.25rem;
732
+ border-radius: 9999px;
733
+ font-size: var(--font-size-small);
734
+ background-color: var(--color-primary-soft);
735
+ color: var(--color-primary);
736
+ }
737
+
738
+ /* Button components */
739
+ .btn {
740
+ display: inline-block;
741
+ padding: 0.5rem 1rem;
742
+ border-radius: 0.375rem;
743
+ font-weight: var(--font-weight-medium);
744
+ text-decoration: none;
745
+ cursor: pointer;
746
+ border: none;
747
+ }
748
+
749
+ .btn-primary {
750
+ background-color: var(--color-primary);
751
+ color: var(--color-primary-foreground);
752
+ }
753
+
754
+ .btn-success {
755
+ background-color: var(--color-success);
756
+ color: var(--color-success-foreground);
757
+ }
758
+
759
+ .btn-danger {
760
+ background-color: var(--color-danger);
761
+ color: var(--color-danger-foreground);
762
+ }
763
+
764
+ .btn-secondary {
765
+ background-color: var(--color-secondary);
766
+ color: var(--color-secondary-foreground);
767
+ }
768
+
769
+ /* Links styled as buttons — underline for accessibility */
770
+ a.btn-primary { color: var(--color-primary-foreground); }
771
+ a.btn-success { color: var(--color-success-foreground); }
772
+ a.btn-danger { color: var(--color-danger-foreground); }
773
+ a.btn-secondary { color: var(--color-secondary-foreground); }
774
+
775
+ a.btn,
776
+ a.btn-primary,
777
+ a.btn-success,
778
+ a.btn-danger,
779
+ a.btn-secondary {
780
+ text-decoration: underline;
781
+ text-underline-offset: 0.15em;
782
+ }
783
+
784
+ a.btn:hover,
785
+ a.btn-primary:hover,
786
+ a.btn-success:hover,
787
+ a.btn-danger:hover,
788
+ a.btn-secondary:hover {
789
+ text-decoration: none;
790
+ }
791
+
792
+ /* Text color utilities */
793
+ .text-primary { color: var(--color-text); }
794
+ .text-secondary { color: var(--color-text-secondary); }
795
+ .text-tertiary { color: var(--color-text-tertiary); }
796
+ .text-success { color: var(--color-success); }
797
+ .text-warning { color: var(--color-warning); }
798
+ .text-danger { color: var(--color-danger); }
799
+ .text-info { color: var(--color-info); }
800
+
801
+ /* Color palette: styles are in ColorSwatch.vue component */
802
+
803
+ /* ============================================
804
+ 9. Debug Safe Zone Overlay
805
+ Add .debug-safe-zone to body for testing
806
+ ============================================ */
807
+
808
+ .debug-safe-zone .slidev-layout::before {
809
+ content: '';
810
+ position: absolute;
811
+ inset: var(--safe-inset-y) var(--safe-inset-x);
812
+ border: 2px dashed color-mix(in srgb, var(--color-drac-red-500) 50%, transparent);
813
+ pointer-events: none;
814
+ z-index: 9999;
815
+ }
816
+
817
+ /* Safe Zone Demo (for safe-zone-test slide) */
818
+ .safe-zone-demo {
819
+ position: relative;
820
+ width: 100%;
821
+ height: 100%;
822
+ display: flex;
823
+ align-items: center;
824
+ justify-content: center;
825
+ }
826
+
827
+ .safe-zone-border {
828
+ position: absolute;
829
+ inset: 5% 5%;
830
+ border: 3px dashed var(--color-danger);
831
+ border-radius: 0.5rem;
832
+ pointer-events: none;
833
+ }
834
+
835
+ .safe-zone-label {
836
+ position: absolute;
837
+ top: -1.5rem;
838
+ left: 50%;
839
+ transform: translateX(-50%);
840
+ font-size: var(--font-size-small);
841
+ color: var(--color-danger);
842
+ white-space: nowrap;
843
+ }
844
+
845
+ .safe-zone-content {
846
+ text-align: center;
847
+ max-width: 60%;
848
+ }
849
+
850
+ /* ============================================
851
+ 10. Callout Blockquotes (Note/Warning/Tip)
852
+ ============================================ */
853
+
854
+ /* Enhanced blockquote callout base style */
855
+ .slidev-layout blockquote:has(p:first-child strong:first-child) {
856
+ border-left-width: 4px;
857
+ padding: 1rem 1rem 1rem 1.25rem;
858
+ background-color: var(--color-bg-soft);
859
+ border-radius: 0 0.375rem 0.375rem 0;
860
+ }
861
+
862
+ /* Semantic callout classes — apply to blockquote */
863
+ .slidev-layout blockquote.callout-note,
864
+ .callout-note {
865
+ border-left-color: var(--color-info);
866
+ }
867
+
868
+ .slidev-layout blockquote.callout-warning,
869
+ .callout-warning {
870
+ border-left-color: var(--color-warning);
871
+ }
872
+
873
+ .slidev-layout blockquote.callout-tip,
874
+ .callout-tip {
875
+ border-left-color: var(--color-success);
876
+ }
877
+
878
+ .slidev-layout blockquote.callout-danger,
879
+ .callout-danger {
880
+ border-left-color: var(--color-danger);
881
+ }
882
+
883
+ /* ============================================
884
+ 11. Keyboard Focus Styles (WCAG 2.2)
885
+ ============================================ */
886
+
887
+ .slidev-layout :focus-visible {
888
+ outline: 3px solid var(--color-primary);
889
+ outline-offset: 2px;
890
+ }
891
+
892
+ /* Ensure focus is not obscured */
893
+ .slidev-layout :focus-visible {
894
+ scroll-padding: 1rem;
895
+ }
896
+
897
+ /* (Old layout sections 12-27 removed - replaced by section 7 above) */
898
+
899
+ /* ============================================
900
+ 34. Mermaid Diagram Overrides
901
+ ============================================
902
+ Ensure proper text contrast in dark/light themes
903
+ ============================================ */
904
+
905
+ /* ER Diagram - ensure text is readable */
906
+ .mermaid .entityBox {
907
+ fill: var(--color-bg-soft) !important;
908
+ stroke: var(--color-border-strong) !important;
909
+ }
910
+
911
+ .mermaid .entityBox text,
912
+ .mermaid .entityLabel text {
913
+ fill: var(--color-text) !important;
914
+ }
915
+
916
+ /* ER Diagram relationships */
917
+ .mermaid .relationshipLabel text {
918
+ fill: var(--color-text-secondary) !important;
919
+ }
920
+
921
+ /* Ensure attribute text is readable */
922
+ .mermaid .attributeBoxOdd,
923
+ .mermaid .attributeBoxEven {
924
+ fill: var(--color-bg-soft) !important;
925
+ }
926
+
927
+ .mermaid .attributeBoxOdd text,
928
+ .mermaid .attributeBoxEven text {
929
+ fill: var(--color-text) !important;
930
+ }
931
+
932
+ /* State Diagram - transition label contrast */
933
+ .mermaid .statediagram-state rect.divider {
934
+ stroke: var(--color-border) !important;
935
+ }
936
+
937
+ .mermaid .stateLabel .edgeLabel {
938
+ background-color: var(--color-bg-muted) !important;
939
+ }
940
+
941
+ /* ============================================
942
+ 37. SpeechBubble overflow fix
943
+ ============================================ */
944
+
945
+ /* Ensure thought bubble circles are not clipped in overflow: auto containers */
946
+ .bubble-thought.bubble-bottom {
947
+ margin-bottom: 1.5rem;
948
+ }
949
+
950
+ .bubble-thought.bubble-top {
951
+ margin-top: 1.5rem;
952
+ }
953
+
954
+ .bubble-thought.bubble-left {
955
+ margin-left: 2rem;
956
+ }
957
+
958
+ .bubble-thought.bubble-right {
959
+ margin-right: 2rem;
960
+ }
961
+
962
+ /* ============================================
963
+ 38. DeviceMockup Placeholder
964
+ ============================================ */
965
+
966
+ .device-mockup-placeholder {
967
+ padding: 2rem;
968
+ text-align: center;
969
+ }
970
+
971
+ .device-mockup-placeholder h2 {
972
+ margin: 0;
973
+ }
974
+
975
+ .device-mockup-placeholder p {
976
+ color: var(--color-text-secondary);
977
+ text-align: center;
978
+ max-width: none;
979
+ }
980
+
981
+ /* Shiki bg handled by --shiki-color-background in colors.css */
982
+
983
+ /* CodePen: styles are in Iframe.vue component */
984
+
985
+ /* ============================================
986
+ Inline code on overlay/colored backgrounds
987
+ ============================================ */
988
+
989
+ /* Dark overlay: code needs light-on-dark */
990
+ .slide-fullscreen .slide-bg:has(.bg-overlay-dark) ~ .slide-content code {
991
+ background: color-mix(in srgb, var(--color-drac-fg-50) 15%, transparent);
992
+ color: var(--color-drac-fg-50);
993
+ }
994
+
995
+ /* Light overlay: code needs dark-on-light */
996
+ .slide-fullscreen .slide-bg:has(.bg-overlay-light) ~ .slide-content code {
997
+ background: color-mix(in srgb, var(--color-drac-fg-900) 12%, transparent);
998
+ color: var(--color-drac-fg-900);
999
+ }
1000
+
1001
+ /* Split panels: same rules */
1002
+ .slide-panel .slide-bg:has(.bg-overlay-dark) ~ .slide-panel-content code {
1003
+ background: color-mix(in srgb, var(--color-drac-fg-50) 15%, transparent);
1004
+ color: var(--color-drac-fg-50);
1005
+ }
1006
+
1007
+ .slide-panel .slide-bg:has(.bg-overlay-light) ~ .slide-panel-content code {
1008
+ background: color-mix(in srgb, var(--color-drac-fg-900) 12%, transparent);
1009
+ color: var(--color-drac-fg-900);
1010
+ }
1011
+
1012
+ /* Colored background columns: code inherits adapted color */
1013
+ .slidev-layout .slide-col-bg-primary code,
1014
+ .slidev-layout .slide-col-bg-success code,
1015
+ .slidev-layout .slide-col-bg-warning code,
1016
+ .slidev-layout .slide-col-bg-danger code,
1017
+ .slidev-layout .slide-col-bg-info code {
1018
+ background-color: color-mix(in srgb, currentColor 12%, transparent);
1019
+ color: inherit;
1020
+ }
1021
+
1022
+ /* Colored background fullscreen: code adapts */
1023
+ .slide-fullscreen .slide-bg:has(.bg-primary) ~ .slide-content code,
1024
+ .slide-fullscreen .slide-bg:has(.bg-success) ~ .slide-content code,
1025
+ .slide-fullscreen .slide-bg:has(.bg-warning) ~ .slide-content code,
1026
+ .slide-fullscreen .slide-bg:has(.bg-danger) ~ .slide-content code,
1027
+ .slide-fullscreen .slide-bg:has(.bg-info) ~ .slide-content code {
1028
+ background: color-mix(in srgb, currentColor 12%, transparent);
1029
+ color: inherit;
1030
+ }
1031
+
1032
+ /* ============================================
1033
+ Component vertical spacing
1034
+ ============================================ */
1035
+
1036
+ .slide-content > * + *,
1037
+ .slide-single > * + *,
1038
+ .slide-col-body > * + * {
1039
+ margin-top: var(--space-sm);
1040
+ }
1041
+
1042
+ /* Headings already have margin, don't double-up */
1043
+ .slide-content > h1 + *,
1044
+ .slide-content > h2 + *,
1045
+ .slide-content > h3 + *,
1046
+ .slide-single > h1 + *,
1047
+ .slide-single > h2 + *,
1048
+ .slide-single > h3 + * {
1049
+ margin-top: 0;
1050
+ }
1051
+
1052
+ /* (Variant CSS classes removed — replaced by Vue components) */
1053
+