vizcore 0.1.0 → 1.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 (137) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +70 -117
  3. data/docs/.nojekyll +0 -0
  4. data/docs/assets/playground-worker.js +373 -0
  5. data/docs/assets/playground.css +440 -0
  6. data/docs/assets/playground.js +652 -0
  7. data/docs/assets/site.css +744 -0
  8. data/docs/assets/vizcore-demo.gif +0 -0
  9. data/docs/assets/vizcore-poster.png +0 -0
  10. data/docs/assets/vj-tunnel.js +159 -0
  11. data/docs/index.html +225 -0
  12. data/docs/playground.html +81 -0
  13. data/docs/shape_dsl.md +269 -0
  14. data/examples/README.md +59 -0
  15. data/examples/assets/README.md +19 -0
  16. data/examples/audio_inspector.rb +34 -0
  17. data/examples/club_intro_drop.rb +78 -0
  18. data/examples/kansai_rubykaigi_visual.rb +70 -0
  19. data/examples/live_coding_minimal.rb +22 -0
  20. data/examples/midi_controller_show.rb +78 -0
  21. data/examples/midi_scene_switch.rb +3 -1
  22. data/examples/parser_visualizer.rb +48 -0
  23. data/examples/readme_demo.rb +17 -0
  24. data/examples/rhythm_geometry.rb +34 -0
  25. data/examples/ruby_crystal_show.rb +35 -0
  26. data/examples/shader_playground.rb +18 -0
  27. data/examples/unyo_liquid.rb +59 -0
  28. data/examples/vj_ambient_chill_room.rb +124 -0
  29. data/examples/vj_dnb_jungle.rb +170 -0
  30. data/examples/vj_festival_mainstage.rb +245 -0
  31. data/examples/vj_festival_mainstage.yml +17 -0
  32. data/examples/vj_glitch_industrial.rb +164 -0
  33. data/examples/vj_hiphop_cipher.rb +167 -0
  34. data/examples/vj_jpop_idol_live.rb +210 -0
  35. data/examples/vj_synthwave_retro.rb +173 -0
  36. data/examples/vj_techno_warehouse.rb +195 -0
  37. data/frontend/index.html +494 -2
  38. data/frontend/src/audio-inspector.js +40 -0
  39. data/frontend/src/custom-shape-param-controls.js +106 -0
  40. data/frontend/src/live-controls.js +131 -0
  41. data/frontend/src/main.js +1060 -16
  42. data/frontend/src/mapping-target-selector.js +109 -0
  43. data/frontend/src/midi-learn.js +194 -0
  44. data/frontend/src/performance-monitor.js +183 -0
  45. data/frontend/src/plugin-runtime.js +130 -0
  46. data/frontend/src/projector-mode.js +56 -0
  47. data/frontend/src/renderer/engine.js +157 -3
  48. data/frontend/src/renderer/layer-manager.js +442 -30
  49. data/frontend/src/renderer/shader-manager.js +26 -0
  50. data/frontend/src/runtime-control-preset.js +11 -0
  51. data/frontend/src/shader-error-overlay.js +29 -0
  52. data/frontend/src/shader-param-controls.js +93 -0
  53. data/frontend/src/shaders/builtins.js +380 -2
  54. data/frontend/src/shaders/post-effects.js +52 -0
  55. data/frontend/src/shape-editor-controls.js +157 -0
  56. data/frontend/src/visual-regression.js +67 -0
  57. data/frontend/src/visual-settings-preset.js +103 -0
  58. data/frontend/src/visuals/geometry.js +666 -0
  59. data/frontend/src/visuals/image-renderer.js +291 -0
  60. data/frontend/src/visuals/particle-system.js +56 -10
  61. data/frontend/src/visuals/shape-renderer.js +475 -0
  62. data/frontend/src/visuals/spectrogram-renderer.js +226 -0
  63. data/frontend/src/visuals/svg-arc.js +104 -0
  64. data/frontend/src/visuals/text-renderer.js +112 -11
  65. data/frontend/src/websocket-client.js +12 -1
  66. data/lib/vizcore/analysis/adaptive_normalizer.rb +70 -0
  67. data/lib/vizcore/analysis/beat_detector.rb +4 -2
  68. data/lib/vizcore/analysis/bpm_estimator.rb +8 -0
  69. data/lib/vizcore/analysis/feature_recorder.rb +159 -0
  70. data/lib/vizcore/analysis/feature_replay.rb +84 -0
  71. data/lib/vizcore/analysis/pipeline.rb +235 -11
  72. data/lib/vizcore/analysis/tap_tempo.rb +74 -0
  73. data/lib/vizcore/analysis.rb +4 -0
  74. data/lib/vizcore/audio/dummy_sine_input.rb +1 -1
  75. data/lib/vizcore/audio/fixture_input.rb +65 -0
  76. data/lib/vizcore/audio/input_manager.rb +4 -2
  77. data/lib/vizcore/audio/mic_input.rb +24 -8
  78. data/lib/vizcore/audio/portaudio_ffi.rb +106 -1
  79. data/lib/vizcore/audio.rb +1 -0
  80. data/lib/vizcore/cli/doctor.rb +159 -0
  81. data/lib/vizcore/cli/dsl_reference.rb +99 -0
  82. data/lib/vizcore/cli/layer_docs.rb +46 -0
  83. data/lib/vizcore/cli/scene_diagnostics.rb +23 -0
  84. data/lib/vizcore/cli/scene_inspector.rb +136 -0
  85. data/lib/vizcore/cli/scene_validator.rb +337 -0
  86. data/lib/vizcore/cli/shader_template.rb +68 -0
  87. data/lib/vizcore/cli/shader_uniform_docs.rb +54 -0
  88. data/lib/vizcore/cli.rb +689 -18
  89. data/lib/vizcore/config.rb +103 -2
  90. data/lib/vizcore/control_preset.rb +68 -0
  91. data/lib/vizcore/dsl/engine.rb +277 -5
  92. data/lib/vizcore/dsl/layer_builder.rb +1280 -23
  93. data/lib/vizcore/dsl/layer_group_builder.rb +112 -0
  94. data/lib/vizcore/dsl/mapping_resolver.rb +290 -7
  95. data/lib/vizcore/dsl/mapping_transform_builder.rb +71 -0
  96. data/lib/vizcore/dsl/reaction_builder.rb +44 -0
  97. data/lib/vizcore/dsl/scene_builder.rb +61 -5
  98. data/lib/vizcore/dsl/shader_source_resolver.rb +67 -6
  99. data/lib/vizcore/dsl/style_builder.rb +68 -0
  100. data/lib/vizcore/dsl/timeline_builder.rb +138 -0
  101. data/lib/vizcore/dsl/transition_controller.rb +77 -0
  102. data/lib/vizcore/dsl.rb +5 -1
  103. data/lib/vizcore/layer_catalog.rb +275 -0
  104. data/lib/vizcore/project_manifest.rb +152 -0
  105. data/lib/vizcore/renderer/png_writer.rb +57 -0
  106. data/lib/vizcore/renderer/render_sequence.rb +153 -0
  107. data/lib/vizcore/renderer/scene_frame_source.rb +132 -0
  108. data/lib/vizcore/renderer/scene_serializer.rb +36 -3
  109. data/lib/vizcore/renderer/snapshot.rb +38 -0
  110. data/lib/vizcore/renderer/snapshot_renderer.rb +938 -0
  111. data/lib/vizcore/renderer.rb +5 -0
  112. data/lib/vizcore/server/frame_broadcaster.rb +143 -8
  113. data/lib/vizcore/server/gallery_app.rb +155 -0
  114. data/lib/vizcore/server/gallery_page.rb +100 -0
  115. data/lib/vizcore/server/gallery_runner.rb +48 -0
  116. data/lib/vizcore/server/rack_app.rb +203 -4
  117. data/lib/vizcore/server/runner.rb +391 -22
  118. data/lib/vizcore/server/scene_dependency_watcher.rb +79 -0
  119. data/lib/vizcore/server/websocket_handler.rb +60 -10
  120. data/lib/vizcore/server.rb +4 -0
  121. data/lib/vizcore/shape.rb +719 -0
  122. data/lib/vizcore/sync/osc_message.rb +103 -0
  123. data/lib/vizcore/sync/osc_receiver.rb +68 -0
  124. data/lib/vizcore/sync.rb +4 -0
  125. data/lib/vizcore/templates/midi_control_scene.rb +3 -1
  126. data/lib/vizcore/templates/plugin_layer.rb +20 -0
  127. data/lib/vizcore/templates/plugin_readme.md +23 -0
  128. data/lib/vizcore/templates/plugin_renderer.js +43 -0
  129. data/lib/vizcore/templates/plugin_scene.rb +14 -0
  130. data/lib/vizcore/templates/project_readme.md +7 -23
  131. data/lib/vizcore/templates/rubykaigi_scene.rb +30 -0
  132. data/lib/vizcore/version.rb +1 -1
  133. data/lib/vizcore.rb +28 -0
  134. data/scripts/browser_capture.mjs +75 -0
  135. data/sig/vizcore.rbs +461 -0
  136. metadata +94 -3
  137. data/docs/GETTING_STARTED.md +0 -105
