@laitszkin/apollo-toolkit 3.10.0 → 3.11.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 (47) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/analyse-app-logs/scripts/__pycache__/filter_logs_by_time.cpython-312.pyc +0 -0
  3. package/analyse-app-logs/scripts/__pycache__/log_cli_utils.cpython-312.pyc +0 -0
  4. package/analyse-app-logs/scripts/__pycache__/search_logs.cpython-312.pyc +0 -0
  5. package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
  6. package/generate-spec/SKILL.md +17 -15
  7. package/generate-spec/agents/openai.yaml +1 -1
  8. package/generate-spec/references/TEMPLATE_SPEC.md +103 -84
  9. package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
  10. package/init-project-html/SKILL.md +82 -126
  11. package/init-project-html/agents/openai.yaml +17 -8
  12. package/init-project-html/lib/atlas/assets/architecture.css +140 -0
  13. package/init-project-html/lib/atlas/assets/viewer.client.js +93 -0
  14. package/init-project-html/lib/atlas/cli.js +995 -0
  15. package/init-project-html/lib/atlas/layout.js +229 -0
  16. package/init-project-html/lib/atlas/render.js +485 -0
  17. package/init-project-html/lib/atlas/schema.js +310 -0
  18. package/init-project-html/lib/atlas/state.js +402 -0
  19. package/init-project-html/references/TEMPLATE_SPEC.md +123 -84
  20. package/init-project-html/sample-demo/resources/project-architecture/assets/architecture.css +139 -1058
  21. package/init-project-html/sample-demo/resources/project-architecture/assets/viewer.client.js +93 -0
  22. package/init-project-html/sample-demo/resources/project-architecture/atlas/atlas.index.yaml +34 -0
  23. package/init-project-html/sample-demo/resources/project-architecture/atlas/features/get-invite-codes.yaml +159 -0
  24. package/init-project-html/sample-demo/resources/project-architecture/atlas/features/invite-code-registration.yaml +160 -0
  25. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/index.html +67 -52
  26. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-code-generator.html +48 -163
  27. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-issuance-service.html +70 -196
  28. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/postgresql.html +64 -163
  29. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/public-api.html +68 -150
  30. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/web-get-invite-ui.html +65 -138
  31. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/index.html +61 -51
  32. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/postgresql.html +66 -159
  33. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/public-api.html +63 -143
  34. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/registration-service.html +77 -188
  35. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/web-register-ui.html +65 -138
  36. package/init-project-html/sample-demo/resources/project-architecture/index.html +232 -335
  37. package/init-project-html/scripts/architecture.js +65 -247
  38. package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
  39. package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
  40. package/package.json +6 -2
  41. package/read-github-issue/scripts/__pycache__/find_issues.cpython-312.pyc +0 -0
  42. package/read-github-issue/scripts/__pycache__/read_issue.cpython-312.pyc +0 -0
  43. package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
  44. package/spec-to-project-html/SKILL.md +61 -63
  45. package/spec-to-project-html/agents/openai.yaml +14 -8
  46. package/spec-to-project-html/references/TEMPLATE_SPEC.md +96 -83
  47. package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
