@acta-dev/web 1.0.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 (66) hide show
  1. package/LICENSE +21 -0
  2. package/astro.config.mjs +31 -0
  3. package/package.json +62 -0
  4. package/public/favicon.png +0 -0
  5. package/src/components/DocumentSearchList.astro +150 -0
  6. package/src/components/DocumentView.astro +198 -0
  7. package/src/components/LanguageSwitcher.tsx +115 -0
  8. package/src/components/SidebarToggle.tsx +42 -0
  9. package/src/components/ThemeToggle.tsx +129 -0
  10. package/src/components/graph/DocumentGraphIsland.tsx +226 -0
  11. package/src/components/graph/GraphContext.ts +15 -0
  12. package/src/components/graph/graph.css +330 -0
  13. package/src/components/graph/layout.ts +48 -0
  14. package/src/components/graph/nodes.tsx +80 -0
  15. package/src/components/ui/Button.astro +105 -0
  16. package/src/components/ui/Chip.astro +147 -0
  17. package/src/components/ui/Field.astro +29 -0
  18. package/src/components/ui/Input.astro +34 -0
  19. package/src/components/ui/Pill.astro +71 -0
  20. package/src/components/ui/SegmentedControl.astro +105 -0
  21. package/src/components/ui/Select.astro +41 -0
  22. package/src/components/ui/Tooltip.astro +94 -0
  23. package/src/layouts/BaseLayout.astro +147 -0
  24. package/src/lib/documents.test.ts +175 -0
  25. package/src/lib/documents.ts +156 -0
  26. package/src/lib/i18n-client.ts +32 -0
  27. package/src/lib/i18n.ts +92 -0
  28. package/src/lib/project.test.ts +24 -0
  29. package/src/lib/project.ts +120 -0
  30. package/src/lib/search-client.ts +192 -0
  31. package/src/lib/search.test.ts +94 -0
  32. package/src/lib/search.ts +153 -0
  33. package/src/locales/en/common.json +6 -0
  34. package/src/locales/en/dashboard.json +8 -0
  35. package/src/locales/en/documents.json +63 -0
  36. package/src/locales/en/graph.json +19 -0
  37. package/src/locales/en/search.json +7 -0
  38. package/src/locales/en/sidebar.json +25 -0
  39. package/src/locales/en/validation.json +13 -0
  40. package/src/locales/ru/common.json +6 -0
  41. package/src/locales/ru/dashboard.json +8 -0
  42. package/src/locales/ru/documents.json +63 -0
  43. package/src/locales/ru/graph.json +19 -0
  44. package/src/locales/ru/search.json +7 -0
  45. package/src/locales/ru/sidebar.json +25 -0
  46. package/src/locales/ru/validation.json +13 -0
  47. package/src/pages/documents/[id]/index.astro +39 -0
  48. package/src/pages/graph.astro +54 -0
  49. package/src/pages/index.astro +41 -0
  50. package/src/pages/ru/documents/[id]/index.astro +39 -0
  51. package/src/pages/ru/graph.astro +54 -0
  52. package/src/pages/ru/index.astro +41 -0
  53. package/src/pages/ru/search-index-full.json.ts +1 -0
  54. package/src/pages/ru/search.astro +27 -0
  55. package/src/pages/ru/validation.astro +63 -0
  56. package/src/pages/search-index-full.json.ts +12 -0
  57. package/src/pages/search-index.json.ts +12 -0
  58. package/src/pages/search.astro +27 -0
  59. package/src/pages/validation.astro +63 -0
  60. package/src/styles/global.css +1391 -0
  61. package/src/styles/themes/dark.css +61 -0
  62. package/src/styles/themes/light.css +63 -0
  63. package/src/styles/tokens/primitives.css +32 -0
  64. package/src/styles/tokens/semantic.css +34 -0
  65. package/src/styles/tokens/typography.css +28 -0
  66. package/tsconfig.json +11 -0
