aura-security 0.4.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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +446 -0
  3. package/deploy/AWS-DEPLOYMENT.md +358 -0
  4. package/deploy/terraform/main.tf +362 -0
  5. package/deploy/terraform/terraform.tfvars.example +6 -0
  6. package/dist/agents/base.d.ts +44 -0
  7. package/dist/agents/base.js +96 -0
  8. package/dist/agents/index.d.ts +14 -0
  9. package/dist/agents/index.js +17 -0
  10. package/dist/agents/policy/evaluator.d.ts +15 -0
  11. package/dist/agents/policy/evaluator.js +183 -0
  12. package/dist/agents/policy/index.d.ts +12 -0
  13. package/dist/agents/policy/index.js +15 -0
  14. package/dist/agents/policy/validator.d.ts +15 -0
  15. package/dist/agents/policy/validator.js +182 -0
  16. package/dist/agents/scanners/gitleaks.d.ts +14 -0
  17. package/dist/agents/scanners/gitleaks.js +155 -0
  18. package/dist/agents/scanners/grype.d.ts +14 -0
  19. package/dist/agents/scanners/grype.js +109 -0
  20. package/dist/agents/scanners/index.d.ts +15 -0
  21. package/dist/agents/scanners/index.js +27 -0
  22. package/dist/agents/scanners/npm-audit.d.ts +13 -0
  23. package/dist/agents/scanners/npm-audit.js +129 -0
  24. package/dist/agents/scanners/semgrep.d.ts +14 -0
  25. package/dist/agents/scanners/semgrep.js +131 -0
  26. package/dist/agents/scanners/trivy.d.ts +14 -0
  27. package/dist/agents/scanners/trivy.js +122 -0
  28. package/dist/agents/types.d.ts +137 -0
  29. package/dist/agents/types.js +91 -0
  30. package/dist/auditor/index.d.ts +3 -0
  31. package/dist/auditor/index.js +2 -0
  32. package/dist/auditor/pipeline.d.ts +19 -0
  33. package/dist/auditor/pipeline.js +240 -0
  34. package/dist/auditor/validator.d.ts +17 -0
  35. package/dist/auditor/validator.js +58 -0
  36. package/dist/aura/client.d.ts +29 -0
  37. package/dist/aura/client.js +125 -0
  38. package/dist/aura/index.d.ts +4 -0
  39. package/dist/aura/index.js +2 -0
  40. package/dist/aura/server.d.ts +45 -0
  41. package/dist/aura/server.js +343 -0
  42. package/dist/cli.d.ts +17 -0
  43. package/dist/cli.js +1433 -0
  44. package/dist/client/index.d.ts +41 -0
  45. package/dist/client/index.js +170 -0
  46. package/dist/compliance/index.d.ts +40 -0
  47. package/dist/compliance/index.js +292 -0
  48. package/dist/database/index.d.ts +77 -0
  49. package/dist/database/index.js +395 -0
  50. package/dist/index.d.ts +25 -0
  51. package/dist/index.js +762 -0
  52. package/dist/integrations/aura-scanner.d.ts +69 -0
  53. package/dist/integrations/aura-scanner.js +155 -0
  54. package/dist/integrations/aws-scanner.d.ts +63 -0
  55. package/dist/integrations/aws-scanner.js +624 -0
  56. package/dist/integrations/config.d.ts +69 -0
  57. package/dist/integrations/config.js +212 -0
  58. package/dist/integrations/github.d.ts +45 -0
  59. package/dist/integrations/github.js +201 -0
  60. package/dist/integrations/gitlab.d.ts +36 -0
  61. package/dist/integrations/gitlab.js +110 -0
  62. package/dist/integrations/index.d.ts +11 -0
  63. package/dist/integrations/index.js +11 -0
  64. package/dist/integrations/local-scanner.d.ts +146 -0
  65. package/dist/integrations/local-scanner.js +1654 -0
  66. package/dist/integrations/notifications.d.ts +99 -0
  67. package/dist/integrations/notifications.js +305 -0
  68. package/dist/integrations/scanners.d.ts +57 -0
  69. package/dist/integrations/scanners.js +217 -0
  70. package/dist/integrations/slop-scanner.d.ts +69 -0
  71. package/dist/integrations/slop-scanner.js +155 -0
  72. package/dist/integrations/webhook.d.ts +37 -0
  73. package/dist/integrations/webhook.js +256 -0
  74. package/dist/orchestrator/index.d.ts +72 -0
  75. package/dist/orchestrator/index.js +187 -0
  76. package/dist/output/index.d.ts +152 -0
  77. package/dist/output/index.js +399 -0
  78. package/dist/pipeline/index.d.ts +72 -0
  79. package/dist/pipeline/index.js +313 -0
  80. package/dist/sbom/index.d.ts +94 -0
  81. package/dist/sbom/index.js +298 -0
  82. package/dist/schemas/index.d.ts +2 -0
  83. package/dist/schemas/index.js +2 -0
  84. package/dist/schemas/input.schema.d.ts +87 -0
  85. package/dist/schemas/input.schema.js +44 -0
  86. package/dist/schemas/output.schema.d.ts +115 -0
  87. package/dist/schemas/output.schema.js +64 -0
  88. package/dist/serve-visualizer.d.ts +2 -0
  89. package/dist/serve-visualizer.js +78 -0
  90. package/dist/slop/client.d.ts +29 -0
  91. package/dist/slop/client.js +125 -0
  92. package/dist/slop/index.d.ts +4 -0
  93. package/dist/slop/index.js +2 -0
  94. package/dist/slop/server.d.ts +45 -0
  95. package/dist/slop/server.js +343 -0
  96. package/dist/types/events.d.ts +62 -0
  97. package/dist/types/events.js +2 -0
  98. package/dist/types/index.d.ts +1 -0
  99. package/dist/types/index.js +1 -0
  100. package/dist/visualizer/index.d.ts +4 -0
  101. package/dist/visualizer/index.js +181 -0
  102. package/dist/websocket/index.d.ts +88 -0
  103. package/dist/websocket/index.js +195 -0
  104. package/dist/zones/index.d.ts +7 -0
  105. package/dist/zones/index.js +7 -0
  106. package/dist/zones/manager.d.ts +101 -0
  107. package/dist/zones/manager.js +304 -0
  108. package/dist/zones/types.d.ts +78 -0
  109. package/dist/zones/types.js +33 -0
  110. package/package.json +84 -0
  111. package/visualizer/app.js +0 -0
  112. package/visualizer/index-minimal.html +1771 -0
  113. package/visualizer/index.html +2933 -0
  114. package/visualizer/landing.html +1328 -0
  115. package/visualizer/styles.css +0 -0
