@kenjura/ursa 0.76.0 → 0.77.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 (34) hide show
  1. package/CHANGELOG.md +35 -17
  2. package/meta/default.css +33 -0
  3. package/meta/templates/default-template/default.css +1268 -0
  4. package/meta/{default-template.html → templates/default-template/index.html} +15 -0
  5. package/meta/{menu.js → templates/default-template/menu.js} +1 -1
  6. package/meta/templates/default-template/sectionify.js +46 -0
  7. package/meta/{widgets.js → templates/default-template/widgets.js} +126 -0
  8. package/package.json +1 -1
  9. package/src/dev.js +73 -28
  10. package/src/helper/assetBundler.js +471 -0
  11. package/src/helper/build/autoIndex.js +24 -23
  12. package/src/helper/build/cacheBust.js +79 -0
  13. package/src/helper/build/navCache.js +4 -0
  14. package/src/helper/build/templates.js +176 -19
  15. package/src/helper/build/watchCache.js +7 -0
  16. package/src/helper/customMenu.js +4 -2
  17. package/src/helper/dependencyTracker.js +269 -0
  18. package/src/helper/findStyleCss.js +29 -0
  19. package/src/helper/portUtils.js +132 -0
  20. package/src/jobs/generate.js +228 -60
  21. package/src/serve.js +446 -162
  22. package/meta/character-sheet.css +0 -50
  23. /package/meta/{goudy_bookletter_1911-webfont.woff → shared/goudy_bookletter_1911-webfont.woff} +0 -0
  24. /package/meta/{character-sheet/css → templates/character-sheet-template}/character-sheet.css +0 -0
  25. /package/meta/{character-sheet/js → templates/character-sheet-template}/components.js +0 -0
  26. /package/meta/{cssui.bundle.min.css → templates/character-sheet-template/cssui.bundle.min.css} +0 -0
  27. /package/meta/{character-sheet-template.html → templates/character-sheet-template/index.html} +0 -0
  28. /package/meta/{character-sheet/js → templates/character-sheet-template}/main.js +0 -0
  29. /package/meta/{character-sheet/js → templates/character-sheet-template}/model.js +0 -0
  30. /package/meta/{search.js → templates/default-template/search.js} +0 -0
  31. /package/meta/{sticky.js → templates/default-template/sticky.js} +0 -0
  32. /package/meta/{toc-generator.js → templates/default-template/toc-generator.js} +0 -0
  33. /package/meta/{toc.js → templates/default-template/toc.js} +0 -0
  34. /package/meta/{template2.html → templates/template2/index.html} +0 -0
