steppy-dev 0.3.0__py3-none-any.whl

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 (177) hide show
  1. steppy/CHANGELOG.md +862 -0
  2. steppy/__init__.py +9 -0
  3. steppy/__main__.py +13 -0
  4. steppy/_cli_common.py +183 -0
  5. steppy/_docker/Dockerfile.installed +53 -0
  6. steppy/_parallel/__init__.py +7 -0
  7. steppy/_parallel/compose.py +349 -0
  8. steppy/_parallel/event_bus.py +418 -0
  9. steppy/_parallel/failures.py +267 -0
  10. steppy/_parallel/fingerprint.py +141 -0
  11. steppy/_parallel/image.py +380 -0
  12. steppy/_parallel/lastfailed.py +125 -0
  13. steppy/_parallel/lifecycle.py +90 -0
  14. steppy/_parallel/preauth.py +109 -0
  15. steppy/_parallel/progress.py +101 -0
  16. steppy/_parallel/queue.py +385 -0
  17. steppy/_parallel/renderer.py +489 -0
  18. steppy/_parallel/retry.py +316 -0
  19. steppy/_player_bundle/THIRD_PARTY_LICENSES.txt +158 -0
  20. steppy/_player_bundle/__init__.py +100 -0
  21. steppy/_player_bundle/steppy-cursor-legacy.js +2 -0
  22. steppy/_player_bundle/steppy-cursor-legacy.js.map +1 -0
  23. steppy/_player_bundle/steppy-player.js +5419 -0
  24. steppy/_player_bundle/steppy-player.js.map +1 -0
  25. steppy/_player_bundle/steppy-video.js +472 -0
  26. steppy/_player_bundle/steppy-video.js.map +1 -0
  27. steppy/_templating.py +117 -0
  28. steppy/assertions.py +251 -0
  29. steppy/auth.py +493 -0
  30. steppy/build.py +2798 -0
  31. steppy/build_models.py +669 -0
  32. steppy/buildid.py +134 -0
  33. steppy/bundle/__init__.py +47 -0
  34. steppy/bundle/archive.py +239 -0
  35. steppy/bundle/classify.py +329 -0
  36. steppy/bundle/create.py +490 -0
  37. steppy/bundle/hashing.py +28 -0
  38. steppy/bundle/manifest.py +334 -0
  39. steppy/bundle/results.py +546 -0
  40. steppy/bundle_cli.py +455 -0
  41. steppy/captures.py +207 -0
  42. steppy/cli.py +2489 -0
  43. steppy/cloud/__init__.py +58 -0
  44. steppy/cloud/client.py +267 -0
  45. steppy/cloud/upload.py +497 -0
  46. steppy/compat.py +109 -0
  47. steppy/config.py +231 -0
  48. steppy/config_schema.py +87 -0
  49. steppy/contracts/__init__.py +54 -0
  50. steppy/contracts/bundle.py +215 -0
  51. steppy/contracts/report.py +346 -0
  52. steppy/contracts/tours.py +505 -0
  53. steppy/coordinator.py +1352 -0
  54. steppy/coverage/__init__.py +9 -0
  55. steppy/coverage/gaps.py +190 -0
  56. steppy/coverage/manifest.py +193 -0
  57. steppy/coverage/merge.py +363 -0
  58. steppy/coverage/normalize.py +174 -0
  59. steppy/coverage/report.py +178 -0
  60. steppy/coverage/sourcemap.py +219 -0
  61. steppy/coverage/store.py +473 -0
  62. steppy/coverage/triage.py +151 -0
  63. steppy/coverage_cli.py +265 -0
  64. steppy/durations.py +48 -0
  65. steppy/exclusive.py +178 -0
  66. steppy/flaky_cli.py +169 -0
  67. steppy/generator.py +633 -0
  68. steppy/guide.py +1467 -0
  69. steppy/history.py +352 -0
  70. steppy/init_cli.py +330 -0
  71. steppy/locales.py +282 -0
  72. steppy/migrate/__init__.py +35 -0
  73. steppy/migrate/apply.py +194 -0
  74. steppy/migrate/plan.py +199 -0
  75. steppy/migrate/rules.py +465 -0
  76. steppy/migrate/verify.py +163 -0
  77. steppy/migrate_cli.py +152 -0
  78. steppy/models.py +2539 -0
  79. steppy/naming.py +37 -0
  80. steppy/parser.py +475 -0
  81. steppy/pdf.py +193 -0
  82. steppy/presets.py +284 -0
  83. steppy/record_cli.py +796 -0
  84. steppy/report/__init__.py +37 -0
  85. steppy/report/assets.py +197 -0
  86. steppy/report/build.py +261 -0
  87. steppy/report/coverage_source.py +277 -0
  88. steppy/report/model.py +423 -0
  89. steppy/report/render.py +303 -0
  90. steppy/report/source.py +238 -0
  91. steppy/report_cli.py +173 -0
  92. steppy/runmeta.py +114 -0
  93. steppy/selection.py +183 -0
  94. steppy/sitemap.py +205 -0
  95. steppy/skills/steppy-app-tours/SKILL.md +448 -0
  96. steppy/skills/steppy-ci-report/SKILL.md +567 -0
  97. steppy/skills/steppy-scenario-author/SKILL.md +2176 -0
  98. steppy/skills/steppy-template/SKILL.md +676 -0
  99. steppy/templates/_steppy_events.py +291 -0
  100. steppy/templates/_steppy_tours.py +404 -0
  101. steppy/templates/angular/component-interactive.ts.j2 +109 -0
  102. steppy/templates/angular/component-video.ts.j2 +112 -0
  103. steppy/templates/angular/component.ts.j2 +229 -0
  104. steppy/templates/angular/content.ts.j2 +31 -0
  105. steppy/templates/angular/gitignore.j2 +3 -0
  106. steppy/templates/angular/group.component.ts.j2 +39 -0
  107. steppy/templates/angular/onboarding.component.ts.j2 +43 -0
  108. steppy/templates/angular/routes.ts.j2 +34 -0
  109. steppy/templates/ci/github-actions.yml +284 -0
  110. steppy/templates/ci/gitlab-ci.yml +178 -0
  111. steppy/templates/conftest.py.j2 +2405 -0
  112. steppy/templates/guide.book.html.j2 +145 -0
  113. steppy/templates/guide.fragment.html.j2 +257 -0
  114. steppy/templates/guide.html.j2 +301 -0
  115. steppy/templates/guide.md.j2 +18 -0
  116. steppy/templates/init/config.yaml +124 -0
  117. steppy/templates/init/credentials.yaml.example +30 -0
  118. steppy/templates/init/scenarios/example--first-flow.md +53 -0
  119. steppy/templates/report/_head.html.j2 +14 -0
  120. steppy/templates/report/_mark.html.j2 +3 -0
  121. steppy/templates/report/coverage.html.j2 +124 -0
  122. steppy/templates/report/index.html.j2 +203 -0
  123. steppy/templates/report/report.css +401 -0
  124. steppy/templates/report/scenario.html.j2 +137 -0
  125. steppy/templates/static/_headers.j2 +30 -0
  126. steppy/templates/static/_mode_links.html.j2 +22 -0
  127. steppy/templates/static/_seo_head.html.j2 +37 -0
  128. steppy/templates/static/cursor.js.j2 +10 -0
  129. steppy/templates/static/group.html.j2 +78 -0
  130. steppy/templates/static/guides.css +678 -0
  131. steppy/templates/static/index.html.j2 +79 -0
  132. steppy/templates/static/interactive.html.j2 +100 -0
  133. steppy/templates/static/onboarding.html.j2 +64 -0
  134. steppy/templates/static/page.html.j2 +145 -0
  135. steppy/templates/static/robots.txt.j2 +7 -0
  136. steppy/templates/static/video.html.j2 +135 -0
  137. steppy/templates/test_scenario.py.j2 +767 -0
  138. steppy/testids.py +166 -0
  139. steppy/totp.py +26 -0
  140. steppy/tour_spec.py +163 -0
  141. steppy/tours/__init__.py +22 -0
  142. steppy/tours/actions.py +402 -0
  143. steppy/tours/compiler.py +144 -0
  144. steppy/tours/diagnostics.py +137 -0
  145. steppy/tours/emit.py +239 -0
  146. steppy/tours/ids.py +40 -0
  147. steppy/tours/inference.py +399 -0
  148. steppy/tours/model.py +120 -0
  149. steppy/tours/paths.py +126 -0
  150. steppy/tours/pipeline.py +277 -0
  151. steppy/tours/publish.py +124 -0
  152. steppy/tours/replay.py +234 -0
  153. steppy/tours/routes.py +175 -0
  154. steppy/tours/settings.py +164 -0
  155. steppy/tours/text.py +237 -0
  156. steppy/tours_cli.py +219 -0
  157. steppy/tts/__init__.py +280 -0
  158. steppy/tts/cache.py +185 -0
  159. steppy/tts/presets.py +125 -0
  160. steppy/tts/providers/__init__.py +6 -0
  161. steppy/tts/providers/http.py +184 -0
  162. steppy/tts/providers/local.py +207 -0
  163. steppy/tts/providers/null.py +28 -0
  164. steppy/tts/registry.py +201 -0
  165. steppy/tts/track.py +158 -0
  166. steppy/tts/types.py +94 -0
  167. steppy/update_cli.py +460 -0
  168. steppy/video.py +730 -0
  169. steppy/video_cache.py +239 -0
  170. steppy/video_cli.py +271 -0
  171. steppy/worker.py +301 -0
  172. steppy_dev-0.3.0.dist-info/METADATA +1335 -0
  173. steppy_dev-0.3.0.dist-info/RECORD +177 -0
  174. steppy_dev-0.3.0.dist-info/WHEEL +4 -0
  175. steppy_dev-0.3.0.dist-info/entry_points.txt +2 -0
  176. steppy_dev-0.3.0.dist-info/licenses/LICENSE +202 -0
  177. steppy_dev-0.3.0.dist-info/licenses/NOTICE +13 -0