@@ -1,1059 +1,140 @@
1
- /* Shared atlas styles pair with architecture-page.template.html */
2
- :root {
3
- --bg: #0f1419;
4
- --surface: #1a222c;
5
- --surface-elevated: #232d3a;
6
- --text: #e8ecf1;
7
- --muted: #9aa7b2;
8
- --accent: #e07a5f;
9
- --accent-soft: rgba(224, 122, 95, 0.15);
10
- --edge: #4a5b6c;
11
- --ok: #6fcf97;
12
- --font-display: "Fraunces", "Georgia", serif;
13
- --font-body: "Plus Jakarta Sans", "Segoe UI", system-ui, sans-serif;
14
- --radius: 12px;
15
- --shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
16
- }
17
-
18
- @media (prefers-color-scheme: light) {
19
- :root {
20
- --bg: #f4f1ea;
21
- --surface: #ffffff;
22
- --surface-elevated: #faf8f3;
23
- --text: #1a1d22;
24
- --muted: #5c6670;
25
- --accent: #c45c3e;
26
- --accent-soft: rgba(196, 92, 62, 0.12);
27
- --edge: #a8b0b9;
28
- --shadow: 0 8px 28px rgba(26, 29, 34, 0.08);
29
- }
30
- }
31
-
32
- *,
33
- *::before,
34
- *::after {
35
- box-sizing: border-box;
36
- }
37
-
38
- body {
39
- margin: 0;
40
- min-height: 100vh;
41
- font-family: var(--font-body);
42
- font-size: 1rem;
43
- line-height: 1.6;
44
- color: var(--text);
45
- background: radial-gradient(1200px 800px at 10% -10%, rgba(224, 122, 95, 0.08), transparent),
46
- var(--bg);
47
- }
48
-
49
- .atlas-page {
50
- max-width: 1120px;
51
- margin: 0 auto;
52
- padding: 2.5rem 1.5rem 4rem;
53
- position: relative;
54
- }
55
-
56
- .atlas-header {
57
- margin-bottom: 2rem;
58
- }
59
-
60
- .atlas-kicker {
61
- font-size: 0.75rem;
62
- letter-spacing: 0.12em;
63
- text-transform: uppercase;
64
- color: var(--accent);
65
- margin: 0 0 0.5rem;
66
- }
67
-
68
- .atlas-title {
69
- font-family: var(--font-display);
70
- font-weight: 600;
71
- font-size: clamp(2rem, 4vw, 2.75rem);
72
- line-height: 1.15;
73
- margin: 0 0 0.5rem;
74
- }
75
-
76
- .atlas-meta {
77
- color: var(--muted);
78
- font-size: 0.9rem;
79
- margin: 0;
80
- }
81
-
82
- .atlas-summary,
83
- .atlas-legend,
84
- .atlas-diagram,
85
- .atlas-features,
86
- .feature-story,
87
- .feature-modules,
88
- .feature-flows,
89
- .feature-trace {
90
- background: var(--surface);
91
- border-radius: var(--radius);
92
- padding: 1.25rem 1.5rem;
93
- margin-bottom: 1.25rem;
94
- box-shadow: var(--shadow);
95
- }
96
-
97
- .atlas-summary h2,
98
- .atlas-legend h2,
99
- .atlas-diagram h2,
100
- .atlas-features h2,
101
- .feature-story h2,
102
- .feature-modules h2,
103
- .feature-flows h2,
104
- .feature-trace h2 {
105
- font-family: var(--font-display);
106
- font-size: 1.15rem;
107
- margin: 0 0 0.75rem;
108
- }
109
-
110
- .atlas-legend ul {
111
- margin: 0;
112
- padding-left: 1.25rem;
113
- color: var(--muted);
114
- }
115
-
116
- .arch-diagram {
117
- margin: 0;
118
- padding: 0;
119
- background: transparent;
120
- box-shadow: none;
121
- }
122
-
123
- .arch-canvas {
124
- position: relative;
125
- background: var(--surface-elevated);
126
- border-radius: var(--radius);
127
- padding: 1.25rem;
128
- min-height: 280px;
129
- }
130
-
131
- .arch-nodes {
132
- display: grid;
133
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
134
- gap: 1rem;
135
- position: relative;
136
- z-index: 1;
137
- }
138
-
139
- .arch-node {
140
- background: var(--surface);
141
- border: 1px solid var(--edge);
142
- border-radius: calc(var(--radius) - 4px);
143
- padding: 0.85rem 1rem;
144
- transition: border-color 0.15s ease, transform 0.15s ease;
145
- }
146
-
147
- @media (prefers-reduced-motion: reduce) {
148
- .arch-node {
149
- transition: none;
150
- }
151
- }
152
-
153
- .arch-node:hover {
154
- border-color: var(--accent);
155
- transform: translateY(-1px);
156
- }
157
-
158
- .arch-node--ui {
159
- border-top: 3px solid var(--accent);
160
- }
161
-
162
- .arch-node--service {
163
- border-top: 3px solid #7eb8da;
164
- }
165
-
166
- .arch-node--data {
167
- border-top: 3px solid var(--ok);
168
- }
169
-
170
- .arch-node--external {
171
- border-top: 3px solid #d4a837;
172
- border-style: dashed;
173
- }
174
-
175
- .arch-node-title {
176
- font-family: var(--font-display);
177
- font-size: 1rem;
178
- margin: 0 0 0.35rem;
179
- }
180
-
181
- .arch-node-body {
182
- margin: 0;
183
- font-size: 0.85rem;
184
- color: var(--muted);
185
- }
186
-
187
- .arch-edge-list {
188
- list-style: none;
189
- margin: 1rem 0 0;
190
- padding: 0;
191
- font-size: 0.82rem;
192
- color: var(--muted);
193
- }
194
-
195
- .arch-edge-list li {
196
- padding: 0.35rem 0;
197
- border-top: 1px solid var(--edge);
198
- }
199
-
200
- .arch-edge-list code {
201
- color: var(--text);
202
- background: var(--surface-elevated);
203
- padding: 0.1rem 0.35rem;
204
- border-radius: 4px;
205
- font-size: 0.8em;
206
- }
207
-
208
- .arch-caption {
209
- font-size: 0.85rem;
210
- color: var(--muted);
211
- margin-top: 0.75rem;
212
- }
213
-
214
- .atlas-features ul {
215
- list-style: none;
216
- margin: 0;
217
- padding: 0;
218
- }
219
-
220
- .atlas-features li {
221
- margin-bottom: 0.65rem;
222
- }
223
-
224
- .atlas-features a {
225
- color: var(--accent);
226
- font-weight: 600;
227
- text-decoration: none;
228
- }
229
-
230
- .atlas-features a:hover {
231
- text-decoration: underline;
232
- }
233
-
234
- .feature-modules table {
235
- width: 100%;
236
- border-collapse: collapse;
237
- font-size: 0.9rem;
238
- }
239
-
240
- .feature-modules th,
241
- .feature-modules td {
242
- text-align: left;
243
- padding: 0.5rem 0.65rem;
244
- border-bottom: 1px solid var(--edge);
245
- }
246
-
247
- .feature-modules th {
248
- color: var(--muted);
249
- font-weight: 500;
250
- }
251
-
252
- .breadcrumb {
253
- font-size: 0.9rem;
254
- margin: 0 0 1rem;
255
- }
256
-
257
- .breadcrumb a {
258
- color: var(--accent);
259
- text-decoration: none;
260
- }
261
-
262
- .breadcrumb a:hover {
263
- text-decoration: underline;
264
- }
265
-
266
- /* --- Flowchart (flow-chart): macro / cross-module / internal --- */
267
- .flow-section h2 {
268
- font-family: var(--font-display);
269
- font-size: 1.25rem;
270
- margin: 0 0 1rem;
271
- }
272
-
273
- .flow-chart {
274
- margin: 0 0 1.25rem;
275
- }
276
-
277
- .flow-chart__body {
278
- display: flex;
279
- flex-direction: column;
280
- align-items: center;
281
- gap: 0;
282
- padding: 1.25rem 1rem 1rem;
283
- background: var(--surface-elevated);
284
- border-radius: var(--radius);
285
- max-width: 100%;
286
- }
287
-
288
- .flow-node {
289
- width: 100%;
290
- max-width: 420px;
291
- background: var(--surface);
292
- border: 1px solid var(--edge);
293
- border-radius: calc(var(--radius) - 4px);
294
- padding: 0.85rem 1.1rem;
295
- border-top:3px solid #7eb8da;
296
- }
297
-
298
- .flow-node--module {
299
- max-width: 520px;
300
- border-top-color: #7eb8da;
301
- }
302
-
303
- .flow-node--process {
304
- border-top-color: var(--accent);
305
- }
306
-
307
- .flow-node--decision {
308
- border-top: 3px solid #d4a837;
309
- border-left: 3px solid rgba(212, 168, 55, 0.45);
310
- text-align: center;
311
- position: relative;
312
- max-width: 440px;
313
- }
314
-
315
- .flow-node--decision::before {
316
- content: "Decision";
317
- position: absolute;
318
- top: 0.45rem;
319
- right: 0.65rem;
320
- font-size: 0.6rem;
321
- letter-spacing: 0.1em;
322
- text-transform: uppercase;
323
- color: #d4a837;
324
- font-weight: 600;
325
- }
326
-
327
- .flow-node--decision .flow-node__title {
328
- display: block;
329
- font-size: 0.95rem;
330
- margin: 0.25rem 2.5rem 0.5rem 0.25rem;
331
- text-align: left;
332
- }
333
-
334
- .flow-node__kicker {
335
- display: block;
336
- font-size: 0.65rem;
337
- letter-spacing: 0.08em;
338
- text-transform: uppercase;
339
- color: var(--muted);
340
- margin-bottom: 0.25rem;
341
- }
342
-
343
- .flow-node__title {
344
- font-family: var(--font-display);
345
- display: block;
346
- font-size: 1rem;
347
- }
348
-
349
- .flow-node__body {
350
- font-size: 0.82rem;
351
- color: var(--muted);
352
- margin: 0.4rem 0 0;
353
- }
354
-
355
- .flow-branch-row {
356
- display: grid;
357
- grid-template-columns: 1fr 1fr;
358
- gap: 0.75rem;
359
- margin-top: 0.5rem;
360
- text-align: left;
361
- }
362
-
363
- .flow-branch {
364
- background: var(--surface-elevated);
365
- border-radius: 6px;
366
- padding: 0.45rem 0.6rem;
367
- border: 1px solid var(--edge);
368
- }
369
-
370
- .flow-branch__label {
371
- font-size: 0.7rem;
372
- font-weight: 600;
373
- color: var(--accent);
374
- text-transform: uppercase;
375
- letter-spacing: 0.06em;
376
- }
377
-
378
- .flow-branch__note {
379
- font-size: 0.78rem;
380
- margin: 0.25rem 0 0;
381
- color: var(--muted);
382
- }
383
-
384
- .flow-connector {
385
- display: flex;
386
- justify-content: center;
387
- color: var(--accent);
388
- margin: -0.1rem 0;
389
- }
390
-
391
- .flow-connector--dashed .flow-connector__svg line {
392
- stroke-dasharray: 5 4;
393
- opacity: 0.85;
394
- }
395
-
396
- .flow-connector--failure,
397
- .flow-connector--rollback {
398
- color: #e07a5f;
399
- opacity: 0.95;
400
- }
401
-
402
- .flow-connector--failure .flow-connector__svg line,
403
- .flow-connector--rollback .flow-connector__svg line {
404
- stroke-dasharray: 6 5;
405
- stroke-width: 2;
406
- }
407
-
408
- @media (prefers-color-scheme: light) {
409
- .flow-connector--failure,
410
- .flow-connector--rollback {
411
- color: #b3472b;
412
- }
413
- }
414
-
415
- .flow-node--failure {
416
- border-top: 3px solid #e07a5f;
417
- border-left: 2px solid rgba(224, 122, 95, 0.35);
418
- background: var(--accent-soft);
419
- }
420
-
421
- .flow-node--failure .flow-node__kicker {
422
- color: #e07a5f;
423
- }
424
-
425
- .flow-node--rollback {
426
- border-top: 3px dashed #9aa7b2;
427
- font-size: 0.9rem;
428
- }
429
-
430
- .flow-edge-rollback {
431
- display: block;
432
- margin-top: 0.35rem;
433
- padding: 0.35rem 0.5rem;
434
- background: var(--surface-elevated);
435
- border-radius: 6px;
436
- font-size: 0.82em;
437
- border-left: 3px solid #e07a5f;
438
- }
439
-
440
- .flow-edge-rollback a {
441
- color: var(--accent);
442
- font-weight: 600;
443
- }
444
-
445
- .flow-edge-manifest {
446
- margin: 0.75rem 0 0;
447
- padding-left: 1.25rem;
448
- font-size: 0.82rem;
449
- color: var(--muted);
450
- }
451
-
452
- .flow-edge-manifest li {
453
- margin-bottom: 0.45rem;
454
- }
455
-
456
- .flow-edge-from,
457
- .flow-edge-to {
458
- font-family: ui-monospace, monospace;
459
- font-size: 0.78em;
460
- color: var(--text);
461
- }
462
-
463
- .flow-edge-label {
464
- display: inline-block;
465
- font-weight: 600;
466
- color: var(--text);
467
- margin: 0 0.25rem;
468
- }
469
-
470
- .flow-edge-note {
471
- display: block;
472
- font-size: 0.9em;
473
- margin-top: 0.15rem;
474
- }
475
-
476
- .flow-caption {
477
- font-size: 0.85rem;
478
- color: var(--muted);
479
- margin-top: 0.65rem;
480
- }
481
-
482
- .flow-glossary {
483
- background: var(--surface);
484
- border-radius: var(--radius);
485
- padding: 1.25rem 1.5rem;
486
- margin-bottom: 1.25rem;
487
- box-shadow: var(--shadow);
488
- }
1
+ /* architecture.css styling for the declarative atlas. The CLI copies
2
+ * this file into <outDir>/assets/. Style hooks (class names) are owned
3
+ * by render.js so agents never need to touch HTML by hand. */
489
4
 
