@rohal12/spindle 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 (65) hide show
  1. package/README.md +66 -0
  2. package/dist/pkg/format.js +1 -0
  3. package/dist/pkg/index.js +12 -0
  4. package/dist/pkg/types/globals.d.ts +18 -0
  5. package/dist/pkg/types/index.d.ts +158 -0
  6. package/package.json +71 -0
  7. package/src/components/App.tsx +53 -0
  8. package/src/components/Passage.tsx +36 -0
  9. package/src/components/PassageLink.tsx +35 -0
  10. package/src/components/SaveLoadDialog.tsx +403 -0
  11. package/src/components/SettingsDialog.tsx +106 -0
  12. package/src/components/StoryInterface.tsx +31 -0
  13. package/src/components/macros/Back.tsx +23 -0
  14. package/src/components/macros/Button.tsx +49 -0
  15. package/src/components/macros/Checkbox.tsx +41 -0
  16. package/src/components/macros/Computed.tsx +100 -0
  17. package/src/components/macros/Cycle.tsx +39 -0
  18. package/src/components/macros/Do.tsx +46 -0
  19. package/src/components/macros/For.tsx +113 -0
  20. package/src/components/macros/Forward.tsx +25 -0
  21. package/src/components/macros/Goto.tsx +23 -0
  22. package/src/components/macros/If.tsx +63 -0
  23. package/src/components/macros/Include.tsx +52 -0
  24. package/src/components/macros/Listbox.tsx +42 -0
  25. package/src/components/macros/MacroLink.tsx +107 -0
  26. package/src/components/macros/Numberbox.tsx +43 -0
  27. package/src/components/macros/Print.tsx +48 -0
  28. package/src/components/macros/QuickLoad.tsx +33 -0
  29. package/src/components/macros/QuickSave.tsx +22 -0
  30. package/src/components/macros/Radiobutton.tsx +59 -0
  31. package/src/components/macros/Repeat.tsx +53 -0
  32. package/src/components/macros/Restart.tsx +27 -0
  33. package/src/components/macros/Saves.tsx +25 -0
  34. package/src/components/macros/Set.tsx +36 -0
  35. package/src/components/macros/SettingsButton.tsx +29 -0
  36. package/src/components/macros/Stop.tsx +12 -0
  37. package/src/components/macros/StoryTitle.tsx +20 -0
  38. package/src/components/macros/Switch.tsx +69 -0
  39. package/src/components/macros/Textarea.tsx +41 -0
  40. package/src/components/macros/Textbox.tsx +40 -0
  41. package/src/components/macros/Timed.tsx +63 -0
  42. package/src/components/macros/Type.tsx +83 -0
  43. package/src/components/macros/Unset.tsx +25 -0
  44. package/src/components/macros/VarDisplay.tsx +44 -0
  45. package/src/components/macros/Widget.tsx +18 -0
  46. package/src/components/macros/option-utils.ts +14 -0
  47. package/src/expression.ts +93 -0
  48. package/src/index.tsx +120 -0
  49. package/src/markup/ast.ts +284 -0
  50. package/src/markup/markdown.ts +21 -0
  51. package/src/markup/render.tsx +537 -0
  52. package/src/markup/tokenizer.ts +581 -0
  53. package/src/parser.ts +72 -0
  54. package/src/registry.ts +21 -0
  55. package/src/saves/idb.ts +165 -0
  56. package/src/saves/save-manager.ts +317 -0
  57. package/src/saves/types.ts +40 -0
  58. package/src/settings.ts +96 -0
  59. package/src/store.ts +317 -0
  60. package/src/story-api.ts +129 -0
  61. package/src/story-init.ts +67 -0
  62. package/src/story-variables.ts +166 -0
  63. package/src/styles.css +780 -0
  64. package/src/utils/parse-delay.ts +14 -0
  65. package/src/widgets/widget-registry.ts +15 -0