@@ -0,0 +1,678 @@
1
+ /* Steppy static guide stylesheet — shared across all generated pages.
2
+ Generated by `steppy build` (target=static). The guide content rules
3
+ mirror the inline <style> in templates/guide.fragment.html.j2; the
4
+ site chrome rules (.steppy-site-header, .steppy-main, .steppy-locale-switch,
5
+ .steppy-index-list, .steppy-site-footer) are unique to the static target. */
6
+
7
+ /* ── Site chrome ─────────────────────────────────────────────────────── */
8
+
9
+ body {
10
+ margin: 0;
11
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
12
+ color: #333;
13
+ background: #fafbfc;
14
+ }
15
+
16
+ .steppy-site-header {
17
+ display: flex;
18
+ align-items: center;
19
+ gap: 24px;
20
+ flex-wrap: wrap;
21
+ padding: 16px 32px;
22
+ background: #ffffff;
23
+ border-bottom: 1px solid #e1e4e8;
24
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
25
+ }
26
+
27
+ .steppy-site-title {
28
+ font-size: 18px;
29
+ font-weight: 700;
30
+ color: #2c3e50;
31
+ text-decoration: none;
32
+ }
33
+
34
+ a.steppy-site-title:hover {
35
+ color: #3498db;
36
+ }
37
+
38
+ .steppy-breadcrumb {
39
+ font-size: 14px;
40
+ color: #7f8c8d;
41
+ }
42
+
43
+ .steppy-breadcrumb a {
44
+ color: #3498db;
45
+ text-decoration: none;
46
+ }
47
+
48
+ .steppy-breadcrumb a:hover {
49
+ text-decoration: underline;
50
+ }
51
+
52
+ .steppy-breadcrumb-sep {
53
+ margin: 0 6px;
54
+ color: #bdc3c7;
55
+ }
56
+
57
+ .steppy-locale-switch {
58
+ margin-left: auto;
59
+ }
60
+
61
+ .steppy-locale-switch ul {
62
+ list-style: none;
63
+ margin: 0;
64
+ padding: 0;
65
+ display: flex;
66
+ gap: 8px;
67
+ }
68
+
69
+ .steppy-locale-switch a,
70
+ .steppy-locale-switch span {
71
+ display: inline-block;
72
+ padding: 4px 12px;
73
+ border-radius: 16px;
74
+ font-size: 13px;
75
+ font-weight: 600;
76
+ text-decoration: none;
77
+ }
78
+
79
+ .steppy-locale-switch a {
80
+ color: #3498db;
81
+ border: 1px solid #d6eaf8;
82
+ }
83
+
84
+ .steppy-locale-switch a:hover {
85
+ background: #ebf5fb;
86
+ }
87
+
88
+ .steppy-locale-switch span[aria-current="true"] {
89
+ background: #3498db;
90
+ color: #ffffff;
91
+ }
92
+
93
+ /* Guide-format row (Step by Step / Interactive / Video). Emitted by
94
+ static/_mode_links.html.j2 on every rendering of a guide that has more than
95
+ one. Muted next to the locale switcher on purpose: this row moves you between
96
+ presentations of the page you are already on, not between languages. */
97
+ .steppy-mode-links ul {
98
+ list-style: none;
99
+ margin: 0;
100
+ padding: 0;
101
+ display: flex;
102
+ gap: 8px;
103
+ }
104
+
105
+ .steppy-mode-links a,
106
+ .steppy-mode-links span {
107
+ display: inline-block;
108
+ padding: 4px 12px;
109
+ border-radius: 16px;
110
+ font-size: 13px;
111
+ font-weight: 600;
112
+ text-decoration: none;
113
+ }
114
+
115
+ .steppy-mode-links a {
116
+ color: #5d6d7e;
117
+ border: 1px solid #e5e8eb;
118
+ }
119
+
120
+ .steppy-mode-links a:hover {
121
+ background: #f4f6f7;
122
+ }
123
+
124
+ .steppy-mode-links span[aria-current="true"] {
125
+ background: #eaeded;
126
+ color: #2c3e50;
127
+ }
128
+
129
+ /* Layout switcher (desktop / mobile) — same shape as locale switcher. */
130
+ /* "Download PDF" link — only emitted when the site was built with
131
+ `steppy build --pdf`, and hidden in print (see the @media print block). */
132
+ .steppy-pdf-link {
133
+ display: inline-flex;
134
+ align-items: center;
135
+ gap: 6px;
136
+ padding: 4px 10px;
137
+ border: 1px solid #d6dbdf;
138
+ border-radius: 4px;
139
+ color: #2c3e50;
140
+ text-decoration: none;
141
+ font-size: 13px;
142
+ }
143
+
144
+ .steppy-pdf-link:hover {
145
+ background: #ebf5fb;
146
+ }
147
+
148
+ .steppy-layout-switch {
149
+ display: flex;
150
+ gap: 8px;
151
+ }
152
+
153
+ .steppy-layout-switch ul {
154
+ list-style: none;
155
+ margin: 0;
156
+ padding: 0;
157
+ display: flex;
158
+ gap: 4px;
159
+ }
160
+
161
+ .steppy-layout-switch button {
162
+ border: 1px solid #d6dbdf;
163
+ background: #ffffff;
164
+ color: #2c3e50;
165
+ text-decoration: none;
166
+ padding: 4px 8px;
167
+ border-radius: 4px;
168
+ font-size: 13px;
169
+ font-family: inherit;
170
+ cursor: pointer;
171
+ }
172
+
173
+ .steppy-layout-switch button:hover {
174
+ background: #ebf5fb;
175
+ }
176
+
177
+ .steppy-layout-switch button[aria-current="true"] {
178
+ background: #3498db;
179
+ color: #ffffff;
180
+ border-color: #3498db;
181
+ }
182
+
183
+ /* In-page layout toggle: the JS adds .steppy-layout-active to the matching
184
+ wrapper. Layout names are arbitrary (declared in build config) so we can't
185
+ hardcode attribute selectors here — class toggle keeps it open-ended. */
186
+ .steppy-layout {
187
+ display: none;
188
+ }
189
+
190
+ .steppy-layout.steppy-layout-active {
191
+ display: block;
192
+ }
193
+
194
+ .steppy-main {
195
+ padding: 32px 16px;
196
+ }
197
+
198
+ .steppy-site-footer {
199
+ padding: 24px 32px;
200
+ text-align: center;
201
+ color: #95a5a6;
202
+ font-size: 13px;
203
+ border-top: 1px solid #e1e4e8;
204
+ background: #ffffff;
205
+ margin-top: 48px;
206
+ }
207
+
208
+ .steppy-site-footer a {
209
+ color: #3498db;
210
+ }
211
+
212
+ /* ── Index page ──────────────────────────────────────────────────────── */
213
+
214
+ .steppy-index {
215
+ max-width: 720px;
216
+ margin: 0 auto;
217
+ }
218
+
219
+ .steppy-index h1 {
220
+ font-size: 28px;
221
+ color: #2c3e50;
222
+ border-bottom: 3px solid #3498db;
223
+ padding-bottom: 12px;
224
+ margin-bottom: 24px;
225
+ }
226
+
227
+ .steppy-index-list {
228
+ list-style: none;
229
+ margin: 0;
230
+ padding: 0;
231
+ }
232
+
233
+ .steppy-index-list li {
234
+ margin-bottom: 12px;
235
+ }
236
+
237
+ .steppy-index-list a {
238
+ display: block;
239
+ padding: 16px 20px;
240
+ background: #ffffff;
241
+ border: 1px solid #e1e4e8;
242
+ border-radius: 6px;
243
+ text-decoration: none;
244
+ color: #2c3e50;
245
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
246
+ }
247
+
248
+ .steppy-index-list a:hover {
249
+ border-color: #3498db;
250
+ box-shadow: 0 2px 8px rgba(52, 152, 219, 0.12);
251
+ }
252
+
253
+ .steppy-index-title {
254
+ font-size: 18px;
255
+ font-weight: 600;
256
+ display: block;
257
+ }
258
+
259
+ .steppy-index-eyebrow {
260
+ display: block;
261
+ font-size: 11px;
262
+ font-weight: 700;
263
+ letter-spacing: 0.08em;
264
+ text-transform: uppercase;
265
+ color: #3498db;
266
+ margin-bottom: 4px;
267
+ }
268
+
269
+ .steppy-index-meta {
270
+ display: block;
271
+ font-size: 13px;
272
+ color: #7f8c8d;
273
+ margin-top: 4px;
274
+ }
275
+
276
+ .steppy-index-desc {
277
+ display: block;
278
+ font-size: 14px;
279
+ color: #555;
280
+ margin-top: 6px;
281
+ }
282
+
283
+ .steppy-index-empty {
284
+ color: #7f8c8d;
285
+ font-style: italic;
286
+ }
287
+
288
+ .steppy-index-onboarding a {
289
+ border-left: 4px solid #3498db;
290
+ }
291
+
292
+ .steppy-index-group a {
293
+ border-left: 4px solid #95a5a6;
294
+ }
295
+
296
+ .steppy-group-description {
297
+ color: #555;
298
+ margin: -12px 0 24px 0;
299
+ font-size: 15px;
300
+ }
301
+
302
+ /* ── Onboarding landing page ─────────────────────────────────────────── */
303
+
304
+ .steppy-onboarding {
305
+ max-width: 720px;
306
+ margin: 0 auto;
307
+ }
308
+
309
+ .steppy-onboarding h1 {
310
+ font-size: 28px;
311
+ color: #2c3e50;
312
+ border-bottom: 3px solid #3498db;
313
+ padding-bottom: 12px;
314
+ margin-bottom: 16px;
315
+ }
316
+
317
+ .steppy-onboarding-description {
318
+ font-size: 16px;
319
+ color: #555;
320
+ margin-bottom: 24px;
321
+ }
322
+
323
+ .steppy-onboarding-steps {
324
+ list-style: none;
325
+ counter-reset: steppy-onb;
326
+ margin: 0 0 32px 0;
327
+ padding: 0;
328
+ }
329
+
330
+ .steppy-onboarding-steps li {
331
+ margin-bottom: 12px;
332
+ }
333
+
334
+ .steppy-onboarding-steps a {
335
+ display: flex;
336
+ align-items: center;
337
+ gap: 14px;
338
+ padding: 14px 18px;
339
+ background: #ffffff;
340
+ border: 1px solid #e1e4e8;
341
+ border-radius: 6px;
342
+ text-decoration: none;
343
+ color: #2c3e50;
344
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
345
+ }
346
+
347
+ .steppy-onboarding-steps a:hover {
348
+ border-color: #3498db;
349
+ box-shadow: 0 2px 8px rgba(52, 152, 219, 0.12);
350
+ }
351
+
352
+ .steppy-onboarding-step-number {
353
+ display: inline-flex;
354
+ align-items: center;
355
+ justify-content: center;
356
+ width: 32px;
357
+ height: 32px;
358
+ background-color: #3498db;
359
+ color: #ffffff;
360
+ border-radius: 50%;
361
+ font-weight: 700;
362
+ font-size: 15px;
363
+ flex-shrink: 0;
364
+ }
365
+
366
+ .steppy-onboarding-step-title {
367
+ font-size: 16px;
368
+ font-weight: 600;
369
+ }
370
+
371
+ .steppy-onboarding-cta {
372
+ text-align: center;
373
+ }
374
+
375
+ .steppy-onboarding-start {
376
+ display: inline-block;
377
+ padding: 12px 28px;
378
+ background: #3498db;
379
+ color: #ffffff;
380
+ font-weight: 600;
381
+ text-decoration: none;
382
+ border-radius: 6px;
383
+ transition: background 0.15s ease;
384
+ }
385
+
386
+ .steppy-onboarding-start:hover {
387
+ background: #2980b9;
388
+ }
389
+
390
+ /* ── Onboarding strip (per-guide page) ───────────────────────────────── */
391
+
392
+ .steppy-onboarding-strip {
393
+ display: flex;
394
+ flex-wrap: wrap;
395
+ align-items: center;
396
+ justify-content: space-between;
397
+ gap: 12px;
398
+ padding: 10px 32px;
399
+ background: #ebf5fb;
400
+ border-bottom: 1px solid #d6eaf8;
401
+ font-size: 14px;
402
+ }
403
+
404
+ .steppy-onboarding-strip a {
405
+ color: #2980b9;
406
+ text-decoration: none;
407
+ font-weight: 600;
408
+ }
409
+
410
+ .steppy-onboarding-strip a:hover {
411
+ text-decoration: underline;
412
+ }
413
+
414
+ .steppy-onboarding-strip-progress {
415
+ color: #2c3e50;
416
+ }
417
+
418
+ .steppy-onboarding-strip-nav {
419
+ display: inline-flex;
420
+ gap: 16px;
421
+ }
422
+
423
+ .steppy-onboarding-disabled {
424
+ color: #95a5a6;
425
+ cursor: default;
426
+ font-weight: 500;
427
+ }
428
+
429
+ /* ── Guide content (mirrors guide.fragment.html.j2 inline styles) ───── */
430
+
431
+ .steppy-guide {
432
+ --steppy-cursor-size: 24px;
433
+ --steppy-cursor-color: #0f172a;
434
+ --steppy-cursor-accent: #2563eb;
435
+ --steppy-cursor-ring: rgba(37, 99, 235, 0.55);
436
+ --steppy-cursor-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
437
+ --steppy-z-screenshot: 1;
438
+ --steppy-z-cursor: 10;
439
+ --steppy-z-ripple: 11;
440
+ --steppy-z-glyph: 12;
441
+ /* Print/PDF: cap how tall a screenshot may render. Chromium cannot split
442
+ an image across a page break — an uncapped full-page or mobile capture
443
+ is clipped instead. Scaled down, it fits. */
444
+ --steppy-print-max-image-height: 180mm;
445
+ line-height: 1.6;
446
+ color: #333;
447
+ max-width: 900px;
448
+ margin: 0 auto;
449
+ }
450
+
451
+ .steppy-guide h1 {
452
+ font-size: 32px;
453
+ color: #2c3e50;
454
+ margin-bottom: 10px;
455
+ border-bottom: 3px solid #3498db;
456
+ padding-bottom: 10px;
457
+ }
458
+
459
+ .steppy-guide .steppy-role-badge {
460
+ display: inline-block;
461
+ background-color: #3498db;
462
+ color: white;
463
+ padding: 6px 16px;
464
+ border-radius: 20px;
465
+ font-size: 14px;
466
+ font-weight: 600;
467
+ margin-bottom: 30px;
468
+ }
469
+
470
+ .steppy-guide .steppy-step {
471
+ margin-bottom: 50px;
472
+ }
473
+
474
+ .steppy-guide .steppy-step h2 {
475
+ font-size: 24px;
476
+ color: #2c3e50;
477
+ margin-bottom: 15px;
478
+ display: flex;
479
+ align-items: center;
480
+ }
481
+
482
+ .steppy-guide .steppy-step-number {
483
+ display: inline-flex;
484
+ align-items: center;
485
+ justify-content: center;
486
+ width: 36px;
487
+ height: 36px;
488
+ background-color: #3498db;
489
+ color: white;
490
+ border-radius: 50%;
491
+ font-weight: bold;
492
+ font-size: 18px;
493
+ margin-right: 12px;
494
+ flex-shrink: 0;
495
+ }
496
+
497
+ .steppy-guide .steppy-step-subtitle {
498
+ font-size: 18px;
499
+ color: #7f8c8d;
500
+ font-weight: 500;
501
+ margin-top: -10px;
502
+ margin-bottom: 15px;
503
+ font-style: italic;
504
+ }
505
+
506
+ .steppy-guide .steppy-step-content {
507
+ font-size: 16px;
508
+ color: #555;
509
+ margin-bottom: 20px;
510
+ line-height: 1.8;
511
+ }
512
+
513
+ .steppy-guide .steppy-stage {
514
+ position: relative;
515
+ line-height: 0;
516
+ }
517
+
518
+ .steppy-guide .steppy-stage img {
519
+ /* width:auto caps display at the screenshot's intrinsic pixel width so a
520
+ dense capture (e.g. mobile at device_scale_factor=3) fills the column,
521
+ while a low-res capture renders at native size instead of upscaled/blurry.
522
+ max-width:100% keeps it responsive. */
523
+ width: auto;
524
+ max-width: 100%;
525
+ height: auto;
526
+ border: 1px solid #ddd;
527
+ border-radius: 4px;
528
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
529
+ display: block;
530
+ position: relative;
531
+ z-index: var(--steppy-z-screenshot);
532
+ }
533
+
534
+ .steppy-guide .steppy-cursor {
535
+ position: absolute;
536
+ top: 0;
537
+ left: 0;
538
+ width: var(--steppy-cursor-size);
539
+ height: var(--steppy-cursor-size);
540
+ pointer-events: none;
541
+ z-index: var(--steppy-z-cursor);
542
+ opacity: 0;
543
+ transition: opacity 200ms ease-in-out;
544
+ background: var(--steppy-cursor-color);
545
+ clip-path: polygon(0 0, 0 75%, 25% 55%, 45% 95%, 60% 85%, 40% 50%, 75% 40%);
546
+ filter: drop-shadow(var(--steppy-cursor-shadow));
547
+ transform-origin: 0 0;
548
+ }
549
+
550
+ .steppy-guide .steppy-cursor.visible {
551
+ opacity: 1;
552
+ }
553
+
554
+ .steppy-guide .steppy-cursor.pulse {
555
+ animation: steppy-pulse-anim 200ms ease-in-out;
556
+ }
557
+
558
+ @keyframes steppy-pulse-anim {
559
+ 0%, 100% { transform: scale(1); }
560
+ 50% { transform: scale(1.25); }
561
+ }
562
+
563
+ .steppy-guide .steppy-ripple {
564
+ position: absolute;
565
+ top: 0;
566
+ left: 0;
567
+ width: 12px;
568
+ height: 12px;
569
+ margin-left: -6px;
570
+ margin-top: -6px;
571
+ border-radius: 50%;
572
+ border: 2px solid var(--steppy-cursor-ring);
573
+ background: transparent;
574
+ z-index: var(--steppy-z-ripple);
575
+ pointer-events: none;
576
+ opacity: 0;
577
+ }
578
+
579
+ .steppy-guide .steppy-ripple.fire {
580
+ animation: steppy-ripple-anim 500ms ease-out forwards;
581
+ }
582
+
583
+ @keyframes steppy-ripple-anim {
584
+ 0% { width: 12px; height: 12px; margin-left: -6px; margin-top: -6px; opacity: 0.9; }
585
+ 100% { width: 72px; height: 72px; margin-left: -36px; margin-top: -36px; opacity: 0; }
586
+ }
587
+
588
+ .steppy-guide .steppy-kbd {
589
+ position: absolute;
590
+ top: 0;
591
+ left: 0;
592
+ background: #111827;
593
+ color: #fff;
594
+ font: 12px/1 ui-monospace, Menlo, Consolas, monospace;
595
+ padding: 5px 7px;
596
+ border-radius: 4px;
597
+ z-index: var(--steppy-z-glyph);
598
+ opacity: 0;
599
+ pointer-events: none;
600
+ white-space: nowrap;
601
+ transition: opacity 150ms ease-in-out;
602
+ }
603
+
604
+ .steppy-guide .steppy-kbd.visible {
605
+ opacity: 1;
606
+ }
607
+
608
+ @media print {
609
+ /* Site chrome is navigation — it means nothing on paper, and dropping it
610
+ is what lets `steppy build --pdf` print the published page as-is.
611
+ (Inactive layouts are already display:none, so a multi-layout page
612
+ prints exactly the layout the reader is looking at.) */
613
+ .steppy-site-header,
614
+ .steppy-breadcrumb,
615
+ .steppy-locale-switch,
616
+ .steppy-layout-switch,
617
+ .steppy-mode-links,
618
+ .steppy-onboarding-strip,
619
+ .steppy-pdf-link,
620
+ .steppy-site-footer {
621
+ display: none !important;
622
+ }
623
+
624
+ body {
625
+ background: #fff;
626
+ /* Keep the step badges / role chip coloured even when the viewer
627
+ disables background graphics. */
628
+ -webkit-print-color-adjust: exact;
629
+ print-color-adjust: exact;
630
+ }
631
+
632
+ .steppy-main {
633
+ padding: 0;
634
+ margin: 0;
635
+ }
636
+
637
+ .steppy-guide .steppy-step {
638
+ page-break-inside: avoid;
639
+ }
640
+
641
+ .steppy-guide .steppy-stage img {
642
+ max-height: var(--steppy-print-max-image-height);
643
+ box-shadow: none;
644
+ page-break-inside: avoid;
645
+ }
646
+
647
+ .steppy-guide .steppy-cursor,
648
+ .steppy-guide .steppy-ripple,
649
+ .steppy-guide .steppy-kbd {
650
+ display: none;
651
+ }
652
+ }
653
+
654
+ @media (max-width: 768px) {
655
+ .steppy-site-header {
656
+ padding: 12px 16px;
657
+ gap: 12px;
658
+ }
659
+
660
+ .steppy-locale-switch {
661
+ margin-left: 0;
662
+ width: 100%;
663
+ }
664
+
665
+ .steppy-guide h1 {
666
+ font-size: 24px;
667
+ }
668
+
669
+ .steppy-guide .steppy-step h2 {
670
+ font-size: 20px;
671
+ }
672
+
673
+ .steppy-guide .steppy-step-number {
674
+ width: 30px;
675
+ height: 30px;
676
+ font-size: 16px;
677
+ }
678
+ }