@syke1/mcp-server 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 (41) hide show
  1. package/README.md +112 -0
  2. package/dist/ai/analyzer.d.ts +3 -0
  3. package/dist/ai/analyzer.js +120 -0
  4. package/dist/ai/realtime-analyzer.d.ts +20 -0
  5. package/dist/ai/realtime-analyzer.js +182 -0
  6. package/dist/graph.d.ts +13 -0
  7. package/dist/graph.js +105 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +518 -0
  10. package/dist/languages/cpp.d.ts +2 -0
  11. package/dist/languages/cpp.js +109 -0
  12. package/dist/languages/dart.d.ts +2 -0
  13. package/dist/languages/dart.js +162 -0
  14. package/dist/languages/go.d.ts +2 -0
  15. package/dist/languages/go.js +111 -0
  16. package/dist/languages/java.d.ts +2 -0
  17. package/dist/languages/java.js +113 -0
  18. package/dist/languages/plugin.d.ts +20 -0
  19. package/dist/languages/plugin.js +148 -0
  20. package/dist/languages/python.d.ts +2 -0
  21. package/dist/languages/python.js +129 -0
  22. package/dist/languages/ruby.d.ts +2 -0
  23. package/dist/languages/ruby.js +97 -0
  24. package/dist/languages/rust.d.ts +2 -0
  25. package/dist/languages/rust.js +121 -0
  26. package/dist/languages/typescript.d.ts +2 -0
  27. package/dist/languages/typescript.js +138 -0
  28. package/dist/license/validator.d.ts +23 -0
  29. package/dist/license/validator.js +297 -0
  30. package/dist/tools/analyze-impact.d.ts +23 -0
  31. package/dist/tools/analyze-impact.js +102 -0
  32. package/dist/tools/gate-build.d.ts +25 -0
  33. package/dist/tools/gate-build.js +243 -0
  34. package/dist/watcher/file-cache.d.ts +56 -0
  35. package/dist/watcher/file-cache.js +241 -0
  36. package/dist/web/public/app.js +2398 -0
  37. package/dist/web/public/index.html +258 -0
  38. package/dist/web/public/style.css +1827 -0
  39. package/dist/web/server.d.ts +29 -0
  40. package/dist/web/server.js +744 -0
  41. package/package.json +50 -0
