1:root {
2 --bg: #14161a;
3 --panel: #1d2026;
4 --panel2: #23272f;
5 --border: #31363f;
6 --text: #d6dae2;
7 --muted: #8b93a1;
8 --accent: #e8a33d;
9 --accent2: #4dd0e1;
10 --good: #6fbf73;
11 --warn: #e57373;
12 font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
13}
15* { box-sizing: border-box; }
17html, body, #root {
18 margin: 0;
19 height: 100%;
20 background: var(--bg);
21 color: var(--text);
22}
24.app {
25 display: flex;
26 flex-direction: column;
27 height: 100vh;
28}
30.topbar {
31 display: flex;
32 align-items: center;
33 gap: 10px;
34 padding: 8px 14px;
35 background: var(--panel);
36 border-bottom: 1px solid var(--border);
37 flex-wrap: wrap;
38}
40.topbar h1 {
41 font-size: 16px;
42 margin: 0 12px 0 0;
43 font-weight: 600;
44 color: var(--accent);
45 white-space: nowrap;
46}
48button {
49 background: var(--panel2);
50 color: var(--text);
51 border: 1px solid var(--border);
52 border-radius: 6px;
53 padding: 6px 14px;
54 font-size: 13px;
55 cursor: pointer;
56}
57button:hover { border-color: var(--muted); }
58button:disabled { opacity: 0.45; cursor: default; }
59button.primary {
60 background: var(--accent);
61 color: #1a1204;
62 border-color: var(--accent);
63 font-weight: 600;
64}
65button.play {
66 background: var(--good);
67 color: #06210a;
68 border-color: var(--good);
69 font-weight: 600;
70}
71button.play.preview {
72 background: transparent;
73 color: var(--accent);
74 border-color: var(--accent);
75}
76button.loop.active {
77 background: var(--accent2);
78 color: #062a2f;
79 border-color: var(--accent2);
80 font-weight: 600;
81}
82button.code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
83button.code.active { border-color: var(--accent2); color: var(--accent2); }
85.status {
86 margin-left: auto;
87 font-size: 12px;
88 color: var(--muted);
89 display: flex;
90 align-items: center;
91 gap: 8px;
92 min-width: 180px;
93 justify-content: flex-end;
94}
96.badge {
97 font-size: 11px;
98 border-radius: 10px;
99 padding: 2px 8px;
100 border: 1px solid var(--border);
101}
102.badge.preview { color: var(--accent); border-color: var(--accent); }
103.badge.full { color: var(--good); border-color: var(--good); }
104.badge.err { color: var(--warn); border-color: var(--warn); }
106.progressbar {
107 width: 90px;
108 height: 6px;
109 background: var(--panel2);
110 border-radius: 3px;
111 overflow: hidden;
112}
113.progressbar > div {
114 height: 100%;
115 background: var(--accent2);
116 transition: width 0.1s linear;
117}
119.main {
120 display: flex;
121 flex: 1;
122 min-height: 0;
123}
125.sidebar {
126 width: 340px;
127 min-width: 340px;
128 overflow-y: auto;
129 background: var(--panel);
130 border-right: 1px solid var(--border);
131 padding: 8px;
132}
134.content {
135 flex: 1;
136 overflow-y: auto;
137 padding: 10px;
138 display: grid;
139 grid-template-columns: 1fr 1fr;
140 gap: 10px;
141 align-content: start;
142}
144.card {
145 background: var(--panel);
146 border: 1px solid var(--border);
147 border-radius: 8px;
148 padding: 8px 10px 10px;
149 min-width: 0;
150}
151.card.wide { grid-column: 1 / -1; }
152.card h2 {
153 font-size: 12px;
154 text-transform: uppercase;
155 letter-spacing: 0.06em;
156 color: var(--muted);
157 margin: 0 0 6px;
158 font-weight: 600;
159}
160.card canvas { display: block; width: 100%; }
162.scene3d { height: 380px; position: relative; }
163.scene3d canvas { height: 100%; border-radius: 6px; }
164.scene-hint {
165 position: absolute;
166 bottom: 10px;
167 right: 14px;
168 font-size: 11px;
169 color: var(--muted);
170 pointer-events: none;
171}
173/* Parameter panel */
174details.group {
175 border: 1px solid var(--border);
176 border-radius: 6px;
177 margin-bottom: 6px;
178 background: var(--panel2);
179}
180details.group summary {
181 cursor: pointer;
182 padding: 6px 10px;
183 font-size: 13px;
184 font-weight: 600;
185 user-select: none;
186}
187details.group[open] summary { border-bottom: 1px solid var(--border); }
188.group-body { padding: 6px 10px 8px; }
190.param-row { margin-bottom: 8px; }
191.param-label {
192 display: flex;
193 justify-content: space-between;
194 font-size: 12px;
195 margin-bottom: 2px;
196 align-items: baseline;
197}
198.param-label .name { color: var(--text); }
199.param-controls { display: flex; gap: 8px; align-items: center; }
200.param-controls input[type='range'] { flex: 1; accent-color: var(--accent2); }
201.param-controls input[type='number'] {
202 width: 88px;
203 background: var(--bg);
204 color: var(--text);
205 border: 1px solid var(--border);
206 border-radius: 4px;
207 padding: 3px 5px;
208 font-size: 12px;
209}
210.param-controls select, .param-controls input[type='checkbox'] {
211 background: var(--bg);
212 color: var(--text);
213 border: 1px solid var(--border);
214 border-radius: 4px;
215 font-size: 12px;
216}
217.param-help { font-size: 11px; color: var(--muted); margin-top: 1px; }
219/* Diagnostics */
220.diag table { border-collapse: collapse; font-size: 12px; width: 100%; }
221.diag td, .diag th {
222 padding: 2px 8px 2px 0;
223 text-align: left;
224 color: var(--text);
225 font-weight: 400;
226}
227.diag th { color: var(--muted); white-space: nowrap; }
228.diag .partials { font-variant-numeric: tabular-nums; }
229.warning { color: var(--warn); font-size: 12px; margin-top: 4px; }
230.cachenote { color: var(--muted); font-size: 11px; margin-top: 6px; }
232.mode-list { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
233.mode-list button { padding: 3px 10px; font-size: 12px; }
234.mode-list button.active { border-color: var(--accent2); color: var(--accent2); }
236/* Code panel */
237.modal-backdrop {
238 position: fixed;
239 inset: 0;
240 background: rgba(8, 10, 13, 0.72);
241 display: flex;
242 align-items: center;
243 justify-content: center;
244 z-index: 50;
245}
247.code-panel {
248 width: min(1180px, 94vw);
249 height: min(860px, 92vh);
250 background: var(--panel);
251 border: 1px solid var(--border);
252 border-radius: 10px;
253 display: flex;
254 flex-direction: column;
255 overflow: hidden;
256}
258.code-header {
259 display: flex;
260 align-items: center;
261 gap: 10px;
262 padding: 9px 12px;
263 border-bottom: 1px solid var(--border);
264}
265.code-header h2 {
266 margin: 0;
267 font-size: 13px;
268 text-transform: uppercase;
269 letter-spacing: 0.06em;
270 color: var(--accent);
271}
272.code-header button:last-child { margin-left: 0; }
273.code-note {
274 font-size: 11.5px;
275 color: var(--muted);
276 margin-right: auto;
277}
279.code-body { display: flex; flex: 1; min-height: 0; }
281.code-files {
282 width: 236px;
283 min-width: 236px;
284 border-right: 1px solid var(--border);
285 overflow-y: auto;
286 padding: 6px;
287}
288.code-files button {
289 display: flex;
290 align-items: center;
291 justify-content: space-between;
292 gap: 6px;
293 width: 100%;
294 text-align: left;
295 background: transparent;
296 border: 1px solid transparent;
297 border-radius: 5px;
298 padding: 5px 8px;
299 margin-bottom: 2px;
300 font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
301 font-size: 12px;
302}
303.code-files button:hover { background: var(--panel2); }
304.code-files button.active {
305 background: var(--panel2);
306 border-color: var(--accent2);
307 color: var(--accent2);
308}
309.code-files .fname { display: flex; align-items: center; gap: 5px; }
310.code-files .dot {
311 width: 6px;
312 height: 6px;
313 border-radius: 50%;
314 background: var(--accent);
315}
316.code-files .ftag {
317 font-size: 9.5px;
318 color: var(--muted);
319 text-transform: uppercase;
320 letter-spacing: 0.05em;
321 font-family: system-ui, sans-serif;
322}
324.code-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
325.code-toolbar {
326 display: flex;
327 align-items: center;
328 gap: 10px;
329 padding: 6px 10px;
330 border-bottom: 1px solid var(--border);
331 font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
332 font-size: 12px;
333 color: var(--text);
334}
335.code-hint {
336 font-size: 11px;
337 color: var(--muted);
338 font-family: system-ui, sans-serif;
339}
340.code-editor { flex: 1; min-height: 0; overflow: hidden; }
342.code-error {
343 border-top: 1px solid var(--warn);
344 background: #2a1a1a;
345 color: #ffb4a9;
346 padding: 7px 12px;
347 font-size: 12px;
348 font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
349}
351.error-card { border-color: var(--warn); }
352.error-card h2 { color: var(--warn); }
353.error-card div { font-size: 12px; }
354.error-card strong { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
356@media (max-width: 1100px) {
357 .content { grid-template-columns: 1fr; }
358}
360/* Sidebar credit */
361.sidebar-credit {
362 margin-top: 10px;
363 padding: 8px 10px 12px;
364 border-top: 1px solid var(--border);
365 font-size: 11px;
366 line-height: 1.5;
367 color: var(--muted);
368}
369.sidebar-credit a { color: var(--accent2); }
370button.linklike {
371 background: none;
372 border: none;
373 padding: 0;
374 margin-top: 4px;
375 font-size: 11.5px;
376 color: var(--accent);
377 cursor: pointer;
378}
379button.linklike:hover { text-decoration: underline; border: none; }
381/* Tutorial */
382.tut-loading {
383 flex: 1;
384 display: flex;
385 align-items: center;
386 justify-content: center;
387 color: var(--muted);
388}
390.tutorial {
391 flex: 1;
392 min-height: 0;
393 display: flex;
394 overflow-y: auto;
395 scroll-behavior: smooth;
396 background: var(--bg);
397}
399.tut-toc {
400 position: sticky;
401 top: 0;
402 align-self: flex-start;
403 width: 230px;
404 min-width: 230px;
405 padding: 26px 8px 16px 16px;
406 display: none;
407 flex-direction: column;
408 gap: 2px;
409}
410@media (min-width: 1050px) {
411 .tut-toc { display: flex; }
412}
413.tut-toc-head {
414 font-size: 12px;
415 text-transform: uppercase;
416 letter-spacing: 0.06em;
417 color: var(--accent);
418 font-weight: 600;
419 margin-bottom: 8px;
420}
421.tut-toc a {
422 color: var(--muted);
423 text-decoration: none;
424 font-size: 12.5px;
425 padding: 3px 6px;
426 border-radius: 4px;
427}
428.tut-toc a:hover { color: var(--text); background: var(--panel2); }
429.tut-toc button { margin-top: 14px; font-size: 12px; }
431.tut-body {
432 flex: 1;
433 max-width: 860px;
434 padding: 24px 28px 80px;
435 font-size: 14.5px;
436 line-height: 1.65;
437}
438.tut-body section { scroll-margin-top: 14px; }
439.tut-header h1 {
440 font-size: 26px;
441 margin: 6px 0 12px;
442 color: var(--accent);
443}
444.tut-lede {
445 font-size: 15px;
446 color: var(--text);
447}
448.tut-body h2 {
449 font-size: 19px;
450 margin: 40px 0 10px;
451 color: var(--accent);
452 border-bottom: 1px solid var(--border);
453 padding-bottom: 6px;
454}
455.tut-body p { margin: 10px 0; }
456.tut-body a { color: var(--accent2); }
457.tut-body code {
458 font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
459 font-size: 0.92em;
460 background: var(--panel2);
461 border: 1px solid var(--border);
462 border-radius: 4px;
463 padding: 0 4px;
464}
466.tut-eq {
467 display: flex;
468 align-items: center;
469 gap: 10px;
470 margin: 14px 0;
471 overflow-x: auto;
472 padding: 4px 2px;
473}
474.tut-eq-body { flex: 1; text-align: center; }
475.tut-eq-tag { color: var(--muted); font-size: 13px; white-space: nowrap; }
476.tut-eq .katex { font-size: 1.02em; }
478.tut-fig {
479 margin: 18px 0;
480 padding: 10px 12px 12px;
481 background: var(--panel);
482 border: 1px solid var(--border);
483 border-radius: 8px;
484}
485.tut-fig canvas { display: block; width: 100%; border-radius: 4px; }
486.tut-fig figcaption {
487 font-size: 12.5px;
488 line-height: 1.55;
489 color: var(--muted);
490 margin-top: 8px;
491}
492.tut-fig figcaption i, .tut-fig figcaption b { color: var(--text); }
494.tut-controls {
495 display: flex;
496 flex-wrap: wrap;
497 gap: 12px 22px;
498 align-items: center;
499 margin-top: 8px;
500}
501.tut-controls button { font-size: 12px; padding: 4px 10px; }
502.tut-controls button.tut-active { border-color: var(--accent2); color: var(--accent2); }
503.tut-slider {
504 display: flex;
505 align-items: center;
506 gap: 8px;
507 font-size: 12px;
508 color: var(--muted);
509}
510.tut-slider input[type='range'] { width: 150px; accent-color: var(--accent2); }
511.tut-slider-name { white-space: nowrap; }
512.tut-slider-val {
513 color: var(--text);
514 font-variant-numeric: tabular-nums;
515 min-width: 62px;
516}
518.tut-pipe {
519 width: 100%;
520 height: auto;
521 margin: 10px 0;
522 background: var(--panel);
523 border: 1px solid var(--border);
524 border-radius: 8px;
525}
527.tut-steps { padding-left: 22px; }
528.tut-steps li { margin: 7px 0; }
529.tut-list { padding-left: 22px; }
530.tut-list li { margin: 9px 0; }
531.tut-refs { padding-left: 22px; font-size: 13.5px; }
532.tut-refs li { margin: 8px 0; }
534/* Strike picker */
535.strike-picker { position: relative; }
536.strike-picker canvas { display: block; width: 100%; }
537.picker-hint {
538 font-size: 11px;
539 color: var(--muted);
540 text-align: right;
541 margin-top: 2px;
542}
544.preset-row {
545 display: flex;
546 align-items: center;
547 gap: 8px;
548 padding: 8px 10px 4px;
549}
550.preset-row label {
551 font-size: 12px;
552 color: var(--muted, #888);
553}
554.preset-row select {
555 flex: 1;
556 min-width: 0;
557}
558.preset-note {
559 padding: 2px 10px 8px;
560 font-size: 11.5px;
561 line-height: 1.45;
562 color: var(--muted, #888);
563}