create-planet 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 (35) hide show
  1. package/index.js +235 -0
  2. package/package.json +20 -0
  3. package/template/.claude/settings.json +5 -0
  4. package/template/.prettierrc +11 -0
  5. package/template/AGENTS.md +96 -0
  6. package/template/LICENSE +201 -0
  7. package/template/PROTOCOL_DIAGRAMS.md +195 -0
  8. package/template/README.md +51 -0
  9. package/template/astro.config.mjs +20 -0
  10. package/template/package.json +38 -0
  11. package/template/public/favicon.ico +0 -0
  12. package/template/public/map.js +329 -0
  13. package/template/public/planet.css +873 -0
  14. package/template/public/three.min.js +29395 -0
  15. package/template/schema.sql +22 -0
  16. package/template/scripts/inject-do-exports.js +61 -0
  17. package/template/scripts/simulate-universe.js +158 -0
  18. package/template/src/env.d.ts +21 -0
  19. package/template/src/lib/config.ts +52 -0
  20. package/template/src/lib/consensus.ts +127 -0
  21. package/template/src/lib/crypto.ts +89 -0
  22. package/template/src/lib/identity.ts +35 -0
  23. package/template/src/lib/travel.ts +75 -0
  24. package/template/src/pages/api/v1/control-ws.ts +22 -0
  25. package/template/src/pages/api/v1/port.ts +673 -0
  26. package/template/src/pages/control.astro +232 -0
  27. package/template/src/pages/index.astro +1009 -0
  28. package/template/src/pages/manifest.json.ts +37 -0
  29. package/template/src/tests/protocol.test.ts +158 -0
  30. package/template/src/tests/warp-links.test.ts +117 -0
  31. package/template/src/traffic-control.ts +52 -0
  32. package/template/tsconfig.json +9 -0
  33. package/template/vitest.config.ts +12 -0
  34. package/template/wrangler.build.jsonc +36 -0
  35. package/template/wrangler.dev.jsonc +41 -0