@@ -0,0 +1,744 @@
1
+ :root {
2
+ color-scheme: dark;
3
+ --bg: #080a0f;
4
+ --bg-deep: #05070a;
5
+ --surface: rgba(15, 23, 42, 0.76);
6
+ --surface-strong: rgba(15, 23, 42, 0.94);
7
+ --panel: rgba(255, 255, 255, 0.055);
8
+ --panel-hover: rgba(255, 255, 255, 0.085);
9
+ --text: #f8fafc;
10
+ --muted: #aab6c7;
11
+ --muted-strong: #dbeafe;
12
+ --line: rgba(148, 163, 184, 0.22);
13
+ --line-strong: rgba(148, 163, 184, 0.36);
14
+ --cyan: #38bdf8;
15
+ --green: #22c55e;
16
+ --acid: #a3e635;
17
+ --rose: #fb7185;
18
+ --amber: #facc15;
19
+ --purple: #8b5cf6;
20
+ --shadow: 0 24px 90px rgba(0, 0, 0, 0.42);
21
+ --max-width: 1120px;
22
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
23
+ letter-spacing: 0;
24
+ }
25
+
26
+ * {
27
+ box-sizing: border-box;
28
+ }
29
+
30
+ html {
31
+ scroll-behavior: smooth;
32
+ }
33
+
34
+ body {
35
+ margin: 0;
36
+ min-width: 320px;
37
+ background-color: var(--bg);
38
+ background-image:
39
+ linear-gradient(115deg, rgba(34, 197, 94, 0.16) 0%, transparent 34%),
40
+ linear-gradient(245deg, rgba(56, 189, 248, 0.14) 0%, transparent 38%),
41
+ linear-gradient(180deg, #080a0f 0%, #0b111a 54%, #07090d 100%);
42
+ color: var(--text);
43
+ }
44
+
45
+ body::before {
46
+ position: fixed;
47
+ inset: 0;
48
+ z-index: 10;
49
+ pointer-events: none;
50
+ content: "";
51
+ background:
52
+ linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
53
+ linear-gradient(90deg, rgba(255, 255, 255, 0.028) 1px, transparent 1px);
54
+ background-size: 48px 48px;
55
+ mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.65), transparent 72%);
56
+ }
57
+
58
+ a {
59
+ color: inherit;
60
+ }
61
+
62
+ img {
63
+ display: block;
64
+ max-width: 100%;
65
+ }
66
+
67
+ code,
68
+ pre {
69
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
70
+ }
71
+
72
+ .skip-link {
73
+ position: fixed;
74
+ left: 1rem;
75
+ top: 1rem;
76
+ z-index: 20;
77
+ min-height: 44px;
78
+ padding: 0.75rem 1rem;
79
+ border-radius: 8px;
80
+ background: var(--text);
81
+ color: #070a0f;
82
+ transform: translateY(-150%);
83
+ }
84
+
85
+ .skip-link:focus {
86
+ transform: translateY(0);
87
+ }
88
+
89
+ .site-header {
90
+ position: fixed;
91
+ top: 1rem;
92
+ left: 50%;
93
+ z-index: 9;
94
+ display: flex;
95
+ width: min(calc(100% - 2rem), var(--max-width));
96
+ align-items: center;
97
+ justify-content: space-between;
98
+ gap: 0.75rem;
99
+ padding: 0.5rem;
100
+ border: 1px solid var(--line);
101
+ border-radius: 8px;
102
+ background: rgba(8, 10, 15, 0.76);
103
+ box-shadow: 0 18px 60px rgba(0, 0, 0, 0.32);
104
+ backdrop-filter: blur(18px);
105
+ transform: translateX(-50%);
106
+ }
107
+
108
+ .brand,
109
+ .nav-cta,
110
+ .site-nav a,
111
+ .button {
112
+ min-height: 44px;
113
+ border-radius: 8px;
114
+ text-decoration: none;
115
+ }
116
+
117
+ .brand {
118
+ display: inline-flex;
119
+ align-items: center;
120
+ gap: 0.55rem;
121
+ padding: 0 0.5rem;
122
+ color: var(--text);
123
+ font-size: 1rem;
124
+ font-weight: 800;
125
+ }
126
+
127
+ .brand::before {
128
+ display: inline-block;
129
+ width: 0.72rem;
130
+ height: 0.72rem;
131
+ border-radius: 3px;
132
+ background: linear-gradient(135deg, var(--green), var(--cyan));
133
+ box-shadow: 0 0 24px rgba(34, 197, 94, 0.45);
134
+ content: "";
135
+ }
136
+
137
+ .site-nav {
138
+ display: flex;
139
+ align-items: center;
140
+ gap: 0.15rem;
141
+ padding: 0.2rem;
142
+ border: 1px solid rgba(148, 163, 184, 0.16);
143
+ border-radius: 8px;
144
+ background: rgba(255, 255, 255, 0.04);
145
+ }
146
+
147
+ .site-nav a,
148
+ .nav-cta {
149
+ display: inline-flex;
150
+ align-items: center;
151
+ justify-content: center;
152
+ padding: 0.65rem 0.9rem;
153
+ color: var(--muted-strong);
154
+ font-size: 0.92rem;
155
+ transition:
156
+ background-color 180ms ease,
157
+ color 180ms ease,
158
+ border-color 180ms ease;
159
+ }
160
+
161
+ .site-nav a:hover,
162
+ .nav-cta:hover {
163
+ color: var(--text);
164
+ background: rgba(255, 255, 255, 0.09);
165
+ }
166
+
167
+ .nav-cta {
168
+ border: 1px solid rgba(34, 197, 94, 0.35);
169
+ background: rgba(34, 197, 94, 0.1);
170
+ color: #dcfce7;
171
+ }
172
+
173
+ .hero {
174
+ position: relative;
175
+ display: grid;
176
+ min-height: 88svh;
177
+ align-items: center;
178
+ overflow: hidden;
179
+ padding: 8rem 1.25rem 4.5rem;
180
+ isolation: isolate;
181
+ }
182
+
183
+ #vj-field,
184
+ .hero-grid {
185
+ position: absolute;
186
+ inset: 0;
187
+ }
188
+
189
+ #vj-field {
190
+ z-index: 0;
191
+ width: 100%;
192
+ height: 100%;
193
+ }
194
+
195
+ .hero-grid {
196
+ z-index: 1;
197
+ opacity: 0.3;
198
+ background:
199
+ linear-gradient(rgba(56, 189, 248, 0.2) 1px, transparent 1px),
200
+ linear-gradient(90deg, rgba(34, 197, 94, 0.16) 1px, transparent 1px);
201
+ background-size: 80px 80px;
202
+ transform: perspective(640px) rotateX(62deg) translateY(12%);
203
+ transform-origin: center bottom;
204
+ }
205
+
206
+ .hero::after {
207
+ position: absolute;
208
+ inset: 0;
209
+ z-index: 2;
210
+ content: "";
211
+ background:
212
+ linear-gradient(90deg, rgba(8, 10, 15, 0.9) 0%, rgba(8, 10, 15, 0.72) 45%, rgba(8, 10, 15, 0.2) 100%),
213
+ linear-gradient(180deg, rgba(8, 10, 15, 0.62) 0%, transparent 34%, rgba(8, 10, 15, 0.92) 100%);
214
+ }
215
+
216
+ .hero-copy {
217
+ position: relative;
218
+ z-index: 3;
219
+ width: min(var(--max-width), 100%);
220
+ margin: 0 auto;
221
+ }
222
+
223
+ .kicker,
224
+ .section-kicker {
225
+ margin: 0 0 0.9rem;
226
+ color: var(--acid);
227
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
228
+ font-size: 0.82rem;
229
+ font-weight: 800;
230
+ text-transform: uppercase;
231
+ }
232
+
233
+ h1,
234
+ h2,
235
+ h3,
236
+ p {
237
+ overflow-wrap: anywhere;
238
+ }
239
+
240
+ h1 {
241
+ margin: 0;
242
+ max-width: 780px;
243
+ font-size: 6.25rem;
244
+ line-height: 0.9;
245
+ text-shadow:
246
+ 0 0 28px rgba(34, 197, 94, 0.24),
247
+ 0 12px 40px rgba(0, 0, 0, 0.6);
248
+ }
249
+
250
+ .hero-title-sub {
251
+ max-width: 720px;
252
+ margin: 1rem 0 0;
253
+ color: var(--text);
254
+ font-size: 2.1rem;
255
+ font-weight: 720;
256
+ line-height: 1.12;
257
+ }
258
+
259
+ .hero-lede {
260
+ max-width: 700px;
261
+ margin: 1.25rem 0 0;
262
+ color: var(--muted-strong);
263
+ font-size: 1.12rem;
264
+ line-height: 1.75;
265
+ }
266
+
267
+ .hero-actions,
268
+ .install-actions {
269
+ display: flex;
270
+ flex-wrap: wrap;
271
+ gap: 0.75rem;
272
+ margin-top: 1.45rem;
273
+ }
274
+
275
+ .button {
276
+ display: inline-flex;
277
+ align-items: center;
278
+ justify-content: center;
279
+ padding: 0.82rem 1.05rem;
280
+ border: 1px solid transparent;
281
+ font-weight: 800;
282
+ cursor: pointer;
283
+ transition:
284
+ background-color 180ms ease,
285
+ border-color 180ms ease,
286
+ color 180ms ease,
287
+ transform 180ms ease,
288
+ box-shadow 180ms ease;
289
+ }
290
+
291
+ .button:hover {
292
+ transform: translateY(-2px);
293
+ }
294
+
295
+ .button:focus-visible,
296
+ .site-nav a:focus-visible,
297
+ .nav-cta:focus-visible,
298
+ .brand:focus-visible,
299
+ .scroll-cue:focus-visible {
300
+ outline: 3px solid var(--amber);
301
+ outline-offset: 3px;
302
+ }
303
+
304
+ .button.is-primary {
305
+ background: var(--green);
306
+ color: #03110a;
307
+ box-shadow: 0 16px 42px rgba(34, 197, 94, 0.24);
308
+ }
309
+
310
+ .button.is-primary:hover {
311
+ background: var(--acid);
312
+ box-shadow: 0 18px 48px rgba(163, 230, 53, 0.24);
313
+ }
314
+
315
+ .button.is-secondary {
316
+ border-color: var(--line-strong);
317
+ background: rgba(15, 23, 42, 0.72);
318
+ color: var(--text);
319
+ }
320
+
321
+ .button.is-secondary:hover {
322
+ border-color: rgba(56, 189, 248, 0.64);
323
+ color: #e0f2fe;
324
+ }
325
+
326
+ .hero-meta {
327
+ display: grid;
328
+ grid-template-columns: repeat(3, minmax(0, 1fr));
329
+ gap: 0.75rem;
330
+ width: min(780px, 100%);
331
+ margin-top: 1.25rem;
332
+ }
333
+
334
+ .hero-meta span {
335
+ display: grid;
336
+ gap: 0.25rem;
337
+ min-height: 78px;
338
+ padding: 0.9rem;
339
+ border: 1px solid rgba(148, 163, 184, 0.22);
340
+ border-radius: 8px;
341
+ background: rgba(15, 23, 42, 0.58);
342
+ color: var(--muted);
343
+ font-size: 0.9rem;
344
+ line-height: 1.45;
345
+ backdrop-filter: blur(12px);
346
+ }
347
+
348
+ .hero-meta strong {
349
+ color: var(--text);
350
+ font-size: 0.94rem;
351
+ }
352
+
353
+ .terminal-strip {
354
+ display: grid;
355
+ gap: 0.38rem;
356
+ width: min(640px, 100%);
357
+ margin-top: 1.35rem;
358
+ padding: 1rem;
359
+ border: 1px solid rgba(34, 197, 94, 0.32);
360
+ border-top: 3px solid var(--green);
361
+ border-radius: 8px;
362
+ background: rgba(3, 7, 18, 0.78);
363
+ box-shadow:
364
+ inset 0 0 42px rgba(56, 189, 248, 0.08),
365
+ 0 20px 70px rgba(0, 0, 0, 0.28);
366
+ backdrop-filter: blur(12px);
367
+ }
368
+
369
+ .terminal-line {
370
+ color: #e5f7ee;
371
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
372
+ font-size: 0.9rem;
373
+ line-height: 1.5;
374
+ }
375
+
376
+ .prompt {
377
+ color: var(--acid);
378
+ }
379
+
380
+ .scroll-cue {
381
+ position: absolute;
382
+ left: 50%;
383
+ bottom: 1.15rem;
384
+ z-index: 3;
385
+ display: inline-flex;
386
+ align-items: center;
387
+ min-height: 44px;
388
+ padding: 0.7rem 0.9rem;
389
+ border: 1px solid var(--line);
390
+ border-radius: 8px;
391
+ background: rgba(15, 23, 42, 0.66);
392
+ color: var(--muted-strong);
393
+ font-size: 0.86rem;
394
+ text-decoration: none;
395
+ transform: translateX(-50%);
396
+ backdrop-filter: blur(12px);
397
+ }
398
+
399
+ .scroll-cue:hover {
400
+ border-color: rgba(34, 197, 94, 0.5);
401
+ color: var(--text);
402
+ }
403
+
404
+ .section {
405
+ scroll-margin-top: 5.5rem;
406
+ padding: 5.5rem 1.25rem;
407
+ border-top: 1px solid var(--line);
408
+ background:
409
+ linear-gradient(180deg, rgba(8, 10, 15, 0.96) 0%, rgba(11, 17, 26, 0.98) 100%),
410
+ repeating-linear-gradient(135deg, rgba(56, 189, 248, 0.08) 0 1px, transparent 1px 22px);
411
+ }
412
+
413
+ .section-dark {
414
+ background:
415
+ linear-gradient(135deg, #0b111a 0%, #101827 52%, #07110e 100%);
416
+ }
417
+
418
+ .section-inner {
419
+ width: min(var(--max-width), 100%);
420
+ margin: 0 auto;
421
+ }
422
+
423
+ .signal-layout,
424
+ .split-layout {
425
+ display: grid;
426
+ grid-template-columns: minmax(0, 0.94fr) minmax(320px, 1.06fr);
427
+ gap: 2rem;
428
+ align-items: center;
429
+ }
430
+
431
+ .section-copy p,
432
+ .section-head p {
433
+ color: var(--muted);
434
+ font-size: 1.04rem;
435
+ line-height: 1.75;
436
+ }
437
+
438
+ .section-head {
439
+ max-width: 780px;
440
+ margin-bottom: 2rem;
441
+ }
442
+
443
+ h2 {
444
+ margin: 0;
445
+ max-width: 760px;
446
+ font-size: 3rem;
447
+ line-height: 1.04;
448
+ }
449
+
450
+ h3 {
451
+ margin: 0;
452
+ font-size: 1.12rem;
453
+ }
454
+
455
+ .signal-steps {
456
+ display: grid;
457
+ gap: 0.75rem;
458
+ margin-top: 1.4rem;
459
+ }
460
+
461
+ .signal-step,
462
+ .example-item {
463
+ border: 1px solid var(--line);
464
+ border-radius: 8px;
465
+ background: var(--panel);
466
+ }
467
+
468
+ .signal-step {
469
+ display: grid;
470
+ gap: 0.2rem;
471
+ padding: 0.95rem;
472
+ }
473
+
474
+ .signal-step strong {
475
+ color: var(--acid);
476
+ }
477
+
478
+ .signal-step span {
479
+ color: var(--muted);
480
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
481
+ font-size: 0.9rem;
482
+ }
483
+
484
+ .poster {
485
+ margin: 0;
486
+ padding: 0.45rem;
487
+ border: 1px solid var(--line);
488
+ border-radius: 8px;
489
+ background: rgba(15, 23, 42, 0.68);
490
+ box-shadow: var(--shadow);
491
+ }
492
+
493
+ .poster img {
494
+ width: 100%;
495
+ border-radius: 6px;
496
+ }
497
+
498
+ .poster figcaption {
499
+ margin: 0.75rem 0.25rem 0.25rem;
500
+ color: var(--muted);
501
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
502
+ font-size: 0.84rem;
503
+ }
504
+
505
+ .feature-list {
506
+ display: grid;
507
+ gap: 0.75rem;
508
+ margin: 1.35rem 0 0;
509
+ padding: 0;
510
+ list-style: none;
511
+ }
512
+
513
+ .feature-list li {
514
+ padding-left: 1rem;
515
+ border-left: 3px solid var(--cyan);
516
+ color: #eef8ff;
517
+ line-height: 1.6;
518
+ }
519
+
520
+ .code-stage,
521
+ .install-commands {
522
+ overflow: hidden;
523
+ border: 1px solid rgba(56, 189, 248, 0.28);
524
+ border-radius: 8px;
525
+ background: rgba(3, 7, 18, 0.84);
526
+ box-shadow:
527
+ inset 0 0 48px rgba(34, 197, 94, 0.06),
528
+ 0 20px 80px rgba(0, 0, 0, 0.32);
529
+ }
530
+
531
+ .code-stage pre,
532
+ .install-commands pre {
533
+ margin: 0;
534
+ padding: 1.2rem;
535
+ white-space: pre-wrap;
536
+ overflow-wrap: anywhere;
537
+ }
538
+
539
+ .code-stage code,
540
+ .install-commands code {
541
+ color: #e9fff2;
542
+ font-size: 0.92rem;
543
+ line-height: 1.65;
544
+ }
545
+
546
+ .example-grid {
547
+ display: grid;
548
+ grid-template-columns: repeat(3, minmax(0, 1fr));
549
+ gap: 1rem;
550
+ }
551
+
552
+ .example-item {
553
+ display: grid;
554
+ gap: 0.9rem;
555
+ align-content: start;
556
+ min-height: 100%;
557
+ padding: 1rem;
558
+ transition:
559
+ background-color 180ms ease,
560
+ border-color 180ms ease,
561
+ transform 180ms ease;
562
+ }
563
+
564
+ .example-item:hover {
565
+ border-color: rgba(56, 189, 248, 0.46);
566
+ background: var(--panel-hover);
567
+ transform: translateY(-2px);
568
+ }
569
+
570
+ .example-item h3 {
571
+ color: #e0f2fe;
572
+ }
573
+
574
+ .example-item p {
575
+ margin: 0;
576
+ color: var(--muted);
577
+ line-height: 1.6;
578
+ }
579
+
580
+ .example-item code {
581
+ display: block;
582
+ padding-top: 0.8rem;
583
+ border-top: 1px solid rgba(148, 163, 184, 0.2);
584
+ color: #bef264;
585
+ font-size: 0.82rem;
586
+ line-height: 1.5;
587
+ overflow-wrap: anywhere;
588
+ }
589
+
590
+ .install-panel {
591
+ display: grid;
592
+ grid-template-columns: minmax(0, 0.85fr) minmax(320px, 1.15fr);
593
+ gap: 1.4rem 2rem;
594
+ align-items: start;
595
+ }
596
+
597
+ .install-actions {
598
+ grid-column: 1 / -1;
599
+ margin-top: 0;
600
+ }
601
+
602
+ .site-footer {
603
+ display: flex;
604
+ flex-wrap: wrap;
605
+ justify-content: space-between;
606
+ gap: 0.75rem;
607
+ padding: 1.5rem 1.25rem;
608
+ border-top: 1px solid var(--line);
609
+ background: var(--bg-deep);
610
+ color: var(--muted);
611
+ }
612
+
613
+ .site-footer a {
614
+ color: #bef264;
615
+ text-decoration: none;
616
+ }
617
+
618
+ .site-footer a:hover {
619
+ color: var(--text);
620
+ }
621
+
622
+ @media (max-width: 920px) {
623
+ .signal-layout,
624
+ .split-layout,
625
+ .install-panel {
626
+ grid-template-columns: 1fr;
627
+ }
628
+
629
+ .example-grid,
630
+ .hero-meta {
631
+ grid-template-columns: 1fr;
632
+ }
633
+
634
+ h1 {
635
+ font-size: 4.8rem;
636
+ }
637
+
638
+ h2 {
639
+ font-size: 2.45rem;
640
+ }
641
+
642
+ .hero-title-sub {
643
+ font-size: 1.75rem;
644
+ }
645
+ }
646
+
647
+ @media (max-width: 680px) {
648
+ .site-header {
649
+ top: 0.75rem;
650
+ width: calc(100% - 1.5rem);
651
+ align-items: center;
652
+ }
653
+
654
+ .site-nav {
655
+ display: none;
656
+ }
657
+
658
+ .hero {
659
+ min-height: auto;
660
+ padding: 5.55rem 1rem 2.25rem;
661
+ }
662
+
663
+ h1 {
664
+ font-size: 3.35rem;
665
+ }
666
+
667
+ h2 {
668
+ font-size: 2rem;
669
+ }
670
+
671
+ .hero-title-sub {
672
+ margin-top: 0.75rem;
673
+ font-size: 1.38rem;
674
+ line-height: 1.2;
675
+ }
676
+
677
+ .hero-title-sub,
678
+ .hero-lede,
679
+ .hero-meta,
680
+ .terminal-strip {
681
+ max-width: 22rem;
682
+ }
683
+
684
+ .hero-lede,
685
+ .section-copy p,
686
+ .section-head p {
687
+ font-size: 1rem;
688
+ }
689
+
690
+ .hero-lede {
691
+ margin-top: 0.9rem;
692
+ line-height: 1.62;
693
+ }
694
+
695
+ .hero-actions {
696
+ margin-top: 1rem;
697
+ }
698
+
699
+ .hero-meta {
700
+ gap: 0.55rem;
701
+ margin-top: 0.95rem;
702
+ }
703
+
704
+ .hero-meta span {
705
+ min-height: auto;
706
+ padding: 0.75rem;
707
+ }
708
+
709
+ .section {
710
+ padding: 3.8rem 1rem;
711
+ }
712
+
713
+ .terminal-strip {
714
+ margin-top: 0.95rem;
715
+ padding: 0.85rem;
716
+ }
717
+
718
+ .terminal-line {
719
+ font-size: 0.82rem;
720
+ }
721
+
722
+ .scroll-cue {
723
+ display: none;
724
+ }
725
+ }
726
+
727
+ @media (prefers-reduced-motion: reduce) {
728
+ html {
729
+ scroll-behavior: auto;
730
+ }
731
+
732
+ *,
733
+ *::before,
734
+ *::after {
735
+ animation-duration: 0.01ms !important;
736
+ animation-iteration-count: 1 !important;
737
+ transition-duration: 0.01ms !important;
738
+ }
739
+
740
+ .button:hover,
741
+ .example-item:hover {
742
+ transform: none;
743
+ }
744
+ }
Binary file
Binary file