@jjlmoya/utils-tabletop 1.5.0 → 1.7.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 (46) hide show
  1. package/package.json +5 -3
  2. package/src/entries.ts +5 -1
  3. package/src/index.ts +2 -0
  4. package/src/tests/locale_completeness.test.ts +2 -1
  5. package/src/tests/tool_validation.test.ts +2 -1
  6. package/src/tool/investigation-board/bibliography.astro +16 -0
  7. package/src/tool/investigation-board/bibliography.ts +12 -0
  8. package/src/tool/investigation-board/boardContextMenu.ts +64 -0
  9. package/src/tool/investigation-board/client.ts +223 -0
  10. package/src/tool/investigation-board/component.astro +23 -0
  11. package/src/tool/investigation-board/components/BoardCanvas.astro +39 -0
  12. package/src/tool/investigation-board/components/CardDrawer.astro +73 -0
  13. package/src/tool/investigation-board/components/ConnectionModal.astro +49 -0
  14. package/src/tool/investigation-board/components/ContextMenu.astro +26 -0
  15. package/src/tool/investigation-board/components/ControlPanel.astro +57 -0
  16. package/src/tool/investigation-board/connectionModal.ts +60 -0
  17. package/src/tool/investigation-board/dom.ts +89 -0
  18. package/src/tool/investigation-board/drawer.ts +110 -0
  19. package/src/tool/investigation-board/entry.ts +59 -0
  20. package/src/tool/investigation-board/i18n/de.ts +209 -0
  21. package/src/tool/investigation-board/i18n/en.ts +209 -0
  22. package/src/tool/investigation-board/i18n/es.ts +209 -0
  23. package/src/tool/investigation-board/i18n/fr.ts +209 -0
  24. package/src/tool/investigation-board/i18n/id.ts +209 -0
  25. package/src/tool/investigation-board/i18n/it.ts +209 -0
  26. package/src/tool/investigation-board/i18n/ja.ts +209 -0
  27. package/src/tool/investigation-board/i18n/ko.ts +209 -0
  28. package/src/tool/investigation-board/i18n/nl.ts +209 -0
  29. package/src/tool/investigation-board/i18n/pl.ts +209 -0
  30. package/src/tool/investigation-board/i18n/pt.ts +209 -0
  31. package/src/tool/investigation-board/i18n/ru.ts +209 -0
  32. package/src/tool/investigation-board/i18n/sv.ts +209 -0
  33. package/src/tool/investigation-board/i18n/tr.ts +209 -0
  34. package/src/tool/investigation-board/i18n/zh.ts +209 -0
  35. package/src/tool/investigation-board/index.ts +11 -0
  36. package/src/tool/investigation-board/interactDrag.ts +58 -0
  37. package/src/tool/investigation-board/investigation-board.css +799 -0
  38. package/src/tool/investigation-board/layout.ts +16 -0
  39. package/src/tool/investigation-board/logic.test.ts +105 -0
  40. package/src/tool/investigation-board/logic.ts +106 -0
  41. package/src/tool/investigation-board/panzoom.ts +24 -0
  42. package/src/tool/investigation-board/renderer.ts +256 -0
  43. package/src/tool/investigation-board/seo.astro +16 -0
  44. package/src/tool/investigation-board/stateManager.ts +126 -0
  45. package/src/tool/investigation-board/types.ts +26 -0
  46. package/src/tools.ts +3 -0