@@ -0,0 +1,873 @@
1
+ :root {
2
+ /* Fixed Space Theme Colors (Sky remains black) */
3
+ --sky-bg: #0b0e14;
4
+ --sky-text: #e0e0e0;
5
+ --sky-text-dim: #888;
6
+ --sky-accent: #4a90e2;
7
+
8
+ /* Theme-Aware Warp Ring Colors (Defaults to Dark) */
9
+ --warp-bg: linear-gradient(
10
+ 180deg,
11
+ rgba(20, 25, 35, 0.8) 0%,
12
+ rgba(10, 15, 25, 0.9) 100%
13
+ );
14
+ --warp-text: #e0e0e0;
15
+ --warp-text-dim: #888;
16
+ --warp-border: #444;
17
+ --warp-accent: #4a90e2;
18
+ --map-bg: #0b0e14;
19
+ --map-grid: rgba(255, 255, 255, 0.05);
20
+ --coord-bg: rgba(255, 255, 255, 0.05);
21
+ --color-outbound: #e67e22;
22
+ --color-inbound: #3498db;
23
+ }
24
+
25
+ @media (prefers-color-scheme: light) {
26
+ :root {
27
+ /* Only Warp Ring section changes in light theme */
28
+ --warp-bg: linear-gradient(
29
+ 180deg,
30
+ rgba(230, 235, 245, 0.8) 0%,
31
+ rgba(220, 225, 235, 0.9) 100%
32
+ );
33
+ --warp-text: #1a1a1a;
34
+ --warp-text-dim: #666;
35
+ --warp-border: #ccc;
36
+ --warp-accent: #2a6dbd;
37
+ --map-bg: #ffffff;
38
+ --map-grid: rgba(0, 0, 0, 0.05);
39
+ --coord-bg: rgba(0, 0, 0, 0.05);
40
+ }
41
+ }
42
+
43
+ body {
44
+ background: var(--sky-bg);
45
+ color: var(--sky-text);
46
+ font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
47
+ display: flex;
48
+ flex-direction: column;
49
+ align-items: center;
50
+ justify-content: flex-start;
51
+ min-height: 100vh;
52
+ margin: 0;
53
+ padding: 4rem 0;
54
+ box-sizing: border-box;
55
+ position: relative;
56
+ transition:
57
+ background 0.3s,
58
+ color 0.3s;
59
+ }
60
+
61
+ h1,
62
+ p {
63
+ padding-left: 2rem;
64
+ padding-right: 2rem;
65
+ max-width: 800px;
66
+ text-align: center;
67
+ }
68
+
69
+ /* Starfield effect - always visible */
70
+ body::before,
71
+ body::after {
72
+ content: "";
73
+ position: absolute;
74
+ top: 0;
75
+ left: 0;
76
+ width: 1px;
77
+ height: 1px;
78
+ background: transparent;
79
+ z-index: -1;
80
+ opacity: 1; /* Always 100% opacity for stars */
81
+ }
82
+
83
+ body::before {
84
+ box-shadow:
85
+ 10vw 20vh #fff,
86
+ 35vw 45vh #fff,
87
+ 80vw 10vh #fff,
88
+ 15vw 85vh #fff,
89
+ 55vw 15vh #fff,
90
+ 90vw 60vh #fff,
91
+ 25vw 30vh #fff,
92
+ 70vw 75vh #fff,
93
+ 45vw 90vh #fff,
94
+ 5vw 50vh #fff,
95
+ 65vw 5vh #fff,
96
+ 85vw 25vh #fff,
97
+ 12vw 12vh rgba(255, 255, 255, 0.5),
98
+ 42vw 82vh rgba(255, 255, 255, 0.5),
99
+ 72vw 32vh rgba(255, 255, 255, 0.5),
100
+ 92vw 92vh rgba(255, 255, 255, 0.5);
101
+ }
102
+
103
+ body::after {
104
+ width: 2px;
105
+ height: 2px;
106
+ box-shadow:
107
+ 20vw 10vh #fff,
108
+ 40vw 60vh #fff,
109
+ 60vw 20vh #fff,
110
+ 80vw 80vh #fff,
111
+ 10vw 90vh #fff,
112
+ 30vw 40vh #fff,
113
+ 50vw 70vh #fff,
114
+ 70vw 10vh #fff,
115
+ 95vw 45vh #fff;
116
+ opacity: 0.5;
117
+ }
118
+
119
+ .planet-container {
120
+ position: relative;
121
+ margin-bottom: 3rem;
122
+ display: flex;
123
+ justify-content: center;
124
+ align-items: center;
125
+ }
126
+
127
+ .planet {
128
+ width: 200px;
129
+ height: 200px;
130
+ background: radial-gradient(circle at 30% 30%, var(--sky-accent), #1b2735);
131
+ border-radius: 50%;
132
+ box-shadow:
133
+ inset -20px -20px 50px rgba(0, 0, 0, 0.5),
134
+ inset 10px 10px 20px rgba(255, 255, 255, 0.1),
135
+ 0 0 60px var(--sky-accent);
136
+ position: relative;
137
+ overflow: hidden;
138
+ z-index: 2;
139
+ }
140
+
141
+ /* Surface craters/texture */
142
+ .planet::before {
143
+ content: "";
144
+ position: absolute;
145
+ width: 100%;
146
+ height: 100%;
147
+ background-image:
148
+ radial-gradient(circle at 70% 20%, rgba(0, 0, 0, 0.15) 5%, transparent 6%),
149
+ radial-gradient(circle at 40% 60%, rgba(0, 0, 0, 0.15) 8%, transparent 9%),
150
+ radial-gradient(circle at 80% 70%, rgba(0, 0, 0, 0.1) 3%, transparent 4%),
151
+ radial-gradient(
152
+ circle at 20% 40%,
153
+ rgba(255, 255, 255, 0.05) 10%,
154
+ transparent 11%
155
+ );
156
+ }
157
+
158
+ .ring {
159
+ position: absolute;
160
+ width: 340px;
161
+ height: 80px;
162
+ border: 12px solid rgba(255, 255, 255, 0.08);
163
+ border-top-color: transparent;
164
+ border-bottom-color: rgba(255, 255, 255, 0.12);
165
+ border-radius: 50%;
166
+ transform: rotate(-20deg);
167
+ z-index: 3;
168
+ pointer-events: none;
169
+ }
170
+
171
+ /* Back half of the ring */
172
+ .ring-back {
173
+ position: absolute;
174
+ width: 340px;
175
+ height: 80px;
176
+ border: 12px solid rgba(255, 255, 255, 0.08);
177
+ border-bottom-color: transparent;
178
+ border-top-color: rgba(255, 255, 255, 0.04);
179
+ border-radius: 50%;
180
+ transform: rotate(-20deg);
181
+ z-index: 1;
182
+ pointer-events: none;
183
+ }
184
+
185
+ .atmosphere {
186
+ position: absolute;
187
+ width: 230px;
188
+ height: 230px;
189
+ border-radius: 50%;
190
+ background: radial-gradient(
191
+ circle,
192
+ rgba(74, 144, 226, 0.1) 0%,
193
+ transparent 70%
194
+ );
195
+ box-shadow: 0 0 40px rgba(74, 144, 226, 0.1);
196
+ z-index: 0;
197
+ }
198
+
199
+ h1 {
200
+ font-size: 2.5rem;
201
+ margin: 0.5rem 0;
202
+ text-transform: uppercase;
203
+ letter-spacing: 4px;
204
+ color: var(--sky-text);
205
+ }
206
+
207
+ p {
208
+ color: var(--sky-text-dim);
209
+ font-style: italic;
210
+ }
211
+
212
+ .warp-ring {
213
+ margin-top: 3rem;
214
+ padding: 4rem 2rem;
215
+ background: var(--warp-bg);
216
+ border-top: 1px dashed var(--warp-border);
217
+ border-bottom: 1px dashed var(--warp-border);
218
+ color: var(--warp-text);
219
+ text-align: center;
220
+ width: 100%;
221
+ box-sizing: border-box;
222
+ transition:
223
+ background 0.3s,
224
+ border 0.3s,
225
+ color 0.3s;
226
+ }
227
+
228
+ .warp-ring-content {
229
+ display: flex;
230
+ flex-direction: column;
231
+ align-items: center;
232
+ gap: 3rem;
233
+ margin-top: 3rem;
234
+ max-width: 1200px;
235
+ margin-left: auto;
236
+ margin-right: auto;
237
+ }
238
+
239
+ @media (min-width: 800px) {
240
+ .warp-ring-content {
241
+ flex-direction: row-reverse;
242
+ justify-content: space-between;
243
+ align-items: flex-start;
244
+ text-align: left;
245
+ }
246
+
247
+ .star-map-wrapper {
248
+ flex: 0 0 auto;
249
+ width: 60%;
250
+ }
251
+
252
+ .warp-links {
253
+ flex: 1;
254
+ margin-top: 0;
255
+ padding-top: 1rem;
256
+ }
257
+ }
258
+
259
+ .star-map-container {
260
+ margin: 0 auto 2rem;
261
+ position: relative;
262
+ width: 60vw;
263
+ height: 60vw;
264
+ min-width: 20em;
265
+ min-height: 20em;
266
+ max-width: 600px;
267
+ max-height: 600px;
268
+ background: var(--map-bg);
269
+ border: 1px solid var(--warp-border);
270
+ border-radius: 4px;
271
+ overflow: hidden;
272
+ transition:
273
+ background 0.3s,
274
+ border 0.3s;
275
+ display: flex;
276
+ justify-content: center;
277
+ align-items: center;
278
+ }
279
+
280
+ #three-container canvas {
281
+ width: 100% !important;
282
+ height: 100% !important;
283
+ }
284
+
285
+ @media (min-width: 800px) {
286
+ .star-map-container {
287
+ width: 100%;
288
+ height: auto;
289
+ aspect-ratio: 1 / 1;
290
+ }
291
+ }
292
+
293
+ .warp-ring h2 {
294
+ font-size: 0.9rem;
295
+ color: var(--warp-text-dim);
296
+ margin-bottom: 1rem;
297
+ text-transform: uppercase;
298
+ }
299
+
300
+ .warp-ring a {
301
+ color: var(--warp-accent);
302
+ text-decoration: none;
303
+ font-weight: bold;
304
+ transition:
305
+ color 0.3s,
306
+ text-shadow 0.3s,
307
+ transform 0.3s;
308
+ }
309
+
310
+ .warp-links {
311
+ list-style: none;
312
+ padding: 0;
313
+ }
314
+
315
+ .warp-links li {
316
+ display: flex;
317
+ justify-content: space-between;
318
+ align-items: center;
319
+ gap: 1rem;
320
+ margin-bottom: 0.5rem;
321
+ width: 100%;
322
+ cursor: pointer;
323
+ border-radius: 4px;
324
+ transition: background 0.2s ease;
325
+ list-style: none;
326
+ }
327
+
328
+ .warp-links li:hover,
329
+ .warp-links li.active {
330
+ background: rgba(255, 255, 255, 0.05);
331
+ }
332
+
333
+ .warp-links li a {
334
+ color: var(--warp-accent);
335
+ text-decoration: none;
336
+ font-weight: bold;
337
+ transition:
338
+ color 0.3s,
339
+ text-shadow 0.3s,
340
+ transform 0.3s;
341
+ overflow: hidden;
342
+ text-overflow: ellipsis;
343
+ white-space: nowrap;
344
+ flex: 1;
345
+ text-align: left;
346
+ }
347
+
348
+ .warp-links li a:hover,
349
+ .warp-links li a.active {
350
+ color: #fff;
351
+ text-shadow: 0 0 10px var(--warp-accent);
352
+ }
353
+
354
+ @media (prefers-color-scheme: light) {
355
+ .warp-links li a:hover,
356
+ .warp-links li a.active {
357
+ color: var(--warp-accent);
358
+ text-shadow: none;
359
+ text-decoration: underline;
360
+ }
361
+ }
362
+
363
+ .coord {
364
+ font-family: "Courier New", Courier, monospace;
365
+ background: var(--coord-bg);
366
+ color: var(--warp-text);
367
+ padding: 2px 6px;
368
+ border-radius: 4px;
369
+ font-size: 0.85em;
370
+ flex: 0 0 auto;
371
+ white-space: nowrap;
372
+ cursor: default;
373
+ }
374
+
375
+ /* Coordinate Display Class */
376
+ .coord-display {
377
+ font-family: "Courier New", Courier, monospace;
378
+ background: var(--coord-bg);
379
+ padding: 2px 6px;
380
+ border-radius: 4px;
381
+ }
382
+
383
+ /* Map Labels */
384
+ .map-label {
385
+ position: absolute;
386
+ bottom: 5px;
387
+ right: 8px;
388
+ font-size: 0.6rem;
389
+ color: #444;
390
+ pointer-events: none;
391
+ z-index: 10;
392
+ }
393
+
394
+ /* Map Legend styles */
395
+ .map-legend {
396
+ display: flex;
397
+ gap: 1.5rem;
398
+ justify-content: center;
399
+ margin-bottom: 2rem;
400
+ font-size: 0.75rem;
401
+ color: #888;
402
+ }
403
+
404
+ .legend-item {
405
+ display: flex;
406
+ align-items: center;
407
+ gap: 0.5rem;
408
+ }
409
+
410
+ .legend-marker {
411
+ display: inline-block;
412
+ width: 10px;
413
+ height: 10px;
414
+ border-radius: 50%;
415
+ }
416
+
417
+ .legend-marker.station {
418
+ border: 1px solid #2ecc71;
419
+ position: relative;
420
+ }
421
+
422
+ .legend-marker.station::before,
423
+ .legend-marker.station::after {
424
+ content: "";
425
+ position: absolute;
426
+ top: 50%;
427
+ left: 50%;
428
+ background: #2ecc71;
429
+ transform: translate(-50%, -50%);
430
+ }
431
+
432
+ .legend-marker.station::before {
433
+ width: 14px;
434
+ height: 1px;
435
+ }
436
+
437
+ .legend-marker.station::after {
438
+ width: 1px;
439
+ height: 14px;
440
+ }
441
+
442
+ .legend-marker.neighbor {
443
+ background: #4a90e2;
444
+ opacity: 0.6;
445
+ }
446
+
447
+ /* Space Port Status Badge */
448
+ .status-badge {
449
+ display: inline-flex;
450
+ align-items: center;
451
+ gap: 0.5rem;
452
+ background: rgba(46, 204, 113, 0.1);
453
+ border: 1px solid rgba(46, 204, 113, 0.3);
454
+ color: #2ecc71;
455
+ padding: 0.4rem 1rem;
456
+ border-radius: 20px;
457
+ font-size: 0.8rem;
458
+ font-weight: bold;
459
+ text-transform: uppercase;
460
+ letter-spacing: 1px;
461
+ margin: 1.5rem 0;
462
+ }
463
+
464
+ .status-badge::before {
465
+ content: "";
466
+ width: 8px;
467
+ height: 8px;
468
+ background: #2ecc71;
469
+ border-radius: 50%;
470
+ box-shadow: 0 0 10px #2ecc71;
471
+ }
472
+
473
+ .space-port {
474
+ width: 100%;
475
+ max-width: 800px;
476
+ background: var(--warp-bg);
477
+ border-top: 1px dashed var(--warp-border);
478
+ border-bottom: 1px dashed var(--warp-border);
479
+ border-left: 1px solid var(--warp-border);
480
+ border-right: 1px solid var(--warp-border);
481
+ border-radius: 8px;
482
+ padding: 1.5rem;
483
+ margin: 1rem 0 4rem 0;
484
+ text-align: left;
485
+ box-sizing: border-box;
486
+ display: flex;
487
+ flex-direction: column;
488
+ gap: 2rem;
489
+ }
490
+
491
+ .traffic-log,
492
+ .mission-archive {
493
+ width: 100%;
494
+ overflow-x: auto;
495
+ }
496
+
497
+ .traffic-log h3,
498
+ .mission-archive h3 {
499
+ font-size: 0.8rem;
500
+ text-transform: uppercase;
501
+ color: var(--warp-text-dim);
502
+ margin-top: 0;
503
+ margin-bottom: 1rem;
504
+ border-bottom: 1px solid var(--warp-border);
505
+ padding-bottom: 0.5rem;
506
+ }
507
+
508
+ .traffic-table,
509
+ .archive-table {
510
+ width: 100%;
511
+ border-collapse: collapse;
512
+ font-family: "Courier New", Courier, monospace;
513
+ font-size: 0.85rem;
514
+ }
515
+
516
+ .traffic-table th,
517
+ .archive-table th {
518
+ text-align: left;
519
+ color: var(--warp-text-dim);
520
+ font-size: 0.7rem;
521
+ text-transform: uppercase;
522
+ padding: 0.5rem;
523
+ border-bottom: 1px solid var(--map-grid);
524
+ }
525
+
526
+ .traffic-table td,
527
+ .archive-table td {
528
+ padding: 0.6rem 0.5rem;
529
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
530
+ }
531
+
532
+ .ship-id {
533
+ font-weight: bold;
534
+ color: var(--warp-accent);
535
+ white-space: nowrap;
536
+ }
537
+
538
+ .status-label,
539
+ .event-label {
540
+ padding: 2px 6px;
541
+ border-radius: 4px;
542
+ font-size: 0.7rem;
543
+ font-weight: bold;
544
+ display: inline-block;
545
+ min-width: 80px;
546
+ text-align: center;
547
+ }
548
+
549
+ /* Preparing (consensus in progress) */
550
+ tr.status-preparing .status-label {
551
+ background: rgba(160, 160, 160, 0.15);
552
+ color: #aaa;
553
+ border: 1px solid rgba(160, 160, 160, 0.3);
554
+ }
555
+ tr.status-preparing .eta-bar-fill {
556
+ background: #aaa;
557
+ }
558
+
559
+ /* Scheduled to Depart (quorum reached, awaiting start time) */
560
+ tr.status-scheduled .status-label {
561
+ background: rgba(241, 196, 15, 0.15);
562
+ color: #f1c40f;
563
+ border: 1px solid rgba(241, 196, 15, 0.3);
564
+ }
565
+ tr.status-scheduled .eta-bar-fill {
566
+ background: #f1c40f;
567
+ }
568
+
569
+ /* Arrived (briefly shown before moving to archive) */
570
+ tr.status-arrived .status-label {
571
+ background: rgba(46, 204, 113, 0.15);
572
+ color: #2ecc71;
573
+ border: 1px solid rgba(46, 204, 113, 0.3);
574
+ }
575
+ tr.status-arrived .eta-bar-fill {
576
+ background: #2ecc71;
577
+ }
578
+
579
+ /* Outbound (departing from this planet) */
580
+ tr.outgoing.status-transit .status-label,
581
+ tr.preparation.status-transit .status-label {
582
+ background: rgba(230, 126, 34, 0.15);
583
+ color: var(--color-outbound);
584
+ border: 1px solid rgba(230, 126, 34, 0.3);
585
+ }
586
+ tr.outgoing.status-transit .eta-bar-fill,
587
+ tr.preparation.status-transit .eta-bar-fill {
588
+ background: var(--color-outbound);
589
+ }
590
+
591
+ /* Inbound (arriving at this planet) */
592
+ tr.incoming.status-transit .status-label {
593
+ background: rgba(52, 152, 219, 0.15);
594
+ color: var(--color-inbound);
595
+ border: 1px solid rgba(52, 152, 219, 0.3);
596
+ }
597
+ tr.incoming.status-transit .eta-bar-fill {
598
+ background: var(--color-inbound);
599
+ }
600
+
601
+ /* Direction arrows in location cells */
602
+ .dir-to {
603
+ color: var(--color-outbound);
604
+ }
605
+
606
+ .dir-from {
607
+ color: var(--color-inbound);
608
+ }
609
+
610
+ /* Planet links in traffic and archive tables */
611
+ .planet-link {
612
+ color: var(--warp-accent);
613
+ text-decoration: none;
614
+ font-weight: bold;
615
+ }
616
+
617
+ .planet-link:hover {
618
+ color: #fff;
619
+ text-shadow: 0 0 10px var(--warp-accent);
620
+ }
621
+
622
+ @media (prefers-color-scheme: light) {
623
+ .planet-link:hover {
624
+ color: var(--warp-accent);
625
+ text-shadow: none;
626
+ }
627
+ }
628
+
629
+ /* Archive event labels */
630
+ .departed .event-label {
631
+ background: rgba(230, 126, 34, 0.15);
632
+ color: var(--color-outbound);
633
+ border: 1px solid rgba(230, 126, 34, 0.3);
634
+ }
635
+
636
+ .arrived .event-label {
637
+ background: rgba(52, 152, 219, 0.15);
638
+ color: var(--color-inbound);
639
+ border: 1px solid rgba(52, 152, 219, 0.3);
640
+ }
641
+
642
+ .location,
643
+ .eta,
644
+ .timestamp {
645
+ color: var(--warp-text-dim);
646
+ }
647
+
648
+ .eta-bar-track {
649
+ margin-top: 4px;
650
+ height: 3px;
651
+ background: rgba(255, 255, 255, 0.08);
652
+ border-radius: 2px;
653
+ overflow: hidden;
654
+ }
655
+
656
+ .eta-bar-fill {
657
+ height: 100%;
658
+ width: 0%;
659
+ border-radius: 2px;
660
+ transition: width 1s linear;
661
+ }
662
+
663
+ .coord-sm {
664
+ font-size: 0.7rem;
665
+ opacity: 0.8;
666
+ font-family: "Courier New", Courier, monospace;
667
+ }
668
+
669
+ /* Flight Deck */
670
+ .flight-deck {
671
+ position: fixed;
672
+ top: 50%;
673
+ left: 50%;
674
+ transform: translate(-50%, -50%);
675
+ width: 300px;
676
+ background: var(--warp-bg);
677
+ border: 1px solid var(--warp-accent);
678
+ border-radius: 8px;
679
+ box-shadow: 0 0 30px rgba(74, 144, 226, 0.3);
680
+ z-index: 1000;
681
+ backdrop-filter: blur(10px);
682
+ padding: 1.5rem;
683
+ transition:
684
+ transform 0.3s ease,
685
+ opacity 0.3s ease;
686
+ }
687
+
688
+ .flight-deck.hidden {
689
+ transform: translate(-50%, calc(-50% + 20px));
690
+ opacity: 0;
691
+ pointer-events: none;
692
+ }
693
+
694
+ .deck-content.hidden {
695
+ display: none;
696
+ }
697
+
698
+ .deck-content h3 {
699
+ margin-top: 0;
700
+ font-size: 0.9rem;
701
+ text-transform: uppercase;
702
+ letter-spacing: 2px;
703
+ color: #fff;
704
+ border-bottom: 1px solid var(--warp-border);
705
+ padding-bottom: 0.5rem;
706
+ margin-bottom: 1rem;
707
+ }
708
+
709
+ .target-info,
710
+ .target-coords,
711
+ .metric {
712
+ margin-bottom: 0.8rem;
713
+ font-size: 0.85rem;
714
+ display: flex;
715
+ justify-content: space-between;
716
+ align-items: center;
717
+ }
718
+
719
+ .flight-deck .label {
720
+ color: var(--warp-text-dim);
721
+ font-weight: bold;
722
+ font-size: 0.7rem;
723
+ text-transform: uppercase;
724
+ }
725
+
726
+ .flight-deck .value {
727
+ color: var(--warp-accent);
728
+ font-weight: bold;
729
+ }
730
+
731
+ .jump-metrics {
732
+ background: rgba(0, 0, 0, 0.2);
733
+ padding: 0.8rem;
734
+ border-radius: 4px;
735
+ margin: 1rem 0;
736
+ }
737
+
738
+ .jump-button {
739
+ width: 100%;
740
+ background: #2ecc71;
741
+ border: none;
742
+ color: #fff;
743
+ padding: 0.8rem;
744
+ border-radius: 4px;
745
+ font-weight: bold;
746
+ cursor: pointer;
747
+ letter-spacing: 2px;
748
+ margin-bottom: 0.5rem;
749
+ transition: background 0.2s;
750
+ }
751
+
752
+ .jump-button:hover {
753
+ background: #27ae60;
754
+ }
755
+
756
+ .jump-button:disabled {
757
+ background: #555;
758
+ cursor: not-allowed;
759
+ }
760
+
761
+ .cancel-button {
762
+ width: 100%;
763
+ background: transparent;
764
+ border: 1px solid #e74c3c;
765
+ color: #e74c3c;
766
+ padding: 0.5rem;
767
+ border-radius: 4px;
768
+ font-size: 0.75rem;
769
+ cursor: pointer;
770
+ }
771
+
772
+ .cancel-button:hover {
773
+ background: rgba(231, 76, 60, 0.1);
774
+ }
775
+
776
+ .land-btn {
777
+ background: #3498db;
778
+ border: none;
779
+ color: #fff;
780
+ padding: 0.4rem 0.8rem;
781
+ border-radius: 4px;
782
+ font-size: 0.7rem;
783
+ font-weight: bold;
784
+ cursor: pointer;
785
+ transition: background 0.2s;
786
+ }
787
+
788
+ .land-btn:hover {
789
+ background: #2980b9;
790
+ }
791
+
792
+ .land-btn:disabled {
793
+ background: #555;
794
+ cursor: not-allowed;
795
+ }
796
+
797
+ .archive-table td {
798
+ font-size: 0.8rem;
799
+ }
800
+
801
+ #archive-controls {
802
+ margin-top: 0.5rem;
803
+ display: flex;
804
+ align-items: center;
805
+ gap: 0.5rem;
806
+ }
807
+
808
+ .archive-see-all,
809
+ .archive-nav {
810
+ background: transparent;
811
+ border: 1px solid var(--warp-accent);
812
+ color: var(--warp-accent);
813
+ padding: 0.25rem 0.6rem;
814
+ border-radius: 4px;
815
+ font-size: 0.75rem;
816
+ cursor: pointer;
817
+ font-family: "Courier New", monospace;
818
+ }
819
+
820
+ .archive-see-all:hover,
821
+ .archive-nav:hover:not(:disabled) {
822
+ background: rgba(74, 144, 226, 0.15);
823
+ }
824
+
825
+ .archive-nav:disabled {
826
+ opacity: 0.35;
827
+ cursor: default;
828
+ }
829
+
830
+ .archive-page-label {
831
+ font-size: 0.75rem;
832
+ color: var(--warp-text-dim);
833
+ font-family: "Courier New", monospace;
834
+ }
835
+
836
+ .archive-extra {
837
+ display: none;
838
+ }
839
+
840
+ .traffic-table.hidden,
841
+ .archive-table.hidden,
842
+ .empty-msg.hidden,
843
+ #archive-controls.hidden,
844
+ #archive-pagination.hidden {
845
+ display: none;
846
+ }
847
+
848
+ @media (max-width: 600px) {
849
+ .traffic-table th:nth-child(3),
850
+ .traffic-table td:nth-child(3),
851
+ .traffic-table th:nth-child(4),
852
+ .traffic-table td:nth-child(4),
853
+ .archive-table th:nth-child(3),
854
+ .archive-table td:nth-child(3),
855
+ .archive-table th:nth-child(4),
856
+ .archive-table td:nth-child(4) {
857
+ display: none;
858
+ }
859
+ }
860
+
861
+ /* Footer styles */
862
+ footer {
863
+ margin-top: 4rem;
864
+ padding: 2rem;
865
+ font-size: 0.9rem;
866
+ color: #555;
867
+ text-align: center;
868
+ }
869
+
870
+ footer a {
871
+ color: #4a90e2;
872
+ text-decoration: none;
873
+ }