@@ -0,0 +1,1391 @@
1
+ @import "./tokens/primitives.css";
2
+ @import "./tokens/typography.css";
3
+ @import "./tokens/semantic.css";
4
+ @import "./themes/light.css";
5
+ @import "./themes/dark.css";
6
+
7
+ /* ── Direction A · Press — editorial reading view ─────────────────────── */
8
+
9
+ :root {
10
+ color-scheme: light dark;
11
+ font-family: var(--font-serif);
12
+ background: var(--color-bg);
13
+ color: var(--color-text);
14
+ }
15
+
16
+ * {
17
+ box-sizing: border-box;
18
+ }
19
+
20
+ body {
21
+ margin: 0;
22
+ min-width: 320px;
23
+ background: var(--color-bg);
24
+ color: var(--color-text);
25
+ font-size: 16px;
26
+ line-height: 1.55;
27
+ -webkit-font-smoothing: antialiased;
28
+ text-rendering: optimizeLegibility;
29
+ }
30
+
31
+ a {
32
+ color: inherit;
33
+ text-decoration: none;
34
+ }
35
+
36
+ [hidden] {
37
+ display: none;
38
+ }
39
+
40
+ .sr-only {
41
+ position: absolute;
42
+ width: 1px;
43
+ height: 1px;
44
+ padding: 0;
45
+ margin: -1px;
46
+ overflow: hidden;
47
+ clip: rect(0, 0, 0, 0);
48
+ white-space: nowrap;
49
+ border: 0;
50
+ }
51
+
52
+ .muted {
53
+ color: var(--color-text-muted);
54
+ }
55
+
56
+ /* Form primitives — duplicated here so React islands (graph) can use them too */
57
+ .ui-field {
58
+ display: flex;
59
+ flex-direction: column;
60
+ gap: var(--space-1);
61
+ min-width: 0;
62
+ font-family: var(--font-sans);
63
+ font-size: 10px;
64
+ letter-spacing: 0.16em;
65
+ text-transform: uppercase;
66
+ color: var(--color-text-muted);
67
+ font-weight: 500;
68
+ }
69
+
70
+ .ui-input,
71
+ .ui-select {
72
+ width: 100%;
73
+ padding: var(--space-1-5) 0;
74
+ border: 0;
75
+ border-bottom: 1px solid var(--color-border);
76
+ background: transparent;
77
+ color: var(--color-text);
78
+ font-family: var(--font-sans);
79
+ font-size: 13px;
80
+ outline: none;
81
+ }
82
+
83
+ .ui-input {
84
+ font-family: var(--font-serif);
85
+ font-size: 16px;
86
+ }
87
+
88
+ .ui-input::placeholder {
89
+ color: var(--color-text-muted);
90
+ font-style: italic;
91
+ }
92
+
93
+ .ui-select {
94
+ padding-right: var(--space-4);
95
+ appearance: none;
96
+ background-image:
97
+ linear-gradient(45deg, transparent 50%, var(--color-text-muted) 50%),
98
+ linear-gradient(135deg, var(--color-text-muted) 50%, transparent 50%);
99
+ background-position:
100
+ calc(100% - 6px) 12px,
101
+ calc(100% - 2px) 12px;
102
+ background-size: 4px 4px;
103
+ background-repeat: no-repeat;
104
+ cursor: pointer;
105
+ }
106
+
107
+ .ui-input:focus-visible,
108
+ .ui-select:focus-visible {
109
+ border-bottom-color: var(--color-accent);
110
+ }
111
+
112
+ /* ── Shell ────────────────────────────────────────────────────────────── */
113
+ .app-shell {
114
+ display: grid;
115
+ grid-template-columns: var(--sidebar-width, 220px) minmax(0, 1fr);
116
+ min-height: 100vh;
117
+ transition: grid-template-columns 0.18s ease;
118
+ }
119
+
120
+ :root[data-sidebar="collapsed"] .app-shell {
121
+ --sidebar-width: 64px;
122
+ }
123
+
124
+ /* ── Sidebar ──────────────────────────────────────────────────────────── */
125
+ .sidebar {
126
+ position: sticky;
127
+ top: 0;
128
+ height: 100vh;
129
+ padding: var(--space-7) var(--space-6) var(--space-6);
130
+ border-right: 1px solid var(--color-border);
131
+ background: var(--color-panel-muted);
132
+ display: flex;
133
+ flex-direction: column;
134
+ gap: var(--space-7);
135
+ overflow: hidden;
136
+ }
137
+
138
+ .sidebar-head {
139
+ display: flex;
140
+ align-items: flex-start;
141
+ justify-content: space-between;
142
+ gap: var(--space-2);
143
+ padding-bottom: var(--space-4-5);
144
+ border-bottom: 1px solid var(--color-border-soft);
145
+ }
146
+
147
+ .brand {
148
+ display: flex;
149
+ gap: var(--space-3);
150
+ align-items: center;
151
+ min-width: 0;
152
+ }
153
+
154
+ .brand-mark {
155
+ display: none;
156
+ width: 28px;
157
+ height: 28px;
158
+ place-items: center;
159
+ }
160
+
161
+ .brand-mark > img {
162
+ width: 28px;
163
+ height: 28px;
164
+ }
165
+
166
+ .brand-label {
167
+ display: flex;
168
+ flex-direction: column;
169
+ gap: var(--space-1);
170
+ min-width: 0;
171
+ }
172
+
173
+ .brand-wordmark {
174
+ display: inline-flex;
175
+ align-items: baseline;
176
+ font-family: var(--font-serif);
177
+ font-weight: 500;
178
+ font-style: italic;
179
+ font-size: 30px;
180
+ letter-spacing: -0.01em;
181
+ line-height: 1;
182
+ color: var(--color-text);
183
+ }
184
+
185
+ .brand-wordmark::before {
186
+ content: "";
187
+ display: inline-block;
188
+ width: 8px;
189
+ height: 8px;
190
+ background: var(--color-accent);
191
+ border-radius: 50%;
192
+ margin-right: var(--space-2);
193
+ transform: translateY(-3px);
194
+ }
195
+
196
+ .brand-kicker {
197
+ font-family: var(--font-sans);
198
+ font-size: 10px;
199
+ letter-spacing: 0.16em;
200
+ text-transform: uppercase;
201
+ color: var(--color-text-muted);
202
+ font-weight: 500;
203
+ }
204
+
205
+ .ui-sidebar-toggle {
206
+ display: inline-grid;
207
+ place-items: center;
208
+ width: 24px;
209
+ height: 24px;
210
+ padding: 0;
211
+ border: 1px solid var(--color-border);
212
+ border-radius: 50%;
213
+ background: transparent;
214
+ color: var(--color-text-muted);
215
+ font: inherit;
216
+ font-family: var(--font-sans);
217
+ font-size: var(--text-md);
218
+ line-height: 1;
219
+ cursor: pointer;
220
+ flex: none;
221
+ transition:
222
+ color var(--duration-hover) var(--ease-out),
223
+ border-color var(--duration-hover) var(--ease-out),
224
+ transform var(--duration-press) var(--ease-out);
225
+ }
226
+
227
+ .ui-sidebar-toggle:hover,
228
+ .ui-sidebar-toggle:focus-visible {
229
+ color: var(--color-text);
230
+ border-color: var(--color-text);
231
+ outline: none;
232
+ }
233
+
234
+ .ui-sidebar-toggle:active {
235
+ transform: scale(0.94);
236
+ }
237
+
238
+ .nav {
239
+ display: flex;
240
+ flex-direction: column;
241
+ gap: 2px;
242
+ }
243
+
244
+ .nav a {
245
+ display: flex;
246
+ align-items: center;
247
+ gap: var(--space-3);
248
+ padding: var(--space-2) 0;
249
+ font-family: var(--font-sans);
250
+ font-size: 13px;
251
+ font-weight: 500;
252
+ color: var(--color-text-muted);
253
+ letter-spacing: 0.005em;
254
+ transition: color 0.15s;
255
+ }
256
+
257
+ .nav-num {
258
+ font-family: var(--font-mono);
259
+ font-size: 10px;
260
+ letter-spacing: 0.04em;
261
+ width: 18px;
262
+ flex: none;
263
+ color: var(--color-text-muted);
264
+ opacity: 0.55;
265
+ }
266
+
267
+ .nav-letter {
268
+ display: none;
269
+ font-family: var(--font-sans);
270
+ font-size: 13px;
271
+ font-weight: 600;
272
+ text-transform: uppercase;
273
+ }
274
+
275
+ .nav-bar {
276
+ width: 0;
277
+ height: 1.5px;
278
+ margin-left: auto;
279
+ background: var(--color-border);
280
+ transition:
281
+ width 0.15s,
282
+ background 0.15s;
283
+ }
284
+
285
+ .nav a:hover {
286
+ color: var(--color-text);
287
+ }
288
+
289
+ .nav a.is-active {
290
+ color: var(--color-text);
291
+ font-weight: 600;
292
+ }
293
+
294
+ .nav a.is-active .nav-bar {
295
+ width: 18px;
296
+ background: var(--color-accent);
297
+ }
298
+
299
+ .sidebar-foot {
300
+ margin-top: auto;
301
+ display: flex;
302
+ flex-direction: column;
303
+ gap: var(--space-3-5);
304
+ padding-top: var(--space-3-5);
305
+ border-top: 1px solid var(--color-border-soft);
306
+ }
307
+
308
+ /* Collapsed sidebar — hide labels, center the nav numbers */
309
+ :root[data-sidebar="collapsed"] .sidebar {
310
+ padding: var(--space-4-5) var(--space-2);
311
+ align-items: center;
312
+ }
313
+
314
+ :root[data-sidebar="collapsed"] .brand-label,
315
+ :root[data-sidebar="collapsed"] .nav-label,
316
+ :root[data-sidebar="collapsed"] .nav-bar {
317
+ display: none;
318
+ }
319
+
320
+ :root[data-sidebar="collapsed"] .brand-mark {
321
+ display: grid;
322
+ }
323
+
324
+ :root[data-sidebar="collapsed"] .sidebar-head {
325
+ border-bottom: 0;
326
+ padding-bottom: 0;
327
+ flex-direction: column;
328
+ align-items: center;
329
+ gap: var(--space-3);
330
+ }
331
+
332
+ :root[data-sidebar="collapsed"] .nav {
333
+ width: 100%;
334
+ }
335
+
336
+ :root[data-sidebar="collapsed"] .nav a {
337
+ justify-content: center;
338
+ }
339
+
340
+ :root[data-sidebar="collapsed"] .nav-num {
341
+ display: none;
342
+ }
343
+
344
+ :root[data-sidebar="collapsed"] .nav-letter {
345
+ display: inline-grid;
346
+ place-items: center;
347
+ }
348
+
349
+ /* ── Main column ──────────────────────────────────────────────────────── */
350
+ .content {
351
+ width: min(1180px, 100%);
352
+ padding: var(--space-10) var(--space-11) 60px;
353
+ min-width: 0;
354
+ overflow: hidden;
355
+ }
356
+
357
+ /* ── Page header / breadcrumbs ────────────────────────────────────────── */
358
+ .page-header {
359
+ margin-bottom: var(--space-6);
360
+ }
361
+
362
+ .eyebrow,
363
+ .crumbs {
364
+ display: flex;
365
+ flex-wrap: wrap;
366
+ align-items: center;
367
+ gap: var(--space-3-5);
368
+ margin: 0 0 var(--space-3-5);
369
+ font-family: var(--font-sans);
370
+ font-size: 11px;
371
+ letter-spacing: 0.18em;
372
+ text-transform: uppercase;
373
+ color: var(--color-text-muted);
374
+ font-weight: 500;
375
+ }
376
+
377
+ .crumbs > .grow {
378
+ flex: 1;
379
+ }
380
+
381
+ .crumbs > span:not(:last-child):not(.grow)::after {
382
+ content: "·";
383
+ margin-left: var(--space-3-5);
384
+ opacity: 0.5;
385
+ }
386
+
387
+ .page-header h1 {
388
+ margin: var(--space-6) 0 var(--space-6);
389
+ font-family: var(--font-serif);
390
+ font-weight: 500;
391
+ font-size: var(--text-display);
392
+ line-height: 1;
393
+ letter-spacing: -0.025em;
394
+ }
395
+
396
+ .page-header h1 .accent-period {
397
+ font-style: italic;
398
+ color: var(--color-accent);
399
+ font-weight: 400;
400
+ }
401
+
402
+ .page-sub {
403
+ margin: var(--space-3-5) 0 0;
404
+ font-family: var(--font-sans);
405
+ font-size: 13px;
406
+ color: var(--color-text-muted);
407
+ letter-spacing: 0.01em;
408
+ }
409
+
410
+ .page-sub b {
411
+ color: var(--color-text);
412
+ font-weight: 600;
413
+ }
414
+
415
+ /* ── Filters / toolbar ────────────────────────────────────────────────── */
416
+ .toolbar {
417
+ margin-top: var(--space-8);
418
+ padding: var(--space-4-5) 0 var(--space-4);
419
+ border-top: 1.5px solid var(--color-text);
420
+ border-bottom: 1px solid var(--color-border);
421
+ display: grid;
422
+ grid-template-columns: 1.6fr repeat(4, 1fr) auto;
423
+ gap: var(--space-6);
424
+ align-items: end;
425
+ }
426
+
427
+ .content-search {
428
+ display: inline-flex;
429
+ align-items: center;
430
+ gap: var(--space-2);
431
+ margin-top: var(--space-3);
432
+ color: var(--color-text-muted);
433
+ font-family: var(--font-sans);
434
+ font-size: 12px;
435
+ }
436
+
437
+ .content-search input[type="checkbox"] {
438
+ width: 14px;
439
+ height: 14px;
440
+ accent-color: var(--color-accent);
441
+ }
442
+
443
+ .content-loading {
444
+ margin-top: var(--space-3);
445
+ font-family: var(--font-sans);
446
+ font-size: 12px;
447
+ }
448
+
449
+ /* ── Document list ────────────────────────────────────────────────────── */
450
+ .document-list {
451
+ display: block;
452
+ margin-top: var(--space-1-5);
453
+ }
454
+
455
+ .document-row {
456
+ display: grid;
457
+ grid-template-columns: 96px minmax(0, 1fr) 140px 96px;
458
+ gap: var(--space-7);
459
+ align-items: baseline;
460
+ padding: var(--space-5) 0;
461
+ border-bottom: 1px solid var(--color-border-soft);
462
+ transition: background var(--duration-hover) var(--ease-out);
463
+ }
464
+
465
+ .document-row:hover {
466
+ background: linear-gradient(
467
+ 90deg,
468
+ transparent,
469
+ var(--color-panel) 6%,
470
+ var(--color-panel) 94%,
471
+ transparent
472
+ );
473
+ }
474
+
475
+ .row-id {
476
+ display: flex;
477
+ align-items: baseline;
478
+ gap: var(--space-1-5);
479
+ font-family: var(--font-mono);
480
+ font-size: 11px;
481
+ letter-spacing: 0.06em;
482
+ color: var(--color-text-muted);
483
+ font-weight: 500;
484
+ padding-top: var(--space-1);
485
+ }
486
+
487
+ .row-main {
488
+ min-width: 0;
489
+ }
490
+
491
+ .document-title {
492
+ display: block;
493
+ font-family: var(--font-serif);
494
+ font-size: 21px;
495
+ font-weight: 500;
496
+ line-height: 1.2;
497
+ letter-spacing: -0.01em;
498
+ color: var(--color-text);
499
+ transition: color var(--duration-hover) var(--ease-out);
500
+ }
501
+
502
+ .document-title:hover {
503
+ color: var(--color-accent);
504
+ }
505
+
506
+ .row-summary {
507
+ margin: var(--space-1-5) 0 0;
508
+ font-family: var(--font-serif);
509
+ font-size: 14px;
510
+ font-style: italic;
511
+ color: var(--color-text-muted);
512
+ line-height: 1.5;
513
+ max-width: 62ch;
514
+ }
515
+
516
+ .row-status {
517
+ align-self: start;
518
+ padding-top: var(--space-1-5);
519
+ }
520
+
521
+ .row-date {
522
+ font-family: var(--font-mono);
523
+ font-size: 11px;
524
+ letter-spacing: 0.04em;
525
+ color: var(--color-text-muted);
526
+ text-align: right;
527
+ padding-top: var(--space-1-5);
528
+ font-variant-numeric: tabular-nums;
529
+ white-space: nowrap;
530
+ }
531
+
532
+ .empty-state {
533
+ margin: 0;
534
+ padding: var(--space-6) 0;
535
+ color: var(--color-text-muted);
536
+ font-style: italic;
537
+ }
538
+
539
+ .list-actions {
540
+ display: flex;
541
+ justify-content: center;
542
+ margin-top: var(--space-6);
543
+ }
544
+
545
+ /* ── Document view ────────────────────────────────────────────────────── */
546
+ .doc-kicker {
547
+ display: flex;
548
+ align-items: center;
549
+ gap: var(--space-3);
550
+ margin-top: var(--space-6);
551
+ font-family: var(--font-sans);
552
+ font-size: 11px;
553
+ letter-spacing: 0.2em;
554
+ text-transform: uppercase;
555
+ color: var(--color-text-muted);
556
+ }
557
+
558
+ .doc-status {
559
+ display: inline-flex;
560
+ align-items: center;
561
+ gap: var(--space-1-5);
562
+ border: 1px solid currentColor;
563
+ padding: var(--space-1) var(--space-2);
564
+ font-weight: 500;
565
+ }
566
+
567
+ .doc-title {
568
+ margin: var(--space-6) 0 var(--space-6);
569
+ font-family: var(--font-serif);
570
+ font-weight: 500;
571
+ font-size: var(--text-3xl);
572
+ line-height: 1.02;
573
+ letter-spacing: -0.025em;
574
+ max-width: 18ch;
575
+ }
576
+
577
+ .doc-byline {
578
+ display: flex;
579
+ flex-wrap: wrap;
580
+ gap: var(--space-4-5);
581
+ padding: var(--space-3) 0;
582
+ border-top: 1px solid var(--color-border);
583
+ border-bottom: 1px solid var(--color-border);
584
+ font-family: var(--font-sans);
585
+ font-size: 12px;
586
+ color: var(--color-text-muted);
587
+ letter-spacing: 0.02em;
588
+ }
589
+
590
+ .doc-byline b {
591
+ color: var(--color-text);
592
+ font-weight: 600;
593
+ }
594
+
595
+ .doc-byline code {
596
+ font-family: var(--font-mono);
597
+ font-size: 12px;
598
+ }
599
+
600
+ .doc-standfirst {
601
+ margin: var(--space-6) 0 0;
602
+ max-width: 62ch;
603
+ font-family: var(--font-serif);
604
+ font-size: 19px;
605
+ font-style: italic;
606
+ line-height: 1.5;
607
+ color: var(--color-text-muted);
608
+ }
609
+
610
+ .document-grid {
611
+ display: grid;
612
+ grid-template-columns: 220px minmax(0, 1fr);
613
+ gap: var(--space-12);
614
+ margin-top: var(--space-7);
615
+ align-items: start;
616
+ }
617
+
618
+ /* Meta sidebar */
619
+ .metadata-panel {
620
+ display: flex;
621
+ flex-direction: column;
622
+ gap: var(--space-6);
623
+ position: sticky;
624
+ top: var(--space-6);
625
+ align-self: start;
626
+ max-height: calc(100vh - 48px);
627
+ overflow-y: auto;
628
+ scrollbar-width: thin;
629
+ /* Recede while reading the body; restore on hover */
630
+ opacity: 0.55;
631
+ transition: opacity 0.4s ease;
632
+ }
633
+
634
+ .metadata-panel:hover,
635
+ .metadata-panel:focus-within {
636
+ opacity: 1;
637
+ transition: opacity 0.15s ease;
638
+ }
639
+
640
+ @media (max-width: 960px) {
641
+ .metadata-panel {
642
+ position: static;
643
+ max-height: none;
644
+ overflow: visible;
645
+ opacity: 1;
646
+ }
647
+ }
648
+
649
+ .meta-block {
650
+ display: flex;
651
+ flex-direction: column;
652
+ gap: var(--space-1);
653
+ }
654
+
655
+ .meta-block dt,
656
+ .meta-lbl {
657
+ font-family: var(--font-sans);
658
+ font-size: 10px;
659
+ letter-spacing: 0.18em;
660
+ text-transform: uppercase;
661
+ color: var(--color-text-muted);
662
+ font-weight: 500;
663
+ }
664
+
665
+ .meta-block dd,
666
+ .meta-val {
667
+ margin: 0;
668
+ font-family: var(--font-serif);
669
+ font-size: 14px;
670
+ color: var(--color-text);
671
+ line-height: 1.45;
672
+ overflow-wrap: anywhere;
673
+ }
674
+
675
+ .meta-val code,
676
+ .meta-block dd code {
677
+ font-family: var(--font-mono);
678
+ font-size: 12px;
679
+ word-break: break-all;
680
+ }
681
+
682
+ .metadata-panel dl {
683
+ display: flex;
684
+ flex-direction: column;
685
+ gap: var(--space-6);
686
+ margin: 0;
687
+ }
688
+
689
+ /* Connections list inside meta sidebar */
690
+ .meta-lbl .ct {
691
+ font-family: var(--font-mono);
692
+ font-size: 10px;
693
+ letter-spacing: 0;
694
+ color: var(--color-text-muted);
695
+ font-weight: 400;
696
+ opacity: 0.8;
697
+ }
698
+
699
+ .meta-links {
700
+ display: flex;
701
+ flex-direction: column;
702
+ margin-top: 2px;
703
+ }
704
+
705
+ .metalink {
706
+ display: flex;
707
+ flex-direction: column;
708
+ gap: 1px;
709
+ padding: var(--space-2) 0;
710
+ border-bottom: 1px dotted var(--color-border);
711
+ transition: color 0.12s;
712
+ }
713
+
714
+ .metalink:first-child {
715
+ padding-top: var(--space-1);
716
+ }
717
+
718
+ .metalink:last-child {
719
+ border-bottom: 0;
720
+ padding-bottom: 0;
721
+ }
722
+
723
+ .metalink .id {
724
+ font-family: var(--font-mono);
725
+ font-size: 9px;
726
+ letter-spacing: 0.08em;
727
+ text-transform: uppercase;
728
+ color: var(--color-text-muted);
729
+ }
730
+
731
+ .metalink .t {
732
+ font-family: var(--font-serif);
733
+ font-size: 13px;
734
+ line-height: 1.3;
735
+ font-weight: 500;
736
+ letter-spacing: -0.005em;
737
+ color: var(--color-text);
738
+ }
739
+
740
+ a.metalink:hover .t {
741
+ color: var(--color-accent);
742
+ }
743
+
744
+ .metalink.empty .t {
745
+ font-style: italic;
746
+ font-weight: 400;
747
+ color: var(--color-text-muted);
748
+ }
749
+
750
+ /* ── Markdown body ────────────────────────────────────────────────────── */
751
+ .markdown {
752
+ min-width: 0;
753
+ max-width: 64ch;
754
+ font-family: var(--font-serif);
755
+ font-size: 17px;
756
+ line-height: 1.65;
757
+ }
758
+
759
+ .markdown h1,
760
+ .markdown h2 {
761
+ font-family: var(--font-serif);
762
+ font-weight: 500;
763
+ font-size: 32px;
764
+ letter-spacing: -0.02em;
765
+ line-height: 1.1;
766
+ margin: var(--space-11) 0 var(--space-3-5);
767
+ position: relative;
768
+ }
769
+
770
+ .markdown h1::before,
771
+ .markdown h2::before {
772
+ content: "";
773
+ display: block;
774
+ width: 28px;
775
+ height: 2px;
776
+ background: var(--color-accent);
777
+ margin-bottom: var(--space-3-5);
778
+ }
779
+
780
+ .markdown h3 {
781
+ font-family: var(--font-serif);
782
+ font-weight: 500;
783
+ font-style: italic;
784
+ font-size: 22px;
785
+ line-height: 1.15;
786
+ margin: var(--space-8) 0 var(--space-3);
787
+ }
788
+
789
+ .markdown h4 {
790
+ font-family: var(--font-sans);
791
+ font-weight: 600;
792
+ font-size: 13px;
793
+ letter-spacing: 0.06em;
794
+ text-transform: uppercase;
795
+ margin: var(--space-6) 0 var(--space-1);
796
+ }
797
+
798
+ .markdown h1:first-child,
799
+ .markdown h2:first-child,
800
+ .markdown h3:first-child,
801
+ .markdown h4:first-child {
802
+ margin-top: 0;
803
+ }
804
+
805
+ .markdown h1:first-child::before,
806
+ .markdown h2:first-child::before {
807
+ content: none;
808
+ }
809
+
810
+ .markdown p {
811
+ margin: 0 0 var(--space-4);
812
+ }
813
+
814
+ .markdown a {
815
+ color: var(--color-accent);
816
+ text-decoration: underline;
817
+ text-underline-offset: 2px;
818
+ }
819
+
820
+ .markdown code {
821
+ font-family: var(--font-mono);
822
+ font-size: 0.85em;
823
+ background: var(--color-border-soft);
824
+ padding: 1px 5px;
825
+ border-radius: 3px;
826
+ color: var(--color-text);
827
+ }
828
+
829
+ .markdown pre {
830
+ overflow-x: auto;
831
+ padding: var(--space-4);
832
+ border: 1px solid var(--color-border);
833
+ border-radius: var(--radius-md);
834
+ background: var(--color-panel-muted);
835
+ }
836
+
837
+ .markdown pre code {
838
+ background: none;
839
+ padding: 0;
840
+ font-size: 0.85em;
841
+ }
842
+
843
+ .markdown ul,
844
+ .markdown ol {
845
+ margin: 0 0 var(--space-4-5);
846
+ padding-left: var(--space-6);
847
+ }
848
+
849
+ .markdown li {
850
+ margin-bottom: var(--space-2);
851
+ }
852
+
853
+ .markdown ul li::marker {
854
+ color: var(--color-accent);
855
+ }
856
+
857
+ .markdown ol {
858
+ list-style: none;
859
+ counter-reset: olc;
860
+ padding-left: 0;
861
+ }
862
+
863
+ .markdown ol li {
864
+ counter-increment: olc;
865
+ padding-left: var(--space-9);
866
+ position: relative;
867
+ }
868
+
869
+ .markdown ol li::before {
870
+ content: counter(olc, decimal-leading-zero);
871
+ position: absolute;
872
+ left: 0;
873
+ top: 1px;
874
+ font-family: var(--font-mono);
875
+ font-size: 12px;
876
+ font-weight: 600;
877
+ letter-spacing: 0.04em;
878
+ color: var(--color-accent);
879
+ }
880
+
881
+ .markdown blockquote {
882
+ margin: 0 0 var(--space-4-5);
883
+ padding-left: var(--space-4-5);
884
+ border-left: 2px solid var(--color-accent);
885
+ color: var(--color-text-muted);
886
+ font-style: italic;
887
+ }
888
+
889
+ .markdown table {
890
+ width: 100%;
891
+ border-collapse: collapse;
892
+ font-family: var(--font-sans);
893
+ font-size: 13px;
894
+ }
895
+
896
+ .markdown th,
897
+ .markdown td {
898
+ padding: var(--space-2) var(--space-3);
899
+ border: 1px solid var(--color-border);
900
+ text-align: left;
901
+ }
902
+
903
+ .markdown th {
904
+ background: var(--color-panel-muted);
905
+ }
906
+
907
+ /* ── Relations / chip lists (external references) ─────────────────────── */
908
+ .relations {
909
+ margin-top: var(--space-8);
910
+ padding-top: var(--space-6);
911
+ border-top: 1px solid var(--color-border);
912
+ }
913
+
914
+ .relations h2 {
915
+ margin: 0 0 var(--space-3);
916
+ font-family: var(--font-serif);
917
+ font-weight: 500;
918
+ font-size: 22px;
919
+ }
920
+
921
+ .relation-group {
922
+ margin-top: var(--space-4);
923
+ }
924
+
925
+ .relation-group-header {
926
+ display: inline-flex;
927
+ align-items: center;
928
+ gap: var(--space-2);
929
+ margin: 0 0 var(--space-2);
930
+ }
931
+
932
+ .relation-group h3 {
933
+ margin: 0;
934
+ font-family: var(--font-sans);
935
+ font-size: 11px;
936
+ letter-spacing: 0.1em;
937
+ text-transform: uppercase;
938
+ color: var(--color-text-muted);
939
+ }
940
+
941
+ .chip-list {
942
+ display: flex;
943
+ flex-wrap: wrap;
944
+ gap: var(--space-2);
945
+ }
946
+
947
+ /* ── Validation issues ────────────────────────────────────────────────── */
948
+ .issue-list {
949
+ display: flex;
950
+ flex-direction: column;
951
+ gap: var(--space-3);
952
+ margin-top: var(--space-4);
953
+ }
954
+
955
+ .issue-list.compact {
956
+ gap: var(--space-2);
957
+ }
958
+
959
+ .issue-list h2 {
960
+ margin: 0 0 var(--space-2);
961
+ font-family: var(--font-serif);
962
+ font-weight: 500;
963
+ font-size: 18px;
964
+ }
965
+
966
+ .issue {
967
+ margin: 0;
968
+ padding: var(--space-3) var(--space-4);
969
+ border-left: 2px solid var(--color-border);
970
+ background: var(--color-panel);
971
+ }
972
+
973
+ .issue div {
974
+ display: flex;
975
+ gap: var(--space-2);
976
+ align-items: center;
977
+ font-family: var(--font-sans);
978
+ font-size: 11px;
979
+ letter-spacing: 0.08em;
980
+ text-transform: uppercase;
981
+ color: var(--color-text-muted);
982
+ }
983
+
984
+ .issue p {
985
+ margin: var(--space-2) 0;
986
+ }
987
+
988
+ .issue a {
989
+ font-family: var(--font-mono);
990
+ font-size: 12px;
991
+ color: var(--color-accent);
992
+ }
993
+
994
+ .severity-error {
995
+ border-left-color: var(--color-danger);
996
+ }
997
+
998
+ .severity-warning {
999
+ border-left-color: var(--color-warning);
1000
+ }
1001
+
1002
+ /* ── Graph view ───────────────────────────────────────────────────────── */
1003
+ .graph-toolbar {
1004
+ margin-top: var(--space-8);
1005
+ margin-bottom: var(--space-4);
1006
+ padding: var(--space-4-5) 0 var(--space-4);
1007
+ border-top: 1.5px solid var(--color-text);
1008
+ border-bottom: 1px solid var(--color-border);
1009
+ display: grid;
1010
+ grid-template-columns: repeat(2, minmax(140px, 220px));
1011
+ gap: var(--space-6);
1012
+ align-items: end;
1013
+ }
1014
+
1015
+ .graph-shell {
1016
+ overflow: hidden;
1017
+ border: 1px solid var(--color-border);
1018
+ border-radius: var(--radius-md);
1019
+ background: var(--color-panel);
1020
+ }
1021
+
1022
+ .graph-legend {
1023
+ display: flex;
1024
+ flex-wrap: wrap;
1025
+ gap: var(--space-4);
1026
+ margin-top: var(--space-3);
1027
+ font-family: var(--font-sans);
1028
+ color: var(--color-text-muted);
1029
+ font-size: 12px;
1030
+ }
1031
+
1032
+ .graph-legend span {
1033
+ display: inline-flex;
1034
+ gap: var(--space-2);
1035
+ align-items: center;
1036
+ }
1037
+
1038
+ .legend-line {
1039
+ display: inline-block;
1040
+ width: 28px;
1041
+ border-top: 2px solid var(--color-text-muted);
1042
+ }
1043
+
1044
+ .legend-line.related {
1045
+ border-top-style: dashed;
1046
+ opacity: 0.7;
1047
+ }
1048
+
1049
+ .legend-line.supersession {
1050
+ border-color: var(--color-warning);
1051
+ }
1052
+
1053
+ .legend-swatch {
1054
+ display: inline-block;
1055
+ width: 14px;
1056
+ height: 14px;
1057
+ border: 1px solid var(--color-border);
1058
+ }
1059
+
1060
+ /* ── Theme + language toggles (sidebar foot) ──────────────────────────── */
1061
+ .ui-theme-toggle {
1062
+ display: inline-flex;
1063
+ gap: var(--space-1);
1064
+ margin: 0;
1065
+ padding: 0;
1066
+ border: 0;
1067
+ }
1068
+
1069
+ .ui-theme-toggle legend {
1070
+ position: absolute;
1071
+ width: 1px;
1072
+ height: 1px;
1073
+ padding: 0;
1074
+ margin: -1px;
1075
+ overflow: hidden;
1076
+ clip: rect(0, 0, 0, 0);
1077
+ white-space: nowrap;
1078
+ border: 0;
1079
+ }
1080
+
1081
+ .ui-theme-toggle label {
1082
+ display: inline-flex;
1083
+ }
1084
+
1085
+ .ui-theme-toggle input {
1086
+ position: absolute;
1087
+ width: 1px;
1088
+ height: 1px;
1089
+ opacity: 0;
1090
+ }
1091
+
1092
+ .ui-theme-toggle span {
1093
+ display: inline-grid;
1094
+ place-items: center;
1095
+ width: 24px;
1096
+ height: 24px;
1097
+ border: 1px solid var(--color-border);
1098
+ border-radius: 50%;
1099
+ color: var(--color-text-muted);
1100
+ cursor: pointer;
1101
+ font-family: var(--font-sans);
1102
+ font-size: var(--text-md);
1103
+ transition:
1104
+ background var(--duration-hover) var(--ease-out),
1105
+ color var(--duration-hover) var(--ease-out),
1106
+ border-color var(--duration-hover) var(--ease-out),
1107
+ transform var(--duration-press) var(--ease-out);
1108
+ }
1109
+
1110
+ .ui-theme-toggle label:active span {
1111
+ transform: scale(0.92);
1112
+ }
1113
+
1114
+ .ui-theme-toggle input:checked + span {
1115
+ background: var(--color-text);
1116
+ color: var(--color-bg);
1117
+ border-color: var(--color-text);
1118
+ }
1119
+
1120
+ .ui-theme-toggle input:focus-visible + span {
1121
+ outline: 2px solid var(--color-accent);
1122
+ outline-offset: 1px;
1123
+ }
1124
+
1125
+ :root[data-sidebar="collapsed"] .sidebar-foot {
1126
+ align-items: center;
1127
+ }
1128
+
1129
+ /* Language popover (scales to N languages) */
1130
+ .lang-switcher {
1131
+ position: relative;
1132
+ font-family: var(--font-sans);
1133
+ }
1134
+
1135
+ .lang-trigger {
1136
+ display: flex;
1137
+ align-items: center;
1138
+ gap: var(--space-2);
1139
+ padding: var(--space-1) 0;
1140
+ border: 0;
1141
+ background: none;
1142
+ cursor: pointer;
1143
+ font-family: inherit;
1144
+ }
1145
+
1146
+ .lang-trigger .code {
1147
+ font-size: 11px;
1148
+ letter-spacing: 0.16em;
1149
+ text-transform: uppercase;
1150
+ color: var(--color-text);
1151
+ font-weight: 500;
1152
+ border-bottom: 1px solid var(--color-accent);
1153
+ padding-bottom: 1px;
1154
+ }
1155
+
1156
+ .lang-trigger .name {
1157
+ font-family: var(--font-serif);
1158
+ font-size: 11px;
1159
+ font-style: italic;
1160
+ color: var(--color-text-muted);
1161
+ }
1162
+
1163
+ .lang-trigger .caret {
1164
+ font-size: 9px;
1165
+ color: var(--color-text-muted);
1166
+ }
1167
+
1168
+ .lang-menu {
1169
+ position: absolute;
1170
+ bottom: calc(100% + var(--space-1-5));
1171
+ left: 0;
1172
+ z-index: 10;
1173
+ min-width: 168px;
1174
+ max-height: 220px;
1175
+ overflow-y: auto;
1176
+ display: flex;
1177
+ flex-direction: column;
1178
+ padding: var(--space-1) 0;
1179
+ background: var(--color-panel);
1180
+ border: 1px solid var(--color-border);
1181
+ box-shadow: var(--shadow-md);
1182
+ transform-origin: bottom left;
1183
+ transition:
1184
+ opacity var(--duration-popover) var(--ease-out),
1185
+ transform var(--duration-popover) var(--ease-out);
1186
+
1187
+ @starting-style {
1188
+ opacity: 0;
1189
+ transform: scale(0.96) translateY(4px);
1190
+ }
1191
+ }
1192
+
1193
+ .lang-menu button {
1194
+ display: flex;
1195
+ align-items: baseline;
1196
+ gap: var(--space-3);
1197
+ padding: var(--space-2) var(--space-3);
1198
+ border: 0;
1199
+ background: none;
1200
+ text-align: left;
1201
+ cursor: pointer;
1202
+ transition: background var(--duration-hover) var(--ease-out);
1203
+ }
1204
+
1205
+ .lang-menu button:hover {
1206
+ background: var(--color-panel-muted);
1207
+ }
1208
+
1209
+ .lang-menu .code {
1210
+ width: 22px;
1211
+ font-family: var(--font-sans);
1212
+ font-size: 10px;
1213
+ font-weight: 600;
1214
+ letter-spacing: 0.14em;
1215
+ text-transform: uppercase;
1216
+ color: var(--color-text);
1217
+ }
1218
+
1219
+ .lang-menu .name {
1220
+ font-family: var(--font-serif);
1221
+ font-style: italic;
1222
+ font-size: 13px;
1223
+ color: var(--color-text-muted);
1224
+ }
1225
+
1226
+ .lang-menu button.is-active .name {
1227
+ color: var(--color-text);
1228
+ }
1229
+
1230
+ :root[data-sidebar="collapsed"] .lang-switcher .name,
1231
+ :root[data-sidebar="collapsed"] .lang-trigger .caret {
1232
+ display: none;
1233
+ }
1234
+
1235
+ /* Theme control — circular toggle expanded, dropdown collapsed */
1236
+ .theme-control {
1237
+ display: contents;
1238
+ }
1239
+
1240
+ .theme-dropdown {
1241
+ display: none;
1242
+ position: relative;
1243
+ }
1244
+
1245
+ .theme-trigger {
1246
+ display: inline-grid;
1247
+ place-items: center;
1248
+ width: 24px;
1249
+ height: 24px;
1250
+ border: 1px solid var(--color-border);
1251
+ border-radius: 50%;
1252
+ background: var(--color-text);
1253
+ color: var(--color-bg);
1254
+ font-family: var(--font-sans);
1255
+ font-size: var(--text-md);
1256
+ cursor: pointer;
1257
+ transition: transform var(--duration-press) var(--ease-out);
1258
+ }
1259
+
1260
+ .theme-trigger:active {
1261
+ transform: scale(0.94);
1262
+ }
1263
+
1264
+ .theme-menu {
1265
+ position: absolute;
1266
+ bottom: calc(100% + var(--space-1-5));
1267
+ left: 0;
1268
+ z-index: 10;
1269
+ display: flex;
1270
+ flex-direction: column;
1271
+ min-width: 140px;
1272
+ padding: var(--space-1) 0;
1273
+ background: var(--color-panel);
1274
+ border: 1px solid var(--color-border);
1275
+ box-shadow: var(--shadow-md);
1276
+ transform-origin: bottom left;
1277
+ transition:
1278
+ opacity var(--duration-popover) var(--ease-out),
1279
+ transform var(--duration-popover) var(--ease-out);
1280
+
1281
+ @starting-style {
1282
+ opacity: 0;
1283
+ transform: scale(0.96) translateY(4px);
1284
+ }
1285
+ }
1286
+
1287
+ .theme-menu button {
1288
+ display: flex;
1289
+ align-items: center;
1290
+ gap: var(--space-3);
1291
+ padding: var(--space-2) var(--space-3);
1292
+ border: 0;
1293
+ background: none;
1294
+ text-align: left;
1295
+ cursor: pointer;
1296
+ color: var(--color-text-muted);
1297
+ transition:
1298
+ background var(--duration-hover) var(--ease-out),
1299
+ color var(--duration-hover) var(--ease-out);
1300
+ }
1301
+
1302
+ .theme-menu button:hover {
1303
+ background: var(--color-panel-muted);
1304
+ }
1305
+
1306
+ .theme-menu button.is-active {
1307
+ color: var(--color-text);
1308
+ }
1309
+
1310
+ .theme-menu .sym {
1311
+ width: 16px;
1312
+ text-align: center;
1313
+ font-family: var(--font-sans);
1314
+ }
1315
+
1316
+ .theme-menu .name {
1317
+ font-family: var(--font-serif);
1318
+ font-style: italic;
1319
+ font-size: 13px;
1320
+ }
1321
+
1322
+ :root[data-sidebar="collapsed"] .ui-theme-toggle {
1323
+ display: none;
1324
+ }
1325
+
1326
+ :root[data-sidebar="collapsed"] .theme-dropdown {
1327
+ display: block;
1328
+ }
1329
+
1330
+ /* ── Responsive ───────────────────────────────────────────────────────── */
1331
+ @media (max-width: 960px) {
1332
+ .document-grid {
1333
+ grid-template-columns: 1fr;
1334
+ gap: var(--space-7);
1335
+ }
1336
+ }
1337
+
1338
+ @media (max-width: 860px) {
1339
+ .app-shell {
1340
+ grid-template-columns: 1fr;
1341
+ }
1342
+
1343
+ .sidebar {
1344
+ position: static;
1345
+ height: auto;
1346
+ flex-direction: column;
1347
+ border-right: 0;
1348
+ border-bottom: 1px solid var(--color-border);
1349
+ }
1350
+
1351
+ .content {
1352
+ padding: var(--space-6);
1353
+ }
1354
+
1355
+ .page-header h1 {
1356
+ font-size: 44px;
1357
+ }
1358
+
1359
+ .toolbar,
1360
+ .graph-toolbar {
1361
+ grid-template-columns: 1fr;
1362
+ gap: var(--space-4);
1363
+ }
1364
+
1365
+ .document-row {
1366
+ grid-template-columns: 1fr auto;
1367
+ gap: var(--space-2) var(--space-4);
1368
+ }
1369
+
1370
+ .row-id {
1371
+ grid-column: 1 / -1;
1372
+ }
1373
+
1374
+ .row-date {
1375
+ grid-column: 1 / -1;
1376
+ text-align: left;
1377
+ }
1378
+ }
1379
+
1380
+ /* ── Reduced motion ───────────────────────────────────────────────────── */
1381
+ /* Keep opacity/color transitions (aid comprehension); drop movement. */
1382
+ @media (prefers-reduced-motion: reduce) {
1383
+ *,
1384
+ *::before,
1385
+ *::after {
1386
+ transition-duration: 0.01ms !important;
1387
+ animation-duration: 0.01ms !important;
1388
+ animation-iteration-count: 1 !important;
1389
+ scroll-behavior: auto !important;
1390
+ }
1391
+ }