@@ -0,0 +1,799 @@
1
+ .investigation-board-main {
2
+ --board-bg: var(--bg-surface);
3
+ --board-grid: rgba(120, 120, 120, 0.15);
4
+ --node-character: #3b82f6;
5
+ --node-clue: #ef4444;
6
+ --node-location: #10b981;
7
+ --node-item: #f59e0b;
8
+ --text-white: #fff;
9
+ --danger-color: #ef4444;
10
+
11
+ position: relative;
12
+ display: flex;
13
+ flex-direction: column;
14
+ background: var(--bg-surface);
15
+ border: 1px solid var(--border-color);
16
+ border-radius: 1rem;
17
+ padding: 0;
18
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
19
+ color: var(--text-base);
20
+ width: 100%;
21
+ max-width: 100%;
22
+ min-width: 0;
23
+ height: calc(100vh - 120px);
24
+ min-height: 500px;
25
+ overflow: hidden;
26
+ box-sizing: border-box;
27
+ }
28
+
29
+ .control-panel {
30
+ position: absolute;
31
+ top: 0;
32
+ left: 0;
33
+ width: 100%;
34
+ height: 100%;
35
+ pointer-events: none;
36
+ z-index: 10;
37
+ box-sizing: border-box;
38
+ padding: 0.75rem;
39
+ }
40
+
41
+ .board-management-row {
42
+ position: absolute;
43
+ top: 0.75rem;
44
+ left: 0.75rem;
45
+ display: flex;
46
+ flex-direction: row;
47
+ align-items: center;
48
+ gap: 0.4rem;
49
+ background: rgba(15, 23, 42, 0.85);
50
+ backdrop-filter: blur(12px);
51
+ border: 1px solid var(--border-color);
52
+ padding: 0.35rem;
53
+ border-radius: 0.6rem;
54
+ pointer-events: auto;
55
+ width: auto;
56
+ margin-bottom: 0;
57
+ }
58
+
59
+ .board-management-row select {
60
+ appearance: none;
61
+ -webkit-appearance: none;
62
+ background-color: var(--bg-page);
63
+ color: var(--text-base);
64
+ border: 1px solid var(--border-color);
65
+ padding: 0.3rem 1.6rem 0.3rem 0.6rem;
66
+ border-radius: 0.4rem;
67
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
68
+ background-repeat: no-repeat;
69
+ background-position: right 0.4rem center;
70
+ background-size: 0.8rem;
71
+ cursor: pointer;
72
+ height: 28px;
73
+ font-size: 0.75rem;
74
+ width: 110px;
75
+ }
76
+
77
+ .board-management-row select,
78
+ .board-management-row button {
79
+ min-width: 0;
80
+ box-sizing: border-box;
81
+ }
82
+
83
+ .board-management-row .btn {
84
+ height: 28px;
85
+ padding: 0.2rem 0.5rem;
86
+ font-size: 0.75rem;
87
+ border-radius: 0.4rem;
88
+ white-space: nowrap;
89
+ }
90
+
91
+ .search-filter-row {
92
+ position: absolute;
93
+ top: 0.75rem;
94
+ right: 0.75rem;
95
+ display: flex;
96
+ flex-direction: column;
97
+ align-items: flex-end;
98
+ gap: 0.4rem;
99
+ width: auto;
100
+ }
101
+
102
+ .search-box {
103
+ width: 140px;
104
+ pointer-events: auto;
105
+ }
106
+
107
+ .search-input {
108
+ width: 100%;
109
+ padding: 0.3rem 0.6rem;
110
+ height: 28px;
111
+ font-size: 0.75rem;
112
+ border-radius: 0.4rem;
113
+ border: 1px solid var(--border-color);
114
+ background: rgba(15, 23, 42, 0.85);
115
+ backdrop-filter: blur(12px);
116
+ color: var(--text-base);
117
+ transition: border-color 0.2s ease;
118
+ box-sizing: border-box;
119
+ }
120
+
121
+ .search-input:focus {
122
+ outline: none;
123
+ border-color: var(--accent);
124
+ }
125
+
126
+ .filter-group {
127
+ display: flex;
128
+ flex-direction: row;
129
+ flex-wrap: wrap;
130
+ gap: 0.25rem;
131
+ justify-content: flex-end;
132
+ width: auto;
133
+ max-width: 180px;
134
+ pointer-events: auto;
135
+ }
136
+
137
+ .btn {
138
+ padding: 0.6rem 1rem;
139
+ border-radius: 0.5rem;
140
+ border: 1px solid var(--border-color);
141
+ background: var(--bg-page);
142
+ color: var(--text-base);
143
+ cursor: pointer;
144
+ font-weight: 600;
145
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
146
+ display: flex;
147
+ align-items: center;
148
+ justify-content: center;
149
+ box-sizing: border-box;
150
+ }
151
+
152
+ .btn:hover {
153
+ background: var(--bg-surface);
154
+ border-color: var(--accent);
155
+ transform: translateY(-1px);
156
+ }
157
+
158
+ .btn-filter {
159
+ padding: 0.2rem 0.4rem;
160
+ font-size: 0.65rem;
161
+ height: 24px;
162
+ border-radius: 0.3rem;
163
+ background: rgba(15, 23, 42, 0.85);
164
+ border: 1px solid var(--border-color);
165
+ color: var(--text-muted);
166
+ }
167
+
168
+ .btn-filter.active {
169
+ background: var(--accent);
170
+ color: var(--text-white);
171
+ border-color: var(--accent);
172
+ }
173
+
174
+ .action-buttons-row {
175
+ position: absolute;
176
+ bottom: 0.75rem;
177
+ left: 50%;
178
+ transform: translateX(-50%);
179
+ display: flex;
180
+ flex-direction: row;
181
+ align-items: center;
182
+ gap: 0.4rem;
183
+ background: rgba(15, 23, 42, 0.85);
184
+ backdrop-filter: blur(12px);
185
+ border: 1px solid var(--border-color);
186
+ padding: 0.35rem;
187
+ border-radius: 0.6rem;
188
+ pointer-events: auto;
189
+ width: auto;
190
+ }
191
+
192
+ .action-buttons-row button {
193
+ min-width: 0;
194
+ box-sizing: border-box;
195
+ }
196
+
197
+ .action-buttons-row .btn {
198
+ height: 32px;
199
+ padding: 0.3rem 0.6rem;
200
+ font-size: 0.75rem;
201
+ border-radius: 0.4rem;
202
+ white-space: nowrap;
203
+ }
204
+
205
+ .btn-primary {
206
+ background: var(--accent);
207
+ color: var(--text-white);
208
+ border-color: var(--accent);
209
+ }
210
+
211
+ .btn-primary:hover {
212
+ background: var(--accent);
213
+ opacity: 0.9;
214
+ }
215
+
216
+ .btn-secondary {
217
+ background: var(--bg-page);
218
+ color: var(--text-base);
219
+ }
220
+
221
+ .btn-danger {
222
+ background: #dc2626;
223
+ color: var(--text-white);
224
+ border-color: #dc2626;
225
+ }
226
+
227
+ .btn-danger:hover {
228
+ background: #b91c1c;
229
+ }
230
+
231
+ .board-canvas-wrapper {
232
+ width: 100%;
233
+ height: 100%;
234
+ border: none;
235
+ border-radius: 1rem;
236
+ background: var(--bg-page);
237
+ position: relative;
238
+ overflow: hidden;
239
+ user-select: none;
240
+ -webkit-user-select: none;
241
+ -webkit-touch-callout: none;
242
+ }
243
+
244
+ .board-viewport {
245
+ width: 100%;
246
+ height: 100%;
247
+ overflow: auto;
248
+ position: relative;
249
+ scroll-behavior: smooth;
250
+ scrollbar-width: none;
251
+ -ms-overflow-style: none;
252
+ }
253
+
254
+ .board-viewport::-webkit-scrollbar {
255
+ display: none;
256
+ }
257
+
258
+ .board-area {
259
+ position: relative;
260
+ background-image: radial-gradient(var(--board-grid) 1.5px, transparent 1.5px);
261
+ background-size: 30px 30px;
262
+ cursor: grab;
263
+ transition: width 0.2s ease, height 0.2s ease;
264
+ }
265
+
266
+ .board-area.grabbing {
267
+ cursor: grabbing;
268
+ }
269
+
270
+ .board-svg {
271
+ position: absolute;
272
+ top: 0;
273
+ left: 0;
274
+ width: 100%;
275
+ height: 100%;
276
+ pointer-events: none;
277
+ z-index: 1;
278
+ }
279
+
280
+ .connection-path {
281
+ fill: none;
282
+ stroke-width: 3px;
283
+ transition: stroke-width 0.2s ease, opacity 0.2s ease;
284
+ }
285
+
286
+ .connection-path.highlighted {
287
+ stroke-width: 5px;
288
+ }
289
+
290
+ .connection-text {
291
+ font-size: 0.8rem;
292
+ font-weight: 700;
293
+ paint-order: stroke;
294
+ stroke: var(--bg-page);
295
+ stroke-width: 5px;
296
+ stroke-linecap: round;
297
+ stroke-linejoin: round;
298
+ dominant-baseline: middle;
299
+ text-anchor: middle;
300
+ }
301
+
302
+ .board-nodes {
303
+ position: absolute;
304
+ top: 0;
305
+ left: 0;
306
+ width: 100%;
307
+ height: 100%;
308
+ pointer-events: none;
309
+ z-index: 2;
310
+ }
311
+
312
+ .board-node {
313
+ position: absolute;
314
+ width: 240px;
315
+ padding: 1rem;
316
+ border-radius: 0.75rem;
317
+ background: var(--bg-surface);
318
+ border: 2px solid var(--border-color);
319
+ color: var(--text-base);
320
+ pointer-events: auto;
321
+ user-select: none;
322
+ cursor: grab;
323
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
324
+ transition: opacity 0.2s ease, transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), border-color 0.2s ease;
325
+ }
326
+
327
+ .board-node:hover {
328
+ transform: translateY(-2px) scale(1.02);
329
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
330
+ }
331
+
332
+ .board-node.dragging {
333
+ cursor: grabbing;
334
+ transform: scale(1.05);
335
+ z-index: 99;
336
+ }
337
+
338
+ .board-node-header {
339
+ display: flex;
340
+ justify-content: space-between;
341
+ align-items: center;
342
+ margin-bottom: 0.50rem;
343
+ }
344
+
345
+ .node-category-badge {
346
+ font-size: 0.65rem;
347
+ font-weight: 700;
348
+ text-transform: uppercase;
349
+ padding: 0.15rem 0.5rem;
350
+ border-radius: 99px;
351
+ color: var(--text-white);
352
+ }
353
+
354
+ .category-character {
355
+ background: var(--node-character);
356
+ }
357
+
358
+ .category-clue {
359
+ background: var(--node-clue);
360
+ }
361
+
362
+ .category-location {
363
+ background: var(--node-location);
364
+ }
365
+
366
+ .category-item {
367
+ background: var(--node-item);
368
+ }
369
+
370
+ .category-custom {
371
+ background: var(--accent);
372
+ }
373
+
374
+ .node-actions {
375
+ display: flex;
376
+ gap: 0.5rem;
377
+ }
378
+
379
+ .node-action-link {
380
+ color: var(--text-base);
381
+ background: var(--bg-page);
382
+ border: 1px solid var(--border-color);
383
+ cursor: pointer;
384
+ border-radius: 4px;
385
+ transition: all 0.2s;
386
+ display: flex;
387
+ align-items: center;
388
+ justify-content: center;
389
+ width: 24px;
390
+ height: 24px;
391
+ padding: 0;
392
+ }
393
+
394
+ .node-action-link:hover {
395
+ background: var(--accent);
396
+ color: var(--text-white);
397
+ border-color: var(--accent);
398
+ }
399
+
400
+ .board-node-title {
401
+ font-size: 1rem;
402
+ font-weight: 700;
403
+ color: var(--text-base);
404
+ overflow-wrap: break-word;
405
+ margin-bottom: 0.25rem;
406
+ }
407
+
408
+ .board-node-desc {
409
+ font-size: 0.8rem;
410
+ color: var(--text-muted);
411
+ line-height: 1.4;
412
+ display: -webkit-box;
413
+ -webkit-line-clamp: 2;
414
+ -webkit-box-orient: vertical;
415
+ overflow: hidden;
416
+ margin-bottom: 0.5rem;
417
+ }
418
+
419
+ .board-node-tags {
420
+ display: flex;
421
+ flex-wrap: wrap;
422
+ gap: 0.25rem;
423
+ }
424
+
425
+ .board-node-tag {
426
+ font-size: 0.65rem;
427
+ background: var(--bg-page);
428
+ border: 1px solid var(--border-color);
429
+ padding: 0.1rem 0.35rem;
430
+ border-radius: 4px;
431
+ color: var(--text-muted);
432
+ }
433
+
434
+ .card-drawer-overlay,
435
+ .modal-overlay {
436
+ position: fixed;
437
+ top: 0;
438
+ left: 0;
439
+ width: 100vw;
440
+ height: 100vh;
441
+ background: rgba(0, 0, 0, 0.4);
442
+ backdrop-filter: blur(4px);
443
+ z-index: 1000;
444
+ display: none;
445
+ align-items: center;
446
+ justify-content: center;
447
+ }
448
+
449
+ .card-drawer-overlay.active,
450
+ .modal-overlay.active {
451
+ display: flex;
452
+ }
453
+
454
+ .card-drawer {
455
+ position: absolute;
456
+ right: 0;
457
+ top: 0;
458
+ height: 100%;
459
+ width: 100%;
460
+ background: var(--bg-surface);
461
+ padding: 1.5rem;
462
+ display: flex;
463
+ flex-direction: column;
464
+ gap: 1.25rem;
465
+ overflow-y: auto;
466
+ color: var(--text-base);
467
+ animation: slide-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);
468
+ }
469
+
470
+ @keyframes slide-in {
471
+ from {
472
+ transform: translateX(100%);
473
+ }
474
+ to {
475
+ transform: translateX(0);
476
+ }
477
+ }
478
+
479
+ .drawer-header,
480
+ .modal-header {
481
+ display: flex;
482
+ justify-content: space-between;
483
+ align-items: center;
484
+ padding-bottom: 1rem;
485
+ border-bottom: 1px solid var(--border-color);
486
+ }
487
+
488
+ .drawer-heading,
489
+ .modal-heading {
490
+ font-size: 1.25rem;
491
+ font-weight: 700;
492
+ color: var(--text-base);
493
+ }
494
+
495
+ .btn-close-drawer,
496
+ .btn-close-modal {
497
+ background: none;
498
+ border: none;
499
+ font-size: 1.5rem;
500
+ color: var(--text-muted);
501
+ cursor: pointer;
502
+ }
503
+
504
+ .drawer-form,
505
+ .modal-form {
506
+ display: flex;
507
+ flex-direction: column;
508
+ gap: 1.25rem;
509
+ }
510
+
511
+ .form-group {
512
+ display: flex;
513
+ flex-direction: column;
514
+ gap: 0.5rem;
515
+ }
516
+
517
+ .form-group label {
518
+ font-size: 0.85rem;
519
+ font-weight: 600;
520
+ color: var(--text-base);
521
+ }
522
+
523
+ .form-control {
524
+ padding: 0.6rem 0.75rem;
525
+ border-radius: 0.4rem;
526
+ border: 1px solid var(--border-color);
527
+ background: var(--bg-page);
528
+ color: var(--text-base);
529
+ }
530
+
531
+ .form-control:focus {
532
+ outline: none;
533
+ border-color: var(--accent);
534
+ }
535
+
536
+ .color-picker {
537
+ padding: 0.2rem;
538
+ height: 40px;
539
+ cursor: pointer;
540
+ }
541
+
542
+ .drawer-actions,
543
+ .modal-actions {
544
+ display: flex;
545
+ gap: 0.75rem;
546
+ margin-top: 1rem;
547
+ }
548
+
549
+ .modal-dialog {
550
+ width: 100%;
551
+ height: 100%;
552
+ background: var(--bg-surface);
553
+ padding: 1.5rem;
554
+ color: var(--text-base);
555
+ animation: scale-up 0.2s ease;
556
+ display: flex;
557
+ flex-direction: column;
558
+ }
559
+
560
+ @keyframes scale-up {
561
+ from {
562
+ transform: scale(0.95);
563
+ opacity: 0;
564
+ }
565
+ to {
566
+ transform: scale(1);
567
+ opacity: 1;
568
+ }
569
+ }
570
+
571
+ .dimmed {
572
+ opacity: 0.25;
573
+ }
574
+
575
+ .highlight-source {
576
+ transform: scale(1.03);
577
+ box-shadow: 0 0 25px rgba(244, 63, 94, 0.2);
578
+ }
579
+
580
+ .connection-banner {
581
+ display: none;
582
+ position: absolute;
583
+ top: 10px;
584
+ left: 50%;
585
+ transform: translateX(-50%);
586
+ background: var(--accent);
587
+ color: var(--text-white);
588
+ padding: 0.6rem 1.2rem;
589
+ border-radius: 99px;
590
+ font-size: 0.85rem;
591
+ font-weight: 700;
592
+ z-index: 10;
593
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
594
+ width: 90%;
595
+ text-align: center;
596
+ }
597
+
598
+ .connection-banner.active {
599
+ display: block;
600
+ }
601
+
602
+ .board-node-notes {
603
+ margin: 0.5rem 0;
604
+ padding-left: 1.2rem;
605
+ font-size: 0.75rem;
606
+ color: var(--text-muted);
607
+ list-style-type: disc;
608
+ pointer-events: none;
609
+ }
610
+
611
+ .board-node-notes li {
612
+ margin-bottom: 0.2rem;
613
+ line-height: 1.3;
614
+ }
615
+
616
+ .notes-input-list {
617
+ display: flex;
618
+ flex-direction: column;
619
+ gap: 0.5rem;
620
+ }
621
+
622
+ .note-input-row {
623
+ display: flex;
624
+ gap: 0.5rem;
625
+ align-items: center;
626
+ }
627
+
628
+ .btn-sm {
629
+ padding: 0.35rem 0.7rem;
630
+ font-size: 0.75rem;
631
+ border-radius: 0.3rem;
632
+ align-self: flex-start;
633
+ }
634
+
635
+ .zoom-controls {
636
+ position: absolute;
637
+ bottom: 1rem;
638
+ right: 1rem;
639
+ display: flex;
640
+ align-items: center;
641
+ gap: 0.4rem;
642
+ background: var(--bg-surface);
643
+ border: 1px solid var(--border-color);
644
+ padding: 0.4rem;
645
+ border-radius: 99px;
646
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
647
+ z-index: 100;
648
+ }
649
+
650
+ .zoom-btn {
651
+ width: 2rem;
652
+ height: 2rem;
653
+ border-radius: 50%;
654
+ border: 1px solid var(--border-color);
655
+ background: var(--bg-page);
656
+ color: var(--text-base);
657
+ font-weight: 700;
658
+ display: flex;
659
+ align-items: center;
660
+ justify-content: center;
661
+ cursor: pointer;
662
+ transition: all 0.2s;
663
+ }
664
+
665
+ .zoom-btn:hover {
666
+ background: var(--accent);
667
+ color: var(--text-white);
668
+ border-color: var(--accent);
669
+ }
670
+
671
+ .zoom-value {
672
+ font-size: 0.75rem;
673
+ font-weight: 700;
674
+ color: var(--text-base);
675
+ min-width: 2.5rem;
676
+ text-align: center;
677
+ user-select: none;
678
+ }
679
+
680
+ @media (min-width: 769px) {
681
+ .investigation-board-main {
682
+ height: 650px;
683
+ }
684
+
685
+ .card-drawer {
686
+ max-width: 450px;
687
+ border-left: 1px solid var(--border-color);
688
+ }
689
+
690
+ .modal-dialog {
691
+ max-width: 450px;
692
+ height: auto;
693
+ border-radius: 0.75rem;
694
+ border: 1px solid var(--border-color);
695
+ }
696
+
697
+ .connection-banner {
698
+ width: auto;
699
+ }
700
+ }
701
+
702
+ .investigation-board-main.immersive {
703
+ position: fixed;
704
+ top: 0;
705
+ left: 0;
706
+ width: 100vw;
707
+ height: 100vh;
708
+ z-index: 9999;
709
+ border-radius: 0;
710
+ border: none;
711
+ margin: 0;
712
+ padding: 0;
713
+ background: var(--bg-surface);
714
+ }
715
+
716
+ .investigation-board-main.immersive .control-panel {
717
+ display: none;
718
+ }
719
+
720
+ .investigation-board-main.immersive .board-canvas-wrapper {
721
+ flex: 1;
722
+ display: flex;
723
+ flex-direction: column;
724
+ height: 100%;
725
+ border: none;
726
+ border-radius: 0;
727
+ }
728
+
729
+ .investigation-board-main.immersive .board-viewport {
730
+ flex: 1;
731
+ height: auto;
732
+ }
733
+
734
+ .context-menu {
735
+ position: fixed;
736
+ display: none;
737
+ background: rgba(15, 23, 42, 0.95);
738
+ backdrop-filter: blur(12px);
739
+ border: 1px solid var(--border-color);
740
+ border-radius: 0.5rem;
741
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
742
+ padding: 0.35rem;
743
+ z-index: 10000;
744
+ min-width: 130px;
745
+ flex-direction: column;
746
+ gap: 0.15rem;
747
+ }
748
+
749
+ .context-menu.active {
750
+ display: flex;
751
+ }
752
+
753
+ .context-menu-item {
754
+ display: flex;
755
+ align-items: center;
756
+ gap: 0.5rem;
757
+ width: 100%;
758
+ padding: 0.4rem 0.6rem;
759
+ background: none;
760
+ border: none;
761
+ color: var(--text-base);
762
+ font-size: 0.75rem;
763
+ font-weight: 600;
764
+ text-align: left;
765
+ cursor: pointer;
766
+ border-radius: 0.3rem;
767
+ transition: background 0.15s ease;
768
+ }
769
+
770
+ .context-menu-item:hover {
771
+ background: rgba(255, 255, 255, 0.08);
772
+ }
773
+
774
+ .context-menu-item svg {
775
+ color: var(--text-muted);
776
+ }
777
+
778
+ .context-menu-item:hover svg {
779
+ color: var(--text-base);
780
+ }
781
+
782
+ .context-menu-item.danger {
783
+ color: var(--danger-color);
784
+ }
785
+
786
+ .context-menu-item.danger svg {
787
+ color: var(--danger-color);
788
+ }
789
+
790
+ .context-menu-item.danger:hover {
791
+ background: rgba(239, 68, 68, 0.15);
792
+ }
793
+
794
+ @media (max-width: 768px) {
795
+ .zoom-controls {
796
+ bottom: 4.5rem;
797
+ right: 0.75rem;
798
+ }
799
+ }