package/src/styles.css ADDED
@@ -0,0 +1,780 @@
1
+ *,
2
+ *::before,
3
+ *::after {
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ html {
8
+ font-size: 16px;
9
+ -webkit-text-size-adjust: 100%;
10
+ }
11
+
12
+ body {
13
+ margin: 0;
14
+ padding: 0;
15
+ font-family: Georgia, 'Times New Roman', serif;
16
+ line-height: 1.75;
17
+ color: #e0e0e0;
18
+ background-color: #1a1a2e;
19
+ min-height: 100vh;
20
+ }
21
+
22
+ tw-storydata {
23
+ display: none !important;
24
+ }
25
+
26
+ #story {
27
+ max-width: 42em;
28
+ margin: 0 auto;
29
+ padding: 2em 1.5em;
30
+ }
31
+
32
+ .passage {
33
+ animation: passage-fade-in 0.3s ease-in;
34
+ }
35
+
36
+ @keyframes passage-fade-in {
37
+ from {
38
+ opacity: 0;
39
+ transform: translateY(8px);
40
+ }
41
+ to {
42
+ opacity: 1;
43
+ transform: translateY(0);
44
+ }
45
+ }
46
+
47
+ .passage-link {
48
+ color: #64b5f6;
49
+ text-decoration: none;
50
+ border-bottom: 1px solid rgba(100, 181, 246, 0.3);
51
+ transition:
52
+ color 0.2s,
53
+ border-color 0.2s;
54
+ cursor: pointer;
55
+ }
56
+
57
+ .passage-link:hover {
58
+ color: #90caf9;
59
+ border-bottom-color: #90caf9;
60
+ }
61
+
62
+ .passage-link:active {
63
+ color: #42a5f5;
64
+ }
65
+
66
+ .macro-button {
67
+ background: rgba(100, 181, 246, 0.15);
68
+ color: #64b5f6;
69
+ border: 1px solid rgba(100, 181, 246, 0.4);
70
+ border-radius: 4px;
71
+ padding: 0.25em 0.75em;
72
+ font: inherit;
73
+ font-size: 0.95em;
74
+ cursor: pointer;
75
+ transition:
76
+ background 0.2s,
77
+ border-color 0.2s;
78
+ }
79
+
80
+ .macro-button:hover {
81
+ background: rgba(100, 181, 246, 0.25);
82
+ border-color: #90caf9;
83
+ }
84
+
85
+ .macro-button:active {
86
+ background: rgba(100, 181, 246, 0.35);
87
+ }
88
+
89
+ .error {
90
+ color: #ef5350;
91
+ font-family: monospace;
92
+ padding: 1em;
93
+ border: 1px solid #ef5350;
94
+ border-radius: 4px;
95
+ background: rgba(239, 83, 80, 0.1);
96
+ }
97
+
98
+ .loading {
99
+ text-align: center;
100
+ padding: 2em;
101
+ opacity: 0.6;
102
+ }
103
+
104
+ /* Menu bar */
105
+
106
+ .story-menubar {
107
+ position: sticky;
108
+ top: 0;
109
+ z-index: 100;
110
+ display: flex;
111
+ align-items: center;
112
+ gap: 0.5em;
113
+ padding: 0.5em 1.5em;
114
+ background: #16213e;
115
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
116
+ font-family: system-ui, sans-serif;
117
+ font-size: 0.9em;
118
+ }
119
+
120
+ .story-title {
121
+ flex: 1;
122
+ font-weight: 600;
123
+ color: #e0e0e0;
124
+ white-space: nowrap;
125
+ overflow: hidden;
126
+ text-overflow: ellipsis;
127
+ }
128
+
129
+ .menubar-button {
130
+ background: transparent;
131
+ color: #9e9e9e;
132
+ border: 1px solid transparent;
133
+ padding: 0.35em 0.7em;
134
+ border-radius: 4px;
135
+ cursor: pointer;
136
+ font: inherit;
137
+ transition:
138
+ color 0.2s,
139
+ background 0.2s;
140
+ }
141
+
142
+ .menubar-button:hover {
143
+ color: #e0e0e0;
144
+ background: rgba(255, 255, 255, 0.08);
145
+ }
146
+
147
+ .menubar-button:disabled {
148
+ opacity: 0.4;
149
+ cursor: default;
150
+ }
151
+
152
+ .menubar-button:disabled:hover {
153
+ color: #9e9e9e;
154
+ background: transparent;
155
+ }
156
+
157
+ /* Settings dialog */
158
+
159
+ .settings-overlay {
160
+ position: fixed;
161
+ inset: 0;
162
+ z-index: 200;
163
+ display: flex;
164
+ align-items: center;
165
+ justify-content: center;
166
+ background: rgba(0, 0, 0, 0.6);
167
+ }
168
+
169
+ .settings-panel {
170
+ background: #16213e;
171
+ border: 1px solid rgba(255, 255, 255, 0.1);
172
+ border-radius: 8px;
173
+ width: 90%;
174
+ max-width: 400px;
175
+ max-height: 80vh;
176
+ overflow-y: auto;
177
+ color: #e0e0e0;
178
+ font-family: system-ui, sans-serif;
179
+ }
180
+
181
+ .settings-header {
182
+ display: flex;
183
+ align-items: center;
184
+ justify-content: space-between;
185
+ padding: 1em 1.25em;
186
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
187
+ font-weight: 600;
188
+ }
189
+
190
+ .settings-close {
191
+ background: transparent;
192
+ border: none;
193
+ color: #9e9e9e;
194
+ font-size: 1.1em;
195
+ cursor: pointer;
196
+ padding: 0.25em;
197
+ line-height: 1;
198
+ }
199
+
200
+ .settings-close:hover {
201
+ color: #e0e0e0;
202
+ }
203
+
204
+ .settings-body {
205
+ padding: 1em 1.25em;
206
+ display: flex;
207
+ flex-direction: column;
208
+ gap: 1em;
209
+ }
210
+
211
+ .settings-row {
212
+ display: flex;
213
+ align-items: center;
214
+ justify-content: space-between;
215
+ gap: 1em;
216
+ }
217
+
218
+ .settings-row select,
219
+ .settings-row input[type='range'] {
220
+ accent-color: #64b5f6;
221
+ }
222
+
223
+ .settings-row select {
224
+ background: #1a1a2e;
225
+ color: #e0e0e0;
226
+ border: 1px solid rgba(255, 255, 255, 0.15);
227
+ border-radius: 4px;
228
+ padding: 0.3em 0.5em;
229
+ font: inherit;
230
+ }
231
+
232
+ .settings-row input[type='checkbox'] {
233
+ accent-color: #64b5f6;
234
+ width: 1.1em;
235
+ height: 1.1em;
236
+ }
237
+
238
+ /* Saves dialog */
239
+
240
+ .saves-overlay {
241
+ position: fixed;
242
+ inset: 0;
243
+ z-index: 200;
244
+ display: flex;
245
+ align-items: center;
246
+ justify-content: center;
247
+ background: rgba(0, 0, 0, 0.6);
248
+ }
249
+
250
+ .saves-panel {
251
+ background: #16213e;
252
+ border: 1px solid rgba(255, 255, 255, 0.1);
253
+ border-radius: 8px;
254
+ width: 90%;
255
+ max-width: 550px;
256
+ max-height: 80vh;
257
+ display: flex;
258
+ flex-direction: column;
259
+ color: #e0e0e0;
260
+ font-family: system-ui, sans-serif;
261
+ }
262
+
263
+ .saves-header {
264
+ display: flex;
265
+ align-items: center;
266
+ justify-content: space-between;
267
+ padding: 1em 1.25em;
268
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
269
+ font-weight: 600;
270
+ flex-shrink: 0;
271
+ }
272
+
273
+ .saves-header-left {
274
+ display: flex;
275
+ align-items: center;
276
+ gap: 0.75em;
277
+ }
278
+
279
+ .saves-mode-toggle {
280
+ display: flex;
281
+ gap: 0;
282
+ border: 1px solid rgba(255, 255, 255, 0.15);
283
+ border-radius: 4px;
284
+ overflow: hidden;
285
+ }
286
+
287
+ .saves-mode-toggle button {
288
+ background: transparent;
289
+ color: #9e9e9e;
290
+ border: none;
291
+ padding: 0.3em 0.8em;
292
+ font: inherit;
293
+ font-size: 0.85em;
294
+ font-weight: 600;
295
+ cursor: pointer;
296
+ transition:
297
+ background 0.2s,
298
+ color 0.2s;
299
+ }
300
+
301
+ .saves-mode-toggle button.active {
302
+ background: rgba(100, 181, 246, 0.2);
303
+ color: #64b5f6;
304
+ }
305
+
306
+ .saves-mode-toggle button:hover:not(.active) {
307
+ color: #e0e0e0;
308
+ }
309
+
310
+ .saves-close {
311
+ background: transparent;
312
+ border: none;
313
+ color: #9e9e9e;
314
+ font-size: 1.1em;
315
+ cursor: pointer;
316
+ padding: 0.25em;
317
+ line-height: 1;
318
+ }
319
+
320
+ .saves-close:hover {
321
+ color: #e0e0e0;
322
+ }
323
+
324
+ .saves-body {
325
+ padding: 0.75em 1.25em;
326
+ overflow-y: auto;
327
+ flex: 1;
328
+ min-height: 0;
329
+ }
330
+
331
+ .saves-empty {
332
+ text-align: center;
333
+ padding: 2em 1em;
334
+ opacity: 0.5;
335
+ font-size: 0.9em;
336
+ }
337
+
338
+ .saves-toolbar {
339
+ display: flex;
340
+ gap: 0.5em;
341
+ padding: 0.5em 1.25em;
342
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
343
+ flex-shrink: 0;
344
+ }
345
+
346
+ .saves-toolbar-button {
347
+ background: rgba(255, 255, 255, 0.05);
348
+ color: #9e9e9e;
349
+ border: 1px solid rgba(255, 255, 255, 0.1);
350
+ border-radius: 4px;
351
+ padding: 0.3em 0.7em;
352
+ font: inherit;
353
+ font-size: 0.8em;
354
+ cursor: pointer;
355
+ transition:
356
+ background 0.2s,
357
+ color 0.2s;
358
+ }
359
+
360
+ .saves-toolbar-button:hover {
361
+ background: rgba(255, 255, 255, 0.1);
362
+ color: #e0e0e0;
363
+ }
364
+
365
+ .playthrough-group {
366
+ margin-bottom: 0.75em;
367
+ }
368
+
369
+ .playthrough-header {
370
+ display: flex;
371
+ align-items: center;
372
+ gap: 0.5em;
373
+ padding: 0.4em 0;
374
+ cursor: pointer;
375
+ user-select: none;
376
+ font-size: 0.85em;
377
+ color: #9e9e9e;
378
+ transition: color 0.2s;
379
+ }
380
+
381
+ .playthrough-header:hover {
382
+ color: #e0e0e0;
383
+ }
384
+
385
+ .playthrough-chevron {
386
+ display: inline-block;
387
+ font-size: 0.7em;
388
+ transition: transform 0.2s;
389
+ }
390
+
391
+ .playthrough-chevron.open {
392
+ transform: rotate(90deg);
393
+ }
394
+
395
+ .playthrough-label {
396
+ font-weight: 600;
397
+ }
398
+
399
+ .playthrough-date {
400
+ opacity: 0.6;
401
+ font-size: 0.9em;
402
+ }
403
+
404
+ .playthrough-saves {
405
+ display: flex;
406
+ flex-direction: column;
407
+ gap: 0.4em;
408
+ padding-left: 0.25em;
409
+ }
410
+
411
+ .save-slot {
412
+ display: flex;
413
+ align-items: center;
414
+ gap: 0.75em;
415
+ padding: 0.5em 0.6em;
416
+ background: rgba(255, 255, 255, 0.03);
417
+ border: 1px solid rgba(255, 255, 255, 0.06);
418
+ border-radius: 6px;
419
+ transition: background 0.15s;
420
+ }
421
+
422
+ .save-slot:hover {
423
+ background: rgba(255, 255, 255, 0.06);
424
+ }
425
+
426
+ .save-slot-info {
427
+ flex: 1;
428
+ min-width: 0;
429
+ }
430
+
431
+ .save-slot-title {
432
+ font-weight: 500;
433
+ font-size: 0.9em;
434
+ white-space: nowrap;
435
+ overflow: hidden;
436
+ text-overflow: ellipsis;
437
+ }
438
+
439
+ .save-slot-meta {
440
+ font-size: 0.75em;
441
+ color: #9e9e9e;
442
+ display: flex;
443
+ gap: 0.75em;
444
+ }
445
+
446
+ .save-slot-actions {
447
+ display: flex;
448
+ gap: 0.3em;
449
+ flex-shrink: 0;
450
+ }
451
+
452
+ .save-slot-action {
453
+ background: transparent;
454
+ color: #9e9e9e;
455
+ border: 1px solid transparent;
456
+ border-radius: 3px;
457
+ padding: 0.2em 0.5em;
458
+ font: inherit;
459
+ font-size: 0.75em;
460
+ cursor: pointer;
461
+ transition:
462
+ color 0.2s,
463
+ background 0.2s;
464
+ white-space: nowrap;
465
+ }
466
+
467
+ .save-slot-action:hover {
468
+ color: #e0e0e0;
469
+ background: rgba(255, 255, 255, 0.08);
470
+ }
471
+
472
+ .save-slot-action.primary {
473
+ color: #64b5f6;
474
+ border-color: rgba(100, 181, 246, 0.3);
475
+ }
476
+
477
+ .save-slot-action.primary:hover {
478
+ background: rgba(100, 181, 246, 0.15);
479
+ }
480
+
481
+ .save-slot-action.danger:hover {
482
+ color: #ef5350;
483
+ background: rgba(239, 83, 80, 0.1);
484
+ }
485
+
486
+ .save-slot-new {
487
+ display: flex;
488
+ align-items: center;
489
+ justify-content: center;
490
+ padding: 0.5em;
491
+ margin-top: 0.25em;
492
+ border: 1px dashed rgba(255, 255, 255, 0.12);
493
+ border-radius: 6px;
494
+ color: #9e9e9e;
495
+ font: inherit;
496
+ font-size: 0.8em;
497
+ background: transparent;
498
+ cursor: pointer;
499
+ width: 100%;
500
+ transition:
501
+ color 0.2s,
502
+ border-color 0.2s,
503
+ background 0.2s;
504
+ }
505
+
506
+ .save-slot-new:hover {
507
+ color: #64b5f6;
508
+ border-color: rgba(100, 181, 246, 0.3);
509
+ background: rgba(100, 181, 246, 0.05);
510
+ }
511
+
512
+ .saves-status {
513
+ padding: 0.5em 1.25em;
514
+ font-size: 0.8em;
515
+ color: #81c784;
516
+ border-top: 1px solid rgba(255, 255, 255, 0.08);
517
+ flex-shrink: 0;
518
+ text-align: center;
519
+ }
520
+
521
+ .saves-status.error {
522
+ color: #ef5350;
523
+ border: none;
524
+ border-radius: 0;
525
+ padding: 0.5em 1.25em;
526
+ font-family: inherit;
527
+ background: transparent;
528
+ }
529
+
530
+ .save-rename-input {
531
+ background: #1a1a2e;
532
+ color: #e0e0e0;
533
+ border: 1px solid rgba(100, 181, 246, 0.4);
534
+ border-radius: 3px;
535
+ padding: 0.15em 0.4em;
536
+ font: inherit;
537
+ font-size: 0.9em;
538
+ width: 100%;
539
+ }
540
+
541
+ .save-rename-input:focus {
542
+ outline: none;
543
+ border-color: #64b5f6;
544
+ }
545
+
546
+ /* Macro: link */
547
+
548
+ .macro-link {
549
+ color: #64b5f6;
550
+ text-decoration: none;
551
+ border-bottom: 1px solid rgba(100, 181, 246, 0.3);
552
+ transition:
553
+ color 0.2s,
554
+ border-color 0.2s;
555
+ cursor: pointer;
556
+ }
557
+
558
+ .macro-link:hover {
559
+ color: #90caf9;
560
+ border-bottom-color: #90caf9;
561
+ }
562
+
563
+ /* Macro: form inputs */
564
+
565
+ .macro-textbox,
566
+ .macro-numberbox,
567
+ .macro-textarea {
568
+ background: #1a1a2e;
569
+ color: #e0e0e0;
570
+ border: 1px solid rgba(255, 255, 255, 0.15);
571
+ border-radius: 4px;
572
+ padding: 0.3em 0.5em;
573
+ font: inherit;
574
+ }
575
+
576
+ .macro-textbox:focus,
577
+ .macro-numberbox:focus,
578
+ .macro-textarea:focus {
579
+ outline: none;
580
+ border-color: #64b5f6;
581
+ }
582
+
583
+ .macro-textarea {
584
+ min-height: 3em;
585
+ resize: vertical;
586
+ }
587
+
588
+ .macro-checkbox,
589
+ .macro-radiobutton {
590
+ cursor: pointer;
591
+ display: inline-flex;
592
+ align-items: center;
593
+ gap: 0.3em;
594
+ }
595
+
596
+ .macro-checkbox input,
597
+ .macro-radiobutton input {
598
+ accent-color: #64b5f6;
599
+ }
600
+
601
+ /* Macro: listbox */
602
+
603
+ .macro-listbox {
604
+ background: #1a1a2e;
605
+ color: #e0e0e0;
606
+ border: 1px solid rgba(255, 255, 255, 0.15);
607
+ border-radius: 4px;
608
+ padding: 0.3em 0.5em;
609
+ font: inherit;
610
+ }
611
+
612
+ /* Macro: cycle */
613
+
614
+ .macro-cycle {
615
+ background: rgba(100, 181, 246, 0.15);
616
+ color: #64b5f6;
617
+ border: 1px solid rgba(100, 181, 246, 0.4);
618
+ border-radius: 4px;
619
+ padding: 0.25em 0.75em;
620
+ font: inherit;
621
+ cursor: pointer;
622
+ transition:
623
+ background 0.2s,
624
+ border-color 0.2s;
625
+ }
626
+
627
+ .macro-cycle:hover {
628
+ background: rgba(100, 181, 246, 0.25);
629
+ border-color: #90caf9;
630
+ }
631
+
632
+ /* Markdown wrapper — invisible to layout */
633
+
634
+ .md {
635
+ display: contents;
636
+ }
637
+
638
+ /* Markdown block elements inside passages */
639
+
640
+ .passage p {
641
+ margin: 0.6em 0;
642
+ }
643
+
644
+ .passage p:first-child {
645
+ margin-top: 0;
646
+ }
647
+
648
+ .passage p:last-child {
649
+ margin-bottom: 0;
650
+ }
651
+
652
+ .passage h1,
653
+ .passage h2,
654
+ .passage h3,
655
+ .passage h4,
656
+ .passage h5,
657
+ .passage h6 {
658
+ margin: 1em 0 0.4em;
659
+ line-height: 1.3;
660
+ color: #f0f0f0;
661
+ }
662
+
663
+ .passage h1 {
664
+ font-size: 1.8em;
665
+ }
666
+ .passage h2 {
667
+ font-size: 1.5em;
668
+ }
669
+ .passage h3 {
670
+ font-size: 1.25em;
671
+ }
672
+ .passage h4 {
673
+ font-size: 1.1em;
674
+ }
675
+ .passage h5 {
676
+ font-size: 1em;
677
+ }
678
+ .passage h6 {
679
+ font-size: 0.9em;
680
+ opacity: 0.8;
681
+ }
682
+
683
+ .passage code {
684
+ font-family: 'Fira Code', 'Cascadia Code', 'Consolas', monospace;
685
+ font-size: 0.9em;
686
+ background: rgba(255, 255, 255, 0.08);
687
+ padding: 0.15em 0.35em;
688
+ border-radius: 3px;
689
+ }
690
+
691
+ .passage pre {
692
+ background: rgba(0, 0, 0, 0.3);
693
+ border: 1px solid rgba(255, 255, 255, 0.08);
694
+ border-radius: 6px;
695
+ padding: 1em;
696
+ overflow-x: auto;
697
+ margin: 0.8em 0;
698
+ }
699
+
700
+ .passage pre code {
701
+ background: none;
702
+ padding: 0;
703
+ border-radius: 0;
704
+ font-size: 0.85em;
705
+ }
706
+
707
+ .passage blockquote {
708
+ border-left: 3px solid rgba(100, 181, 246, 0.5);
709
+ margin: 0.8em 0;
710
+ padding: 0.4em 1em;
711
+ color: #b0b0b0;
712
+ }
713
+
714
+ .passage blockquote p {
715
+ margin: 0.3em 0;
716
+ }
717
+
718
+ .passage ul,
719
+ .passage ol {
720
+ margin: 0.6em 0;
721
+ padding-left: 1.8em;
722
+ }
723
+
724
+ .passage li {
725
+ margin: 0.2em 0;
726
+ }
727
+
728
+ .passage hr {
729
+ border: none;
730
+ border-top: 1px solid rgba(255, 255, 255, 0.12);
731
+ margin: 1.2em 0;
732
+ }
733
+
734
+ .passage table {
735
+ border-collapse: collapse;
736
+ width: 100%;
737
+ margin: 0.8em 0;
738
+ }
739
+
740
+ .passage th,
741
+ .passage td {
742
+ border: 1px solid rgba(255, 255, 255, 0.12);
743
+ padding: 0.5em 0.75em;
744
+ text-align: left;
745
+ }
746
+
747
+ .passage th {
748
+ background: rgba(255, 255, 255, 0.06);
749
+ font-weight: 600;
750
+ }
751
+
752
+ .passage tr:nth-child(even) {
753
+ background: rgba(255, 255, 255, 0.02);
754
+ }
755
+
756
+ .passage del {
757
+ opacity: 0.5;
758
+ }
759
+
760
+ .passage strong {
761
+ color: #f0f0f0;
762
+ }
763
+
764
+ /* Macro: type (typewriter) */
765
+
766
+ .macro-type-cursor::after {
767
+ content: '\2588';
768
+ animation: type-blink 0.7s step-end infinite;
769
+ color: #64b5f6;
770
+ }
771
+
772
+ .macro-type-done .macro-type-cursor::after {
773
+ display: none;
774
+ }
775
+
776
+ @keyframes type-blink {
777
+ 50% {
778
+ opacity: 0;
779
+ }
780
+ }