@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,486 @@
1
+ /* ============================================
2
+ slidev-theme-troshab — Motion System
3
+ ============================================
4
+
5
+ Based on IBM Carbon Design Motion Guidelines
6
+ https://carbondesignsystem.com/elements/motion/overview/
7
+
8
+ PRINCIPLES:
9
+ 1. Purposeful — motion guides focus, not distracts
10
+ 2. Responsive — motion gives feedback
11
+ 3. Natural — follows physics, not linear
12
+ 4. Automatic — smart defaults based on content type
13
+
14
+ ============================================ */
15
+
16
+ /* ============================================
17
+ 1. Motion Tokens
18
+ ============================================ */
19
+
20
+ :root {
21
+ /* --- Easing Functions (IBM Carbon) --- */
22
+ /* Standard: default for most animations */
23
+ --ease-standard: cubic-bezier(0.2, 0.0, 0.38, 0.9);
24
+ /* Enter: elements entering the viewport */
25
+ --ease-enter: cubic-bezier(0.0, 0.0, 0.38, 0.9);
26
+ /* Exit: elements leaving the viewport */
27
+ --ease-exit: cubic-bezier(0.2, 0.0, 1.0, 0.9);
28
+ /* Expressive: for decorative/expressive animations */
29
+ --ease-expressive: cubic-bezier(0.4, 0.14, 0.3, 1.0);
30
+
31
+ /* --- Durations (IBM Carbon) --- */
32
+ --dur-fast-01: 70ms; /* micro-interactions */
33
+ --dur-fast-02: 110ms; /* small UI elements */
34
+ --dur-moderate-01: 150ms; /* medium complexity */
35
+ --dur-moderate-02: 240ms; /* opening/closing */
36
+ --dur-slow-01: 400ms; /* large movements */
37
+ --dur-slow-02: 700ms; /* complex sequences */
38
+
39
+ /* --- Exit Timing Modifier (Material Design) --- */
40
+ /* Exit animations should be ~20% faster than enter */
41
+ --dur-exit-modifier: 0.8;
42
+
43
+ /* --- Movement Distances --- */
44
+ --shift-xs: 6px; /* subtle */
45
+ --shift-sm: 12px; /* small */
46
+ --shift-md: 20px; /* medium */
47
+ --shift-lg: 28px; /* large */
48
+
49
+ /* --- Scale Values --- */
50
+ --scale-subtle: 0.985;
51
+ --scale-moderate: 0.95;
52
+ --scale-dramatic: 0.9;
53
+
54
+ /* --- Default Motion Mode (calm) --- */
55
+ --motion-duration: var(--dur-moderate-02);
56
+ --motion-ease: var(--ease-standard);
57
+ --motion-shift: var(--shift-md);
58
+ --motion-scale: var(--scale-subtle);
59
+
60
+ /* --- Stagger Delays --- */
61
+ --stagger-base: 50ms;
62
+ }
63
+
64
+ /* ============================================
65
+ 2. Motion Modes
66
+ ============================================
67
+
68
+ Apply class to slide or container:
69
+ - (default): calm, minimal motion
70
+ - .motion-crisp: faster, smaller amplitudes
71
+ - .motion-expressive: softer, longer durations
72
+ */
73
+
74
+ /* Crisp mode — faster, snappier */
75
+ .motion-crisp {
76
+ --motion-duration: var(--dur-moderate-01);
77
+ --motion-ease: var(--ease-standard);
78
+ --motion-shift: var(--shift-sm);
79
+ --motion-scale: 0.99;
80
+ --stagger-base: 30ms;
81
+ }
82
+
83
+ /* Expressive mode — slower, more dramatic */
84
+ .motion-expressive {
85
+ --motion-duration: var(--dur-slow-01);
86
+ --motion-ease: var(--ease-expressive);
87
+ --motion-shift: var(--shift-lg);
88
+ --motion-scale: var(--scale-moderate);
89
+ --stagger-base: 70ms;
90
+ }
91
+
92
+ /* ============================================
93
+ 3. v-click Reveal Styles
94
+ ============================================
95
+
96
+ Default Slidev v-click behavior is fade + subtle rise.
97
+
98
+ Apply class to container for different effects:
99
+ - (default): fade + subtle rise
100
+ - .reveal-fade: opacity only
101
+ - .reveal-slide: slide from right
102
+ - .reveal-pop: scale up
103
+
104
+ Automatic detection by content type (no class needed):
105
+ - Code blocks: fade only (no movement disrupts alignment)
106
+ - Tables: fade only
107
+ - Lists: subtle slide from left
108
+ - Large text (KPIs): pop effect
109
+ - Blockquotes: fade only
110
+ */
111
+
112
+ /* Default v-click: fade + subtle rise */
113
+ .slidev-vclick-target {
114
+ transition:
115
+ opacity var(--motion-duration) var(--ease-enter),
116
+ transform var(--motion-duration) var(--ease-enter);
117
+ }
118
+
119
+ .slidev-vclick-hidden {
120
+ opacity: 0;
121
+ transform: translateY(var(--shift-sm));
122
+ }
123
+
124
+ /* reveal-fade: opacity only */
125
+ .slidev-layout.reveal-fade .slidev-vclick-hidden,
126
+ .slidev-layout.reveal-fade li.slidev-vclick-hidden,
127
+ .slidev-layout.reveal-fade pre.slidev-vclick-hidden,
128
+ .slidev-layout.reveal-fade .shiki.slidev-vclick-hidden,
129
+ .slidev-layout.reveal-fade table.slidev-vclick-hidden,
130
+ .slidev-layout.reveal-fade blockquote.slidev-vclick-hidden,
131
+ .slidev-layout.reveal-fade img.slidev-vclick-hidden,
132
+ .slidev-layout.reveal-fade svg.slidev-vclick-hidden {
133
+ opacity: 0;
134
+ transform: none;
135
+ }
136
+
137
+ /* reveal-slide: slide from right */
138
+ .slidev-layout.reveal-slide .slidev-vclick-hidden,
139
+ .slidev-layout.reveal-slide li.slidev-vclick-hidden,
140
+ .slidev-layout.reveal-slide pre.slidev-vclick-hidden,
141
+ .slidev-layout.reveal-slide .shiki.slidev-vclick-hidden,
142
+ .slidev-layout.reveal-slide table.slidev-vclick-hidden,
143
+ .slidev-layout.reveal-slide blockquote.slidev-vclick-hidden,
144
+ .slidev-layout.reveal-slide img.slidev-vclick-hidden,
145
+ .slidev-layout.reveal-slide svg.slidev-vclick-hidden {
146
+ opacity: 0;
147
+ transform: translateX(var(--motion-shift));
148
+ }
149
+
150
+ /* reveal-pop: scale up */
151
+ .slidev-layout.reveal-pop .slidev-vclick-hidden,
152
+ .slidev-layout.reveal-pop li.slidev-vclick-hidden,
153
+ .slidev-layout.reveal-pop pre.slidev-vclick-hidden,
154
+ .slidev-layout.reveal-pop .shiki.slidev-vclick-hidden,
155
+ .slidev-layout.reveal-pop table.slidev-vclick-hidden,
156
+ .slidev-layout.reveal-pop blockquote.slidev-vclick-hidden,
157
+ .slidev-layout.reveal-pop img.slidev-vclick-hidden,
158
+ .slidev-layout.reveal-pop svg.slidev-vclick-hidden {
159
+ opacity: 0;
160
+ transform: scale(var(--scale-moderate));
161
+ }
162
+
163
+ /* ============================================
164
+ 3b. Automatic Content-Type Detection
165
+ ============================================
166
+
167
+ Smart v-click reveal based on element type.
168
+ These override the default rise animation for specific content.
169
+ */
170
+
171
+ /* Code blocks: fade only (no movement disrupts alignment) */
172
+ .slidev-layout pre.slidev-vclick-hidden,
173
+ .slidev-layout .shiki.slidev-vclick-hidden,
174
+ .slidev-layout pre .slidev-vclick-hidden,
175
+ .slidev-layout .shiki .slidev-vclick-hidden {
176
+ transform: none;
177
+ }
178
+
179
+ /* Tables: fade only (preserves alignment) */
180
+ .slidev-layout table.slidev-vclick-hidden,
181
+ .slidev-layout table .slidev-vclick-hidden {
182
+ transform: none;
183
+ }
184
+
185
+ /* Blockquotes: fade only (elegant reveal) */
186
+ .slidev-layout blockquote.slidev-vclick-hidden,
187
+ .slidev-layout blockquote .slidev-vclick-hidden {
188
+ transform: none;
189
+ }
190
+
191
+ /* Lists inside v-clicks: subtle slide from left */
192
+ .slidev-layout li.slidev-vclick-hidden {
193
+ transform: translateX(calc(var(--shift-sm) * -1));
194
+ }
195
+
196
+ /* Large text (KPIs, metrics): pop effect */
197
+ .slidev-layout .text-4xl.slidev-vclick-hidden,
198
+ .slidev-layout .text-5xl.slidev-vclick-hidden,
199
+ .slidev-layout .text-6xl.slidev-vclick-hidden,
200
+ .slidev-layout .text-7xl.slidev-vclick-hidden,
201
+ .slidev-layout .text-8xl.slidev-vclick-hidden,
202
+ .slidev-layout [class*="font-size-h1"].slidev-vclick-hidden,
203
+ .slidev-layout .fact-value.slidev-vclick-hidden {
204
+ transform: scale(var(--scale-moderate));
205
+ }
206
+
207
+ /* Images: fade only */
208
+ .slidev-layout img.slidev-vclick-hidden {
209
+ transform: none;
210
+ }
211
+
212
+ /* Diagrams (mermaid, SVG): fade only */
213
+ .slidev-layout .mermaid.slidev-vclick-hidden,
214
+ .slidev-layout svg.slidev-vclick-hidden {
215
+ transform: none;
216
+ }
217
+
218
+ /* ============================================
219
+ 3c. List Stagger Pattern
220
+ ============================================
221
+
222
+ Natural stagger for v-clicks on list items.
223
+ Limited to 6 items (Material Design: avoid "crawling" effect).
224
+ */
225
+
226
+ /* Default stagger delays */
227
+ .slidev-layout li.slidev-vclick-target:nth-child(1) { transition-delay: 0ms; }
228
+ .slidev-layout li.slidev-vclick-target:nth-child(2) { transition-delay: var(--stagger-base); }
229
+ .slidev-layout li.slidev-vclick-target:nth-child(3) { transition-delay: calc(var(--stagger-base) * 2); }
230
+ .slidev-layout li.slidev-vclick-target:nth-child(4) { transition-delay: calc(var(--stagger-base) * 3); }
231
+ .slidev-layout li.slidev-vclick-target:nth-child(5) { transition-delay: calc(var(--stagger-base) * 4); }
232
+ .slidev-layout li.slidev-vclick-target:nth-child(6) { transition-delay: calc(var(--stagger-base) * 5); }
233
+ /* Items 7+ get no additional delay to avoid "crawling" */
234
+ .slidev-layout li.slidev-vclick-target:nth-child(n+7) { transition-delay: calc(var(--stagger-base) * 5); }
235
+
236
+ /* Reset delay when item becomes visible (avoid lingering delay) */
237
+ .slidev-layout li.slidev-vclick-target:not(.slidev-vclick-hidden) {
238
+ transition-delay: 0ms;
239
+ }
240
+
241
+ /* ============================================
242
+ 4. Layout Entrance Animations
243
+ ============================================
244
+
245
+ CSS-based entrance animations for key layouts.
246
+
247
+ SEMANTIC DIRECTION PHILOSOPHY:
248
+ - Headings (h1, h2, h3): "fall" from above ↓
249
+ - Content (single block): "rise" from below ↑
250
+ - Two columns: slide from sides ← →
251
+ - Grid (3-4 cols): all items rise from below ↑
252
+ */
253
+
254
+ /* --- Fullscreen mode: slide+fade from below, staggered --- */
255
+ .slide-fullscreen .slide-content h1 {
256
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) both;
257
+ }
258
+
259
+ .slide-fullscreen .slide-content h2 {
260
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 2) both;
261
+ }
262
+
263
+ .slide-fullscreen .slide-content > *:not(h1):not(h2) {
264
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
265
+ }
266
+
267
+ /* Fullscreen with bg: fade bg first, content slides up after */
268
+ .slide-no-padding .slide-content {
269
+ animation: entrance-fade var(--dur-moderate-02) var(--ease-enter) both;
270
+ }
271
+
272
+ .slide-no-padding .slide-content > * {
273
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
274
+ }
275
+
276
+ /* ============================================
277
+ 4b. Columns Mode Entrance Animations
278
+ ============================================
279
+
280
+ SEQUENCE: title (rise) -> subtitle (rise) -> columns
281
+ - 1/3/4 columns: rise from below, right after title/subtitle
282
+ - 2 columns: left from left, right from right
283
+ If no subtitle, columns appear sooner (delay * 2 instead of * 4)
284
+ */
285
+
286
+ /* Title: slide+fade from below (first) */
287
+ .slide-title {
288
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) both;
289
+ }
290
+
291
+ /* Subtitle: slide+fade from below (second) */
292
+ .slide-subtitle {
293
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 2) both;
294
+ }
295
+
296
+ /* --- Single column: rise from below --- */
297
+ .slide-single {
298
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
299
+ }
300
+
301
+ /* Single col without title+subtitle: faster start */
302
+ .slide-columns > .slide-single:first-child {
303
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) both;
304
+ }
305
+
306
+ /* Blockquotes in single col: fade only */
307
+ .slide-single > blockquote {
308
+ animation: entrance-fade var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
309
+ }
310
+
311
+ /* --- 2 columns: slide from sides toward center --- */
312
+ .slide-grid > .slide-col:first-child:nth-last-child(2) {
313
+ animation: entrance-slide-right var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
314
+ }
315
+
316
+ .slide-grid > .slide-col:last-child:nth-last-child(2) {
317
+ animation: entrance-slide-left var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
318
+ }
319
+
320
+ /* --- 3+ columns: all rise from below --- */
321
+ .slide-grid > .slide-col:first-child:nth-last-child(n+3),
322
+ .slide-grid > .slide-col:first-child:nth-last-child(n+3) ~ .slide-col {
323
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
324
+ }
325
+
326
+ /* ============================================
327
+ 4c. Split Mode Entrance Animations
328
+ ============================================
329
+
330
+ Split panels: left from left, right from right
331
+ */
332
+
333
+ /* Left half slides from left edge */
334
+ .slide-split > *:first-child {
335
+ animation: entrance-slide-right var(--dur-moderate-02) var(--ease-enter) both;
336
+ }
337
+
338
+ /* Right half slides from right edge */
339
+ .slide-split > *:last-child:not(:first-child) {
340
+ animation: entrance-slide-left var(--dur-moderate-02) var(--ease-enter) both;
341
+ }
342
+
343
+ /* Split bg-only panel: fade */
344
+ .slide-panel-bg-only {
345
+ animation: entrance-fade var(--dur-moderate-02) var(--ease-enter) both;
346
+ }
347
+
348
+ /* Split caption overlay: slides up after */
349
+ .slide-caption-overlay {
350
+ animation: entrance-rise var(--dur-moderate-02) var(--ease-enter) calc(var(--stagger-base) * 4) both;
351
+ }
352
+
353
+ /* ============================================
354
+ 5. Keyframe Animations
355
+ ============================================ */
356
+
357
+ @keyframes entrance-fade {
358
+ from {
359
+ opacity: 0;
360
+ }
361
+ to {
362
+ opacity: 1;
363
+ }
364
+ }
365
+
366
+ /* Fall from above — for headings */
367
+ @keyframes entrance-fall {
368
+ from {
369
+ opacity: 0;
370
+ transform: translateY(calc(var(--shift-md) * -1));
371
+ }
372
+ to {
373
+ opacity: 1;
374
+ transform: translateY(0);
375
+ }
376
+ }
377
+
378
+ /* Rise from below — for content */
379
+ @keyframes entrance-rise {
380
+ from {
381
+ opacity: 0;
382
+ transform: translateY(var(--shift-md));
383
+ }
384
+ to {
385
+ opacity: 1;
386
+ transform: translateY(0);
387
+ }
388
+ }
389
+
390
+ @keyframes entrance-scale {
391
+ from {
392
+ opacity: 0;
393
+ transform: scale(var(--scale-moderate));
394
+ }
395
+ to {
396
+ opacity: 1;
397
+ transform: scale(1);
398
+ }
399
+ }
400
+
401
+ /* Slide from left side (element comes from left) */
402
+ @keyframes entrance-slide-right {
403
+ from {
404
+ opacity: 0;
405
+ transform: translateX(calc(var(--shift-md) * -1));
406
+ }
407
+ to {
408
+ opacity: 1;
409
+ transform: translateX(0);
410
+ }
411
+ }
412
+
413
+ /* Slide from right side (element comes from right) */
414
+ @keyframes entrance-slide-left {
415
+ from {
416
+ opacity: 0;
417
+ transform: translateX(var(--shift-md));
418
+ }
419
+ to {
420
+ opacity: 1;
421
+ transform: translateX(0);
422
+ }
423
+ }
424
+
425
+ /* ============================================
426
+ 6. Utility Classes
427
+ ============================================ */
428
+
429
+ /* Delay utilities for staggered animations */
430
+ .delay-100 { animation-delay: 100ms; }
431
+ .delay-200 { animation-delay: 200ms; }
432
+ .delay-300 { animation-delay: 300ms; }
433
+ .delay-400 { animation-delay: 400ms; }
434
+ .delay-500 { animation-delay: 500ms; }
435
+
436
+ /* Duration utilities */
437
+ .duration-fast { animation-duration: var(--dur-fast-02); }
438
+ .duration-moderate { animation-duration: var(--dur-moderate-02); }
439
+ .duration-slow { animation-duration: var(--dur-slow-01); }
440
+
441
+ /* No animation utility */
442
+ .no-animate {
443
+ animation: none !important;
444
+ transition: none !important;
445
+ }
446
+
447
+ /* ============================================
448
+ 7. Reduced Motion Support (WCAG 2.1)
449
+ ============================================
450
+
451
+ Users with vestibular disorders or motion sensitivity
452
+ can enable "Reduce motion" in their OS settings.
453
+ This disables all non-essential animations.
454
+
455
+ TODO: Uncomment when ready to enable reduced motion support
456
+ */
457
+
458
+ /*
459
+ @media (prefers-reduced-motion: reduce) {
460
+ .slidev-layout *,
461
+ .slide-fullscreen *,
462
+ .slide-content *,
463
+ .slide-columns *,
464
+ .slide-title,
465
+ .slide-single,
466
+ .slide-grid > .slide-col,
467
+ .slide-panel,
468
+ .slide-panel-content,
469
+ .slide-caption-overlay,
470
+ .slidev-layout .grid > * {
471
+ animation: none !important;
472
+ animation-duration: 0.01ms !important;
473
+ animation-delay: 0ms !important;
474
+ }
475
+
476
+ .slidev-vclick-target {
477
+ transition-duration: 0.01ms !important;
478
+ transition-delay: 0ms !important;
479
+ }
480
+
481
+ .slidev-vclick-hidden {
482
+ opacity: 0;
483
+ transform: none !important;
484
+ }
485
+ }
486
+ */
package/uno.config.ts ADDED
@@ -0,0 +1,67 @@
1
+ import { defineConfig } from 'unocss'
2
+
3
+ export default defineConfig({
4
+ // Safelist for dynamic classes that UnoCSS can't detect via static analysis
5
+ safelist: [
6
+ // Column spans for two-cols layout
7
+ 'col-span-3', 'col-span-4', 'col-span-5', 'col-span-6', 'col-span-7', 'col-span-8', 'col-span-9',
8
+ // Grid classes
9
+ 'grid', 'grid-cols-12',
10
+ // Gap classes
11
+ 'gap-0', 'gap-1', 'gap-2', 'gap-4', 'gap-6', 'gap-8',
12
+ // Alignment classes
13
+ 'items-start', 'items-center', 'items-end',
14
+ ],
15
+
16
+ shortcuts: {
17
+ // 12-column grid system
18
+ 'grid-cols': 'grid grid-cols-12 gap-4',
19
+
20
+ // Column width shortcuts (left column width)
21
+ 'is-3': 'col-span-3',
22
+ 'is-4': 'col-span-4',
23
+ 'is-5': 'col-span-5',
24
+ 'is-6': 'col-span-6',
25
+ 'is-7': 'col-span-7',
26
+ 'is-8': 'col-span-8',
27
+ 'is-9': 'col-span-9',
28
+
29
+ // Semantic aliases
30
+ 'is-half': 'col-span-6',
31
+ 'is-one-third': 'col-span-4',
32
+ 'is-two-thirds': 'col-span-8',
33
+ 'is-one-quarter': 'col-span-3',
34
+ 'is-three-quarters': 'col-span-9',
35
+
36
+ // Layout utilities
37
+ 'slide-content': 'h-full w-full p-8',
38
+ 'slide-content-full': 'h-full w-full',
39
+ 'flex-center': 'flex items-center justify-center',
40
+ 'flex-col-center': 'flex flex-col items-center justify-center',
41
+
42
+ // Text utilities
43
+ 'text-slide-title': 'text-4xl font-bold mb-4',
44
+ 'text-slide-subtitle': 'text-2xl opacity-80',
45
+ 'text-section-title': 'text-5xl font-bold',
46
+ 'text-quote': 'text-3xl italic leading-relaxed',
47
+ 'text-quote-author': 'text-xl opacity-70 mt-4',
48
+
49
+ // Note: Block and Theorem component styles are defined in CSS (colors.css + base.css)
50
+ // to properly use CSS variables for theming. Do not add UnoCSS shortcuts for these.
51
+ },
52
+
53
+ rules: [
54
+ // Dynamic column spans
55
+ [/^col-left-(\d+)$/, ([, d]) => ({ 'grid-column': `span ${d}` })],
56
+ [/^col-right-(\d+)$/, ([, d]) => ({ 'grid-column': `span ${12 - parseInt(d)}` })],
57
+ ],
58
+
59
+ theme: {
60
+ extend: {
61
+ fontFamily: {
62
+ sans: ['IBM Plex Sans', 'system-ui', '-apple-system', 'sans-serif'],
63
+ mono: ['IBM Plex Mono', 'Consolas', 'Monaco', 'monospace'],
64
+ },
65
+ },
66
+ },
67
+ })