490
- .flow-glossary h2 {
491
- font-family: var(--font-display);
492
- font-size: 1.15rem;
493
- margin: 0 0 0.75rem;
494
- }
495
-
496
- .flow-glossary h3 {
497
- font-family: var(--font-display);
498
- font-size: 1rem;
499
- margin: 1.25rem 0 0.5rem;
500
- }
501
-
502
- .flow-glossary h3:first-of-type {
503
- margin-top: 0;
504
- }
505
-
506
- .flow-glossary table {
507
- width: 100%;
508
- border-collapse: collapse;
509
- font-size: 0.88rem;
510
- }
511
-
512
- .flow-glossary th,
513
- .flow-glossary td {
514
- text-align: left;
515
- padding: 0.45rem 0.55rem;
516
- border-bottom: 1px solid var(--edge);
517
- vertical-align: top;
518
- }
519
-
520
- .flow-glossary th {
521
- color: var(--muted);
522
- font-weight: 500;
523
- width: 18%;
524
- }
525
-
526
- .flow-glossary td code {
527
- font-size: 0.85em;
528
- background: var(--surface-elevated);
529
- padding: 0.1rem 0.3rem;
530
- border-radius: 4px;
531
- }
532
-
533
- /* Page-level SVG marker defs (see TEMPLATE_SPEC.md) */
534
- .flow-defs {
535
- position: absolute;
536
- width: 0;
537
- height: 0;
538
- overflow: hidden;
539
- pointer-events: none;
540
- }
541
-
542
- .flow-path-divider {
543
- text-align: center;
544
- font-size: 0.8rem;
545
- letter-spacing: 0.06em;
546
- color: var(--muted);
547
- margin: 0.65rem 0 0.35rem;
548
- width: 100%;
549
- max-width: 420px;
550
- }
551
-
552
- /* Feature folder: submodule nav + rollback return strip */
553
- .submodule-nav {
554
- background: var(--surface);
555
- border-radius: var(--radius);
556
- padding: 1.25rem 1.5rem;
557
- margin-bottom: 1.25rem;
558
- box-shadow: var(--shadow);
559
- }
560
-
561
- .submodule-nav h2 {
562
- font-family: var(--font-display);
563
- font-size: 1.15rem;
564
- margin: 0 0 0.75rem;
565
- }
566
-
567
- .submodule-nav table {
568
- width: 100%;
569
- border-collapse: collapse;
570
- font-size: 0.9rem;
571
- }
572
-
573
- .submodule-nav th,
574
- .submodule-nav td {
575
- text-align: left;
576
- padding: 0.5rem 0.65rem;
577
- border-bottom: 1px solid var(--edge);
578
- }
579
-
580
- .submodule-nav th {
581
- color: var(--muted);
582
- font-weight: 500;
583
- }
584
-
585
- .flow-node--submodule .flow-node__title a {
586
- color: var(--accent);
587
- text-decoration: none;
588
- font-weight: 600;
589
- }
590
-
591
- .flow-node--submodule .flow-node__title a:hover {
592
- text-decoration: underline;
593
- }
594
-
595
- .flow-node--feature-cap {
596
- border-top-color: #9b7ed9;
597
- max-width: 480px;
598
- text-align: center;
599
- }
600
-
601
- .flow-node--feature-cap .flow-node__title a {
602
- color: var(--accent);
603
- font-weight: 700;
604
- }
605
-
606
- .flow-return-row {
607
- display: flex;
608
- align-items: center;
609
- justify-content: center;
610
- flex-wrap: wrap;
611
- gap: 0.5rem 0.75rem;
612
- width: 100%;
613
- max-width: 520px;
614
- margin: 0.35rem auto 0.75rem;
615
- padding: 0.65rem 0.85rem;
616
- background: var(--accent-soft);
617
- border: 1px dashed var(--accent);
618
- border-radius: var(--radius);
619
- color: var(--text);
620
- }
621
-
622
- .flow-return-row__endpoint {
623
- font-size: 0.82rem;
624
- max-width: 200px;
625
- }
626
-
627
- .flow-return-row__label {
628
- display: block;
629
- font-size: 0.62rem;
630
- letter-spacing: 0.08em;
631
- text-transform: uppercase;
632
- color: var(--accent);
633
- font-weight: 600;
634
- }
635
-
636
- .flow-return-row__hint {
637
- display: block;
638
- font-size: 0.75rem;
639
- color: var(--muted);
640
- margin-top: 0.2rem;
641
- }
642
-
643
- .flow-return-row a {
644
- color: var(--accent);
645
- font-weight: 600;
646
- }
647
-
648
- .flow-return-arrow {
649
- flex-shrink: 0;
650
- color: #e07a5f;
651
- }
652
-
653
- @media (prefers-color-scheme: light) {
654
- .flow-return-arrow {
655
- color: #b3472b;
656
- }
657
- }
658
-
659
- .submodule-role {
660
- background: var(--surface);
661
- border-radius: var(--radius);
662
- padding: 1rem 1.25rem;
663
- margin-bottom: 1.25rem;
664
- box-shadow: var(--shadow);
665
- }
666
-
667
- .submodule-role h2 {
668
- font-family: var(--font-display);
669
- font-size: 1.05rem;
670
- margin: 0 0 0.5rem;
671
- }
672
-
673
- /* ============================================================
674
- Macro SVG graph (feature × submodule, many-to-many)
675
- ============================================================ */
676
- .flow-chart--svg {
677
- margin: 0 0 1.25rem;
678
- }
679
-
680
- .macro-svg__wrap {
681
- background: var(--surface-elevated);
682
- border-radius: var(--radius);
683
- padding: 0.75rem;
684
- overflow-x: auto;
685
- }
686
-
687
- .macro-svg {
688
- display: block;
689
- width: 100%;
690
- height: auto;
691
- min-width: 880px;
692
- max-width: 1240px;
693
- font-family: var(--font-body);
694
- }
695
-
696
- /* Actors */
697
- .macro-svg .m-actor rect {
698
- fill: var(--surface);
699
- stroke: var(--edge);
700
- stroke-width: 1.4;
701
- }
702
- .macro-svg .m-actor text {
703
- fill: var(--text);
704
- font-size: 14px;
705
- font-weight: 600;
706
- font-family: var(--font-display);
707
- }
708
-
709
- /* Feature cluster (the big dashed box that contains submodules) */
710
- .macro-svg .m-cluster__rect {
711
- fill: rgba(155, 126, 217, 0.06);
712
- stroke: #9b7ed9;
713
- stroke-width: 1.5;
714
- stroke-dasharray: 8 5;
715
- }
716
- .macro-svg .m-cluster__title {
717
- fill: var(--accent);
718
- font-size: 14px;
719
- font-weight: 700;
720
- font-family: var(--font-display);
721
- letter-spacing: 0.02em;
722
- }
723
- .macro-svg .m-cluster__title:hover {
724
- text-decoration: underline;
725
- }
726
- .macro-svg .m-cluster__sub {
727
- fill: var(--muted);
728
- font-size: 11px;
729
- }
730
-
731
- /* Submodule node */
732
- .macro-svg .m-sub rect {
733
- fill: var(--surface);
734
- stroke: var(--edge);
735
- stroke-width: 1.4;
736
- transition: stroke 0.15s ease;
737
- }
738
- .macro-svg .m-sub:hover rect {
739
- stroke: var(--accent);
740
- stroke-width: 2;
741
- }
742
- .macro-svg .m-sub__title {
743
- fill: var(--text);
744
- font-size: 13px;
745
- font-weight: 600;
746
- }
747
- .macro-svg .m-sub__kind {
748
- fill: var(--muted);
749
- font-size: 10.5px;
750
- }
751
- .macro-svg .m-sub--db rect {
752
- fill: rgba(111, 207, 151, 0.08);
753
- stroke: var(--ok);
754
- }
755
-
756
- /* Edges */
757
- .macro-svg .m-edge path {
758
- fill: none;
759
- stroke: var(--edge);
760
- stroke-width: 1.4;
761
- }
762
- .macro-svg .m-edge--call {
763
- color: var(--text);
764
- }
765
- .macro-svg .m-edge--call path {
766
- stroke: currentColor;
767
- stroke-width: 1.6;
768
- }
769
- .macro-svg .m-edge--return {
770
- color: var(--muted);
771
- }
772
- .macro-svg .m-edge--return path {
773
- stroke: currentColor;
774
- stroke-width: 1.1;
775
- stroke-dasharray: 5 4;
776
- }
777
- .macro-svg .m-edge--cross {
778
- color: var(--accent);
779
- }
780
- .macro-svg .m-edge--cross path {
781
- stroke: var(--accent);
782
- stroke-width: 2.4;
783
- stroke-dasharray: 10 5;
784
- opacity: 0.9;
785
- }
786
-
787
- .macro-svg .m-edge__label {
788
- fill: var(--muted);
789
- font-size: 10.5px;
790
- }
791
- .macro-svg .m-edge__label--cross {
792
- fill: var(--accent);
793
- font-weight: 600;
794
- font-size: 11.5px;
795
- }
796
-
797
- @media (prefers-color-scheme: light) {
798
- .macro-svg .m-cluster__rect {
799
- fill: rgba(155, 126, 217, 0.08);
800
- }
801
- .macro-svg .m-sub--db rect {
802
- fill: rgba(111, 207, 151, 0.14);
803
- }
804
- }
805
-
806
- /* ============================================================
807
- Macro manifest list (under SVG)
808
- ============================================================ */
809
- .flow-edge-manifest--macro {
810
- margin-top: 1rem;
811
- }
812
- .flow-edge-manifest--macro li[data-edge-kind="call"] {
813
- border-left: 3px solid var(--text);
814
- padding-left: 0.6rem;
815
- }
816
- .flow-edge-manifest--macro li[data-edge-kind="return"] {
817
- border-left: 3px solid var(--muted);
818
- padding-left: 0.6rem;
819
- font-style: italic;
820
- }
821
- .flow-edge-manifest--macro li[data-edge-kind="data-row"] {
822
- border-left: 3px solid var(--accent);
823
- padding-left: 0.6rem;
824
- font-weight: 600;
825
- }
826
-
827
- /* ============================================================
828
- Submodule page: I/O table + variables + internal data flow
829
- ============================================================ */
830
- .sub-io,
831
- .sub-vars,
832
- .sub-dataflow,
833
- .sub-errors {
834
- background: var(--surface);
835
- border-radius: var(--radius);
836
- padding: 1.1rem 1.35rem;
837
- margin-bottom: 1.1rem;
838
- box-shadow: var(--shadow);
839
- }
840
-
841
- .sub-io h2,
842
- .sub-vars h2,
843
- .sub-dataflow h2,
844
- .sub-errors h2 {
845
- font-family: var(--font-display);
846
- font-size: 1.1rem;
847
- margin: 0 0 0.75rem;
848
- }
849
-
850
- .sub-vars__intro {
851
- margin: 0 0 0.6rem;
852
- color: var(--muted);
853
- font-size: 0.86rem;
854
- }
855
-
856
- .sub-vars table {
857
- width: 100%;
858
- border-collapse: collapse;
859
- font-size: 0.86rem;
860
- }
861
- .sub-vars th,
862
- .sub-vars td {
863
- text-align: left;
864
- padding: 0.55rem 0.65rem;
865
- border-bottom: 1px solid var(--edge);
866
- vertical-align: top;
867
- }
868
- .sub-vars th {
869
- color: var(--muted);
870
- font-weight: 500;
871
- font-size: 0.78rem;
872
- letter-spacing: 0.04em;
873
- text-transform: uppercase;
874
- }
875
- .sub-vars code {
876
- background: var(--surface-elevated);
877
- padding: 0.08rem 0.3rem;
878
- border-radius: 3px;
879
- font-size: 0.8em;
880
- }
881
- .sub-vars__name {
882
- font-family: ui-monospace, "SF Mono", Menlo, monospace;
883
- font-weight: 600;
884
- color: var(--text);
885
- white-space: nowrap;
886
- }
887
- .sub-vars__type {
888
- font-family: ui-monospace, "SF Mono", Menlo, monospace;
889
- color: var(--muted);
890
- }
891
- .sub-vars__scope {
892
- display: inline-block;
893
- padding: 0.12rem 0.5rem;
894
- border-radius: 999px;
895
- font-size: 0.7rem;
896
- letter-spacing: 0.05em;
897
- text-transform: uppercase;
898
- background: var(--surface-elevated);
899
- color: var(--muted);
900
- border: 1px solid var(--edge);
901
- }
902
- .sub-vars__scope--call {
903
- border-color: rgba(126, 184, 218, 0.5);
904
- color: #7eb8da;
905
- }
906
- .sub-vars__scope--tx {
907
- border-color: rgba(212, 168, 55, 0.55);
908
- color: #d4a837;
909
- }
910
- .sub-vars__scope--persist {
911
- border-color: rgba(111, 207, 151, 0.55);
912
- color: var(--ok);
913
- }
914
- .sub-vars__scope--instance {
915
- border-color: rgba(155, 126, 217, 0.55);
916
- color: #9b7ed9;
917
- }
918
- .sub-vars__scope--loop {
919
- border-color: rgba(224, 122, 95, 0.55);
920
- color: var(--accent);
921
- }
922
-
923
- .sub-io table {
924
- width: 100%;
925
- border-collapse: collapse;
926
- font-size: 0.86rem;
927
- }
928
- .sub-io th,
929
- .sub-io td {
930
- text-align: left;
931
- padding: 0.55rem 0.65rem;
932
- border-bottom: 1px solid var(--edge);
933
- vertical-align: top;
934
- }
935
- .sub-io th {
936
- color: var(--muted);
937
- font-weight: 500;
938
- font-size: 0.78rem;
939
- letter-spacing: 0.04em;
940
- text-transform: uppercase;
941
- }
942
- .sub-io code {
943
- background: var(--surface-elevated);
944
- padding: 0.08rem 0.3rem;
945
- border-radius: 3px;
946
- font-size: 0.8em;
947
- }
948
-
949
- .sub-io__signature {
950
- font-family: ui-monospace, "SF Mono", Menlo, monospace;
951
- font-size: 0.84rem;
952
- color: var(--text);
953
- }
954
- .sub-io__side {
955
- display: inline-block;
956
- padding: 0.1rem 0.4rem;
957
- border-radius: 4px;
958
- font-size: 0.7rem;
959
- letter-spacing: 0.05em;
960
- text-transform: uppercase;
961
- margin-right: 0.25rem;
962
- }
963
- .sub-io__side--pure {
964
- background: rgba(111, 207, 151, 0.18);
965
- color: var(--ok);
966
- }
967
- .sub-io__side--io {
968
- background: rgba(212, 168, 55, 0.18);
969
- color: #d4a837;
970
- }
971
- .sub-io__side--write {
972
- background: rgba(224, 122, 95, 0.18);
973
- color: var(--accent);
974
- }
975
-
976
- .sub-dataflow ol {
977
- margin: 0;
978
- padding-left: 1.2rem;
979
- color: var(--text);
980
- }
981
- .sub-dataflow li {
982
- margin-bottom: 0.5rem;
983
- line-height: 1.55;
984
- }
985
- .sub-dataflow code {
986
- background: var(--surface-elevated);
987
- padding: 0.08rem 0.3rem;
988
- border-radius: 3px;
989
- }
990
-
991
- /* tiny inline SVG graph for in-submodule data movement */
992
- .sub-dataflow__svg {
993
- display: block;
994
- width: 100%;
995
- max-width: 720px;
996
- height: auto;
997
- margin-top: 0.75rem;
998
- background: var(--surface-elevated);
999
- border-radius: calc(var(--radius) - 4px);
1000
- padding: 0.5rem;
1001
- }
1002
- .sub-dataflow__svg .d-node rect {
1003
- fill: var(--surface);
1004
- stroke: var(--edge);
1005
- }
1006
- .sub-dataflow__svg .d-node text {
1007
- fill: var(--text);
1008
- font-size: 12px;
1009
- }
1010
- .sub-dataflow__svg .d-edge {
1011
- stroke: var(--text);
1012
- fill: none;
1013
- stroke-width: 1.4;
1014
- }
1015
- .sub-dataflow__svg .d-edge--side {
1016
- stroke: var(--accent);
1017
- stroke-dasharray: 4 3;
1018
- }
1019
- .sub-dataflow__svg .d-label {
1020
- fill: var(--muted);
1021
- font-size: 10.5px;
1022
- }
1023
-
1024
- /* Submodule index list on macro page */
1025
- .atlas-submodule-index {
1026
- background: var(--surface);
1027
- border-radius: var(--radius);
1028
- padding: 1.1rem 1.35rem;
1029
- margin-bottom: 1.25rem;
1030
- box-shadow: var(--shadow);
1031
- }
1032
- .atlas-submodule-index h2 {
1033
- font-family: var(--font-display);
1034
- font-size: 1.1rem;
1035
- margin: 0 0 0.6rem;
1036
- }
1037
- .atlas-submodule-index ul {
1038
- list-style: none;
1039
- margin: 0;
1040
- padding: 0;
1041
- }
1042
- .atlas-submodule-index li {
1043
- margin-bottom: 0.5rem;
1044
- font-size: 0.92rem;
1045
- }
1046
- .atlas-submodule-index strong {
1047
- color: var(--accent);
1048
- font-family: var(--font-display);
1049
- margin-right: 0.3rem;
1050
- }
1051
- .atlas-submodule-index a {
1052
- color: var(--text);
1053
- text-decoration: none;
1054
- border-bottom: 1px dotted var(--edge);
1055
- }
1056
- .atlas-submodule-index a:hover {
1057
- color: var(--accent);
1058
- border-bottom-color: var(--accent);
1059
- }
5
+ :root {
6
+ color-scheme: light dark;
7
+ --bg: #0f172a;
8
+ --panel: #111827;
9
+ --panel-soft: #1f2937;
10
+ --text: #e5e7eb;
11
+ --muted: #9ca3af;
12
+ --border: #334155;
13
+ --accent: #38bdf8;
14
+ --kind-ui: #38bdf8;
15
+ --kind-api: #818cf8;
16
+ --kind-service: #34d399;
17
+ --kind-db: #fbbf24;
18
+ --kind-pure-fn: #cbd5e1;
19
+ --kind-queue: #a78bfa;
20
+ --kind-external: #fb7185;
21
+ --edge-call: #60a5fa;
22
+ --edge-return: #94a3b8;
23
+ --edge-data-row: #fbbf24;
24
+ --edge-failure: #fb7185;
25
+ }
26
+
27
+ * { box-sizing: border-box; }
28
+ html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text); font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
29
+
30
+ a { color: var(--accent); text-decoration: none; }
31
+ a:hover { text-decoration: underline; }
32
+
33
+ h1, h2 { margin: 0 0 12px; font-weight: 600; letter-spacing: -0.01em; }
34
+ h1 { font-size: 28px; }
35
+ h2 { font-size: 18px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; font-size: 13px; }
36
+
37
+ p { line-height: 1.55; color: var(--text); }
38
+
39
+ /* ---- atlas (macro) ---- */
40
+ .atlas-header { padding: 28px 40px 16px; border-bottom: 1px solid var(--border); background: var(--panel); }
41
+ .atlas-summary { color: var(--muted); max-width: 80ch; margin: 8px 0 0; }
42
+
43
+ .atlas-main { display: grid; grid-template-columns: minmax(0, 3fr) minmax(280px, 1fr); gap: 24px; padding: 24px 40px 48px; }
44
+
45
+ .atlas-canvas { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px; position: relative; }
46
+ .atlas-canvas__toolbar { position: absolute; top: 16px; right: 16px; display: flex; gap: 4px; z-index: 2; }
47
+ .atlas-canvas__toolbar button { background: var(--panel-soft); color: var(--text); border: 1px solid var(--border); padding: 4px 12px; border-radius: 6px; cursor: pointer; font-size: 13px; }
48
+ .atlas-canvas__toolbar button:hover { border-color: var(--accent); color: var(--accent); }
49
+
50
+ .atlas-canvas__viewport { width: 100%; max-height: 72vh; overflow: hidden; border-radius: 8px; background: #0b1220; }
51
+ .atlas-canvas__viewport.is-grabbing { cursor: grabbing; }
52
+ .atlas-canvas__viewport:not(.is-grabbing) { cursor: grab; }
53
+
54
+ .atlas-svg { width: 100%; height: auto; max-height: 72vh; display: block; user-select: none; touch-action: none; }
55
+
56
+ .atlas-legend { list-style: none; padding: 12px 4px 0; margin: 0; display: flex; gap: 18px; flex-wrap: wrap; font-size: 12px; color: var(--muted); }
57
+ .atlas-legend li { display: inline-flex; align-items: center; gap: 6px; }
58
+ .legend-swatch { display: inline-block; width: 18px; height: 4px; border-radius: 2px; }
59
+ .legend-swatch--call { background: var(--edge-call); }
60
+ .legend-swatch--return { background: var(--edge-return); }
61
+ .legend-swatch--data-row { background: var(--edge-data-row); }
62
+ .legend-swatch--failure { background: var(--edge-failure); }
63
+
64
+ .atlas-index { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px; max-height: 80vh; overflow: auto; }
65
+
66
+ .atlas-submodule-index { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
67
+ .atlas-submodule-index__item a { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 4px 8px; padding: 8px 10px; background: var(--panel-soft); border: 1px solid var(--border); border-radius: 8px; color: inherit; }
68
+ .atlas-submodule-index__item a:hover { border-color: var(--accent); }
69
+ .atlas-submodule-index__feature { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; grid-column: 1 / 3; }
70
+ .atlas-submodule-index__sub { font-weight: 600; }
71
+ .atlas-submodule-index__kind { font-size: 11px; padding: 1px 8px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border); color: var(--muted); }
72
+ .atlas-submodule-index__role { margin: 4px 10px 0; font-size: 12px; color: var(--muted); }
73
+
74
+ /* ---- SVG macro ---- */
75
+ .m-cluster__bg { fill: rgba(15, 23, 42, 0.55); stroke: var(--border); stroke-width: 1; }
76
+ .m-cluster__title { font-family: ui-sans-serif, system-ui, sans-serif; font-size: 14px; fill: var(--text); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
77
+ .m-node rect { fill: var(--panel-soft); stroke: var(--border); stroke-width: 1; transition: stroke 120ms ease; }
78
+ .m-node:hover rect { stroke: var(--accent); }
79
+ .m-node__title { font-size: 13px; font-weight: 600; fill: var(--text); }
80
+ .m-node__kind { font-size: 11px; fill: var(--muted); }
81
+ .m-node__role { font-size: 11px; fill: var(--muted); }
82
+
83
+ .m-node--ui rect { stroke: var(--kind-ui); }
84
+ .m-node--api rect { stroke: var(--kind-api); }
85
+ .m-node--service rect { stroke: var(--kind-service); }
86
+ .m-node--db rect { stroke: var(--kind-db); }
87
+ .m-node--pure-fn rect { stroke: var(--kind-pure-fn); }
88
+ .m-node--queue rect { stroke: var(--kind-queue); }
89
+ .m-node--external rect { stroke: var(--kind-external); }
90
+
91
+ .m-edge path { stroke-width: 1.6; }
92
+ .m-edge--call path { stroke: var(--edge-call); }
93
+ .m-edge--return path { stroke: var(--edge-return); stroke-dasharray: 6 4; }
94
+ .m-edge--data-row path { stroke: var(--edge-data-row); }
95
+ .m-edge--failure path { stroke: var(--edge-failure); }
96
+
97
+ .m-arrow path { fill: currentColor; }
98
+ .m-arrow--call { color: var(--edge-call); }
99
+ .m-arrow--return { color: var(--edge-return); }
100
+ .m-arrow--data-row { color: var(--edge-data-row); }
101
+ .m-arrow--failure { color: var(--edge-failure); }
102
+
103
+ .m-edge__label { fill: var(--muted); font-size: 11px; }
104
+
105
+ /* ---- feature page ---- */
106
+ .feature-header, .submodule-header { padding: 24px 40px 12px; border-bottom: 1px solid var(--border); background: var(--panel); }
107
+ .feature-breadcrumb, .submodule-breadcrumb { font-size: 13px; color: var(--muted); margin-bottom: 8px; }
108
+ .feature-depends { font-size: 13px; color: var(--muted); margin: 8px 0 0; }
109
+ .feature-main, .submodule-main { padding: 24px 40px 48px; display: flex; flex-direction: column; gap: 32px; }
110
+ .feature-story p { max-width: 80ch; }
111
+
112
+ .submodule-nav { list-style: none; padding: 0; margin: 0; display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
113
+ .submodule-card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; }
114
+ .submodule-card__link { display: flex; align-items: center; justify-content: space-between; color: inherit; font-weight: 600; }
115
+ .submodule-card__kind { font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--border); color: var(--muted); }
116
+ .submodule-card__role { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
117
+
118
+ .feature-edges__list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
119
+ .feature-edges__item { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 2fr); gap: 8px; padding: 8px 12px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; font-size: 13px; }
120
+ .feature-edges__kind { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; align-self: center; }
121
+ .feature-edges__item--call { border-left: 4px solid var(--edge-call); }
122
+ .feature-edges__item--return { border-left: 4px solid var(--edge-return); }
123
+ .feature-edges__item--data-row { border-left: 4px solid var(--edge-data-row); }
124
+ .feature-edges__item--failure { border-left: 4px solid var(--edge-failure); }
125
+
126
+ /* ---- submodule page ---- */
127
+ .submodule-kind { display: inline-block; font-size: 12px; padding: 2px 10px; border-radius: 999px; border: 1px solid var(--border); color: var(--muted); margin-left: 8px; vertical-align: middle; text-transform: uppercase; letter-spacing: 0.06em; }
128
+ .submodule-role { color: var(--muted); margin: 8px 0 0; max-width: 80ch; }
129
+
130
+ .sub-table { width: 100%; border-collapse: collapse; font-size: 13px; }
131
+ .sub-table th, .sub-table td { padding: 8px 12px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
132
+ .sub-table th { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; background: var(--panel); }
133
+
134
+ .sub-section__empty { color: var(--muted); font-style: italic; font-size: 13px; }
135
+
136
+ .sub-dataflow__svg { width: 100%; max-width: 480px; }
137
+ .sub-dataflow__step rect { fill: var(--panel); stroke: var(--border); }
138
+ .sub-dataflow__step text { fill: var(--text); font-size: 13px; }
139
+ .sub-dataflow__arrow { stroke: var(--muted); stroke-width: 1.4; }
140
+ .sub-dataflow__empty { color: var(--muted); font-style: italic; }