mythos-sentinel 0.1.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 (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +362 -0
  3. package/action.yml +43 -0
  4. package/assets/banner.png +0 -0
  5. package/bin/mythos-sentinel-mcp.js +7 -0
  6. package/bin/mythos-sentinel.js +8 -0
  7. package/docs/ARCHITECTURE.md +55 -0
  8. package/docs/BASE_X402.md +33 -0
  9. package/docs/BAZAAR_ADAPTER.md +41 -0
  10. package/docs/DASHBOARD.md +22 -0
  11. package/docs/FALLBACK_ROUTING.md +37 -0
  12. package/docs/MCP.md +70 -0
  13. package/docs/PASSIVE_SCORING.md +33 -0
  14. package/docs/ROUTESCORE.md +101 -0
  15. package/docs/RUNTIME_MCP_PROXY.md +90 -0
  16. package/docs/SPEND_FIREWALL.md +50 -0
  17. package/docs/TELEMETRY.md +74 -0
  18. package/docs/THREAT_MODEL.md +28 -0
  19. package/docs/X402_RECEIPTS.md +54 -0
  20. package/examples/base/mythos.policy.json +142 -0
  21. package/examples/claude_desktop/mcp.json +8 -0
  22. package/examples/codex/AGENTS.md +31 -0
  23. package/examples/cursor/mcp.json +8 -0
  24. package/examples/github/verify.yml +29 -0
  25. package/examples/routescore/services.yml +19 -0
  26. package/examples/skill/mythos.skill.json +20 -0
  27. package/package.json +79 -0
  28. package/schemas/agent-receipt.schema.json +17 -0
  29. package/schemas/policy.schema.json +322 -0
  30. package/schemas/sentinel-report.schema.json +14 -0
  31. package/schemas/skill.manifest.schema.json +42 -0
  32. package/src/cli.js +570 -0
  33. package/src/core/fs.js +88 -0
  34. package/src/core/path-utils.js +54 -0
  35. package/src/core/policy.js +326 -0
  36. package/src/core/receipt.js +52 -0
  37. package/src/core/routescore.js +576 -0
  38. package/src/core/snapshot.js +35 -0
  39. package/src/core/telemetry.js +214 -0
  40. package/src/core/x402-receipts.js +303 -0
  41. package/src/index.js +19 -0
  42. package/src/mcp/proxy.js +493 -0
  43. package/src/mcp/server.js +226 -0
  44. package/src/report/format.js +53 -0
  45. package/src/report/sarif.js +50 -0
  46. package/src/scanner/rules.js +185 -0
  47. package/src/scanner/scan.js +118 -0
  48. package/src/ui/server.js +346 -0
  49. package/src/ui/static/app.js +210 -0
  50. package/src/ui/static/index.html +342 -0
  51. package/src/ui/static/styles.css +904 -0
  52. package/src/version.js +2 -0
@@ -0,0 +1,904 @@
1
+ :root {
2
+ --bg: #07080b;
3
+ --panel: #0e1015;
4
+ --panel-hover: #13161d;
5
+ --panel-light: #161a23;
6
+ --border: #1a1d24;
7
+ --border-hover: #272c38;
8
+ --border-focus: #f59e0b;
9
+
10
+ --text: #f4f4f6;
11
+ --text-muted: #848995;
12
+ --text-inverse: #07080b;
13
+
14
+ --accent: #f59e0b; /* Amber */
15
+ --accent-hover: #d97706;
16
+ --accent-muted: rgba(245, 158, 11, 0.08);
17
+ --accent-border: rgba(245, 158, 11, 0.25);
18
+
19
+ --green: #10b981;
20
+ --green-bg: rgba(16, 185, 129, 0.06);
21
+ --green-border: rgba(16, 185, 129, 0.2);
22
+
23
+ --red: #ef4444;
24
+ --red-bg: rgba(239, 68, 68, 0.06);
25
+ --red-border: rgba(239, 68, 68, 0.2);
26
+
27
+ --blue: #3b82f6;
28
+ --blue-bg: rgba(59, 130, 246, 0.06);
29
+ --blue-border: rgba(59, 130, 246, 0.2);
30
+
31
+ --sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
32
+ --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace;
33
+ }
34
+
35
+ * {
36
+ box-sizing: border-box;
37
+ margin: 0;
38
+ padding: 0;
39
+ }
40
+
41
+ html {
42
+ scroll-behavior: smooth;
43
+ background-color: var(--bg);
44
+ }
45
+
46
+ body {
47
+ margin: 0;
48
+ color: var(--text);
49
+ font-family: var(--sans);
50
+ background-color: var(--bg);
51
+ -webkit-font-smoothing: antialiased;
52
+ -moz-osx-font-smoothing: grayscale;
53
+ line-height: 1.5;
54
+ }
55
+
56
+ /* Custom Scrollbar */
57
+ ::-webkit-scrollbar {
58
+ width: 8px;
59
+ height: 8px;
60
+ }
61
+ ::-webkit-scrollbar-track {
62
+ background: var(--bg);
63
+ }
64
+ ::-webkit-scrollbar-thumb {
65
+ background: var(--border);
66
+ border-radius: 4px;
67
+ }
68
+ ::-webkit-scrollbar-thumb:hover {
69
+ background: var(--border-hover);
70
+ }
71
+
72
+ /* Shell Layout */
73
+ .shell {
74
+ width: min(1320px, calc(100% - 48px));
75
+ margin: 0 auto;
76
+ padding: 40px 0 80px;
77
+ display: flex;
78
+ flex-direction: column;
79
+ gap: 40px;
80
+ }
81
+
82
+ /* 1. Hero / Overview */
83
+ .hero {
84
+ border: 1px solid var(--border);
85
+ background-color: var(--panel);
86
+ border-radius: 12px;
87
+ padding: 40px;
88
+ display: flex;
89
+ flex-direction: column;
90
+ gap: 28px;
91
+ }
92
+
93
+ .brand {
94
+ display: flex;
95
+ align-items: center;
96
+ gap: 10px;
97
+ }
98
+
99
+ .logo-icon {
100
+ color: var(--accent);
101
+ font-size: 20px;
102
+ font-weight: 800;
103
+ }
104
+
105
+ .logo-text {
106
+ font-weight: 700;
107
+ letter-spacing: -0.03em;
108
+ font-size: 18px;
109
+ color: var(--text);
110
+ }
111
+
112
+ .hero-content {
113
+ display: flex;
114
+ flex-direction: column;
115
+ gap: 16px;
116
+ max-width: 840px;
117
+ }
118
+
119
+ .tagline {
120
+ font-size: clamp(32px, 4vw, 56px);
121
+ font-weight: 800;
122
+ line-height: 1.1;
123
+ letter-spacing: -0.04em;
124
+ color: var(--text);
125
+ }
126
+
127
+ .description {
128
+ color: var(--text-muted);
129
+ font-size: clamp(16px, 1.8vw, 18px);
130
+ line-height: 1.6;
131
+ }
132
+
133
+ .status-chips {
134
+ display: flex;
135
+ flex-wrap: wrap;
136
+ gap: 8px;
137
+ margin-top: 4px;
138
+ }
139
+
140
+ .chip {
141
+ background-color: var(--panel-light);
142
+ border: 1px solid var(--border);
143
+ color: var(--text-muted);
144
+ font-family: var(--mono);
145
+ font-size: 11px;
146
+ text-transform: uppercase;
147
+ letter-spacing: 0.05em;
148
+ padding: 4px 10px;
149
+ border-radius: 6px;
150
+ }
151
+
152
+ .hero-actions {
153
+ display: flex;
154
+ gap: 12px;
155
+ flex-wrap: wrap;
156
+ margin-top: 12px;
157
+ }
158
+
159
+ /* Buttons */
160
+ .btn {
161
+ display: inline-flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ appearance: none;
165
+ border: 1px solid var(--border);
166
+ background-color: var(--panel-light);
167
+ color: var(--text);
168
+ border-radius: 8px;
169
+ padding: 10px 20px;
170
+ font-size: 13px;
171
+ font-weight: 600;
172
+ cursor: pointer;
173
+ transition: all 0.2s ease;
174
+ font-family: var(--sans);
175
+ text-decoration: none;
176
+ }
177
+
178
+ .btn:hover {
179
+ border-color: var(--border-hover);
180
+ background-color: var(--panel-hover);
181
+ }
182
+
183
+ .btn-primary {
184
+ background-color: var(--accent);
185
+ color: var(--text-inverse);
186
+ border-color: var(--accent);
187
+ }
188
+
189
+ .btn-primary:hover {
190
+ background-color: var(--accent-hover);
191
+ border-color: var(--accent-hover);
192
+ }
193
+
194
+ .btn-secondary {
195
+ border-color: var(--border);
196
+ background-color: var(--panel);
197
+ }
198
+
199
+ .btn-secondary:hover {
200
+ border-color: var(--border-hover);
201
+ background-color: var(--panel-hover);
202
+ }
203
+
204
+ .btn-ghost {
205
+ background-color: transparent;
206
+ border-color: transparent;
207
+ color: var(--text-muted);
208
+ }
209
+
210
+ .btn-ghost:hover {
211
+ background-color: var(--panel-light);
212
+ color: var(--text);
213
+ }
214
+
215
+ .btn-full {
216
+ width: 100%;
217
+ }
218
+
219
+ .btn-compact {
220
+ padding: 6px 12px;
221
+ font-size: 12px;
222
+ }
223
+
224
+ .btn-copy {
225
+ padding: 4px 8px;
226
+ font-family: var(--mono);
227
+ font-size: 10px;
228
+ border-radius: 4px;
229
+ text-transform: uppercase;
230
+ color: var(--text-muted);
231
+ }
232
+
233
+ /* Sections */
234
+ .section {
235
+ display: flex;
236
+ flex-direction: column;
237
+ gap: 20px;
238
+ }
239
+
240
+ .section-header {
241
+ display: flex;
242
+ flex-direction: column;
243
+ gap: 6px;
244
+ }
245
+
246
+ .section-header-split {
247
+ display: flex;
248
+ justify-content: space-between;
249
+ align-items: flex-end;
250
+ gap: 20px;
251
+ flex-wrap: wrap;
252
+ }
253
+
254
+ .section-title {
255
+ font-size: 20px;
256
+ font-weight: 700;
257
+ letter-spacing: -0.02em;
258
+ }
259
+
260
+ .section-subtitle {
261
+ font-size: 14px;
262
+ color: var(--text-muted);
263
+ }
264
+
265
+ /* 2. Status Metrics */
266
+ .metrics-grid {
267
+ display: grid;
268
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
269
+ gap: 16px;
270
+ }
271
+
272
+ .metric-card {
273
+ border: 1px solid var(--border);
274
+ background-color: var(--panel);
275
+ border-radius: 8px;
276
+ padding: 16px;
277
+ display: flex;
278
+ flex-direction: column;
279
+ gap: 8px;
280
+ }
281
+
282
+ .metric-label {
283
+ font-family: var(--mono);
284
+ font-size: 11px;
285
+ color: var(--text-muted);
286
+ text-transform: uppercase;
287
+ letter-spacing: 0.05em;
288
+ }
289
+
290
+ .metric-value {
291
+ font-size: 22px;
292
+ font-weight: 700;
293
+ color: var(--text);
294
+ overflow: hidden;
295
+ text-overflow: ellipsis;
296
+ white-space: nowrap;
297
+ }
298
+
299
+ /* Forms & Panels */
300
+ .panel {
301
+ border: 1px solid var(--border);
302
+ background-color: var(--panel);
303
+ border-radius: 12px;
304
+ padding: 24px;
305
+ display: flex;
306
+ flex-direction: column;
307
+ gap: 20px;
308
+ }
309
+
310
+ .panel-header {
311
+ display: flex;
312
+ justify-content: space-between;
313
+ align-items: center;
314
+ border-bottom: 1px solid var(--border);
315
+ padding-bottom: 14px;
316
+ }
317
+
318
+ .panel-header h3 {
319
+ font-size: 15px;
320
+ font-weight: 700;
321
+ letter-spacing: -0.01em;
322
+ }
323
+
324
+ /* Forms */
325
+ .form-group {
326
+ display: flex;
327
+ flex-direction: column;
328
+ gap: 6px;
329
+ }
330
+
331
+ .form-row {
332
+ display: grid;
333
+ grid-template-columns: repeat(3, 1fr);
334
+ gap: 12px;
335
+ }
336
+
337
+ label {
338
+ font-family: var(--mono);
339
+ font-size: 11px;
340
+ color: var(--text-muted);
341
+ text-transform: uppercase;
342
+ letter-spacing: 0.05em;
343
+ }
344
+
345
+ input, textarea, select {
346
+ width: 100%;
347
+ border: 1px solid var(--border);
348
+ background-color: var(--panel-light);
349
+ border-radius: 6px;
350
+ color: var(--text);
351
+ padding: 10px 12px;
352
+ font-family: var(--mono);
353
+ font-size: 13px;
354
+ outline: none;
355
+ transition: border-color 0.2s ease;
356
+ }
357
+
358
+ input:hover, textarea:hover, select:hover {
359
+ border-color: var(--border-hover);
360
+ }
361
+
362
+ input:focus, textarea:focus, select:focus {
363
+ border-color: var(--border-focus);
364
+ }
365
+
366
+ textarea {
367
+ resize: vertical;
368
+ line-height: 1.5;
369
+ }
370
+
371
+ /* Badges */
372
+ .badge {
373
+ font-family: var(--mono);
374
+ font-size: 10px;
375
+ font-weight: 700;
376
+ text-transform: uppercase;
377
+ padding: 2px 6px;
378
+ border-radius: 4px;
379
+ background-color: var(--panel-light);
380
+ border: 1px solid var(--border);
381
+ }
382
+
383
+ .badge-currency {
384
+ color: var(--green);
385
+ border-color: var(--green-border);
386
+ background-color: var(--green-bg);
387
+ }
388
+
389
+ /* 3. Adaptive Spend Firewall */
390
+ .firewall-grid {
391
+ display: grid;
392
+ grid-template-columns: 1.2fr 0.8fr;
393
+ gap: 20px;
394
+ }
395
+
396
+ .behavior-panel {
397
+ display: flex;
398
+ flex-direction: column;
399
+ }
400
+
401
+ .rules-list {
402
+ display: flex;
403
+ flex-direction: column;
404
+ gap: 2px;
405
+ flex-grow: 1;
406
+ }
407
+
408
+ .rule-item {
409
+ display: flex;
410
+ justify-content: space-between;
411
+ align-items: center;
412
+ padding: 12px 0;
413
+ border-bottom: 1px solid var(--border);
414
+ }
415
+
416
+ .rule-item:last-of-type {
417
+ border-bottom: none;
418
+ }
419
+
420
+ .rule-trigger {
421
+ font-size: 13px;
422
+ color: var(--text-muted);
423
+ }
424
+
425
+ .rule-action {
426
+ font-family: var(--mono);
427
+ font-size: 12px;
428
+ font-weight: 600;
429
+ }
430
+
431
+ .action-allow { color: var(--green); }
432
+ .action-cap { color: var(--blue); }
433
+ .action-trial { color: var(--accent); }
434
+ .action-approval { color: var(--accent); }
435
+ .action-block { color: var(--red); }
436
+
437
+ .panel-footer-text {
438
+ font-size: 12px;
439
+ color: var(--text-muted);
440
+ line-height: 1.5;
441
+ border-top: 1px solid var(--border);
442
+ padding-top: 14px;
443
+ margin-top: auto;
444
+ }
445
+
446
+ /* 4. RouteScore & Telemetry Lists */
447
+ .route-metrics-grid {
448
+ display: grid;
449
+ grid-template-columns: repeat(5, 1fr);
450
+ gap: 16px;
451
+ margin-bottom: 4px;
452
+ }
453
+
454
+ .route-metrics-grid > div {
455
+ background-color: var(--panel);
456
+ border: 1px solid var(--border);
457
+ border-radius: 8px;
458
+ padding: 16px;
459
+ display: flex;
460
+ flex-direction: column;
461
+ gap: 6px;
462
+ }
463
+
464
+ .route-metrics-grid > div span {
465
+ font-family: var(--mono);
466
+ font-size: 10px;
467
+ color: var(--text-muted);
468
+ text-transform: uppercase;
469
+ letter-spacing: 0.05em;
470
+ }
471
+
472
+ .route-metrics-grid > div strong {
473
+ font-size: 20px;
474
+ font-weight: 700;
475
+ color: var(--text);
476
+ }
477
+
478
+ .catalog-grid, .telemetry-grid {
479
+ display: grid;
480
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
481
+ gap: 16px;
482
+ }
483
+
484
+ .service-card {
485
+ border: 1px solid var(--border);
486
+ background-color: var(--panel);
487
+ border-radius: 8px;
488
+ padding: 16px;
489
+ display: flex;
490
+ flex-direction: column;
491
+ gap: 10px;
492
+ min-height: 180px;
493
+ transition: all 0.2s ease;
494
+ }
495
+
496
+ .service-card:hover {
497
+ border-color: var(--border-hover);
498
+ }
499
+
500
+ .service-top {
501
+ display: flex;
502
+ justify-content: space-between;
503
+ align-items: center;
504
+ }
505
+
506
+ .service-top strong {
507
+ font-size: 14px;
508
+ font-weight: 600;
509
+ color: var(--text);
510
+ }
511
+
512
+ .score {
513
+ font-family: var(--mono);
514
+ font-size: 11px;
515
+ font-weight: 700;
516
+ padding: 2px 6px;
517
+ border-radius: 4px;
518
+ background-color: var(--panel-light);
519
+ border: 1px solid var(--border);
520
+ }
521
+
522
+ .score.low {
523
+ color: var(--green);
524
+ border-color: var(--green-border);
525
+ background-color: var(--green-bg);
526
+ }
527
+
528
+ .score.medium {
529
+ color: var(--blue);
530
+ border-color: var(--blue-border);
531
+ background-color: var(--blue-bg);
532
+ }
533
+
534
+ .score.elevated {
535
+ color: var(--accent);
536
+ border-color: var(--accent-border);
537
+ background-color: var(--accent-muted);
538
+ }
539
+
540
+ .score.high {
541
+ color: var(--red);
542
+ border-color: var(--red-border);
543
+ background-color: var(--red-bg);
544
+ }
545
+
546
+ .muted-row {
547
+ font-family: var(--mono);
548
+ font-size: 11px;
549
+ color: var(--text-muted);
550
+ }
551
+
552
+ .service-card p {
553
+ font-size: 13px;
554
+ color: var(--text-muted);
555
+ line-height: 1.5;
556
+ margin: 0;
557
+ flex-grow: 1;
558
+ }
559
+
560
+ .service-card small {
561
+ font-size: 11px;
562
+ color: var(--text-muted);
563
+ border-top: 1px solid var(--border);
564
+ padding-top: 8px;
565
+ display: block;
566
+ }
567
+
568
+ .service-card.compact-card {
569
+ min-height: auto;
570
+ gap: 8px;
571
+ }
572
+
573
+ /* Privacy Banner */
574
+ .privacy-banner {
575
+ display: flex;
576
+ align-items: flex-start;
577
+ gap: 12px;
578
+ background-color: var(--panel);
579
+ border: 1px solid var(--border);
580
+ padding: 16px;
581
+ border-radius: 8px;
582
+ }
583
+
584
+ .banner-icon {
585
+ font-size: 16px;
586
+ line-height: 1;
587
+ }
588
+
589
+ .banner-text {
590
+ font-size: 13px;
591
+ color: var(--text-muted);
592
+ line-height: 1.5;
593
+ }
594
+
595
+ .banner-text strong {
596
+ color: var(--text);
597
+ }
598
+
599
+ .quiet-box {
600
+ border: 1px dashed var(--border);
601
+ border-radius: 8px;
602
+ padding: 30px;
603
+ text-align: center;
604
+ color: var(--text-muted);
605
+ font-size: 13px;
606
+ grid-column: 1 / -1;
607
+ }
608
+
609
+ /* 6. Playground & Live Checks */
610
+ .playground-grid {
611
+ display: grid;
612
+ grid-template-columns: repeat(3, 1fr);
613
+ gap: 20px;
614
+ }
615
+
616
+ .check-card {
617
+ display: flex;
618
+ flex-direction: column;
619
+ justify-content: space-between;
620
+ }
621
+
622
+ .check-card-header {
623
+ display: flex;
624
+ flex-direction: column;
625
+ gap: 4px;
626
+ }
627
+
628
+ .check-type {
629
+ font-family: var(--mono);
630
+ font-size: 10px;
631
+ font-weight: 700;
632
+ color: var(--accent);
633
+ letter-spacing: 0.1em;
634
+ }
635
+
636
+ .check-card h3 {
637
+ font-size: 16px;
638
+ font-weight: 700;
639
+ }
640
+
641
+ .check-inputs {
642
+ display: flex;
643
+ flex-direction: column;
644
+ gap: 10px;
645
+ margin: 16px 0;
646
+ flex-grow: 1;
647
+ justify-content: center;
648
+ }
649
+
650
+ /* Console Output Pane */
651
+ .console-panel {
652
+ display: flex;
653
+ flex-direction: column;
654
+ gap: 12px;
655
+ padding: 0;
656
+ overflow: hidden;
657
+ border-radius: 8px;
658
+ }
659
+
660
+ .console-header {
661
+ display: flex;
662
+ justify-content: space-between;
663
+ align-items: center;
664
+ padding: 12px 16px;
665
+ background-color: var(--panel-light);
666
+ border-bottom: 1px solid var(--border);
667
+ }
668
+
669
+ .console-title {
670
+ display: flex;
671
+ align-items: center;
672
+ gap: 6px;
673
+ }
674
+
675
+ .console-dot {
676
+ width: 10px;
677
+ height: 10px;
678
+ border-radius: 50%;
679
+ }
680
+
681
+ .console-dot.red { background-color: var(--red); }
682
+ .console-dot.yellow { background-color: var(--accent); }
683
+ .console-dot.green { background-color: var(--green); }
684
+
685
+ .console-label {
686
+ font-family: var(--mono);
687
+ font-size: 11px;
688
+ color: var(--text-muted);
689
+ text-transform: uppercase;
690
+ letter-spacing: 0.05em;
691
+ margin-left: 6px;
692
+ }
693
+
694
+ .console {
695
+ border: none;
696
+ background-color: #040507;
697
+ color: #d1d5db;
698
+ padding: 20px;
699
+ font-family: var(--mono);
700
+ font-size: 13px;
701
+ line-height: 1.6;
702
+ white-space: pre-wrap;
703
+ word-break: break-all;
704
+ overflow-y: auto;
705
+ min-height: 140px;
706
+ border-left: 4px solid var(--border);
707
+ }
708
+
709
+ .console.empty {
710
+ color: var(--text-muted);
711
+ }
712
+
713
+ .console.state-allow {
714
+ border-left-color: var(--green);
715
+ }
716
+
717
+ .console.state-approval {
718
+ border-left-color: var(--accent);
719
+ }
720
+
721
+ .console.state-block {
722
+ border-left-color: var(--red);
723
+ }
724
+
725
+ /* Findings container */
726
+ .findings-container {
727
+ display: flex;
728
+ flex-direction: column;
729
+ gap: 10px;
730
+ padding: 0 16px 16px;
731
+ background-color: #040507;
732
+ }
733
+
734
+ .finding {
735
+ background-color: var(--panel);
736
+ border: 1px solid var(--border);
737
+ border-radius: 6px;
738
+ padding: 12px 14px;
739
+ display: flex;
740
+ flex-direction: column;
741
+ gap: 6px;
742
+ }
743
+
744
+ .finding .top {
745
+ display: flex;
746
+ justify-content: space-between;
747
+ align-items: center;
748
+ }
749
+
750
+ .finding .top strong {
751
+ font-size: 13px;
752
+ font-weight: 600;
753
+ color: var(--text);
754
+ }
755
+
756
+ .finding div {
757
+ font-family: var(--mono);
758
+ font-size: 11px;
759
+ color: var(--text-muted);
760
+ }
761
+
762
+ .finding small {
763
+ font-size: 12px;
764
+ color: var(--text-muted);
765
+ line-height: 1.4;
766
+ }
767
+
768
+ .badge.critical, .badge.high {
769
+ color: var(--red);
770
+ border-color: var(--red-border);
771
+ background-color: var(--red-bg);
772
+ }
773
+
774
+ .badge.medium {
775
+ color: var(--accent);
776
+ border-color: var(--accent-border);
777
+ background-color: var(--accent-muted);
778
+ }
779
+
780
+ .badge.low, .badge.info {
781
+ color: var(--green);
782
+ border-color: var(--green-border);
783
+ background-color: var(--green-bg);
784
+ }
785
+
786
+ /* 7. Setup configurations */
787
+ .setup-grid {
788
+ display: grid;
789
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
790
+ gap: 20px;
791
+ }
792
+
793
+ .setup-card {
794
+ display: flex;
795
+ flex-direction: column;
796
+ gap: 12px;
797
+ }
798
+
799
+ .setup-card .panel-header {
800
+ border-bottom: none;
801
+ padding-bottom: 0;
802
+ align-items: flex-start;
803
+ }
804
+
805
+ .setup-desc {
806
+ font-size: 12px;
807
+ color: var(--text-muted);
808
+ margin-top: 4px;
809
+ }
810
+
811
+ .code-block {
812
+ min-width: 0;
813
+ max-width: 100%;
814
+ background-color: #040507;
815
+ border: 1px solid var(--border);
816
+ border-radius: 6px;
817
+ padding: 16px;
818
+ font-family: var(--mono);
819
+ font-size: 12px;
820
+ line-height: 1.5;
821
+ color: #c1c3c7;
822
+ overflow: auto;
823
+ height: 240px;
824
+ white-space: pre;
825
+ overflow-x: auto;
826
+ }
827
+
828
+ /* Action controls */
829
+ .action-controls {
830
+ display: flex;
831
+ gap: 8px;
832
+ align-items: center;
833
+ }
834
+
835
+ .action-controls select {
836
+ width: auto;
837
+ padding: 8px 12px;
838
+ font-size: 12px;
839
+ }
840
+
841
+ /* Footer */
842
+ .site-footer {
843
+ border-top: 1px solid var(--border);
844
+ padding-top: 24px;
845
+ display: flex;
846
+ justify-content: space-between;
847
+ align-items: center;
848
+ color: var(--text-muted);
849
+ font-size: 13px;
850
+ flex-wrap: wrap;
851
+ gap: 12px;
852
+ }
853
+
854
+ .footer-brand {
855
+ font-weight: 700;
856
+ letter-spacing: -0.02em;
857
+ color: var(--text);
858
+ }
859
+
860
+ /* Responsive Queries */
861
+ @media (max-width: 1080px) {
862
+ .firewall-grid {
863
+ grid-template-columns: 1fr;
864
+ }
865
+ .setup-grid {
866
+ grid-template-columns: 1fr;
867
+ }
868
+ .route-metrics-grid {
869
+ grid-template-columns: repeat(3, 1fr);
870
+ }
871
+ }
872
+
873
+ @media (max-width: 768px) {
874
+ .shell {
875
+ width: min(100% - 32px, 1320px);
876
+ padding: 24px 0 48px;
877
+ gap: 32px;
878
+ }
879
+ .hero {
880
+ padding: 24px;
881
+ }
882
+ .tagline {
883
+ font-size: 28px;
884
+ }
885
+ .playground-grid {
886
+ grid-template-columns: 1fr;
887
+ }
888
+ .route-metrics-grid {
889
+ grid-template-columns: repeat(2, 1fr);
890
+ }
891
+ .site-footer {
892
+ flex-direction: column;
893
+ align-items: flex-start;
894
+ }
895
+ }
896
+
897
+ @media (max-width: 480px) {
898
+ .route-metrics-grid {
899
+ grid-template-columns: 1fr;
900
+ }
901
+ .form-row {
902
+ grid-template-columns: 1fr;
903
+ }
904
+ }