@@ -0,0 +1,1268 @@
1
+ body, html {
2
+ margin: 0;
3
+ padding: 0;
4
+ }
5
+ body {
6
+ font-family: sans-serif;
7
+ }
8
+
9
+ :root {
10
+ --article-width: 50rem;
11
+ --global-nav-height: 48px;
12
+ --twisty-size: 1.1rem;
13
+ }
14
+
15
+ @media (prefers-color-scheme: dark) {
16
+ :root {
17
+ --bg-color: #121212;
18
+ --text-color: #f2f2f2;
19
+ --nav-top-bg: #242424;
20
+ --widget-bg: #242424;
21
+ --widget-border: #3a3a3a;
22
+ }
23
+ }
24
+
25
+ @media (prefers-color-scheme: light) {
26
+ :root {
27
+ --bg-color: white;
28
+ --text-color: black;
29
+ --nav-top-bg: #f2f2f2;
30
+ --widget-bg: #f2f2f2;
31
+ --widget-border: #ddd;
32
+ }
33
+ }
34
+
35
+ body {
36
+ background: var(--bg-color);
37
+ color: var(--text-color);
38
+ }
39
+
40
+ /* Inactive/broken links */
41
+ a.inactive {
42
+ filter: brightness(0.5);
43
+ cursor: not-allowed;
44
+ text-decoration: line-through;
45
+ }
46
+
47
+ h1 {
48
+ max-width: var(--article-width);
49
+ overflow: hidden ;
50
+ text-overflow: ellipsis;
51
+ }
52
+
53
+ nav#nav-global {
54
+ background-color: var(--nav-top-bg);
55
+ height: var(--global-nav-height);
56
+ position: fixed;
57
+ top: 0;
58
+ left: 0;
59
+ width: 100vw;
60
+ display: grid;
61
+ grid-template-columns: 1fr var(--article-width) 1fr;
62
+ align-items: center;
63
+ padding: 0 8px;
64
+ box-sizing: border-box;
65
+ z-index: 1001;
66
+
67
+ button.menu-button {
68
+ color: var(--text-color);
69
+ font-size: calc(var(--global-nav-height) / 2);
70
+ line-height: 1;
71
+ padding: 8px;
72
+ background: none;
73
+ border: none;
74
+ cursor: pointer;
75
+ }
76
+ button.menu-button:hover {
77
+ opacity: 0.7;
78
+ }
79
+
80
+ /* Left controls: menu button + left-side widgets */
81
+ .nav-left-controls {
82
+ display: flex;
83
+ align-items: center;
84
+ justify-self: start;
85
+ gap: 0;
86
+ }
87
+
88
+ /* Center container for search and top menu */
89
+ .nav-center {
90
+ width: calc(var(--article-width) + 38px);
91
+ justify-self: center;
92
+ position: relative;
93
+ }
94
+
95
+ .search-wrapper {
96
+ position: relative;
97
+ width: 100%;
98
+ }
99
+
100
+ input#global-search {
101
+ width: 100%;
102
+ height: calc(var(--global-nav-height) - 16px);
103
+ border-radius: 5px;
104
+ background: rgba(0,0,0,0.25);
105
+ color: var(--text-color);
106
+ border-width: 0px;
107
+ padding: 0 2.5rem 0 1rem;
108
+ box-sizing: border-box;
109
+ }
110
+
111
+ .search-clear-button {
112
+ position: absolute;
113
+ right: 8px;
114
+ top: 50%;
115
+ transform: translateY(-50%);
116
+ background: none;
117
+ border: none;
118
+ color: var(--text-color);
119
+ font-size: 1.25rem;
120
+ line-height: 1;
121
+ cursor: pointer;
122
+ padding: 4px 8px;
123
+ opacity: 0.6;
124
+ transition: opacity 0.2s ease;
125
+ }
126
+
127
+ .search-clear-button:hover {
128
+ opacity: 1;
129
+ }
130
+
131
+ .search-clear-button.hidden {
132
+ display: none;
133
+ }
134
+ }
135
+
136
+ /* ==========================================
137
+ WIDGET SYSTEM STYLES
138
+ Nav widgets (TOC, Search, Profile, Recent Activity)
139
+ ========================================== */
140
+
141
+ /* Widget bar in the nav right column */
142
+ nav#nav-global .nav-right-controls {
143
+ display: flex;
144
+ align-items: center;
145
+ justify-self: end;
146
+ gap: 0;
147
+ }
148
+
149
+ .widget-bar {
150
+ display: flex;
151
+ align-items: center;
152
+ gap: 0;
153
+ }
154
+
155
+ /* Ursa update indicator (loading spinner in nav bar) */
156
+ .ursa-update-indicator {
157
+ display: none;
158
+ align-items: center;
159
+ justify-content: center;
160
+ width: var(--global-nav-height);
161
+ height: var(--global-nav-height);
162
+ opacity: 0.7;
163
+ }
164
+ .ursa-spinner {
165
+ width: 14px;
166
+ height: 14px;
167
+ border: 2px solid rgba(128, 128, 128, 0.3);
168
+ border-top-color: rgba(128, 128, 128, 0.8);
169
+ border-radius: 50%;
170
+ animation: ursa-spin 0.8s linear infinite;
171
+ }
172
+ .ursa-update-gray .ursa-spinner {
173
+ border-color: rgba(128, 128, 128, 0.3);
174
+ border-top-color: rgba(128, 128, 128, 0.8);
175
+ }
176
+ .ursa-update-green .ursa-spinner {
177
+ border-color: rgba(76, 175, 80, 0.3);
178
+ border-top-color: rgba(76, 175, 80, 0.9);
179
+ }
180
+ @keyframes ursa-spin {
181
+ to { transform: rotate(360deg); }
182
+ }
183
+
184
+ .widget-button {
185
+ display: flex;
186
+ align-items: center;
187
+ justify-content: center;
188
+ background: none;
189
+ border: none;
190
+ color: var(--text-color);
191
+ font-size: 1.1rem;
192
+ width: var(--global-nav-height);
193
+ height: var(--global-nav-height);
194
+ cursor: pointer;
195
+ opacity: 0.7;
196
+ transition: opacity 0.15s ease, background-color 0.15s ease;
197
+ }
198
+
199
+ .widget-button:hover {
200
+ opacity: 1;
201
+ background-color: rgba(128, 128, 128, 0.15);
202
+ }
203
+
204
+ .widget-button.active {
205
+ opacity: 1;
206
+ background-color: var(--widget-bg);
207
+ }
208
+
209
+ .widget-icon {
210
+ pointer-events: none;
211
+ }
212
+
213
+ /* Widget dropdown panel (right-side, default) */
214
+ .widget-dropdown {
215
+ position: fixed;
216
+ top: var(--global-nav-height);
217
+ right: 0;
218
+ width: min(420px, 100vw);
219
+ max-height: calc(100vh - var(--global-nav-height));
220
+ overflow-y: auto;
221
+ background: var(--widget-bg);
222
+ border-left: 1px solid var(--widget-border);
223
+ border-bottom: 1px solid var(--widget-border);
224
+ box-shadow: -2px 4px 12px rgba(0, 0, 0, 0.2);
225
+ z-index: 1100;
226
+ transition: opacity 0.15s ease;
227
+ }
228
+
229
+ /* Widget dropdown panel (left-side) */
230
+ .widget-dropdown.widget-dropdown-left {
231
+ right: auto;
232
+ left: 0;
233
+ border-left: none;
234
+ border-right: 1px solid var(--widget-border);
235
+ box-shadow: 2px 4px 12px rgba(0, 0, 0, 0.2);
236
+ }
237
+
238
+ .widget-dropdown.hidden {
239
+ display: none;
240
+ }
241
+
242
+ /* Widget header with title and close button */
243
+ .widget-header {
244
+ display: flex;
245
+ align-items: center;
246
+ justify-content: space-between;
247
+ padding: 0.5rem 0.75rem;
248
+ border-bottom: 1px solid var(--widget-border);
249
+ }
250
+
251
+ .widget-header-title {
252
+ font-weight: 600;
253
+ font-size: 0.85rem;
254
+ text-transform: uppercase;
255
+ letter-spacing: 0.03em;
256
+ opacity: 0.7;
257
+ }
258
+
259
+ .widget-close-btn {
260
+ background: none;
261
+ border: none;
262
+ color: var(--text-color);
263
+ font-size: 1rem;
264
+ cursor: pointer;
265
+ opacity: 0.5;
266
+ padding: 4px 8px;
267
+ line-height: 1;
268
+ border-radius: 3px;
269
+ transition: opacity 0.15s ease, background-color 0.15s ease;
270
+ }
271
+
272
+ .widget-close-btn:hover {
273
+ opacity: 1;
274
+ background-color: rgba(128, 128, 128, 0.2);
275
+ }
276
+
277
+ /* Widget content panels — only the active one is visible */
278
+ .widget-content {
279
+ display: none;
280
+ }
281
+
282
+ .widget-content.active {
283
+ display: block;
284
+ }
285
+
286
+ /* --- TOC Widget --- */
287
+ #widget-content-toc {
288
+ padding: 0.5rem 0;
289
+
290
+ ul {
291
+ list-style: none;
292
+ margin: 0;
293
+ padding: 0;
294
+
295
+ li {
296
+ margin-bottom: 0.15rem;
297
+ padding: 0;
298
+
299
+ > a {
300
+ text-decoration: none;
301
+ color: var(--text-color);
302
+ opacity: 0.75;
303
+ display: block;
304
+ padding: 0.3rem 1rem;
305
+ border-left: 2px solid transparent;
306
+ transition: all 0.2s ease;
307
+ font-size: 0.9rem;
308
+ }
309
+
310
+ > a:hover {
311
+ opacity: 1;
312
+ border-left-color: var(--text-color);
313
+ background-color: rgba(128, 128, 128, 0.1);
314
+ }
315
+
316
+ > a.active {
317
+ opacity: 1;
318
+ border-left-color: aqua;
319
+ background-color: rgba(0, 255, 255, 0.1);
320
+ }
321
+
322
+ /* Indent nested headings */
323
+ &.toc-h1 > a {
324
+ padding-left: 1rem;
325
+ font-weight: 600;
326
+ }
327
+
328
+ &.toc-h2 > a {
329
+ padding-left: 1.5rem;
330
+ font-size: 0.85rem;
331
+ }
332
+
333
+ &.toc-h3 > a {
334
+ padding-left: 2rem;
335
+ font-size: 0.8rem;
336
+ }
337
+ }
338
+ }
339
+ }
340
+
341
+ /* --- Search Widget --- */
342
+ .widget-search-wrapper {
343
+ padding: 0.5rem;
344
+ }
345
+
346
+ .widget-search-input {
347
+ width: 100%;
348
+ height: 40px;
349
+ border-radius: 5px;
350
+ background: rgba(0, 0, 0, 0.15);
351
+ color: var(--text-color);
352
+ border: 1px solid var(--widget-border);
353
+ padding: 0 1rem;
354
+ box-sizing: border-box;
355
+ font-size: 1rem;
356
+ }
357
+
358
+ .widget-search-input:focus {
359
+ outline: none;
360
+ border-color: aqua;
361
+ box-shadow: 0 0 0 2px rgba(0, 255, 255, 0.2);
362
+ }
363
+
364
+ .widget-search-results {
365
+ max-height: calc(100vh - var(--global-nav-height) - 80px);
366
+ overflow-y: auto;
367
+ }
368
+
369
+ .widget-search-results .search-result-item {
370
+ padding: 10px 12px;
371
+ border-bottom: 1px solid var(--widget-border);
372
+ cursor: pointer;
373
+ transition: background-color 0.15s ease;
374
+ }
375
+
376
+ .widget-search-results .search-result-item:last-child {
377
+ border-bottom: none;
378
+ }
379
+
380
+ .widget-search-results .search-result-item:hover,
381
+ .widget-search-results .search-result-item.selected {
382
+ background-color: rgba(128, 128, 128, 0.15);
383
+ }
384
+
385
+ .widget-search-results .search-result-title {
386
+ font-weight: 600;
387
+ margin-bottom: 2px;
388
+ color: var(--text-color);
389
+ font-size: 0.9rem;
390
+ }
391
+
392
+ .widget-search-results .search-result-path {
393
+ font-size: 0.8rem;
394
+ color: var(--text-color);
395
+ opacity: 0.6;
396
+ }
397
+
398
+ .widget-search-results .search-result-message {
399
+ padding: 12px;
400
+ text-align: center;
401
+ color: var(--text-color);
402
+ opacity: 0.6;
403
+ font-style: italic;
404
+ font-size: 0.85rem;
405
+ }
406
+
407
+ .widget-search-results .search-section-header {
408
+ padding: 6px 12px;
409
+ font-size: 0.7em;
410
+ font-weight: 600;
411
+ text-transform: uppercase;
412
+ letter-spacing: 0.5px;
413
+ color: var(--text-color);
414
+ opacity: 0.5;
415
+ background-color: rgba(128, 128, 128, 0.1);
416
+ border-bottom: 1px solid var(--widget-border);
417
+ }
418
+
419
+ /* --- Profile Widget --- */
420
+ .widget-profile-placeholder {
421
+ display: flex;
422
+ flex-direction: column;
423
+ align-items: center;
424
+ padding: 2rem 1rem;
425
+ text-align: center;
426
+ color: var(--text-color);
427
+ opacity: 0.7;
428
+ }
429
+
430
+ .widget-profile-avatar {
431
+ font-size: 3rem;
432
+ margin-bottom: 1rem;
433
+ }
434
+
435
+ .widget-profile-placeholder p {
436
+ margin: 0.5rem 0;
437
+ font-size: 0.9rem;
438
+ }
439
+
440
+ .widget-profile-signin {
441
+ margin-top: 0.5rem;
442
+ padding: 8px 24px;
443
+ background: var(--nav-top-bg);
444
+ border: 1px solid var(--widget-border);
445
+ color: var(--text-color);
446
+ border-radius: 4px;
447
+ cursor: not-allowed;
448
+ opacity: 0.5;
449
+ }
450
+
451
+ .widget-profile-note {
452
+ font-size: 0.75rem;
453
+ opacity: 0.5;
454
+ font-style: italic;
455
+ }
456
+
457
+ /* --- Recent Activity Widget --- */
458
+ .recent-activity-list {
459
+ padding: 0;
460
+ }
461
+
462
+ .recent-activity-loading,
463
+ .recent-activity-empty {
464
+ padding: 1.5rem 1rem;
465
+ text-align: center;
466
+ color: var(--text-color);
467
+ opacity: 0.6;
468
+ font-style: italic;
469
+ font-size: 0.85rem;
470
+ }
471
+
472
+ .recent-activity-items {
473
+ list-style: none;
474
+ margin: 0;
475
+ padding: 0;
476
+ }
477
+
478
+ .recent-activity-item {
479
+ display: flex;
480
+ align-items: baseline;
481
+ justify-content: space-between;
482
+ gap: 0.75rem;
483
+ padding: 0.5rem 0.75rem;
484
+ border-bottom: 1px solid var(--widget-border);
485
+ transition: background-color 0.15s ease;
486
+ }
487
+
488
+ .recent-activity-item:last-child {
489
+ border-bottom: none;
490
+ }
491
+
492
+ .recent-activity-item:hover {
493
+ background-color: rgba(128, 128, 128, 0.1);
494
+ }
495
+
496
+ .recent-activity-link {
497
+ color: var(--text-color);
498
+ text-decoration: none;
499
+ font-size: 0.9rem;
500
+ flex: 1;
501
+ min-width: 0;
502
+ overflow: hidden;
503
+ text-overflow: ellipsis;
504
+ white-space: nowrap;
505
+ }
506
+
507
+ .recent-activity-link:hover {
508
+ text-decoration: underline;
509
+ }
510
+
511
+ .recent-activity-time {
512
+ font-size: 0.75rem;
513
+ color: var(--text-color);
514
+ opacity: 0.5;
515
+ white-space: nowrap;
516
+ flex-shrink: 0;
517
+ }
518
+
519
+ /* Suggested Content Widget Styles */
520
+ .suggested-content-list {
521
+ padding: 0;
522
+ }
523
+
524
+ .suggested-empty {
525
+ padding: 1rem 0.75rem;
526
+ text-align: center;
527
+ color: var(--text-color);
528
+ opacity: 0.6;
529
+ font-style: italic;
530
+ font-size: 0.85rem;
531
+ }
532
+
533
+ .suggested-items {
534
+ list-style: none;
535
+ margin: 0;
536
+ padding: 0;
537
+ }
538
+
539
+ .suggested-item {
540
+ display: flex;
541
+ align-items: baseline;
542
+ justify-content: space-between;
543
+ gap: 0.75rem;
544
+ padding: 0.5rem 0.75rem;
545
+ border-bottom: 1px solid var(--widget-border);
546
+ transition: background-color 0.15s ease;
547
+ }
548
+
549
+ .suggested-item:last-child {
550
+ border-bottom: none;
551
+ }
552
+
553
+ .suggested-item:hover {
554
+ background-color: rgba(128, 128, 128, 0.1);
555
+ }
556
+
557
+ .suggested-link {
558
+ color: var(--text-color);
559
+ text-decoration: none;
560
+ font-size: 0.9rem;
561
+ flex: 1;
562
+ min-width: 0;
563
+ overflow: hidden;
564
+ text-overflow: ellipsis;
565
+ white-space: nowrap;
566
+ }
567
+
568
+ .suggested-link:hover {
569
+ text-decoration: underline;
570
+ }
571
+
572
+ .suggested-meta {
573
+ font-size: 0.75rem;
574
+ color: var(--text-color);
575
+ opacity: 0.5;
576
+ white-space: nowrap;
577
+ flex-shrink: 0;
578
+ }
579
+
580
+ /* Search functionality styles */
581
+ .search-results {
582
+ position: fixed;
583
+ top: calc(var(--global-nav-height) + 4px);
584
+ left: 50%;
585
+ transform: translateX(-50%);
586
+ width: min(var(--article-width), calc(100vw - 100px));
587
+ background: var(--bg-color);
588
+ border: 1px solid var(--nav-top-bg);
589
+ border-radius: 5px;
590
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
591
+ max-height: 400px;
592
+ overflow-y: auto;
593
+ z-index: 1002;
594
+ }
595
+
596
+ .search-results.hidden {
597
+ display: none;
598
+ }
599
+
600
+ .search-result-item {
601
+ padding: 12px 16px;
602
+ border-bottom: 1px solid var(--nav-top-bg);
603
+ cursor: pointer;
604
+ transition: background-color 0.2s ease;
605
+ }
606
+
607
+ .search-result-item:last-child {
608
+ border-bottom: none;
609
+ }
610
+
611
+ .search-result-item:hover,
612
+ .search-result-item.selected {
613
+ background-color: var(--nav-top-bg);
614
+ }
615
+
616
+ .search-result-title {
617
+ font-weight: 600;
618
+ margin-bottom: 4px;
619
+ color: var(--text-color);
620
+ }
621
+
622
+ .search-result-path {
623
+ font-size: 0.85em;
624
+ color: var(--text-color);
625
+ opacity: 0.7;
626
+ }
627
+
628
+ .search-result-message {
629
+ padding: 16px;
630
+ text-align: center;
631
+ color: var(--text-color);
632
+ opacity: 0.7;
633
+ font-style: italic;
634
+ }
635
+
636
+ /* Search section styling (for combined path/full-text results) */
637
+ .search-section {
638
+ border-bottom: 1px solid var(--nav-top-bg);
639
+ }
640
+
641
+ .search-section:last-child {
642
+ border-bottom: none;
643
+ }
644
+
645
+ .search-section-header {
646
+ padding: 8px 16px;
647
+ font-size: 0.75em;
648
+ font-weight: 600;
649
+ text-transform: uppercase;
650
+ letter-spacing: 0.5px;
651
+ color: var(--text-color);
652
+ opacity: 0.6;
653
+ background-color: color-mix(in srgb, var(--nav-top-bg) 50%, transparent);
654
+ border-bottom: 1px solid var(--nav-top-bg);
655
+ }
656
+
657
+ .search-show-more {
658
+ display: block;
659
+ width: 100%;
660
+ padding: 8px 16px;
661
+ background: transparent;
662
+ border: none;
663
+ color: var(--link-color);
664
+ font-size: 0.85em;
665
+ cursor: pointer;
666
+ text-align: center;
667
+ transition: background-color 0.2s ease;
668
+ }
669
+
670
+ .search-show-more:hover {
671
+ background-color: var(--nav-top-bg);
672
+ text-decoration: underline;
673
+ }
674
+
675
+ /* ==========================================
676
+ TOP NAVIGATION MENU STYLES
677
+ When body[data-menu-position="top"] is set
678
+ ========================================== */
679
+
680
+ /* Top menu container - positioning handled by parent .nav-center */
681
+ nav#nav-main-top {
682
+ display: none;
683
+ width: 100%;
684
+ }
685
+
686
+ /* Show top menu when position is top */
687
+ body[data-menu-position="top"] nav#nav-main-top {
688
+ display: flex;
689
+ align-items: center;
690
+ }
691
+
692
+ /* Hide inline search when top menu is present — widget handles search */
693
+ body[data-menu-position="top"] nav#nav-global .search-wrapper-inline {
694
+ display: none;
695
+ }
696
+
697
+ /* Hide side nav when top menu is active */
698
+ body[data-menu-position="top"] nav#nav-main {
699
+ display: none;
700
+ }
701
+
702
+ /* Full-width article when side nav is hidden */
703
+ body[data-menu-position="top"] article#main-content {
704
+ margin-left: auto;
705
+ margin-right: auto;
706
+ }
707
+
708
+ /* Update nav-global grid to accommodate top menu - keep search+avatar together on right */
709
+ body[data-menu-position="top"] nav#nav-global {
710
+ grid-template-columns: 1fr var(--article-width) 1fr;
711
+ }
712
+
713
+ /* Top-level menu list */
714
+ nav#nav-main-top .top-menu-level {
715
+ display: flex;
716
+ list-style: none;
717
+ margin: 0;
718
+ padding: 0;
719
+ gap: 0;
720
+ }
721
+
722
+ /* Top-level menu items */
723
+ nav#nav-main-top .top-menu-item {
724
+ position: relative;
725
+ padding: 0;
726
+ margin: 0;
727
+ }
728
+
729
+ nav#nav-main-top .top-menu-label {
730
+ display: block;
731
+ padding: 0px 16px;
732
+ line-height: var(--global-nav-height);
733
+ color: var(--text-color);
734
+ text-decoration: none;
735
+ white-space: nowrap;
736
+ cursor: pointer;
737
+ transition: background-color 0.15s ease;
738
+ }
739
+
740
+ nav#nav-main-top .top-menu-label:hover {
741
+ background-color: rgba(255, 255, 255, 0.1);
742
+ }
743
+
744
+ nav#nav-main-top a.top-menu-label:hover {
745
+ text-decoration: none;
746
+ }
747
+
748
+ /* Dropdown indicator for items with children */
749
+ nav#nav-main-top .top-menu-item.has-dropdown > .top-menu-label::after {
750
+ content: '▼';
751
+ font-size: 0.4em;
752
+ margin-left: 6px;
753
+ opacity: 0.6;
754
+ vertical-align: bottom;
755
+ }
756
+
757
+ /* Use widget-bg for dropdown/flyout backgrounds (shared CSS var) */
758
+ nav#nav-main-top .top-menu-dropdown {
759
+ display: none;
760
+ position: absolute;
761
+ top: 100%;
762
+ left: 0;
763
+ min-width: 200px;
764
+ max-height: calc(100vh - var(--global-nav-height) - 20px);
765
+ overflow-y: auto;
766
+ background-color: var(--widget-bg);
767
+ border: 1px solid var(--widget-border);
768
+ border-radius: 4px;
769
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
770
+ list-style: none;
771
+ margin: 0;
772
+ padding: 0;
773
+ z-index: 1005;
774
+ }
775
+
776
+ /* Show dropdown on hover */
777
+ nav#nav-main-top .top-menu-item.has-dropdown:hover > .top-menu-dropdown {
778
+ display: block;
779
+ }
780
+
781
+ /* Dropdown items */
782
+ nav#nav-main-top .dropdown-item {
783
+ position: relative;
784
+ }
785
+
786
+ nav#nav-main-top .dropdown-label {
787
+ display: flex;
788
+ align-items: center;
789
+ justify-content: space-between;
790
+ padding: 8px 16px;
791
+ color: var(--text-color);
792
+ text-decoration: none;
793
+ white-space: nowrap;
794
+ cursor: pointer;
795
+ transition: background-color 0.15s ease;
796
+ }
797
+
798
+ nav#nav-main-top .dropdown-label:hover {
799
+ background-color: var(--nav-top-bg);
800
+ }
801
+
802
+ nav#nav-main-top a.dropdown-label:hover {
803
+ text-decoration: none;
804
+ }
805
+
806
+ /* Flyout indicator */
807
+ nav#nav-main-top .flyout-indicator {
808
+ font-size: 0.7em;
809
+ opacity: 0.6;
810
+ margin-left: 8px;
811
+ }
812
+
813
+ /* Flyout menu (nested children) */
814
+ nav#nav-main-top .top-menu-flyout {
815
+ display: none;
816
+ position: absolute;
817
+ left: 100%;
818
+ top: -1px;
819
+ min-width: 200px;
820
+ max-height: calc(100vh - var(--global-nav-height) - 20px);
821
+ overflow-y: auto;
822
+ background-color: var(--widget-bg);
823
+ border: 1px solid var(--widget-border);
824
+ border-radius: 4px;
825
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
826
+ list-style: none;
827
+ margin: 0;
828
+ padding: 0;
829
+ z-index: 1006;
830
+ }
831
+
832
+ /* Show flyout on hover */
833
+ nav#nav-main-top .dropdown-item.has-flyout:hover > .top-menu-flyout {
834
+ display: block;
835
+ }
836
+
837
+ nav#nav-main {
838
+ position: fixed;
839
+ top: calc(var(--global-nav-height));
840
+ left: 0;
841
+ width: 260px;
842
+ max-height: calc(100vh - var(--global-nav-height));
843
+ overflow: hidden;
844
+ padding: 0;
845
+ font-size: 0.85rem;
846
+ transition: transform 0.2s ease;
847
+ }
848
+
849
+ /* Collapsed state for desktop - slide off screen */
850
+ nav#nav-main.collapsed {
851
+ transform: translateX(-100%);
852
+ }
853
+
854
+ /* When nav is collapsed, article can use full width */
855
+ body:has(nav#nav-main.collapsed) article#main-content {
856
+ margin-left: auto;
857
+ margin-right: auto;
858
+ }
859
+
860
+ nav#nav-main {
861
+ /* Column-based menu styles */
862
+
863
+ .menu-loading {
864
+ padding: 1rem;
865
+ opacity: 0.6;
866
+ text-align: center;
867
+ }
868
+
869
+ /* Container that clips the columns */
870
+ .menu-columns-container {
871
+ width: 100%;
872
+ height: calc(100vh - var(--global-nav-height) - 40px);
873
+ overflow: hidden;
874
+ position: relative;
875
+ }
876
+
877
+ /* Wrapper that holds all columns and transforms for scrolling */
878
+ .menu-columns-wrapper {
879
+ display: flex;
880
+ height: 100%;
881
+ min-height: 0; /* Allow flex children to shrink */
882
+ transition: transform 0.25s ease-out;
883
+ }
884
+
885
+ /* Individual column */
886
+ .menu-column {
887
+ width: 130px;
888
+ min-width: 130px;
889
+ flex-shrink: 0;
890
+ height: 100%;
891
+ min-height: 0; /* Allow flex child to shrink and enable scrolling */
892
+ overflow-y: auto;
893
+ overflow-x: hidden;
894
+ border-right: 1px solid rgba(128, 128, 128, 0.15);
895
+
896
+ /* Scrollbar styling */
897
+ &::-webkit-scrollbar {
898
+ width: 4px;
899
+ }
900
+ &::-webkit-scrollbar-track {
901
+ background: transparent;
902
+ }
903
+ &::-webkit-scrollbar-thumb {
904
+ background: rgba(128, 128, 128, 0.2);
905
+ border-radius: 2px;
906
+ }
907
+ &::-webkit-scrollbar-thumb:hover {
908
+ background: rgba(128, 128, 128, 0.4);
909
+ }
910
+ }
911
+
912
+ .menu-column:last-child {
913
+ border-right: none;
914
+ }
915
+
916
+ /* Column list */
917
+ .menu-column-list {
918
+ list-style: none;
919
+ margin: 0;
920
+ padding: 4px 0;
921
+ }
922
+
923
+ /* Column item */
924
+ .menu-column-item {
925
+ margin: 0;
926
+ padding: 0;
927
+ }
928
+
929
+ .menu-column-item-row {
930
+ display: flex;
931
+ align-items: center;
932
+ padding: 6px 8px;
933
+ margin: 1px 4px;
934
+ border-radius: 4px;
935
+ cursor: pointer;
936
+ transition: background-color 0.15s ease;
937
+ gap: 4px;
938
+ }
939
+
940
+ .menu-column-item-row:hover {
941
+ background-color: rgba(128, 128, 128, 0.15);
942
+ }
943
+
944
+ /* Label styling */
945
+ .menu-column-label {
946
+ flex: 1;
947
+ text-decoration: none;
948
+ color: var(--text-color);
949
+ opacity: 0.85;
950
+ white-space: nowrap;
951
+ overflow: hidden;
952
+ text-overflow: ellipsis;
953
+ font-weight: 400;
954
+ line-height: 1.3;
955
+ text-transform: capitalize;
956
+ font-size: 0.8rem;
957
+ }
958
+
959
+ .menu-column-item-row:hover .menu-column-label {
960
+ opacity: 1;
961
+ }
962
+
963
+ /* Arrow for folders */
964
+ .menu-column-arrow {
965
+ opacity: 0.4;
966
+ font-size: 12px;
967
+ flex-shrink: 0;
968
+ }
969
+
970
+ .menu-column-item.has-children .menu-column-item-row:hover .menu-column-arrow {
971
+ opacity: 0.8;
972
+ }
973
+
974
+ /* Selected item (on path to current doc) */
975
+ .menu-column-item.selected > .menu-column-item-row {
976
+ background-color: rgba(128, 128, 128, 0.2);
977
+ }
978
+
979
+ .menu-column-item.selected > .menu-column-item-row .menu-column-label {
980
+ font-weight: 500;
981
+ opacity: 1;
982
+ }
983
+
984
+ /* Current page item */
985
+ .menu-column-item.current-page > .menu-column-item-row {
986
+ background-color: rgba(0, 255, 255, 0.2);
987
+ }
988
+
989
+ .menu-column-item.current-page > .menu-column-item-row .menu-column-label {
990
+ font-weight: 600;
991
+ opacity: 1;
992
+ }
993
+
994
+ /* Index file styling - appears at top of menu with subtle emphasis */
995
+ .menu-column-item.is-index > .menu-column-item-row {
996
+ border-bottom: 1px solid rgba(128, 128, 128, 0.15);
997
+ margin-bottom: 4px;
998
+ padding-bottom: 8px;
999
+ }
1000
+
1001
+ .menu-column-item.is-index > .menu-column-item-row .menu-column-label {
1002
+ font-weight: 500;
1003
+ opacity: 0.95;
1004
+ }
1005
+
1006
+ /* Scroll buttons */
1007
+ .menu-scroll-btn {
1008
+ position: absolute;
1009
+ top: 50%;
1010
+ transform: translateY(-50%);
1011
+ width: 24px;
1012
+ height: 48px;
1013
+ background: rgba(0, 0, 0, 0.4);
1014
+ border: none;
1015
+ color: var(--text-color);
1016
+ font-size: 18px;
1017
+ cursor: pointer;
1018
+ z-index: 10;
1019
+ border-radius: 4px;
1020
+ transition: all 0.2s ease;
1021
+ display: flex;
1022
+ align-items: center;
1023
+ justify-content: center;
1024
+ }
1025
+
1026
+ .menu-scroll-btn:hover:not(:disabled) {
1027
+ background: rgba(0, 0, 0, 0.6);
1028
+ }
1029
+
1030
+ .menu-scroll-btn:disabled {
1031
+ cursor: default;
1032
+ }
1033
+
1034
+ .menu-scroll-btn.scroll-left {
1035
+ left: 2px;
1036
+ }
1037
+
1038
+ .menu-scroll-btn.scroll-right {
1039
+ right: 2px;
1040
+ }
1041
+
1042
+ /* Scroll indicator for current doc */
1043
+ .menu-scroll-indicator {
1044
+ position: absolute;
1045
+ bottom: 8px;
1046
+ left: 50%;
1047
+ transform: translateX(-50%);
1048
+ z-index: 10;
1049
+ }
1050
+
1051
+ .menu-scroll-indicator .scroll-to-current {
1052
+ background: rgba(0, 255, 255, 0.3);
1053
+ border: 1px solid rgba(0, 255, 255, 0.5);
1054
+ color: var(--text-color);
1055
+ padding: 4px 12px;
1056
+ border-radius: 12px;
1057
+ font-size: 0.75rem;
1058
+ cursor: pointer;
1059
+ transition: all 0.2s ease;
1060
+ white-space: nowrap;
1061
+ }
1062
+
1063
+ .menu-scroll-indicator .scroll-to-current:hover {
1064
+ background: rgba(0, 255, 255, 0.5);
1065
+ }
1066
+ }
1067
+
1068
+ article#main-content {
1069
+ width: var(--article-width);
1070
+ margin: calc(var(--global-nav-height) + 16px) auto 0 auto;
1071
+
1072
+ img {
1073
+ max-width: 100%;
1074
+ }
1075
+ }
1076
+
1077
+ /* Breadcrumb navigation */
1078
+ .breadcrumbs {
1079
+ display: flex;
1080
+ align-items: center;
1081
+ flex-wrap: wrap;
1082
+ gap: 0;
1083
+ font-size: 0.8rem;
1084
+ margin-bottom: 0.25rem;
1085
+ color: var(--text-color);
1086
+ opacity: 0.55;
1087
+ }
1088
+
1089
+ .breadcrumb-link {
1090
+ color: var(--text-color);
1091
+ text-decoration: none;
1092
+ transition: opacity 0.15s ease;
1093
+ }
1094
+
1095
+ .breadcrumb-link:hover {
1096
+ opacity: 1;
1097
+ text-decoration: underline;
1098
+ }
1099
+
1100
+ .breadcrumb-sep {
1101
+ margin: 0 0.4em;
1102
+ opacity: 0.4;
1103
+ font-size: 0.85em;
1104
+ }
1105
+
1106
+ .breadcrumb-current {
1107
+ font-weight: 500;
1108
+ }
1109
+
1110
+ /* Footer styles */
1111
+ footer#site-footer {
1112
+ width: var(--article-width);
1113
+ margin: 3rem auto 2rem auto;
1114
+ padding-top: 2rem;
1115
+ border-top: 1px solid rgba(128, 128, 128, 0.3);
1116
+ text-align: center;
1117
+
1118
+ .footer-content {
1119
+ margin-bottom: 1.5rem;
1120
+ font-size: 0.95rem;
1121
+ opacity: 0.85;
1122
+ }
1123
+
1124
+ .footer-meta {
1125
+ font-size: 0.8rem;
1126
+ opacity: 0.6;
1127
+ margin-bottom: 0.5rem;
1128
+
1129
+ a {
1130
+ color: inherit;
1131
+ }
1132
+ }
1133
+
1134
+ .footer-copyright {
1135
+ font-size: 0.8rem;
1136
+ opacity: 0.6;
1137
+ }
1138
+ }
1139
+
1140
+ @media (max-width: 800px) {
1141
+ footer#site-footer {
1142
+ width: calc(100vw - 2rem);
1143
+ margin: 3rem 1rem 2rem 1rem;
1144
+ }
1145
+ }
1146
+
1147
+ @media (max-width: 800px) {
1148
+ nav#nav-global {
1149
+ display: flex;
1150
+
1151
+ .search-wrapper {
1152
+ flex: 1;
1153
+ width: auto;
1154
+ max-width: none;
1155
+ margin: 0 8px;
1156
+ }
1157
+
1158
+ input#global-search {
1159
+ width: 100%;
1160
+ }
1161
+ }
1162
+ article#main-content {
1163
+ width: calc(100vw - 2rem);
1164
+ margin: calc(var(--global-nav-height) + 16px) 1rem 0 1rem;
1165
+ }
1166
+ h1 {
1167
+ font-size: 1.5rem;
1168
+ }
1169
+
1170
+ /* On mobile, hide the top menu and show search inline instead */
1171
+ body[data-menu-position="top"] nav#nav-main-top {
1172
+ display: none !important;
1173
+ }
1174
+ body[data-menu-position="top"] nav#nav-global .search-wrapper-inline {
1175
+ display: block !important;
1176
+ }
1177
+
1178
+ /* Hide widget buttons on mobile — they're accessible via the inline search and mobile menu */
1179
+ .widget-bar {
1180
+ display: none !important;
1181
+ }
1182
+
1183
+ /* Hide widget dropdown on mobile */
1184
+ .widget-dropdown {
1185
+ display: none !important;
1186
+ }
1187
+
1188
+ nav#nav-main {
1189
+ display: none !important;
1190
+ position: fixed;
1191
+ top: var(--global-nav-height);
1192
+ left: 0;
1193
+ width: 100vw;
1194
+ height: calc(100vh - var(--global-nav-height));
1195
+ max-width: none;
1196
+ background: var(--bg-color);
1197
+ z-index: 1000;
1198
+ overflow-y: auto;
1199
+ margin: 0;
1200
+ padding: 0;
1201
+ transform: none; /* Reset desktop transform */
1202
+ }
1203
+ nav#nav-main.active {
1204
+ display: block !important;
1205
+ }
1206
+ nav#nav-main.collapsed {
1207
+ display: none !important;
1208
+ transform: none;
1209
+ }
1210
+
1211
+ /* Mobile menu list styles */
1212
+ nav#nav-main .mobile-menu-list {
1213
+ list-style: none;
1214
+ margin: 0;
1215
+ padding: 0;
1216
+ }
1217
+
1218
+ nav#nav-main .mobile-menu-item {
1219
+ border-bottom: 1px solid rgba(128, 128, 128, 0.15);
1220
+ }
1221
+
1222
+ nav#nav-main .mobile-menu-label {
1223
+ display: block;
1224
+ padding: 14px 20px;
1225
+ color: var(--text-color);
1226
+ text-decoration: none;
1227
+ font-size: 1rem;
1228
+ }
1229
+
1230
+ nav#nav-main a.mobile-menu-label:hover {
1231
+ background-color: rgba(128, 128, 128, 0.1);
1232
+ }
1233
+
1234
+ nav#nav-main span.mobile-menu-label {
1235
+ opacity: 0.5;
1236
+ }
1237
+
1238
+ /* Indent deeper levels */
1239
+ nav#nav-main .mobile-menu-depth-1 .mobile-menu-label { padding-left: 40px; font-size: 0.95rem; }
1240
+ nav#nav-main .mobile-menu-depth-2 .mobile-menu-label { padding-left: 56px; font-size: 0.9rem; }
1241
+ nav#nav-main .mobile-menu-depth-3 .mobile-menu-label { padding-left: 72px; font-size: 0.85rem; }
1242
+ nav#nav-main .mobile-menu-depth-4 .mobile-menu-label { padding-left: 88px; font-size: 0.85rem; }
1243
+
1244
+ /* Current page highlight in mobile menu */
1245
+ nav#nav-main .mobile-menu-current .mobile-menu-label {
1246
+ font-weight: 600;
1247
+ background-color: rgba(0, 255, 255, 0.1);
1248
+ }
1249
+
1250
+ /* Home item styling */
1251
+ nav#nav-main .mobile-menu-home .mobile-menu-label {
1252
+ font-weight: 600;
1253
+ border-bottom: 2px solid rgba(128, 128, 128, 0.25);
1254
+ }
1255
+
1256
+ /* Override desktop indentation for mobile */
1257
+ nav#nav-main > ul > li > ul > li > .menu-item-row,
1258
+ nav#nav-main > ul > li > ul > li > ul > li > .menu-item-row,
1259
+ nav#nav-main > ul > li > ul > li > ul > li > ul > li > .menu-item-row {
1260
+ padding-left: 8px;
1261
+ }
1262
+ html {
1263
+ font-size: 18px;
1264
+ /* Prevents zoomed out appearance on mobile */
1265
+ -webkit-text-size-adjust: 100%;
1266
+ text-size-adjust: 100%;
1267
+ }
1268
+ }