@@ -0,0 +1,1827 @@
1
+ * { margin: 0; padding: 0; box-sizing: border-box; }
2
+
3
+ :root {
4
+ --bg-primary: #050a18;
5
+ --bg-secondary: #0a1628;
6
+ --bg-tertiary: #132244;
7
+ --text-primary: #c8d6e5;
8
+ --text-secondary: #5a7599;
9
+ --accent: #00d4ff;
10
+ --accent-dim: #006680;
11
+ --risk-high: #ff2d55;
12
+ --risk-medium: #ff9f0a;
13
+ --risk-low: #30d158;
14
+ --risk-none: #3a4f6f;
15
+ --border: #1a2d4d;
16
+ --glow-cyan: 0 0 20px rgba(0,212,255,0.3);
17
+ --glow-red: 0 0 20px rgba(255,45,85,0.3);
18
+ }
19
+
20
+ body {
21
+ font-family: 'Consolas', 'SF Mono', 'Fira Code', monospace;
22
+ background: var(--bg-primary);
23
+ color: var(--text-primary);
24
+ height: 100vh;
25
+ display: flex;
26
+ flex-direction: column;
27
+ overflow: hidden;
28
+ }
29
+
30
+ /* Scanline overlay */
31
+ #scanline {
32
+ position: fixed;
33
+ top: 0; left: 0; right: 0; bottom: 0;
34
+ pointer-events: none;
35
+ z-index: 999;
36
+ background: repeating-linear-gradient(
37
+ 0deg,
38
+ transparent,
39
+ transparent 2px,
40
+ rgba(0,212,255,0.015) 2px,
41
+ rgba(0,212,255,0.015) 4px
42
+ );
43
+ }
44
+
45
+ /* ── Top Bar ── */
46
+ #topbar {
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: space-between;
50
+ padding: 0 24px;
51
+ height: 52px;
52
+ background: linear-gradient(180deg, var(--bg-secondary) 0%, var(--bg-primary) 100%);
53
+ border-bottom: 1px solid var(--border);
54
+ flex-shrink: 0;
55
+ position: relative;
56
+ }
57
+
58
+ #topbar::after {
59
+ content: '';
60
+ position: absolute;
61
+ bottom: -1px;
62
+ left: 0; right: 0;
63
+ height: 1px;
64
+ background: linear-gradient(90deg, transparent 0%, var(--accent) 50%, transparent 100%);
65
+ opacity: 0.5;
66
+ }
67
+
68
+ .logo {
69
+ display: flex;
70
+ align-items: center;
71
+ gap: 12px;
72
+ }
73
+
74
+ .pulse-ring {
75
+ position: relative;
76
+ width: 18px;
77
+ height: 18px;
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ }
82
+
83
+ .pulse-ring::before {
84
+ content: '';
85
+ position: absolute;
86
+ width: 18px; height: 18px;
87
+ border-radius: 50%;
88
+ border: 1px solid var(--risk-high);
89
+ animation: pulse-ring 2s ease-out infinite;
90
+ }
91
+
92
+ .pulse-dot {
93
+ width: 6px;
94
+ height: 6px;
95
+ border-radius: 50%;
96
+ background: var(--risk-high);
97
+ box-shadow: 0 0 8px var(--risk-high);
98
+ animation: pulse-glow 2s ease-in-out infinite;
99
+ }
100
+
101
+ @keyframes pulse-ring {
102
+ 0% { transform: scale(1); opacity: 0.8; }
103
+ 100% { transform: scale(2.5); opacity: 0; }
104
+ }
105
+
106
+ @keyframes pulse-glow {
107
+ 0%, 100% { opacity: 1; }
108
+ 50% { opacity: 0.4; }
109
+ }
110
+
111
+ .logo-text {
112
+ font-size: 22px;
113
+ font-weight: 700;
114
+ letter-spacing: 6px;
115
+ color: var(--accent);
116
+ text-shadow: var(--glow-cyan);
117
+ }
118
+
119
+ .logo-sub {
120
+ font-size: 10px;
121
+ color: var(--text-secondary);
122
+ letter-spacing: 3px;
123
+ text-transform: uppercase;
124
+ }
125
+
126
+ .top-controls {
127
+ display: flex;
128
+ gap: 8px;
129
+ }
130
+
131
+ .top-btn {
132
+ padding: 5px 14px;
133
+ background: transparent;
134
+ color: var(--text-secondary);
135
+ border: 1px solid var(--border);
136
+ border-radius: 2px;
137
+ cursor: pointer;
138
+ font-size: 10px;
139
+ font-family: inherit;
140
+ letter-spacing: 2px;
141
+ transition: all 0.2s;
142
+ }
143
+
144
+ .top-btn:hover {
145
+ color: var(--accent);
146
+ border-color: var(--accent);
147
+ box-shadow: var(--glow-cyan);
148
+ }
149
+
150
+ .stats {
151
+ display: flex;
152
+ gap: 24px;
153
+ }
154
+
155
+ .stat-block {
156
+ display: flex;
157
+ flex-direction: column;
158
+ align-items: center;
159
+ gap: 2px;
160
+ }
161
+
162
+ .stat-label {
163
+ font-size: 9px;
164
+ color: var(--text-secondary);
165
+ letter-spacing: 2px;
166
+ }
167
+
168
+ .stat-value {
169
+ font-size: 16px;
170
+ font-weight: 700;
171
+ color: var(--accent);
172
+ font-variant-numeric: tabular-nums;
173
+ }
174
+
175
+ .stat-block.threat .stat-value {
176
+ color: var(--risk-high);
177
+ text-shadow: var(--glow-red);
178
+ }
179
+
180
+ /* ── Main Layout ── */
181
+ main {
182
+ display: flex;
183
+ flex: 1;
184
+ overflow: hidden;
185
+ }
186
+
187
+ /* ── Graph Panel ── */
188
+ #graph-panel {
189
+ flex: 1 1 0;
190
+ min-width: 300px;
191
+ display: flex;
192
+ flex-direction: column;
193
+ position: relative;
194
+ background: radial-gradient(ellipse at center, #0d1a30 0%, var(--bg-primary) 70%);
195
+ }
196
+
197
+ #graph-toolbar {
198
+ display: flex;
199
+ gap: 8px;
200
+ padding: 8px 16px;
201
+ background: rgba(10,22,40,0.9);
202
+ border-bottom: 1px solid var(--border);
203
+ align-items: center;
204
+ z-index: 5;
205
+ }
206
+
207
+ #graph-toolbar button {
208
+ padding: 5px 14px;
209
+ background: transparent;
210
+ color: var(--text-secondary);
211
+ border: 1px solid var(--border);
212
+ border-radius: 2px;
213
+ cursor: pointer;
214
+ font-size: 10px;
215
+ font-family: inherit;
216
+ letter-spacing: 2px;
217
+ text-transform: uppercase;
218
+ transition: all 0.2s;
219
+ }
220
+
221
+ #graph-toolbar button:hover {
222
+ color: var(--accent);
223
+ border-color: var(--accent);
224
+ box-shadow: var(--glow-cyan);
225
+ }
226
+
227
+ #graph-toolbar button.active {
228
+ color: var(--accent);
229
+ border-color: var(--accent-dim);
230
+ background: rgba(0,212,255,0.08);
231
+ }
232
+
233
+ #search-input {
234
+ margin-left: auto;
235
+ padding: 5px 14px;
236
+ background: rgba(0,0,0,0.3);
237
+ color: var(--accent);
238
+ border: 1px solid var(--border);
239
+ border-radius: 2px;
240
+ font-size: 11px;
241
+ font-family: inherit;
242
+ letter-spacing: 1px;
243
+ width: 220px;
244
+ outline: none;
245
+ transition: border-color 0.2s;
246
+ }
247
+
248
+ #search-input::placeholder { color: var(--text-secondary); letter-spacing: 2px; }
249
+ #search-input:focus { border-color: var(--accent); box-shadow: var(--glow-cyan); }
250
+
251
+ #3d-graph {
252
+ flex: 1;
253
+ cursor: grab;
254
+ min-height: 400px;
255
+ position: relative;
256
+ }
257
+
258
+ #3d-graph canvas {
259
+ display: block;
260
+ }
261
+
262
+ #3d-graph:active { cursor: grabbing; }
263
+
264
+ /* Path Mode Indicator */
265
+ #path-indicator {
266
+ position: absolute;
267
+ top: 52px;
268
+ left: 50%;
269
+ transform: translateX(-50%);
270
+ display: flex;
271
+ align-items: center;
272
+ gap: 12px;
273
+ padding: 8px 20px;
274
+ background: rgba(255,45,85,0.15);
275
+ border: 1px solid var(--risk-high);
276
+ border-radius: 3px;
277
+ z-index: 15;
278
+ font-size: 11px;
279
+ letter-spacing: 2px;
280
+ color: var(--risk-high);
281
+ animation: path-pulse 1.5s ease-in-out infinite;
282
+ }
283
+
284
+ @keyframes path-pulse {
285
+ 0%, 100% { box-shadow: 0 0 10px rgba(255,45,85,0.2); }
286
+ 50% { box-shadow: 0 0 25px rgba(255,45,85,0.5); }
287
+ }
288
+
289
+ #path-indicator.hidden { display: none; }
290
+
291
+ #btn-cancel-path {
292
+ padding: 3px 10px;
293
+ background: transparent;
294
+ color: var(--risk-high);
295
+ border: 1px solid var(--risk-high);
296
+ border-radius: 2px;
297
+ cursor: pointer;
298
+ font-size: 9px;
299
+ font-family: inherit;
300
+ letter-spacing: 2px;
301
+ }
302
+
303
+ /* Layer Legend */
304
+ #layer-legend {
305
+ position: absolute;
306
+ bottom: 50px;
307
+ left: 16px;
308
+ display: flex;
309
+ gap: 6px;
310
+ z-index: 12;
311
+ }
312
+
313
+ .legend-item {
314
+ display: flex;
315
+ align-items: center;
316
+ gap: 5px;
317
+ padding: 4px 10px;
318
+ background: rgba(3,7,18,0.85);
319
+ border: 1px solid var(--border);
320
+ border-radius: 2px;
321
+ cursor: pointer;
322
+ transition: all 0.2s;
323
+ font-size: 10px;
324
+ letter-spacing: 1px;
325
+ backdrop-filter: blur(4px);
326
+ user-select: none;
327
+ }
328
+
329
+ .legend-item:hover {
330
+ border-color: var(--accent);
331
+ box-shadow: var(--glow-cyan);
332
+ }
333
+
334
+ .legend-item.filtered {
335
+ opacity: 0.35;
336
+ text-decoration: line-through;
337
+ }
338
+
339
+ .legend-dot {
340
+ width: 8px;
341
+ height: 8px;
342
+ border-radius: 50%;
343
+ flex-shrink: 0;
344
+ }
345
+
346
+ .legend-label { font-weight: 600; color: var(--text-primary); }
347
+ .legend-count { color: var(--text-secondary); }
348
+
349
+ /* Layer badge */
350
+ .layer-badge {
351
+ display: inline-block;
352
+ padding: 1px 8px;
353
+ border: 1px solid;
354
+ border-radius: 2px;
355
+ font-size: 10px;
356
+ font-weight: 700;
357
+ letter-spacing: 2px;
358
+ }
359
+
360
+ /* Node Tooltip */
361
+ #node-tooltip {
362
+ position: fixed;
363
+ padding: 8px 14px;
364
+ background: rgba(10,22,40,0.95);
365
+ border: 1px solid var(--accent-dim);
366
+ border-radius: 2px;
367
+ font-size: 11px;
368
+ color: var(--accent);
369
+ pointer-events: none;
370
+ z-index: 100;
371
+ white-space: nowrap;
372
+ box-shadow: var(--glow-cyan);
373
+ backdrop-filter: blur(4px);
374
+ }
375
+
376
+ #node-tooltip.hidden { display: none; }
377
+
378
+ /* ── Resize Handle ── */
379
+ #resize-handle {
380
+ width: 8px;
381
+ cursor: col-resize;
382
+ background: var(--bg-secondary);
383
+ position: relative;
384
+ flex-shrink: 0;
385
+ z-index: 20;
386
+ transition: background 0.2s;
387
+ border-left: 1px solid var(--border);
388
+ border-right: 1px solid var(--border);
389
+ }
390
+
391
+ #resize-handle::before {
392
+ content: '';
393
+ position: absolute;
394
+ top: 50%;
395
+ left: 50%;
396
+ transform: translate(-50%, -50%);
397
+ width: 2px;
398
+ height: 48px;
399
+ border-radius: 2px;
400
+ background: var(--text-secondary);
401
+ opacity: 0.5;
402
+ transition: all 0.2s;
403
+ }
404
+
405
+ #resize-handle::after {
406
+ content: '';
407
+ position: absolute;
408
+ top: 50%;
409
+ left: 50%;
410
+ transform: translate(-50%, -50%);
411
+ width: 2px;
412
+ height: 48px;
413
+ border-radius: 2px;
414
+ background: var(--text-secondary);
415
+ opacity: 0;
416
+ box-shadow: -3px 0 0 var(--text-secondary), 3px 0 0 var(--text-secondary);
417
+ transition: all 0.2s;
418
+ }
419
+
420
+ #resize-handle:hover {
421
+ background: rgba(0, 212, 255, 0.08);
422
+ border-color: var(--accent-dim);
423
+ }
424
+
425
+ #resize-handle:hover::before {
426
+ background: var(--accent);
427
+ height: 64px;
428
+ opacity: 1;
429
+ box-shadow: var(--glow-cyan);
430
+ }
431
+
432
+ #resize-handle:hover::after {
433
+ opacity: 0.4;
434
+ height: 64px;
435
+ }
436
+
437
+ #resize-handle.dragging {
438
+ background: rgba(0, 212, 255, 0.12);
439
+ border-color: var(--accent);
440
+ }
441
+
442
+ #resize-handle.dragging::before {
443
+ background: var(--accent);
444
+ height: 100%;
445
+ opacity: 1;
446
+ box-shadow: var(--glow-cyan);
447
+ }
448
+
449
+ #resize-handle.dragging::after {
450
+ opacity: 0;
451
+ }
452
+
453
+ /* ── Right Panel ── */
454
+ #right-panel {
455
+ width: 380px;
456
+ flex: 0 0 380px;
457
+ display: flex;
458
+ flex-direction: column;
459
+ border-left: 1px solid var(--border);
460
+ background: var(--bg-secondary);
461
+ overflow: hidden;
462
+ position: relative;
463
+ }
464
+
465
+ #right-panel::before {
466
+ content: '';
467
+ position: absolute;
468
+ top: 0; left: -1px;
469
+ width: 1px;
470
+ height: 100%;
471
+ background: linear-gradient(180deg, var(--accent) 0%, transparent 30%, transparent 70%, var(--accent) 100%);
472
+ opacity: 0.3;
473
+ }
474
+
475
+ /* Panel Tabs */
476
+ #panel-tabs {
477
+ display: flex;
478
+ border-bottom: 1px solid var(--border);
479
+ flex-shrink: 0;
480
+ }
481
+
482
+ .panel-tab {
483
+ flex: 1;
484
+ padding: 10px 0;
485
+ background: transparent;
486
+ color: var(--text-secondary);
487
+ border: none;
488
+ border-bottom: 2px solid transparent;
489
+ cursor: pointer;
490
+ font-size: 11px;
491
+ font-family: inherit;
492
+ font-weight: 600;
493
+ letter-spacing: 3px;
494
+ transition: all 0.2s;
495
+ }
496
+
497
+ .panel-tab:hover { color: var(--accent); }
498
+
499
+ .panel-tab.active {
500
+ color: var(--accent);
501
+ border-bottom-color: var(--accent);
502
+ background: rgba(0,212,255,0.05);
503
+ }
504
+
505
+ .tab-content {
506
+ display: none;
507
+ flex: 1;
508
+ flex-direction: column;
509
+ overflow: hidden;
510
+ }
511
+
512
+ .tab-content.active {
513
+ display: flex;
514
+ }
515
+
516
+ #right-panel section {
517
+ padding: 14px 18px;
518
+ border-bottom: 1px solid var(--border);
519
+ }
520
+
521
+ #right-panel h3 {
522
+ font-size: 10px;
523
+ font-weight: 600;
524
+ color: var(--accent);
525
+ margin-bottom: 10px;
526
+ letter-spacing: 3px;
527
+ text-transform: uppercase;
528
+ display: flex;
529
+ align-items: center;
530
+ gap: 6px;
531
+ }
532
+
533
+ .hud-icon {
534
+ font-size: 12px;
535
+ opacity: 0.7;
536
+ }
537
+
538
+ #file-info { flex-shrink: 0; }
539
+ #impact-list { flex: 1; overflow-y: auto; }
540
+
541
+ #ai-panel {
542
+ flex: 1.2;
543
+ display: flex;
544
+ flex-direction: column;
545
+ overflow: hidden;
546
+ }
547
+
548
+ .ai-header {
549
+ display: flex;
550
+ justify-content: space-between;
551
+ align-items: center;
552
+ margin-bottom: 10px;
553
+ }
554
+
555
+ .ai-header h3 { margin-bottom: 0; }
556
+
557
+ #btn-ai-analyze {
558
+ padding: 5px 16px;
559
+ background: transparent;
560
+ color: var(--accent);
561
+ border: 1px solid var(--accent-dim);
562
+ border-radius: 2px;
563
+ cursor: pointer;
564
+ font-size: 10px;
565
+ font-family: inherit;
566
+ font-weight: 600;
567
+ letter-spacing: 2px;
568
+ transition: all 0.3s;
569
+ }
570
+
571
+ #btn-ai-analyze:disabled {
572
+ color: var(--text-secondary);
573
+ border-color: var(--border);
574
+ cursor: not-allowed;
575
+ }
576
+
577
+ #btn-ai-analyze:not(:disabled):hover {
578
+ background: rgba(0,212,255,0.15);
579
+ box-shadow: var(--glow-cyan);
580
+ }
581
+
582
+ #ai-content {
583
+ flex: 1;
584
+ overflow-y: auto;
585
+ font-size: 12px;
586
+ line-height: 1.7;
587
+ }
588
+
589
+ /* ── Code Preview ── */
590
+ #code-panel {
591
+ flex: 1;
592
+ display: flex;
593
+ flex-direction: column;
594
+ overflow: hidden;
595
+ }
596
+
597
+ #code-content {
598
+ flex: 1;
599
+ overflow-y: auto;
600
+ font-size: 11px;
601
+ line-height: 1.6;
602
+ }
603
+
604
+ .code-block {
605
+ background: rgba(0,0,0,0.4);
606
+ border: 1px solid var(--border);
607
+ border-radius: 3px;
608
+ padding: 12px;
609
+ overflow-x: auto;
610
+ white-space: pre;
611
+ font-family: 'Consolas', monospace;
612
+ font-size: 10px;
613
+ line-height: 1.5;
614
+ color: var(--text-primary);
615
+ tab-size: 2;
616
+ }
617
+
618
+ .code-block .line-num {
619
+ color: var(--text-secondary);
620
+ display: inline-block;
621
+ width: 36px;
622
+ text-align: right;
623
+ margin-right: 12px;
624
+ user-select: none;
625
+ opacity: 0.5;
626
+ }
627
+
628
+ /* ── Simulation Panel ── */
629
+ #sim-panel {
630
+ flex: 1;
631
+ display: flex;
632
+ flex-direction: column;
633
+ overflow: hidden;
634
+ }
635
+
636
+ #sim-content {
637
+ flex: 1;
638
+ overflow-y: auto;
639
+ font-size: 12px;
640
+ line-height: 1.7;
641
+ }
642
+
643
+ .sim-severity {
644
+ display: inline-block;
645
+ padding: 3px 12px;
646
+ border-radius: 2px;
647
+ font-size: 11px;
648
+ font-weight: 700;
649
+ letter-spacing: 2px;
650
+ margin: 8px 0;
651
+ }
652
+
653
+ .sim-severity.CRITICAL { background: rgba(255,45,85,0.3); color: #ff2d55; border: 1px solid #ff2d55; }
654
+ .sim-severity.HIGH { background: rgba(255,45,85,0.2); color: #ff6b8a; border: 1px solid #ff6b8a; }
655
+ .sim-severity.MEDIUM { background: rgba(255,159,10,0.2); color: var(--risk-medium); border: 1px solid var(--risk-medium); }
656
+ .sim-severity.LOW { background: rgba(48,209,88,0.2); color: var(--risk-low); border: 1px solid var(--risk-low); }
657
+
658
+ .sim-section {
659
+ margin: 10px 0;
660
+ padding: 8px 0;
661
+ border-top: 1px solid rgba(26,45,77,0.5);
662
+ }
663
+
664
+ .sim-section h4 {
665
+ font-size: 10px;
666
+ color: var(--risk-high);
667
+ letter-spacing: 2px;
668
+ margin-bottom: 6px;
669
+ }
670
+
671
+ .sim-file {
672
+ font-size: 11px;
673
+ color: var(--text-secondary);
674
+ padding: 2px 0;
675
+ cursor: pointer;
676
+ }
677
+
678
+ .sim-file:hover { color: var(--accent); }
679
+
680
+ .placeholder {
681
+ color: var(--text-secondary);
682
+ font-size: 11px;
683
+ letter-spacing: 1px;
684
+ }
685
+
686
+ /* ── File Info Styles ── */
687
+ .file-detail { margin-bottom: 6px; font-size: 12px; }
688
+ .file-detail .label { color: var(--text-secondary); }
689
+ .file-detail .value { color: var(--text-primary); font-weight: 600; }
690
+
691
+ .risk-badge {
692
+ display: inline-block;
693
+ padding: 2px 10px;
694
+ border-radius: 2px;
695
+ font-size: 10px;
696
+ font-weight: 700;
697
+ letter-spacing: 2px;
698
+ text-transform: uppercase;
699
+ }
700
+
701
+ .risk-badge.HIGH { background: rgba(255,45,85,0.2); color: var(--risk-high); border: 1px solid rgba(255,45,85,0.4); }
702
+ .risk-badge.MEDIUM { background: rgba(255,159,10,0.2); color: var(--risk-medium); border: 1px solid rgba(255,159,10,0.4); }
703
+ .risk-badge.LOW { background: rgba(48,209,88,0.2); color: var(--risk-low); border: 1px solid rgba(48,209,88,0.4); }
704
+ .risk-badge.NONE { background: rgba(58,79,111,0.2); color: var(--risk-none); border: 1px solid rgba(58,79,111,0.4); }
705
+
706
+ /* ── Impact List ── */
707
+ .impact-item {
708
+ padding: 4px 0;
709
+ font-size: 11px;
710
+ color: var(--text-secondary);
711
+ border-bottom: 1px solid rgba(26,45,77,0.5);
712
+ cursor: pointer;
713
+ transition: color 0.2s;
714
+ }
715
+
716
+ .impact-item:hover { color: var(--accent); }
717
+ .impact-item.direct { color: var(--risk-high); }
718
+ .impact-item.transitive { color: var(--risk-medium); }
719
+
720
+ /* ── AI Content ── */
721
+ #ai-content h2 { font-size: 13px; margin: 14px 0 6px; color: var(--accent); letter-spacing: 1px; }
722
+ #ai-content h3 { font-size: 12px; margin: 10px 0 4px; color: var(--text-primary); }
723
+ #ai-content p { margin-bottom: 6px; }
724
+ #ai-content ul { padding-left: 16px; margin-bottom: 6px; }
725
+ #ai-content li { margin-bottom: 2px; }
726
+ #ai-content code {
727
+ background: rgba(0,212,255,0.1);
728
+ color: var(--accent);
729
+ padding: 1px 6px;
730
+ border-radius: 2px;
731
+ font-size: 11px;
732
+ }
733
+
734
+ /* ── Loading ── */
735
+ .loading {
736
+ display: flex;
737
+ align-items: center;
738
+ gap: 10px;
739
+ color: var(--accent);
740
+ font-size: 11px;
741
+ letter-spacing: 2px;
742
+ }
743
+
744
+ .spinner {
745
+ width: 14px;
746
+ height: 14px;
747
+ border: 2px solid var(--border);
748
+ border-top-color: var(--accent);
749
+ border-radius: 50%;
750
+ animation: spin 0.8s linear infinite;
751
+ }
752
+
753
+ @keyframes spin { to { transform: rotate(360deg); } }
754
+
755
+ /* ── Context Menu ── */
756
+ #context-menu {
757
+ position: fixed;
758
+ min-width: 180px;
759
+ background: rgba(10,22,40,0.97);
760
+ border: 1px solid var(--accent-dim);
761
+ border-radius: 3px;
762
+ z-index: 200;
763
+ box-shadow: var(--glow-cyan), 0 8px 32px rgba(0,0,0,0.5);
764
+ backdrop-filter: blur(8px);
765
+ padding: 4px 0;
766
+ }
767
+
768
+ #context-menu.hidden { display: none; }
769
+
770
+ .ctx-item {
771
+ padding: 8px 16px;
772
+ font-size: 10px;
773
+ letter-spacing: 2px;
774
+ color: var(--text-primary);
775
+ cursor: pointer;
776
+ transition: all 0.15s;
777
+ }
778
+
779
+ .ctx-item:hover {
780
+ background: rgba(0,212,255,0.12);
781
+ color: var(--accent);
782
+ }
783
+
784
+ .ctx-divider {
785
+ height: 1px;
786
+ background: var(--border);
787
+ margin: 4px 0;
788
+ }
789
+
790
+ /* ── Stats Overlay ── */
791
+ #stats-overlay {
792
+ position: fixed;
793
+ top: 0; left: 0; right: 0; bottom: 0;
794
+ background: rgba(5,10,24,0.85);
795
+ z-index: 300;
796
+ display: flex;
797
+ align-items: center;
798
+ justify-content: center;
799
+ backdrop-filter: blur(4px);
800
+ }
801
+
802
+ #stats-overlay.hidden { display: none; }
803
+
804
+ .stats-panel {
805
+ background: var(--bg-secondary);
806
+ border: 1px solid var(--accent-dim);
807
+ border-radius: 6px;
808
+ width: 650px;
809
+ max-height: 80vh;
810
+ overflow-y: auto;
811
+ box-shadow: var(--glow-cyan), 0 16px 64px rgba(0,0,0,0.5);
812
+ }
813
+
814
+ .stats-header {
815
+ display: flex;
816
+ justify-content: space-between;
817
+ align-items: center;
818
+ padding: 16px 20px;
819
+ border-bottom: 1px solid var(--border);
820
+ }
821
+
822
+ .stats-header h3 {
823
+ font-size: 12px;
824
+ color: var(--accent);
825
+ letter-spacing: 3px;
826
+ }
827
+
828
+ .stats-header button {
829
+ background: transparent;
830
+ border: none;
831
+ color: var(--text-secondary);
832
+ font-size: 20px;
833
+ cursor: pointer;
834
+ }
835
+
836
+ .stats-header button:hover { color: var(--accent); }
837
+
838
+ .stats-body { padding: 16px 20px; }
839
+
840
+ .stats-row {
841
+ display: flex;
842
+ gap: 16px;
843
+ margin-bottom: 16px;
844
+ }
845
+
846
+ .stats-card {
847
+ flex: 1;
848
+ background: rgba(0,0,0,0.3);
849
+ border: 1px solid var(--border);
850
+ border-radius: 4px;
851
+ padding: 12px;
852
+ }
853
+
854
+ .stats-card h4 {
855
+ font-size: 9px;
856
+ color: var(--text-secondary);
857
+ letter-spacing: 2px;
858
+ margin-bottom: 8px;
859
+ }
860
+
861
+ .stats-summary {
862
+ font-size: 11px;
863
+ color: var(--text-secondary);
864
+ padding: 10px;
865
+ border-top: 1px solid var(--border);
866
+ line-height: 1.8;
867
+ }
868
+
869
+ /* ── Keyboard Shortcuts Overlay ── */
870
+ #shortcuts-overlay {
871
+ position: fixed;
872
+ top: 0; left: 0; right: 0; bottom: 0;
873
+ background: rgba(5,10,24,0.85);
874
+ z-index: 300;
875
+ display: flex;
876
+ align-items: center;
877
+ justify-content: center;
878
+ backdrop-filter: blur(4px);
879
+ }
880
+
881
+ #shortcuts-overlay.hidden { display: none; }
882
+
883
+ .shortcuts-panel {
884
+ background: var(--bg-secondary);
885
+ border: 1px solid var(--accent-dim);
886
+ border-radius: 6px;
887
+ padding: 24px 32px;
888
+ min-width: 320px;
889
+ box-shadow: var(--glow-cyan);
890
+ }
891
+
892
+ .shortcuts-panel h3 {
893
+ font-size: 12px;
894
+ color: var(--accent);
895
+ letter-spacing: 3px;
896
+ margin-bottom: 16px;
897
+ }
898
+
899
+ .shortcut-row {
900
+ display: flex;
901
+ align-items: center;
902
+ gap: 16px;
903
+ padding: 6px 0;
904
+ font-size: 12px;
905
+ }
906
+
907
+ .shortcut-row kbd {
908
+ display: inline-block;
909
+ min-width: 32px;
910
+ text-align: center;
911
+ padding: 3px 8px;
912
+ background: rgba(0,212,255,0.1);
913
+ border: 1px solid var(--accent-dim);
914
+ border-radius: 3px;
915
+ color: var(--accent);
916
+ font-size: 11px;
917
+ font-family: inherit;
918
+ font-weight: 700;
919
+ }
920
+
921
+ .shortcut-row span { color: var(--text-secondary); }
922
+
923
+ #btn-close-shortcuts {
924
+ display: block;
925
+ width: 100%;
926
+ margin-top: 16px;
927
+ padding: 8px;
928
+ background: transparent;
929
+ color: var(--accent);
930
+ border: 1px solid var(--accent-dim);
931
+ border-radius: 3px;
932
+ cursor: pointer;
933
+ font-size: 10px;
934
+ font-family: inherit;
935
+ letter-spacing: 3px;
936
+ transition: all 0.2s;
937
+ }
938
+
939
+ #btn-close-shortcuts:hover {
940
+ background: rgba(0,212,255,0.1);
941
+ box-shadow: var(--glow-cyan);
942
+ }
943
+
944
+ /* ── Cycles Overlay ── */
945
+ #cycles-overlay {
946
+ position: fixed;
947
+ top: 0; left: 0; right: 0; bottom: 0;
948
+ background: rgba(5,10,24,0.85);
949
+ z-index: 300;
950
+ display: flex;
951
+ align-items: center;
952
+ justify-content: center;
953
+ backdrop-filter: blur(4px);
954
+ }
955
+
956
+ #cycles-overlay.hidden { display: none; }
957
+
958
+ .cycles-panel {
959
+ background: var(--bg-secondary);
960
+ border: 1px solid var(--risk-high);
961
+ border-radius: 6px;
962
+ width: 500px;
963
+ max-height: 70vh;
964
+ overflow-y: auto;
965
+ box-shadow: var(--glow-red);
966
+ }
967
+
968
+ .cycles-header {
969
+ display: flex;
970
+ justify-content: space-between;
971
+ align-items: center;
972
+ padding: 16px 20px;
973
+ border-bottom: 1px solid var(--border);
974
+ }
975
+
976
+ .cycles-header h3 {
977
+ font-size: 12px;
978
+ color: var(--risk-high);
979
+ letter-spacing: 3px;
980
+ }
981
+
982
+ .cycles-header button {
983
+ background: transparent;
984
+ border: none;
985
+ color: var(--text-secondary);
986
+ font-size: 20px;
987
+ cursor: pointer;
988
+ }
989
+
990
+ #cycles-content {
991
+ padding: 16px 20px;
992
+ }
993
+
994
+ .cycle-item {
995
+ margin-bottom: 12px;
996
+ padding: 10px;
997
+ background: rgba(255,45,85,0.05);
998
+ border: 1px solid rgba(255,45,85,0.2);
999
+ border-radius: 3px;
1000
+ }
1001
+
1002
+ .cycle-item h4 {
1003
+ font-size: 10px;
1004
+ color: var(--risk-high);
1005
+ letter-spacing: 2px;
1006
+ margin-bottom: 6px;
1007
+ }
1008
+
1009
+ .cycle-path {
1010
+ font-size: 11px;
1011
+ color: var(--text-secondary);
1012
+ line-height: 1.8;
1013
+ }
1014
+
1015
+ .cycle-path .arrow { color: var(--risk-high); margin: 0 4px; }
1016
+ .cycle-path .file { cursor: pointer; }
1017
+ .cycle-path .file:hover { color: var(--accent); }
1018
+
1019
+ .no-cycles {
1020
+ text-align: center;
1021
+ padding: 30px;
1022
+ color: var(--risk-low);
1023
+ font-size: 12px;
1024
+ letter-spacing: 2px;
1025
+ }
1026
+
1027
+ /* ── Hub Drawer ── */
1028
+ #hub-drawer {
1029
+ position: fixed;
1030
+ bottom: 0;
1031
+ left: 0;
1032
+ right: 380px;
1033
+ background: var(--bg-secondary);
1034
+ border-top: 1px solid var(--border);
1035
+ transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
1036
+ z-index: 10;
1037
+ }
1038
+
1039
+ #hub-drawer.collapsed { transform: translateY(calc(100% - 32px)); }
1040
+
1041
+ #btn-toggle-hub {
1042
+ display: block;
1043
+ width: 100%;
1044
+ padding: 7px;
1045
+ background: rgba(0,212,255,0.05);
1046
+ color: var(--accent);
1047
+ border: none;
1048
+ border-bottom: 1px solid var(--border);
1049
+ cursor: pointer;
1050
+ font-size: 10px;
1051
+ font-family: inherit;
1052
+ font-weight: 600;
1053
+ letter-spacing: 3px;
1054
+ }
1055
+
1056
+ #btn-toggle-hub:hover { background: rgba(0,212,255,0.1); }
1057
+
1058
+ #hub-content {
1059
+ padding: 8px 18px;
1060
+ max-height: 200px;
1061
+ overflow-y: auto;
1062
+ }
1063
+
1064
+ .hub-item {
1065
+ display: flex;
1066
+ align-items: center;
1067
+ padding: 5px 0;
1068
+ font-size: 11px;
1069
+ border-bottom: 1px solid rgba(26,45,77,0.5);
1070
+ cursor: pointer;
1071
+ transition: color 0.2s;
1072
+ }
1073
+
1074
+ .hub-item:hover { color: var(--accent); }
1075
+ .hub-rank { color: var(--text-secondary); width: 28px; }
1076
+ .hub-name { flex: 1; }
1077
+ .hub-count { color: var(--text-secondary); margin-right: 10px; font-variant-numeric: tabular-nums; }
1078
+
1079
+ /* ── Node Labels Overlay ── */
1080
+ #node-labels {
1081
+ position: absolute;
1082
+ top: 0; left: 0; right: 0; bottom: 0;
1083
+ pointer-events: none;
1084
+ z-index: 8;
1085
+ overflow: hidden;
1086
+ }
1087
+ .node-lbl {
1088
+ position: absolute;
1089
+ font-family: 'Consolas', monospace;
1090
+ font-size: 10px;
1091
+ font-weight: 700;
1092
+ color: #ffffff;
1093
+ background: rgba(5, 10, 24, 0.7);
1094
+ border: 1px solid rgba(0, 212, 255, 0.4);
1095
+ border-radius: 3px;
1096
+ padding: 2px 5px;
1097
+ white-space: nowrap;
1098
+ transform: translate(-50%, 0);
1099
+ text-shadow: 0 0 4px rgba(0,0,0,1);
1100
+ letter-spacing: 0.5px;
1101
+ line-height: 1.4;
1102
+ }
1103
+ .node-lbl .lbl-dim {
1104
+ opacity: 0.6;
1105
+ font-weight: 400;
1106
+ }
1107
+
1108
+ /* ── Path Highlight ── */
1109
+ .path-node-marker {
1110
+ position: absolute;
1111
+ width: 20px;
1112
+ height: 20px;
1113
+ border-radius: 50%;
1114
+ border: 2px solid #ffff00;
1115
+ box-shadow: 0 0 15px rgba(255,255,0,0.5);
1116
+ pointer-events: none;
1117
+ transform: translate(-50%, -50%);
1118
+ animation: path-marker-pulse 1s ease-in-out infinite;
1119
+ z-index: 9;
1120
+ }
1121
+
1122
+ @keyframes path-marker-pulse {
1123
+ 0%, 100% { transform: translate(-50%, -50%) scale(1); }
1124
+ 50% { transform: translate(-50%, -50%) scale(1.3); }
1125
+ }
1126
+
1127
+ /* ═══════════════════════════════════════════
1128
+ STAR WARS CODE CRAWL
1129
+ ═══════════════════════════════════════════ */
1130
+
1131
+ #code-crawl {
1132
+ position: absolute;
1133
+ right: 20px;
1134
+ top: 60px;
1135
+ width: 500px;
1136
+ max-height: 500px;
1137
+ pointer-events: auto;
1138
+ z-index: 7;
1139
+ overflow: hidden;
1140
+ display: none;
1141
+ border-radius: 4px;
1142
+ }
1143
+
1144
+ #code-crawl.active {
1145
+ display: block;
1146
+ }
1147
+
1148
+ #crawl-header {
1149
+ position: absolute;
1150
+ top: 0;
1151
+ left: 0; right: 0;
1152
+ padding: 6px 12px;
1153
+ display: flex;
1154
+ justify-content: space-between;
1155
+ align-items: center;
1156
+ z-index: 2;
1157
+ background: linear-gradient(180deg, rgba(5,10,24,0.98) 60%, transparent 100%);
1158
+ }
1159
+
1160
+ #crawl-file-name {
1161
+ font-size: 9px;
1162
+ color: var(--accent);
1163
+ letter-spacing: 2px;
1164
+ font-weight: 600;
1165
+ text-transform: uppercase;
1166
+ opacity: 0.7;
1167
+ }
1168
+
1169
+ #crawl-status {
1170
+ font-size: 9px;
1171
+ letter-spacing: 2px;
1172
+ color: var(--risk-low);
1173
+ }
1174
+
1175
+ #crawl-status.modifying {
1176
+ color: var(--risk-high);
1177
+ animation: status-blink 0.6s ease-in-out infinite;
1178
+ }
1179
+
1180
+ @keyframes status-blink {
1181
+ 0%, 100% { opacity: 1; }
1182
+ 50% { opacity: 0.3; }
1183
+ }
1184
+
1185
+ #crawl-viewport {
1186
+ position: absolute;
1187
+ top: 28px; left: 0; right: 0; bottom: 0;
1188
+ overflow-y: auto;
1189
+ overflow-x: hidden;
1190
+ }
1191
+
1192
+ #crawl-content {
1193
+ padding: 4px 8px;
1194
+ }
1195
+
1196
+ /* Individual crawl line — VS Code Dark+ style base */
1197
+ .crawl-line {
1198
+ font-family: 'Consolas', 'SF Mono', 'Fira Code', monospace;
1199
+ font-size: 11px;
1200
+ line-height: 1.5;
1201
+ white-space: pre;
1202
+ color: #d4d4d4;
1203
+ overflow: hidden;
1204
+ text-overflow: ellipsis;
1205
+ }
1206
+
1207
+ .crawl-line .cl-num {
1208
+ display: inline-block;
1209
+ width: 28px;
1210
+ text-align: right;
1211
+ margin-right: 10px;
1212
+ color: rgba(90, 117, 153, 0.4);
1213
+ user-select: none;
1214
+ font-size: 9px;
1215
+ }
1216
+
1217
+ /* ── VS Code Dark+ Syntax Colors ── */
1218
+ .crawl-line .kw { color: #569cd6; } /* keywords: import, class, if, return, final, const, void */
1219
+ .crawl-line .type { color: #4ec9b0; } /* types: String, int, Widget, List, Map, bool */
1220
+ .crawl-line .str { color: #ce9178; } /* strings */
1221
+ .crawl-line .cmt { color: #6a9955; font-style: italic; } /* comments */
1222
+ .crawl-line .num { color: #b5cea8; } /* numbers */
1223
+ .crawl-line .fn { color: #dcdcaa; } /* function calls */
1224
+ .crawl-line .ann { color: #d7ba7d; } /* annotations @override */
1225
+ .crawl-line .punc { color: #808080; } /* punctuation: {}(); */
1226
+ .crawl-line .prop { color: #9cdcfe; } /* properties/variables */
1227
+
1228
+ /* File separator */
1229
+ .crawl-separator {
1230
+ padding: 10px 0 4px 0;
1231
+ font-size: 9px;
1232
+ font-weight: 700;
1233
+ letter-spacing: 2px;
1234
+ text-transform: uppercase;
1235
+ border-top: 1px solid rgba(0, 212, 255, 0.12);
1236
+ margin-top: 8px;
1237
+ }
1238
+
1239
+ .crawl-separator .sep-path { color: var(--accent); opacity: 0.6; }
1240
+ .crawl-separator .sep-layer { font-size: 8px; opacity: 0.4; margin-left: 6px; }
1241
+
1242
+ /* ── Real-time diff styles ── */
1243
+ .diff-marker {
1244
+ display: inline-block;
1245
+ width: 14px;
1246
+ font-weight: 700;
1247
+ text-align: center;
1248
+ margin-right: 4px;
1249
+ }
1250
+ .crawl-line.added .diff-marker { color: #30d158; }
1251
+ .crawl-line.removed .diff-marker { color: #ff2d55; }
1252
+ .crawl-line.changed .diff-marker { color: #ff9f0a; }
1253
+
1254
+ .crawl-line.added {
1255
+ background: rgba(48, 209, 88, 0.12);
1256
+ box-shadow: inset 3px 0 0 #30d158;
1257
+ animation: diff-flash-green 0.6s ease-out;
1258
+ }
1259
+
1260
+ .crawl-line.removed {
1261
+ background: rgba(255, 45, 85, 0.1);
1262
+ box-shadow: inset 3px 0 0 #ff2d55;
1263
+ animation: diff-flash-red 0.6s ease-out;
1264
+ }
1265
+ .crawl-line.removed .old-code {
1266
+ text-decoration: line-through;
1267
+ opacity: 0.6;
1268
+ }
1269
+
1270
+ .crawl-line.changed {
1271
+ background: rgba(255, 159, 10, 0.1);
1272
+ box-shadow: inset 3px 0 0 #ff9f0a;
1273
+ animation: diff-flash-yellow 0.6s ease-out;
1274
+ }
1275
+
1276
+ .crawl-line.modified {
1277
+ background: rgba(48, 209, 88, 0.08);
1278
+ box-shadow: inset 3px 0 0 #30d158;
1279
+ }
1280
+
1281
+ .crawl-line.error-line {
1282
+ background: rgba(255, 45, 85, 0.1);
1283
+ box-shadow: inset 3px 0 0 #ff2d55;
1284
+ animation: error-flash 1s ease-in-out 3;
1285
+ }
1286
+
1287
+ .diff-banner {
1288
+ padding: 6px 12px;
1289
+ margin-bottom: 4px;
1290
+ font-size: 10px;
1291
+ font-weight: 700;
1292
+ letter-spacing: 2px;
1293
+ border-left: 3px solid;
1294
+ }
1295
+ .diff-banner.diff-added { color: #30d158; border-color: #30d158; background: rgba(48,209,88,0.08); }
1296
+ .diff-banner.diff-removed { color: #ff2d55; border-color: #ff2d55; background: rgba(255,45,85,0.08); }
1297
+ .diff-banner.diff-deleted { color: #ff2d55; border-color: #ff2d55; background: rgba(255,45,85,0.1); }
1298
+ .diff-banner.diff-modified { color: #ff9f0a; border-color: #ff9f0a; background: rgba(255,159,10,0.08); }
1299
+ .diff-banner.diff-analysis {
1300
+ border-color: var(--accent);
1301
+ background: rgba(0,212,255,0.06);
1302
+ font-weight: 400;
1303
+ font-size: 11px;
1304
+ letter-spacing: 0;
1305
+ line-height: 1.4;
1306
+ margin-top: 2px;
1307
+ }
1308
+
1309
+ @keyframes diff-flash-green {
1310
+ 0% { background: rgba(48, 209, 88, 0.4); }
1311
+ 100% { background: rgba(48, 209, 88, 0.12); }
1312
+ }
1313
+ @keyframes diff-flash-red {
1314
+ 0% { background: rgba(255, 45, 85, 0.35); }
1315
+ 100% { background: rgba(255, 45, 85, 0.1); }
1316
+ }
1317
+ @keyframes diff-flash-yellow {
1318
+ 0% { background: rgba(255, 159, 10, 0.35); }
1319
+ 100% { background: rgba(255, 159, 10, 0.1); }
1320
+ }
1321
+
1322
+ @keyframes error-flash {
1323
+ 0%, 100% { background: rgba(255, 45, 85, 0.1); }
1324
+ 50% { background: rgba(255, 45, 85, 0.25); }
1325
+ }
1326
+
1327
+ /* ── Scrollbar ── */
1328
+ ::-webkit-scrollbar { width: 4px; }
1329
+ ::-webkit-scrollbar-track { background: transparent; }
1330
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
1331
+ ::-webkit-scrollbar-thumb:hover { background: var(--accent-dim); }
1332
+
1333
+ /* ═══════════════════════════════════════════ */
1334
+ /* SSE Status Indicator */
1335
+ /* ═══════════════════════════════════════════ */
1336
+ .sse-indicator {
1337
+ font-size: 9px;
1338
+ letter-spacing: 1.5px;
1339
+ padding: 2px 8px;
1340
+ border-radius: 3px;
1341
+ border: 1px solid var(--border);
1342
+ margin-left: 12px;
1343
+ font-weight: 600;
1344
+ transition: all 0.3s;
1345
+ }
1346
+ .sse-indicator.connected {
1347
+ color: var(--risk-low);
1348
+ border-color: var(--risk-low);
1349
+ text-shadow: 0 0 8px rgba(48,209,88,0.5);
1350
+ }
1351
+ .sse-indicator.offline {
1352
+ color: var(--text-secondary);
1353
+ border-color: var(--text-secondary);
1354
+ }
1355
+ .sse-indicator.warning {
1356
+ color: var(--risk-medium);
1357
+ border-color: var(--risk-medium);
1358
+ animation: sse-pulse 1s infinite;
1359
+ }
1360
+ .sse-indicator.analyzing {
1361
+ color: var(--accent);
1362
+ border-color: var(--accent);
1363
+ animation: sse-pulse 0.5s infinite;
1364
+ }
1365
+ .sse-indicator.danger {
1366
+ color: var(--risk-high);
1367
+ border-color: var(--risk-high);
1368
+ animation: sse-pulse 0.3s infinite;
1369
+ text-shadow: 0 0 12px rgba(255,45,85,0.6);
1370
+ }
1371
+ .sse-indicator.critical {
1372
+ color: #ff0040;
1373
+ border-color: #ff0040;
1374
+ background: rgba(255,0,64,0.15);
1375
+ animation: sse-pulse 0.2s infinite;
1376
+ text-shadow: 0 0 16px rgba(255,0,64,0.8);
1377
+ }
1378
+ .sse-indicator.safe {
1379
+ color: var(--risk-low);
1380
+ border-color: var(--risk-low);
1381
+ }
1382
+
1383
+ @keyframes sse-pulse {
1384
+ 0%, 100% { opacity: 1; }
1385
+ 50% { opacity: 0.4; }
1386
+ }
1387
+
1388
+ /* Pulse dot states */
1389
+ .pulse-dot.connected { background: var(--risk-low); box-shadow: 0 0 8px var(--risk-low); }
1390
+ .pulse-dot.warning { background: var(--risk-medium); box-shadow: 0 0 8px var(--risk-medium); }
1391
+ .pulse-dot.analyzing { background: var(--accent); box-shadow: 0 0 12px var(--accent); }
1392
+ .pulse-dot.danger { background: var(--risk-high); box-shadow: 0 0 12px var(--risk-high); }
1393
+ .pulse-dot.critical { background: #ff0040; box-shadow: 0 0 16px #ff0040; }
1394
+ .pulse-dot.offline { background: var(--text-secondary); box-shadow: none; }
1395
+
1396
+ /* ═══════════════════════════════════════════ */
1397
+ /* Realtime Monitor Panel */
1398
+ /* ═══════════════════════════════════════════ */
1399
+ #live-panel {
1400
+ padding: 12px;
1401
+ }
1402
+ #realtime-log {
1403
+ max-height: calc(100vh - 200px);
1404
+ overflow-y: auto;
1405
+ }
1406
+ .rt-event {
1407
+ display: flex;
1408
+ align-items: center;
1409
+ gap: 6px;
1410
+ padding: 4px 8px;
1411
+ margin-bottom: 2px;
1412
+ border-radius: 3px;
1413
+ font-size: 11px;
1414
+ border-left: 2px solid transparent;
1415
+ }
1416
+ .rt-event.rt-modified { border-left-color: var(--risk-medium); background: rgba(255,159,10,0.06); }
1417
+ .rt-event.rt-added { border-left-color: var(--risk-low); background: rgba(48,209,88,0.06); }
1418
+ .rt-event.rt-deleted { border-left-color: var(--risk-high); background: rgba(255,45,85,0.06); }
1419
+ .rt-event.rt-analyzing { border-left-color: var(--accent); background: rgba(0,212,255,0.06); }
1420
+ .rt-event.rt-result { border-left-color: var(--text-secondary); }
1421
+ .rt-event.rt-result.rt-critical { border-left-color: #ff0040; background: rgba(255,0,64,0.1); }
1422
+ .rt-event.rt-result.rt-danger { border-left-color: var(--risk-high); background: rgba(255,45,85,0.08); }
1423
+ .rt-event.rt-result.rt-warning { border-left-color: var(--risk-medium); background: rgba(255,159,10,0.08); }
1424
+ .rt-event.rt-result.rt-safe { border-left-color: var(--risk-low); background: rgba(48,209,88,0.06); }
1425
+
1426
+ .rt-time {
1427
+ color: var(--text-secondary);
1428
+ font-size: 9px;
1429
+ min-width: 55px;
1430
+ }
1431
+ .rt-icon {
1432
+ font-size: 12px;
1433
+ min-width: 14px;
1434
+ text-align: center;
1435
+ }
1436
+ .rt-event.rt-modified .rt-icon { color: var(--risk-medium); }
1437
+ .rt-event.rt-added .rt-icon { color: var(--risk-low); }
1438
+ .rt-event.rt-deleted .rt-icon { color: var(--risk-high); }
1439
+ .rt-event.rt-analyzing .rt-icon { color: var(--accent); animation: spin 1s linear infinite; }
1440
+
1441
+ @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
1442
+
1443
+ .rt-file {
1444
+ color: var(--text-primary);
1445
+ overflow: hidden;
1446
+ text-overflow: ellipsis;
1447
+ white-space: nowrap;
1448
+ flex: 1;
1449
+ }
1450
+ .rt-diff { color: var(--text-secondary); font-size: 9px; }
1451
+ .rt-msg { color: var(--accent); flex: 1; }
1452
+ .rt-ms { color: var(--text-secondary); font-size: 9px; }
1453
+ .rt-risk {
1454
+ font-size: 9px;
1455
+ font-weight: 700;
1456
+ letter-spacing: 1px;
1457
+ padding: 1px 5px;
1458
+ border-radius: 2px;
1459
+ min-width: 55px;
1460
+ text-align: center;
1461
+ }
1462
+ .rt-risk.critical { color: #ff0040; background: rgba(255,0,64,0.2); }
1463
+ .rt-risk.danger { color: var(--risk-high); background: rgba(255,45,85,0.2); }
1464
+ .rt-risk.warning { color: var(--risk-medium); background: rgba(255,159,10,0.2); }
1465
+ .rt-risk.safe { color: var(--risk-low); background: rgba(48,209,88,0.2); }
1466
+
1467
+ .rt-detail {
1468
+ font-size: 10px;
1469
+ padding: 2px 8px 2px 80px;
1470
+ color: var(--text-secondary);
1471
+ line-height: 1.4;
1472
+ }
1473
+ .rt-detail.rt-broken { color: var(--risk-high); }
1474
+ .rt-detail.rt-warn { color: var(--risk-medium); }
1475
+ .rt-detail.rt-suggestion { color: var(--accent); font-style: italic; }
1476
+
1477
+ /* ═══════════════════════════════════════════ */
1478
+ /* Diff Scroll Animation */
1479
+ /* ═══════════════════════════════════════════ */
1480
+ .crawl-line.diff-flash-active {
1481
+ animation: diff-line-flash 0.8s ease-out;
1482
+ }
1483
+ .crawl-line.diff-flash-active.added {
1484
+ animation: diff-line-flash-green 0.8s ease-out;
1485
+ }
1486
+ .crawl-line.diff-flash-active.removed {
1487
+ animation: diff-line-flash-red 0.8s ease-out;
1488
+ }
1489
+ .crawl-line.diff-flash-active.changed {
1490
+ animation: diff-line-flash-yellow 0.8s ease-out;
1491
+ }
1492
+
1493
+ @keyframes diff-line-flash-green {
1494
+ 0% { background: rgba(48, 209, 88, 0.6); box-shadow: 0 0 20px rgba(48, 209, 88, 0.4); }
1495
+ 100% { background: rgba(48, 209, 88, 0.12); box-shadow: none; }
1496
+ }
1497
+ @keyframes diff-line-flash-red {
1498
+ 0% { background: rgba(255, 45, 85, 0.5); box-shadow: 0 0 20px rgba(255, 45, 85, 0.4); }
1499
+ 100% { background: rgba(255, 45, 85, 0.1); box-shadow: none; }
1500
+ }
1501
+ @keyframes diff-line-flash-yellow {
1502
+ 0% { background: rgba(255, 159, 10, 0.5); box-shadow: 0 0 20px rgba(255, 159, 10, 0.4); }
1503
+ 100% { background: rgba(255, 159, 10, 0.1); box-shadow: none; }
1504
+ }
1505
+ @keyframes diff-line-flash {
1506
+ 0% { background: rgba(200, 214, 229, 0.3); }
1507
+ 100% { background: transparent; }
1508
+ }
1509
+
1510
+ /* Crawl status when modifying */
1511
+ #crawl-status.modifying {
1512
+ color: var(--risk-medium);
1513
+ animation: sse-pulse 0.5s infinite;
1514
+ }
1515
+
1516
+ /* ═══════════════════════════════════════════ */
1517
+ /* Audit Result (post-analysis) */
1518
+ /* ═══════════════════════════════════════════ */
1519
+ .audit-result {
1520
+ display: flex;
1521
+ flex-direction: column;
1522
+ align-items: center;
1523
+ justify-content: center;
1524
+ padding: 40px 24px;
1525
+ text-align: center;
1526
+ animation: audit-fade-in 0.6s ease-out;
1527
+ }
1528
+ .audit-result.audit-clear .audit-icon {
1529
+ font-size: 48px;
1530
+ color: var(--risk-low);
1531
+ text-shadow: 0 0 30px rgba(48, 209, 88, 0.6);
1532
+ margin-bottom: 16px;
1533
+ }
1534
+ .audit-result.audit-clear .audit-title {
1535
+ font-size: 16px;
1536
+ font-weight: 700;
1537
+ color: var(--risk-low);
1538
+ letter-spacing: 1px;
1539
+ margin-bottom: 8px;
1540
+ }
1541
+ .audit-result.audit-clear .audit-detail {
1542
+ font-size: 12px;
1543
+ color: var(--text-primary);
1544
+ opacity: 0.8;
1545
+ margin-bottom: 12px;
1546
+ }
1547
+ .audit-result.audit-clear .audit-file {
1548
+ font-size: 10px;
1549
+ color: var(--accent);
1550
+ margin-bottom: 4px;
1551
+ }
1552
+ .audit-result.audit-clear .audit-meta {
1553
+ font-size: 9px;
1554
+ color: var(--text-secondary);
1555
+ }
1556
+
1557
+ .audit-result.audit-warning {
1558
+ padding: 16px;
1559
+ border: 1px solid var(--risk-medium);
1560
+ border-radius: 6px;
1561
+ margin: 8px;
1562
+ background: rgba(255, 159, 10, 0.06);
1563
+ }
1564
+ .audit-result.audit-warning .audit-icon {
1565
+ font-size: 32px;
1566
+ color: var(--risk-high);
1567
+ text-shadow: 0 0 20px rgba(255, 45, 85, 0.4);
1568
+ margin-bottom: 8px;
1569
+ }
1570
+ .audit-result.audit-warning .audit-title {
1571
+ font-size: 13px;
1572
+ font-weight: 700;
1573
+ color: var(--risk-high);
1574
+ margin-bottom: 6px;
1575
+ }
1576
+ .audit-result.audit-warning .audit-detail {
1577
+ font-size: 11px;
1578
+ color: var(--text-primary);
1579
+ line-height: 1.5;
1580
+ }
1581
+ .audit-result.audit-warning .audit-suggestion {
1582
+ font-size: 10px;
1583
+ color: var(--accent);
1584
+ font-style: italic;
1585
+ margin-top: 8px;
1586
+ }
1587
+ .audit-wait-notice {
1588
+ font-size: 9px;
1589
+ color: #5a9;
1590
+ letter-spacing: 0.5px;
1591
+ margin-top: 10px;
1592
+ padding: 6px 10px;
1593
+ border: 1px solid rgba(90, 170, 153, 0.3);
1594
+ border-radius: 3px;
1595
+ background: rgba(90, 170, 153, 0.08);
1596
+ line-height: 1.5;
1597
+ }
1598
+
1599
+ @keyframes audit-fade-in {
1600
+ 0% { opacity: 0; transform: scale(0.95); }
1601
+ 100% { opacity: 1; transform: scale(1); }
1602
+ }
1603
+
1604
+ /* ═══════════════════════════════════════════ */
1605
+ /* Project Selector */
1606
+ /* ═══════════════════════════════════════════ */
1607
+ .project-selector {
1608
+ display: flex;
1609
+ align-items: center;
1610
+ gap: 8px;
1611
+ margin-left: 16px;
1612
+ max-width: 400px;
1613
+ overflow: hidden;
1614
+ }
1615
+
1616
+ .project-path {
1617
+ font-size: 10px;
1618
+ color: var(--text-secondary);
1619
+ letter-spacing: 0.5px;
1620
+ white-space: nowrap;
1621
+ overflow: hidden;
1622
+ text-overflow: ellipsis;
1623
+ max-width: 300px;
1624
+ direction: rtl;
1625
+ text-align: left;
1626
+ }
1627
+
1628
+ /* ═══════════════════════════════════════════ */
1629
+ /* Project Switch Modal */
1630
+ /* ═══════════════════════════════════════════ */
1631
+ #project-modal {
1632
+ position: fixed;
1633
+ top: 0; left: 0; right: 0; bottom: 0;
1634
+ background: rgba(5,10,24,0.85);
1635
+ z-index: 400;
1636
+ display: flex;
1637
+ align-items: center;
1638
+ justify-content: center;
1639
+ backdrop-filter: blur(4px);
1640
+ }
1641
+
1642
+ #project-modal.hidden { display: none; }
1643
+
1644
+ .project-modal-panel {
1645
+ background: var(--bg-secondary);
1646
+ border: 1px solid var(--accent-dim);
1647
+ border-radius: 6px;
1648
+ padding: 24px 32px;
1649
+ min-width: 500px;
1650
+ box-shadow: var(--glow-cyan), 0 16px 64px rgba(0,0,0,0.5);
1651
+ }
1652
+
1653
+ .project-modal-panel h3 {
1654
+ font-size: 12px;
1655
+ color: var(--accent);
1656
+ letter-spacing: 3px;
1657
+ margin-bottom: 16px;
1658
+ }
1659
+
1660
+ .browse-path-bar {
1661
+ display: flex;
1662
+ align-items: center;
1663
+ gap: 8px;
1664
+ padding: 8px 12px;
1665
+ background: rgba(0,0,0,0.4);
1666
+ border: 1px solid var(--border);
1667
+ border-radius: 3px;
1668
+ margin-bottom: 8px;
1669
+ }
1670
+
1671
+ .browse-nav-btn {
1672
+ padding: 4px 10px;
1673
+ background: transparent;
1674
+ color: var(--text-secondary);
1675
+ border: 1px solid var(--border);
1676
+ border-radius: 2px;
1677
+ cursor: pointer;
1678
+ font-size: 12px;
1679
+ font-family: inherit;
1680
+ font-weight: 700;
1681
+ transition: all 0.2s;
1682
+ flex-shrink: 0;
1683
+ }
1684
+
1685
+ .browse-nav-btn:hover {
1686
+ color: var(--accent);
1687
+ border-color: var(--accent);
1688
+ }
1689
+
1690
+ .browse-path-text {
1691
+ font-size: 11px;
1692
+ color: var(--accent);
1693
+ letter-spacing: 0.5px;
1694
+ white-space: nowrap;
1695
+ overflow: hidden;
1696
+ text-overflow: ellipsis;
1697
+ direction: rtl;
1698
+ text-align: left;
1699
+ flex: 1;
1700
+ }
1701
+
1702
+ .browse-dir-list {
1703
+ max-height: 320px;
1704
+ overflow-y: auto;
1705
+ border: 1px solid var(--border);
1706
+ border-radius: 3px;
1707
+ background: rgba(0,0,0,0.3);
1708
+ }
1709
+
1710
+ .browse-dir-item {
1711
+ display: flex;
1712
+ align-items: center;
1713
+ gap: 8px;
1714
+ padding: 7px 12px;
1715
+ font-size: 11px;
1716
+ color: var(--text-primary);
1717
+ cursor: pointer;
1718
+ transition: all 0.15s;
1719
+ border-bottom: 1px solid rgba(26,45,77,0.3);
1720
+ letter-spacing: 0.5px;
1721
+ }
1722
+
1723
+ .browse-dir-item:last-child { border-bottom: none; }
1724
+
1725
+ .browse-dir-item:hover {
1726
+ background: rgba(0,212,255,0.08);
1727
+ color: var(--accent);
1728
+ }
1729
+
1730
+ .browse-dir-item .dir-icon {
1731
+ font-size: 13px;
1732
+ color: var(--text-secondary);
1733
+ flex-shrink: 0;
1734
+ }
1735
+
1736
+ .browse-dir-item:hover .dir-icon {
1737
+ color: var(--accent);
1738
+ }
1739
+
1740
+ .browse-dir-item .dir-name {
1741
+ flex: 1;
1742
+ overflow: hidden;
1743
+ text-overflow: ellipsis;
1744
+ white-space: nowrap;
1745
+ }
1746
+
1747
+ .browse-empty {
1748
+ padding: 20px;
1749
+ text-align: center;
1750
+ font-size: 11px;
1751
+ color: var(--text-secondary);
1752
+ letter-spacing: 1px;
1753
+ }
1754
+
1755
+ #project-detect-info {
1756
+ min-height: 20px;
1757
+ margin-top: 8px;
1758
+ font-size: 11px;
1759
+ color: var(--text-secondary);
1760
+ letter-spacing: 0.5px;
1761
+ }
1762
+
1763
+ #project-detect-info.error {
1764
+ color: var(--risk-high);
1765
+ }
1766
+
1767
+ #project-detect-info.success {
1768
+ color: var(--risk-low);
1769
+ }
1770
+
1771
+ #project-detect-info.project-detected {
1772
+ color: var(--risk-low);
1773
+ padding: 6px 10px;
1774
+ border: 1px solid rgba(48,209,88,0.3);
1775
+ border-radius: 3px;
1776
+ background: rgba(48,209,88,0.08);
1777
+ }
1778
+
1779
+ .project-modal-actions {
1780
+ display: flex;
1781
+ gap: 10px;
1782
+ margin-top: 16px;
1783
+ justify-content: flex-end;
1784
+ }
1785
+
1786
+ .project-modal-actions button {
1787
+ padding: 8px 24px;
1788
+ background: transparent;
1789
+ color: var(--accent);
1790
+ border: 1px solid var(--accent-dim);
1791
+ border-radius: 3px;
1792
+ cursor: pointer;
1793
+ font-size: 10px;
1794
+ font-family: inherit;
1795
+ font-weight: 600;
1796
+ letter-spacing: 2px;
1797
+ transition: all 0.2s;
1798
+ }
1799
+
1800
+ .project-modal-actions button:hover {
1801
+ background: rgba(0,212,255,0.1);
1802
+ box-shadow: var(--glow-cyan);
1803
+ }
1804
+
1805
+ #btn-project-load {
1806
+ color: var(--risk-low);
1807
+ border-color: var(--risk-low);
1808
+ }
1809
+
1810
+ #btn-project-load:hover {
1811
+ background: rgba(48,209,88,0.15);
1812
+ box-shadow: 0 0 20px rgba(48,209,88,0.3);
1813
+ }
1814
+
1815
+ #btn-project-cancel {
1816
+ color: var(--text-secondary);
1817
+ border-color: var(--border);
1818
+ }
1819
+
1820
+ .project-loading {
1821
+ display: flex;
1822
+ align-items: center;
1823
+ gap: 8px;
1824
+ color: var(--accent);
1825
+ font-size: 11px;
1826
+ letter-spacing: 2px;
1827
+ }