@@ -0,0 +1,1328 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>aurasecurity - Security Scanning Visualized</title>
7
+ <meta name="description" content="Unified security scanning with 3D visualization. One command, all your scanners, complete clarity.">
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
11
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
12
+ <style>
13
+ * {
14
+ margin: 0;
15
+ padding: 0;
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ :root {
20
+ --bg: #030712;
21
+ --bg-elevated: #0f172a;
22
+ --bg-card: rgba(15, 23, 42, 0.6);
23
+ --border: rgba(148, 163, 184, 0.1);
24
+ --text: #f8fafc;
25
+ --text-secondary: #94a3b8;
26
+ --text-muted: #64748b;
27
+ --primary: #06b6d4;
28
+ --primary-glow: rgba(6, 182, 212, 0.4);
29
+ --secondary: #8b5cf6;
30
+ --danger: #ef4444;
31
+ --warning: #f59e0b;
32
+ --success: #10b981;
33
+ }
34
+
35
+ body {
36
+ font-family: 'Inter', sans-serif;
37
+ background: var(--bg);
38
+ color: var(--text);
39
+ line-height: 1.6;
40
+ overflow-x: hidden;
41
+ }
42
+
43
+ h1, h2, h3, h4 {
44
+ font-family: 'Space Grotesk', sans-serif;
45
+ }
46
+
47
+ /* Animated gradient mesh background */
48
+ .mesh-gradient {
49
+ position: fixed;
50
+ top: 0;
51
+ left: 0;
52
+ right: 0;
53
+ bottom: 0;
54
+ z-index: -2;
55
+ background:
56
+ radial-gradient(at 0% 0%, rgba(6, 182, 212, 0.15) 0%, transparent 50%),
57
+ radial-gradient(at 100% 0%, rgba(139, 92, 246, 0.1) 0%, transparent 50%),
58
+ radial-gradient(at 100% 100%, rgba(6, 182, 212, 0.1) 0%, transparent 50%),
59
+ radial-gradient(at 0% 100%, rgba(139, 92, 246, 0.15) 0%, transparent 50%);
60
+ }
61
+
62
+ /* Grid pattern overlay */
63
+ .grid-pattern {
64
+ position: fixed;
65
+ top: 0;
66
+ left: 0;
67
+ right: 0;
68
+ bottom: 0;
69
+ z-index: -1;
70
+ background-image:
71
+ linear-gradient(rgba(148, 163, 184, 0.03) 1px, transparent 1px),
72
+ linear-gradient(90deg, rgba(148, 163, 184, 0.03) 1px, transparent 1px);
73
+ background-size: 60px 60px;
74
+ mask-image: radial-gradient(ellipse at center, black 0%, transparent 70%);
75
+ }
76
+
77
+ /* Navigation */
78
+ nav {
79
+ position: fixed;
80
+ top: 0;
81
+ left: 0;
82
+ right: 0;
83
+ z-index: 100;
84
+ padding: 1rem 2rem;
85
+ }
86
+
87
+ .nav-inner {
88
+ max-width: 1280px;
89
+ margin: 0 auto;
90
+ display: flex;
91
+ justify-content: space-between;
92
+ align-items: center;
93
+ padding: 0.75rem 1.5rem;
94
+ background: rgba(3, 7, 18, 0.8);
95
+ backdrop-filter: blur(20px);
96
+ border: 1px solid var(--border);
97
+ border-radius: 16px;
98
+ }
99
+
100
+ .logo {
101
+ display: flex;
102
+ align-items: center;
103
+ gap: 0.75rem;
104
+ text-decoration: none;
105
+ color: var(--text);
106
+ font-family: 'Space Grotesk', sans-serif;
107
+ font-weight: 700;
108
+ font-size: 1.25rem;
109
+ }
110
+
111
+ .logo-mark {
112
+ width: 36px;
113
+ height: 36px;
114
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
115
+ border-radius: 10px;
116
+ display: flex;
117
+ align-items: center;
118
+ justify-content: center;
119
+ font-size: 1.25rem;
120
+ }
121
+
122
+ .nav-links {
123
+ display: flex;
124
+ align-items: center;
125
+ gap: 0.5rem;
126
+ }
127
+
128
+ .nav-link {
129
+ color: var(--text-secondary);
130
+ text-decoration: none;
131
+ padding: 0.5rem 1rem;
132
+ border-radius: 8px;
133
+ font-size: 0.875rem;
134
+ font-weight: 500;
135
+ transition: all 0.2s;
136
+ }
137
+
138
+ .nav-link:hover {
139
+ color: var(--text);
140
+ background: rgba(148, 163, 184, 0.1);
141
+ }
142
+
143
+ .btn {
144
+ display: inline-flex;
145
+ align-items: center;
146
+ gap: 0.5rem;
147
+ padding: 0.625rem 1.25rem;
148
+ border-radius: 10px;
149
+ font-size: 0.875rem;
150
+ font-weight: 600;
151
+ text-decoration: none;
152
+ transition: all 0.2s;
153
+ border: none;
154
+ cursor: pointer;
155
+ }
156
+
157
+ .btn-primary {
158
+ background: linear-gradient(135deg, var(--primary), #0891b2);
159
+ color: white;
160
+ box-shadow: 0 0 20px var(--primary-glow);
161
+ }
162
+
163
+ .btn-primary:hover {
164
+ transform: translateY(-2px);
165
+ box-shadow: 0 0 30px var(--primary-glow);
166
+ }
167
+
168
+ .btn-ghost {
169
+ background: transparent;
170
+ color: var(--text);
171
+ border: 1px solid var(--border);
172
+ }
173
+
174
+ .btn-ghost:hover {
175
+ background: rgba(148, 163, 184, 0.1);
176
+ border-color: rgba(148, 163, 184, 0.2);
177
+ }
178
+
179
+ /* Hero Section */
180
+ .hero {
181
+ min-height: 100vh;
182
+ display: flex;
183
+ align-items: center;
184
+ padding: 8rem 2rem 4rem;
185
+ position: relative;
186
+ }
187
+
188
+ .hero-container {
189
+ max-width: 1280px;
190
+ margin: 0 auto;
191
+ display: grid;
192
+ grid-template-columns: 1fr 1fr;
193
+ gap: 4rem;
194
+ align-items: center;
195
+ }
196
+
197
+ .hero-content {
198
+ position: relative;
199
+ z-index: 2;
200
+ }
201
+
202
+ .hero-badge {
203
+ display: inline-flex;
204
+ align-items: center;
205
+ gap: 0.5rem;
206
+ padding: 0.5rem 1rem;
207
+ background: rgba(6, 182, 212, 0.1);
208
+ border: 1px solid rgba(6, 182, 212, 0.2);
209
+ border-radius: 100px;
210
+ font-size: 0.8125rem;
211
+ color: var(--primary);
212
+ margin-bottom: 1.5rem;
213
+ }
214
+
215
+ .hero-badge::before {
216
+ content: '';
217
+ width: 6px;
218
+ height: 6px;
219
+ background: var(--primary);
220
+ border-radius: 50%;
221
+ animation: pulse 2s infinite;
222
+ }
223
+
224
+ @keyframes pulse {
225
+ 0%, 100% { opacity: 1; transform: scale(1); }
226
+ 50% { opacity: 0.5; transform: scale(1.2); }
227
+ }
228
+
229
+ .hero h1 {
230
+ font-size: clamp(2.5rem, 5vw, 3.75rem);
231
+ font-weight: 700;
232
+ line-height: 1.1;
233
+ margin-bottom: 1.5rem;
234
+ letter-spacing: -0.02em;
235
+ }
236
+
237
+ .hero h1 .gradient-text {
238
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
239
+ -webkit-background-clip: text;
240
+ -webkit-text-fill-color: transparent;
241
+ background-clip: text;
242
+ }
243
+
244
+ .hero-description {
245
+ font-size: 1.125rem;
246
+ color: var(--text-secondary);
247
+ margin-bottom: 2rem;
248
+ max-width: 480px;
249
+ }
250
+
251
+ .hero-actions {
252
+ display: flex;
253
+ gap: 1rem;
254
+ flex-wrap: wrap;
255
+ }
256
+
257
+ .hero-actions .btn {
258
+ padding: 0.875rem 1.75rem;
259
+ font-size: 0.9375rem;
260
+ }
261
+
262
+ .hero-stats {
263
+ display: flex;
264
+ gap: 2.5rem;
265
+ margin-top: 3rem;
266
+ padding-top: 2rem;
267
+ border-top: 1px solid var(--border);
268
+ }
269
+
270
+ .stat {
271
+ text-align: left;
272
+ }
273
+
274
+ .stat-value {
275
+ font-family: 'Space Grotesk', sans-serif;
276
+ font-size: 1.75rem;
277
+ font-weight: 700;
278
+ color: var(--text);
279
+ }
280
+
281
+ .stat-label {
282
+ font-size: 0.8125rem;
283
+ color: var(--text-muted);
284
+ }
285
+
286
+ /* 3D Scene */
287
+ .hero-3d {
288
+ position: relative;
289
+ height: 500px;
290
+ }
291
+
292
+ #hero-canvas {
293
+ width: 100%;
294
+ height: 100%;
295
+ }
296
+
297
+ /* Bento Grid Features */
298
+ .features-section {
299
+ padding: 6rem 2rem;
300
+ position: relative;
301
+ }
302
+
303
+ .features-container {
304
+ max-width: 1280px;
305
+ margin: 0 auto;
306
+ }
307
+
308
+ .section-header {
309
+ text-align: center;
310
+ margin-bottom: 4rem;
311
+ }
312
+
313
+ .section-header h2 {
314
+ font-size: 2.5rem;
315
+ font-weight: 700;
316
+ margin-bottom: 1rem;
317
+ }
318
+
319
+ .section-header p {
320
+ color: var(--text-secondary);
321
+ font-size: 1.125rem;
322
+ max-width: 600px;
323
+ margin: 0 auto;
324
+ }
325
+
326
+ .bento-grid {
327
+ display: grid;
328
+ grid-template-columns: repeat(3, 1fr);
329
+ grid-template-rows: auto auto;
330
+ gap: 1.5rem;
331
+ }
332
+
333
+ .bento-card {
334
+ background: var(--bg-card);
335
+ backdrop-filter: blur(10px);
336
+ border: 1px solid var(--border);
337
+ border-radius: 20px;
338
+ padding: 2rem;
339
+ transition: all 0.3s;
340
+ position: relative;
341
+ overflow: hidden;
342
+ }
343
+
344
+ .bento-card::before {
345
+ content: '';
346
+ position: absolute;
347
+ top: 0;
348
+ left: 0;
349
+ right: 0;
350
+ height: 1px;
351
+ background: linear-gradient(90deg, transparent, rgba(6, 182, 212, 0.5), transparent);
352
+ opacity: 0;
353
+ transition: opacity 0.3s;
354
+ }
355
+
356
+ .bento-card:hover {
357
+ border-color: rgba(6, 182, 212, 0.3);
358
+ transform: translateY(-4px);
359
+ }
360
+
361
+ .bento-card:hover::before {
362
+ opacity: 1;
363
+ }
364
+
365
+ .bento-card.featured {
366
+ grid-column: span 2;
367
+ }
368
+
369
+ .bento-icon {
370
+ width: 48px;
371
+ height: 48px;
372
+ background: linear-gradient(135deg, rgba(6, 182, 212, 0.2), rgba(139, 92, 246, 0.2));
373
+ border-radius: 12px;
374
+ display: flex;
375
+ align-items: center;
376
+ justify-content: center;
377
+ font-size: 1.5rem;
378
+ margin-bottom: 1.25rem;
379
+ }
380
+
381
+ .bento-card h3 {
382
+ font-size: 1.25rem;
383
+ font-weight: 600;
384
+ margin-bottom: 0.75rem;
385
+ }
386
+
387
+ .bento-card p {
388
+ color: var(--text-secondary);
389
+ font-size: 0.9375rem;
390
+ }
391
+
392
+ /* Code Preview */
393
+ .code-preview {
394
+ margin-top: 1.5rem;
395
+ background: rgba(0, 0, 0, 0.4);
396
+ border-radius: 12px;
397
+ padding: 1rem 1.25rem;
398
+ font-family: 'SF Mono', 'Fira Code', monospace;
399
+ font-size: 0.8125rem;
400
+ overflow-x: auto;
401
+ }
402
+
403
+ .code-line {
404
+ display: flex;
405
+ gap: 0.75rem;
406
+ }
407
+
408
+ .code-prompt {
409
+ color: var(--primary);
410
+ }
411
+
412
+ .code-command {
413
+ color: var(--text);
414
+ }
415
+
416
+ /* SLOP Protocol Section */
417
+ .slop-section {
418
+ padding: 6rem 2rem;
419
+ background: linear-gradient(180deg, rgba(139, 92, 246, 0.02), transparent, rgba(6, 182, 212, 0.02));
420
+ }
421
+
422
+ .slop-container {
423
+ max-width: 1280px;
424
+ margin: 0 auto;
425
+ }
426
+
427
+ .slop-grid {
428
+ display: grid;
429
+ grid-template-columns: repeat(4, 1fr);
430
+ gap: 1.5rem;
431
+ margin-top: 3rem;
432
+ }
433
+
434
+ .slop-card {
435
+ background: var(--bg-card);
436
+ border: 1px solid var(--border);
437
+ border-radius: 16px;
438
+ padding: 1.75rem;
439
+ text-align: center;
440
+ transition: all 0.3s;
441
+ }
442
+
443
+ .slop-card:hover {
444
+ border-color: rgba(6, 182, 212, 0.3);
445
+ transform: translateY(-4px);
446
+ }
447
+
448
+ .slop-letter {
449
+ font-family: 'Space Grotesk', sans-serif;
450
+ font-size: 3rem;
451
+ font-weight: 700;
452
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
453
+ -webkit-background-clip: text;
454
+ -webkit-text-fill-color: transparent;
455
+ background-clip: text;
456
+ margin-bottom: 0.5rem;
457
+ }
458
+
459
+ .slop-word {
460
+ font-family: 'Space Grotesk', sans-serif;
461
+ font-size: 1.125rem;
462
+ font-weight: 600;
463
+ color: var(--text);
464
+ margin-bottom: 0.75rem;
465
+ }
466
+
467
+ .slop-desc {
468
+ font-size: 0.875rem;
469
+ color: var(--text-secondary);
470
+ line-height: 1.5;
471
+ }
472
+
473
+ /* Team Section */
474
+ .team-section {
475
+ padding: 6rem 2rem;
476
+ }
477
+
478
+ .team-container {
479
+ max-width: 1280px;
480
+ margin: 0 auto;
481
+ }
482
+
483
+ .team-grid {
484
+ display: grid;
485
+ grid-template-columns: repeat(3, 1fr);
486
+ gap: 2rem;
487
+ margin-top: 3rem;
488
+ }
489
+
490
+ .team-card {
491
+ background: var(--bg-card);
492
+ border: 1px solid var(--border);
493
+ border-radius: 16px;
494
+ padding: 2rem;
495
+ text-align: center;
496
+ }
497
+
498
+ .team-icon {
499
+ width: 64px;
500
+ height: 64px;
501
+ margin: 0 auto 1rem;
502
+ background: linear-gradient(135deg, rgba(6, 182, 212, 0.2), rgba(139, 92, 246, 0.2));
503
+ border-radius: 16px;
504
+ display: flex;
505
+ align-items: center;
506
+ justify-content: center;
507
+ font-size: 1.75rem;
508
+ }
509
+
510
+ .team-card h3 {
511
+ font-size: 1.125rem;
512
+ font-weight: 600;
513
+ margin-bottom: 0.5rem;
514
+ }
515
+
516
+ .team-card p {
517
+ font-size: 0.9375rem;
518
+ color: var(--text-secondary);
519
+ }
520
+
521
+ /* Deterministic Section */
522
+ .deterministic-section {
523
+ padding: 6rem 2rem;
524
+ background: linear-gradient(180deg, transparent, rgba(16, 185, 129, 0.03), transparent);
525
+ }
526
+
527
+ .deterministic-container {
528
+ max-width: 900px;
529
+ margin: 0 auto;
530
+ text-align: center;
531
+ }
532
+
533
+ .comparison-grid {
534
+ display: grid;
535
+ grid-template-columns: 1fr 1fr;
536
+ gap: 2rem;
537
+ margin-top: 3rem;
538
+ }
539
+
540
+ .comparison-card {
541
+ background: var(--bg-card);
542
+ border: 1px solid var(--border);
543
+ border-radius: 16px;
544
+ padding: 2rem;
545
+ text-align: left;
546
+ }
547
+
548
+ .comparison-card.bad {
549
+ border-color: rgba(239, 68, 68, 0.3);
550
+ }
551
+
552
+ .comparison-card.good {
553
+ border-color: rgba(16, 185, 129, 0.3);
554
+ }
555
+
556
+ .comparison-header {
557
+ display: flex;
558
+ align-items: center;
559
+ gap: 0.75rem;
560
+ margin-bottom: 1.25rem;
561
+ font-family: 'Space Grotesk', sans-serif;
562
+ font-weight: 600;
563
+ }
564
+
565
+ .comparison-card.bad .comparison-header {
566
+ color: #ef4444;
567
+ }
568
+
569
+ .comparison-card.good .comparison-header {
570
+ color: #10b981;
571
+ }
572
+
573
+ .comparison-list {
574
+ list-style: none;
575
+ font-size: 0.9375rem;
576
+ color: var(--text-secondary);
577
+ }
578
+
579
+ .comparison-list li {
580
+ padding: 0.5rem 0;
581
+ padding-left: 1.5rem;
582
+ position: relative;
583
+ }
584
+
585
+ .comparison-list li::before {
586
+ content: '';
587
+ position: absolute;
588
+ left: 0;
589
+ top: 50%;
590
+ transform: translateY(-50%);
591
+ width: 8px;
592
+ height: 8px;
593
+ border-radius: 50%;
594
+ }
595
+
596
+ .comparison-card.bad .comparison-list li::before {
597
+ background: #ef4444;
598
+ }
599
+
600
+ .comparison-card.good .comparison-list li::before {
601
+ background: #10b981;
602
+ }
603
+
604
+ @media (max-width: 1024px) {
605
+ .slop-grid {
606
+ grid-template-columns: repeat(2, 1fr);
607
+ }
608
+ .team-grid {
609
+ grid-template-columns: 1fr;
610
+ }
611
+ .comparison-grid {
612
+ grid-template-columns: 1fr;
613
+ }
614
+ }
615
+
616
+ @media (max-width: 640px) {
617
+ .slop-grid {
618
+ grid-template-columns: 1fr;
619
+ }
620
+ }
621
+
622
+ /* Tools Section */
623
+ .tools-section {
624
+ padding: 6rem 2rem;
625
+ background: linear-gradient(180deg, transparent, rgba(6, 182, 212, 0.02), transparent);
626
+ }
627
+
628
+ .tools-container {
629
+ max-width: 1280px;
630
+ margin: 0 auto;
631
+ text-align: center;
632
+ }
633
+
634
+ .tools-grid {
635
+ display: flex;
636
+ flex-wrap: wrap;
637
+ gap: 1rem;
638
+ justify-content: center;
639
+ margin-top: 3rem;
640
+ }
641
+
642
+ .tool-chip {
643
+ display: flex;
644
+ align-items: center;
645
+ gap: 0.625rem;
646
+ padding: 0.75rem 1.25rem;
647
+ background: var(--bg-card);
648
+ border: 1px solid var(--border);
649
+ border-radius: 100px;
650
+ font-size: 0.9375rem;
651
+ font-weight: 500;
652
+ transition: all 0.2s;
653
+ }
654
+
655
+ .tool-chip:hover {
656
+ border-color: var(--primary);
657
+ box-shadow: 0 0 20px rgba(6, 182, 212, 0.1);
658
+ }
659
+
660
+ .tool-chip .icon {
661
+ font-size: 1.125rem;
662
+ }
663
+
664
+ /* CTA Section */
665
+ .cta-section {
666
+ padding: 8rem 2rem;
667
+ text-align: center;
668
+ position: relative;
669
+ }
670
+
671
+ .cta-section::before {
672
+ content: '';
673
+ position: absolute;
674
+ top: 50%;
675
+ left: 50%;
676
+ transform: translate(-50%, -50%);
677
+ width: 600px;
678
+ height: 600px;
679
+ background: radial-gradient(circle, rgba(6, 182, 212, 0.1) 0%, transparent 70%);
680
+ pointer-events: none;
681
+ }
682
+
683
+ .cta-content {
684
+ position: relative;
685
+ z-index: 2;
686
+ max-width: 600px;
687
+ margin: 0 auto;
688
+ }
689
+
690
+ .cta-content h2 {
691
+ font-size: 2.5rem;
692
+ font-weight: 700;
693
+ margin-bottom: 1rem;
694
+ }
695
+
696
+ .cta-content p {
697
+ color: var(--text-secondary);
698
+ font-size: 1.125rem;
699
+ margin-bottom: 2rem;
700
+ }
701
+
702
+ .cta-buttons {
703
+ display: flex;
704
+ gap: 1rem;
705
+ justify-content: center;
706
+ flex-wrap: wrap;
707
+ }
708
+
709
+ /* Footer */
710
+ footer {
711
+ padding: 4rem 2rem 2rem;
712
+ border-top: 1px solid var(--border);
713
+ }
714
+
715
+ .footer-container {
716
+ max-width: 1280px;
717
+ margin: 0 auto;
718
+ display: flex;
719
+ justify-content: space-between;
720
+ align-items: center;
721
+ flex-wrap: wrap;
722
+ gap: 2rem;
723
+ }
724
+
725
+ .footer-left {
726
+ display: flex;
727
+ align-items: center;
728
+ gap: 2rem;
729
+ }
730
+
731
+ .footer-links {
732
+ display: flex;
733
+ gap: 1.5rem;
734
+ }
735
+
736
+ .footer-links a {
737
+ color: var(--text-muted);
738
+ text-decoration: none;
739
+ font-size: 0.875rem;
740
+ transition: color 0.2s;
741
+ }
742
+
743
+ .footer-links a:hover {
744
+ color: var(--text);
745
+ }
746
+
747
+ .footer-right {
748
+ color: var(--text-muted);
749
+ font-size: 0.8125rem;
750
+ }
751
+
752
+ /* Responsive */
753
+ @media (max-width: 1024px) {
754
+ .hero-container {
755
+ grid-template-columns: 1fr;
756
+ text-align: center;
757
+ }
758
+
759
+ .hero-content {
760
+ order: 2;
761
+ }
762
+
763
+ .hero-3d {
764
+ order: 1;
765
+ height: 350px;
766
+ }
767
+
768
+ .hero-description {
769
+ margin: 0 auto 2rem;
770
+ }
771
+
772
+ .hero-actions {
773
+ justify-content: center;
774
+ }
775
+
776
+ .hero-stats {
777
+ justify-content: center;
778
+ }
779
+
780
+ .bento-grid {
781
+ grid-template-columns: 1fr;
782
+ }
783
+
784
+ .bento-card.featured {
785
+ grid-column: span 1;
786
+ }
787
+ }
788
+
789
+ @media (max-width: 640px) {
790
+ .nav-links {
791
+ display: none;
792
+ }
793
+
794
+ .hero h1 {
795
+ font-size: 2rem;
796
+ }
797
+
798
+ .hero-stats {
799
+ flex-direction: column;
800
+ gap: 1.5rem;
801
+ align-items: center;
802
+ }
803
+
804
+ .footer-container {
805
+ flex-direction: column;
806
+ text-align: center;
807
+ }
808
+
809
+ .footer-left {
810
+ flex-direction: column;
811
+ }
812
+ }
813
+ </style>
814
+ </head>
815
+ <body>
816
+ <div class="mesh-gradient"></div>
817
+ <div class="grid-pattern"></div>
818
+
819
+ <!-- Navigation -->
820
+ <nav>
821
+ <div class="nav-inner">
822
+ <a href="/" class="logo">
823
+ <div class="logo-mark">🛡️</div>
824
+ aurasecurity
825
+ </a>
826
+ <div class="nav-links">
827
+ <a href="#slop" class="nav-link">SLOP Protocol</a>
828
+ <a href="#features" class="nav-link">Features</a>
829
+ <a href="#team" class="nav-link">Team</a>
830
+ <a href="https://github.com/aurasecurity/aura-security" target="_blank" class="nav-link">GitHub</a>
831
+ <a href="/app" class="btn btn-primary">Open Dashboard</a>
832
+ </div>
833
+ </div>
834
+ </nav>
835
+
836
+ <!-- Hero Section -->
837
+ <section class="hero">
838
+ <div class="hero-container">
839
+ <div class="hero-content">
840
+ <div class="hero-badge">Built by Security Engineers · 100% Deterministic</div>
841
+ <h1>Real security tools.<br><span class="gradient-text">Zero AI hallucinations.</span></h1>
842
+ <p class="hero-description">
843
+ We run Gitleaks, Trivy, Semgrep, and Grype in parallel. Same input = same output, every time.
844
+ No LLM guessing. No false confidence. Just real CVEs and real secrets, with line numbers.
845
+ </p>
846
+ <div class="hero-actions">
847
+ <a href="/app" class="btn btn-primary">
848
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
849
+ <path d="M5 12h14M12 5l7 7-7 7"/>
850
+ </svg>
851
+ Try Dashboard
852
+ </a>
853
+ <a href="https://github.com/aurasecurity/aura-security" target="_blank" class="btn btn-ghost">
854
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
855
+ <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
856
+ </svg>
857
+ View Source
858
+ </a>
859
+ </div>
860
+ <div class="hero-stats">
861
+ <div class="stat">
862
+ <div class="stat-value">0%</div>
863
+ <div class="stat-label">AI Hallucinations</div>
864
+ </div>
865
+ <div class="stat">
866
+ <div class="stat-value">8+</div>
867
+ <div class="stat-label">Real Scanners</div>
868
+ </div>
869
+ <div class="stat">
870
+ <div class="stat-value">SLOP</div>
871
+ <div class="stat-label">Multi-Agent Protocol</div>
872
+ </div>
873
+ </div>
874
+ </div>
875
+
876
+ <div class="hero-3d">
877
+ <div id="hero-canvas"></div>
878
+ </div>
879
+ </div>
880
+ </section>
881
+
882
+ <!-- Features Section -->
883
+ <section class="features-section" id="features">
884
+ <div class="features-container">
885
+ <div class="section-header">
886
+ <h2>No fluff. Just works.</h2>
887
+ <p>One command. Eight scanners. Real vulnerabilities with real line numbers.</p>
888
+ </div>
889
+
890
+ <div class="bento-grid">
891
+ <div class="bento-card featured">
892
+ <div class="bento-icon">⚡</div>
893
+ <h3>Unified Command Interface</h3>
894
+ <p>Run multiple security scanners with a single command. No more juggling terminals and output formats. Results aggregated and normalized automatically.</p>
895
+ <div class="code-preview">
896
+ <div class="code-line">
897
+ <span class="code-prompt">$</span>
898
+ <span class="code-command">aura-security scan ./my-project</span>
899
+ </div>
900
+ </div>
901
+ </div>
902
+
903
+ <div class="bento-card">
904
+ <div class="bento-icon">🎯</div>
905
+ <h3>3D Dashboard</h3>
906
+ <p>Interactive Three.js visualization shows your security posture spatially. Click nodes, filter findings, see the big picture.</p>
907
+ </div>
908
+
909
+ <div class="bento-card">
910
+ <div class="bento-icon">☁️</div>
911
+ <h3>AWS Scanning</h3>
912
+ <p>Audit IAM, S3, EC2, Lambda, and RDS for misconfigurations. Cloud security in the same unified view.</p>
913
+ </div>
914
+
915
+ <div class="bento-card">
916
+ <div class="bento-icon">📡</div>
917
+ <h3>Real-time WebSocket</h3>
918
+ <p>Live updates as scanners run. No polling, no refresh. Findings appear instantly in the dashboard.</p>
919
+ </div>
920
+
921
+ <div class="bento-card featured">
922
+ <div class="bento-icon">🔔</div>
923
+ <h3>Notifications & Integrations</h3>
924
+ <p>Slack, Discord, and custom webhooks. Get alerted on critical findings. Integrates with your existing workflow seamlessly.</p>
925
+ <div class="code-preview">
926
+ <div class="code-line">
927
+ <span class="code-prompt">$</span>
928
+ <span class="code-command">aura-security scan . --notify slack</span>
929
+ </div>
930
+ </div>
931
+ </div>
932
+ </div>
933
+ </div>
934
+ </section>
935
+
936
+ <!-- SLOP Protocol Section -->
937
+ <section class="slop-section" id="slop">
938
+ <div class="slop-container">
939
+ <div class="section-header">
940
+ <h2>The SLOP Protocol</h2>
941
+ <p>Multi-agent architecture that makes AI security scanning actually reliable. Each component is isolated, labeled, and verifiable.</p>
942
+ </div>
943
+
944
+ <div class="slop-grid">
945
+ <div class="slop-card">
946
+ <div class="slop-letter">S</div>
947
+ <div class="slop-word">Segmentation</div>
948
+ <p class="slop-desc">Each scanner runs in its own isolated zone. Gitleaks can't corrupt Trivy's output. One tool failing doesn't break the pipeline.</p>
949
+ </div>
950
+ <div class="slop-card">
951
+ <div class="slop-letter">L</div>
952
+ <div class="slop-word">Labeling</div>
953
+ <p class="slop-desc">Every finding is tagged with its source tool, file path, and line number. You know exactly where each result came from. No black boxes.</p>
954
+ </div>
955
+ <div class="slop-card">
956
+ <div class="slop-letter">O</div>
957
+ <div class="slop-word">Organization</div>
958
+ <p class="slop-desc">Policy agents validate findings before reporting. Duplicate CVEs are merged. False positives are filtered. Clean, actionable output.</p>
959
+ </div>
960
+ <div class="slop-card">
961
+ <div class="slop-letter">P</div>
962
+ <div class="slop-word">Parallelism</div>
963
+ <p class="slop-desc">All scanners run simultaneously. 8 tools don't mean 8x the wait time. Results stream in real-time via WebSocket.</p>
964
+ </div>
965
+ </div>
966
+ </div>
967
+ </section>
968
+
969
+ <!-- Deterministic Section -->
970
+ <section class="deterministic-section">
971
+ <div class="deterministic-container">
972
+ <div class="section-header">
973
+ <h2>Why "Deterministic" Matters</h2>
974
+ <p>LLM-based security tools hallucinate vulnerabilities. We don't.</p>
975
+ </div>
976
+
977
+ <div class="comparison-grid">
978
+ <div class="comparison-card bad">
979
+ <div class="comparison-header">
980
+ <span>✗</span> AI Security Tools
981
+ </div>
982
+ <ul class="comparison-list">
983
+ <li>Different results each run</li>
984
+ <li>Invents CVEs that don't exist</li>
985
+ <li>"Might be vulnerable" confidence theater</li>
986
+ <li>Can't reproduce findings for audits</li>
987
+ <li>Black box reasoning</li>
988
+ </ul>
989
+ </div>
990
+ <div class="comparison-card good">
991
+ <div class="comparison-header">
992
+ <span>✓</span> aurasecurity
993
+ </div>
994
+ <ul class="comparison-list">
995
+ <li>Same input = same output, always</li>
996
+ <li>Only real CVEs from NVD/OSV databases</li>
997
+ <li>Exact file:line for every finding</li>
998
+ <li>Reproducible for compliance audits</li>
999
+ <li>Full transparency on tool sources</li>
1000
+ </ul>
1001
+ </div>
1002
+ </div>
1003
+ </div>
1004
+ </section>
1005
+
1006
+ <!-- Team Section -->
1007
+ <section class="team-section" id="team">
1008
+ <div class="team-container">
1009
+ <div class="section-header">
1010
+ <h2>Built by Security Engineers</h2>
1011
+ <p>Not a wrapper around ChatGPT. Built by people who've actually found bugs.</p>
1012
+ </div>
1013
+
1014
+ <div class="team-grid">
1015
+ <div class="team-card">
1016
+ <div class="team-icon">🔓</div>
1017
+ <h3>Pentest Background</h3>
1018
+ <p>Years of offensive security experience. We know what real vulnerabilities look like because we've exploited them.</p>
1019
+ </div>
1020
+ <div class="team-card">
1021
+ <div class="team-icon">🐛</div>
1022
+ <h3>Bug Bounty Hunters</h3>
1023
+ <p>Found and reported vulnerabilities in production systems. We built this tool because we needed it ourselves.</p>
1024
+ </div>
1025
+ <div class="team-card">
1026
+ <div class="team-icon">📖</div>
1027
+ <h3>Open Source</h3>
1028
+ <p>MIT licensed. Read every line of code. No telemetry, no tracking, no BS. Fork it, audit it, run it air-gapped.</p>
1029
+ </div>
1030
+ </div>
1031
+ </div>
1032
+ </section>
1033
+
1034
+ <!-- Tools Section -->
1035
+ <section class="tools-section" id="tools">
1036
+ <div class="tools-container">
1037
+ <div class="section-header">
1038
+ <h2>Real tools. Not GPT wrappers.</h2>
1039
+ <p>Battle-tested scanners used by actual security teams. We just orchestrate them intelligently.</p>
1040
+ </div>
1041
+
1042
+ <div class="tools-grid">
1043
+ <div class="tool-chip"><span class="icon">🔐</span> Gitleaks</div>
1044
+ <div class="tool-chip"><span class="icon">🛡️</span> Trivy</div>
1045
+ <div class="tool-chip"><span class="icon">🔬</span> Semgrep</div>
1046
+ <div class="tool-chip"><span class="icon">📦</span> npm audit</div>
1047
+ <div class="tool-chip"><span class="icon">🐍</span> pip-audit</div>
1048
+ <div class="tool-chip"><span class="icon">🦀</span> cargo-audit</div>
1049
+ <div class="tool-chip"><span class="icon">🐹</span> govulncheck</div>
1050
+ <div class="tool-chip"><span class="icon">🔎</span> Grype</div>
1051
+ </div>
1052
+ </div>
1053
+ </section>
1054
+
1055
+ <!-- CTA Section -->
1056
+ <section class="cta-section">
1057
+ <div class="cta-content">
1058
+ <h2>Stop guessing. Start scanning.</h2>
1059
+ <p>No signup. No API keys. No cloud dependency. Just clone and run.</p>
1060
+ <div class="cta-buttons">
1061
+ <a href="/app" class="btn btn-primary">Try the Dashboard</a>
1062
+ <a href="https://github.com/aurasecurity/aura-security" target="_blank" class="btn btn-ghost">Read the Code</a>
1063
+ </div>
1064
+ </div>
1065
+ </section>
1066
+
1067
+ <!-- Footer -->
1068
+ <footer>
1069
+ <div class="footer-container">
1070
+ <div class="footer-left">
1071
+ <a href="/" class="logo">
1072
+ <div class="logo-mark">🛡️</div>
1073
+ aurasecurity
1074
+ </a>
1075
+ <div class="footer-links">
1076
+ <a href="https://github.com/aurasecurity/aura-security" target="_blank">GitHub</a>
1077
+ <a href="https://www.npmjs.com/package/aura-security" target="_blank">npm</a>
1078
+ <a href="https://pypi.org/project/aura-security/" target="_blank">PyPI</a>
1079
+ <a href="/app">Dashboard</a>
1080
+ </div>
1081
+ </div>
1082
+ <div class="footer-right">
1083
+ © 2026 aurasecurity · MIT License
1084
+ </div>
1085
+ </div>
1086
+ </footer>
1087
+
1088
+ <script>
1089
+ // Three.js Security Scene
1090
+ const container = document.getElementById('hero-canvas');
1091
+ const scene = new THREE.Scene();
1092
+ const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 1000);
1093
+ const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
1094
+
1095
+ renderer.setSize(container.clientWidth, container.clientHeight);
1096
+ renderer.setClearColor(0x000000, 0);
1097
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
1098
+ container.appendChild(renderer.domElement);
1099
+
1100
+ // Lighting
1101
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
1102
+ scene.add(ambientLight);
1103
+
1104
+ const mainLight = new THREE.DirectionalLight(0xffffff, 0.8);
1105
+ mainLight.position.set(10, 20, 10);
1106
+ scene.add(mainLight);
1107
+
1108
+ const cyanLight = new THREE.PointLight(0x06b6d4, 1, 20);
1109
+ cyanLight.position.set(-5, 5, 5);
1110
+ scene.add(cyanLight);
1111
+
1112
+ const purpleLight = new THREE.PointLight(0x8b5cf6, 0.8, 20);
1113
+ purpleLight.position.set(5, -3, 5);
1114
+ scene.add(purpleLight);
1115
+
1116
+ // Main group for all objects
1117
+ const mainGroup = new THREE.Group();
1118
+
1119
+ // Central Shield/Core
1120
+ const shieldGroup = new THREE.Group();
1121
+
1122
+ // Outer hexagonal shield
1123
+ const shieldShape = new THREE.Shape();
1124
+ const shieldRadius = 1.5;
1125
+ for (let i = 0; i < 6; i++) {
1126
+ const angle = (i / 6) * Math.PI * 2 - Math.PI / 2;
1127
+ const x = Math.cos(angle) * shieldRadius;
1128
+ const y = Math.sin(angle) * shieldRadius;
1129
+ if (i === 0) shieldShape.moveTo(x, y);
1130
+ else shieldShape.lineTo(x, y);
1131
+ }
1132
+ shieldShape.closePath();
1133
+
1134
+ const shieldExtrudeSettings = { depth: 0.3, bevelEnabled: true, bevelThickness: 0.05, bevelSize: 0.05, bevelSegments: 3 };
1135
+ const shieldGeo = new THREE.ExtrudeGeometry(shieldShape, shieldExtrudeSettings);
1136
+ const shieldMat = new THREE.MeshStandardMaterial({
1137
+ color: 0x06b6d4,
1138
+ metalness: 0.8,
1139
+ roughness: 0.2,
1140
+ emissive: 0x06b6d4,
1141
+ emissiveIntensity: 0.1
1142
+ });
1143
+ const shield = new THREE.Mesh(shieldGeo, shieldMat);
1144
+ shield.rotation.x = Math.PI / 2;
1145
+ shieldGroup.add(shield);
1146
+
1147
+ // Inner shield detail
1148
+ const innerShieldGeo = new THREE.ExtrudeGeometry(shieldShape, { depth: 0.1, bevelEnabled: false });
1149
+ const innerShieldMat = new THREE.MeshStandardMaterial({
1150
+ color: 0x0f172a,
1151
+ metalness: 0.9,
1152
+ roughness: 0.1
1153
+ });
1154
+ const innerShield = new THREE.Mesh(innerShieldGeo, innerShieldMat);
1155
+ innerShield.scale.set(0.7, 0.7, 1);
1156
+ innerShield.rotation.x = Math.PI / 2;
1157
+ innerShield.position.z = 0.2;
1158
+ shieldGroup.add(innerShield);
1159
+
1160
+ // Lock icon in center
1161
+ const lockBodyGeo = new THREE.BoxGeometry(0.4, 0.5, 0.15);
1162
+ const lockMat = new THREE.MeshStandardMaterial({ color: 0x06b6d4, metalness: 0.7, roughness: 0.3 });
1163
+ const lockBody = new THREE.Mesh(lockBodyGeo, lockMat);
1164
+ lockBody.position.z = 0.3;
1165
+ shieldGroup.add(lockBody);
1166
+
1167
+ const lockArcGeo = new THREE.TorusGeometry(0.2, 0.05, 8, 16, Math.PI);
1168
+ const lockArc = new THREE.Mesh(lockArcGeo, lockMat);
1169
+ lockArc.position.set(0, 0.25, 0.3);
1170
+ lockArc.rotation.z = Math.PI;
1171
+ shieldGroup.add(lockArc);
1172
+
1173
+ mainGroup.add(shieldGroup);
1174
+
1175
+ // Orbiting security nodes
1176
+ const nodePositions = [
1177
+ { radius: 3, speed: 0.5, offset: 0, color: 0x10b981, icon: 'check' },
1178
+ { radius: 3, speed: 0.5, offset: Math.PI * 0.66, color: 0xf59e0b, icon: 'warning' },
1179
+ { radius: 3, speed: 0.5, offset: Math.PI * 1.33, color: 0xef4444, icon: 'alert' },
1180
+ { radius: 4.2, speed: 0.3, offset: Math.PI * 0.25, color: 0x8b5cf6, icon: 'scan' },
1181
+ { radius: 4.2, speed: 0.3, offset: Math.PI * 0.75, color: 0x06b6d4, icon: 'scan' },
1182
+ { radius: 4.2, speed: 0.3, offset: Math.PI * 1.25, color: 0x10b981, icon: 'scan' },
1183
+ { radius: 4.2, speed: 0.3, offset: Math.PI * 1.75, color: 0x8b5cf6, icon: 'scan' },
1184
+ ];
1185
+
1186
+ const nodes = [];
1187
+ nodePositions.forEach((config, index) => {
1188
+ const nodeGroup = new THREE.Group();
1189
+
1190
+ // Node body - rounded cube style
1191
+ const nodeGeo = new THREE.BoxGeometry(0.5, 0.5, 0.5);
1192
+ const nodeMat = new THREE.MeshStandardMaterial({
1193
+ color: config.color,
1194
+ metalness: 0.6,
1195
+ roughness: 0.3,
1196
+ emissive: config.color,
1197
+ emissiveIntensity: 0.2
1198
+ });
1199
+ const node = new THREE.Mesh(nodeGeo, nodeMat);
1200
+ node.rotation.set(Math.PI / 4, Math.PI / 4, 0);
1201
+ nodeGroup.add(node);
1202
+
1203
+ // Glow ring
1204
+ const ringGeo = new THREE.RingGeometry(0.35, 0.4, 32);
1205
+ const ringMat = new THREE.MeshBasicMaterial({
1206
+ color: config.color,
1207
+ transparent: true,
1208
+ opacity: 0.3,
1209
+ side: THREE.DoubleSide
1210
+ });
1211
+ const ring = new THREE.Mesh(ringGeo, ringMat);
1212
+ nodeGroup.add(ring);
1213
+
1214
+ nodeGroup.userData = config;
1215
+ nodes.push(nodeGroup);
1216
+ mainGroup.add(nodeGroup);
1217
+ });
1218
+
1219
+ // Orbital rings
1220
+ const createOrbitRing = (radius, opacity) => {
1221
+ const ringGeo = new THREE.RingGeometry(radius - 0.02, radius + 0.02, 64);
1222
+ const ringMat = new THREE.MeshBasicMaterial({
1223
+ color: 0x06b6d4,
1224
+ transparent: true,
1225
+ opacity: opacity,
1226
+ side: THREE.DoubleSide
1227
+ });
1228
+ const ring = new THREE.Mesh(ringGeo, ringMat);
1229
+ ring.rotation.x = Math.PI / 2;
1230
+ return ring;
1231
+ };
1232
+
1233
+ mainGroup.add(createOrbitRing(3, 0.15));
1234
+ mainGroup.add(createOrbitRing(4.2, 0.1));
1235
+
1236
+ // Data stream particles
1237
+ const particleCount = 100;
1238
+ const particleGeo = new THREE.BufferGeometry();
1239
+ const particlePositions = new Float32Array(particleCount * 3);
1240
+ const particleSpeeds = [];
1241
+
1242
+ for (let i = 0; i < particleCount; i++) {
1243
+ const angle = Math.random() * Math.PI * 2;
1244
+ const radius = 2 + Math.random() * 3;
1245
+ particlePositions[i * 3] = Math.cos(angle) * radius;
1246
+ particlePositions[i * 3 + 1] = (Math.random() - 0.5) * 2;
1247
+ particlePositions[i * 3 + 2] = Math.sin(angle) * radius;
1248
+ particleSpeeds.push(0.01 + Math.random() * 0.02);
1249
+ }
1250
+
1251
+ particleGeo.setAttribute('position', new THREE.BufferAttribute(particlePositions, 3));
1252
+ const particleMat = new THREE.PointsMaterial({
1253
+ color: 0x06b6d4,
1254
+ size: 0.05,
1255
+ transparent: true,
1256
+ opacity: 0.6
1257
+ });
1258
+ const particles = new THREE.Points(particleGeo, particleMat);
1259
+ mainGroup.add(particles);
1260
+
1261
+ // Tilt the whole scene
1262
+ mainGroup.rotation.x = 0.3;
1263
+ scene.add(mainGroup);
1264
+
1265
+ camera.position.set(0, 2, 8);
1266
+ camera.lookAt(0, 0, 0);
1267
+
1268
+ // Animation
1269
+ let time = 0;
1270
+ function animate() {
1271
+ requestAnimationFrame(animate);
1272
+ time += 0.01;
1273
+
1274
+ // Rotate shield slowly
1275
+ shieldGroup.rotation.z = Math.sin(time * 0.5) * 0.1;
1276
+
1277
+ // Animate orbiting nodes
1278
+ nodes.forEach((node, i) => {
1279
+ const config = node.userData;
1280
+ const angle = time * config.speed + config.offset;
1281
+ node.position.x = Math.cos(angle) * config.radius;
1282
+ node.position.z = Math.sin(angle) * config.radius;
1283
+ node.position.y = Math.sin(time * 2 + i) * 0.2;
1284
+ node.rotation.y = time;
1285
+ });
1286
+
1287
+ // Animate particles
1288
+ const positions = particles.geometry.attributes.position.array;
1289
+ for (let i = 0; i < particleCount; i++) {
1290
+ const idx = i * 3;
1291
+ const x = positions[idx];
1292
+ const z = positions[idx + 2];
1293
+ const angle = Math.atan2(z, x) + particleSpeeds[i];
1294
+ const radius = Math.sqrt(x * x + z * z);
1295
+ positions[idx] = Math.cos(angle) * radius;
1296
+ positions[idx + 2] = Math.sin(angle) * radius;
1297
+ positions[idx + 1] += 0.01;
1298
+ if (positions[idx + 1] > 1) positions[idx + 1] = -1;
1299
+ }
1300
+ particles.geometry.attributes.position.needsUpdate = true;
1301
+
1302
+ // Gentle scene rotation
1303
+ mainGroup.rotation.y = time * 0.1;
1304
+
1305
+ renderer.render(scene, camera);
1306
+ }
1307
+ animate();
1308
+
1309
+ // Handle resize
1310
+ window.addEventListener('resize', () => {
1311
+ camera.aspect = container.clientWidth / container.clientHeight;
1312
+ camera.updateProjectionMatrix();
1313
+ renderer.setSize(container.clientWidth, container.clientHeight);
1314
+ });
1315
+
1316
+ // Smooth scroll
1317
+ document.querySelectorAll('a[href^="#"]').forEach(anchor => {
1318
+ anchor.addEventListener('click', function(e) {
1319
+ e.preventDefault();
1320
+ const target = document.querySelector(this.getAttribute('href'));
1321
+ if (target) {
1322
+ target.scrollIntoView({ behavior: 'smooth' });
1323
+ }
1324
+ });
1325
+ });
1326
+ </script>
1327
+ </body>
1328
+ </html>