File size: 13,690 Bytes
e3387ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/* Styles for the LEO satellite simulation page. */

:root {
  --bg: #05070d;
  --panel: rgba(12, 17, 28, 0.86);
  --border: rgba(140, 160, 200, 0.22);
  --text: #e6ebf5;
  --muted: #8e9ab0;
  --accent: #4ea8ff;
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text);
  font: 13px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; overflow: hidden; }
#scene { position: fixed; inset: 0; }
.card { position: fixed; background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 12px 14px; backdrop-filter: blur(6px); }
#panel { top: 16px; left: 16px; width: 290px; max-height: calc(100% - 32px); overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: rgba(140, 160, 200, 0.35) transparent; }
/* Right column: conjunction list on top; the bottom-right corner shows either the conjunction

   analysis or the selected satellite (opening one closes the other). Each gets half the height. */
#conj { top: 16px; right: 16px; width: 340px; max-height: calc(50% - 24px); overflow-y: auto; display: none;
  scrollbar-width: thin; scrollbar-color: rgba(140, 160, 200, 0.35) transparent; }
.conj-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.conj-next { margin: 8px 0; padding: 6px 8px; border-radius: 6px; background: rgba(255, 77, 77, 0.12);
  border: 1px solid rgba(255, 77, 77, 0.35); }
#info, #conjDetail { top: auto; bottom: 16px; right: 16px; width: 340px; max-height: calc(50% - 24px); overflow-y: auto;
  display: none; scrollbar-width: thin; scrollbar-color: rgba(140, 160, 200, 0.35) transparent; }
#conjDetail { border-color: rgba(255, 77, 77, 0.45); }
#conjFocus:empty { display: none; }
/* Debris-debris red zone warning, in the gap between the left panel and the right column. */
#zoneAlert { top: 16px; left: 322px; right: 372px; display: none; background: rgba(58, 10, 12, 0.9);
  border-color: rgba(255, 77, 77, 0.7); }
#zoneAlert button { float: right; margin-left: 8px; }
/* Suggested avoidance manoeuvre, over the simulation in the same gap at the bottom. */
#planHud { bottom: 16px; left: 322px; right: 372px; display: none; font-size: 12.5px; border-color: rgba(61, 220, 151, 0.6); }
#planHud.red { border-color: rgba(255, 77, 77, 0.7); background: rgba(58, 10, 12, 0.9); }
#planHud button { float: right; margin-left: 8px; }
#planHud .title { font-weight: 600; margin-bottom: 4px; }
#planHud ol { margin: 4px 0; padding-left: 20px; }
#planHud li.done { color: var(--muted); }
#planHud .safe { color: #3ddc97; font-weight: 600; }
.conj-zone { grid-column: 2; color: #ff8a8a; font-size: 11.5px; }
.zone-sats { width: 100%; border-collapse: collapse; margin-top: 6px; font-size: 11.5px; font-variant-numeric: tabular-nums; }
.zone-sats td { padding: 2px 8px 2px 0; }
.zone-sats td:not(:first-child) { text-align: right; white-space: nowrap; }
button.primary { background: rgba(61, 220, 151, 0.18); border-color: rgba(61, 220, 151, 0.6); font-weight: 600; }
button.primary:hover { background: rgba(61, 220, 151, 0.3); }
.planning { margin-top: 8px; padding: 6px 8px; border-radius: 6px; font-size: 12px;
  border: 1px solid rgba(78, 168, 255, 0.5); background: rgba(78, 168, 255, 0.1); }
#conjPlan select { margin-top: 8px; }
#conjPlan ul { margin: 4px 0 0; padding-left: 18px; }
table.plan { width: 100%; border-collapse: collapse; margin: 6px 0; font-size: 12px; font-variant-numeric: tabular-nums; }
table.plan th, table.plan td { padding: 2px 4px; border-bottom: 1px solid var(--border); text-align: right; white-space: nowrap; }
table.plan th:first-child, table.plan td:first-child { text-align: left; }
table.plan .dot { display: inline-block; margin-right: 4px; vertical-align: 0; }
#conjStatus:empty { display: none; }
#conjStatus { margin: 8px 0 0; padding: 6px 8px; border-radius: 6px; font-size: 12px;
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--border); }
#conjStatus.loading { border-color: rgba(78, 168, 255, 0.5); background: rgba(78, 168, 255, 0.1); }
#conjStatus.warn { border-color: rgba(255, 216, 77, 0.5); background: rgba(255, 216, 77, 0.08); }
#conjStatus code { font-size: 11px; }
.spinner { display: inline-block; width: 10px; height: 10px; margin-right: 6px; vertical-align: -1px;
  border: 2px solid rgba(78, 168, 255, 0.35); border-top-color: var(--accent); border-radius: 50%;
  animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
#eventBanner:empty { display: none; }
#eventBanner { margin: 4px 0 8px; padding: 8px 10px; border-radius: 8px; font-size: 12px;
  background: rgba(255, 77, 77, 0.1); border: 1px solid rgba(255, 77, 77, 0.45); }
#eventBanner .title { font-weight: 600; font-size: 13px; margin-bottom: 4px; }
#eventBanner table { width: 100%; border-collapse: collapse; margin: 6px 0; font-variant-numeric: tabular-nums; }
#eventBanner th, #eventBanner td { padding: 2px 4px; text-align: right; border-bottom: 1px solid var(--border); white-space: nowrap; }
#eventBanner td.wrap { white-space: normal; text-align: left; }
#eventBanner th:first-child, #eventBanner td:first-child { text-align: left; }
#notice { position: fixed; top: 16px; left: 50%; transform: translateX(-50%); z-index: 10; max-width: min(560px, calc(100% - 32px));
  padding: 8px 14px; border-radius: 8px; background: rgba(40, 32, 8, 0.92); border: 1px solid rgba(255, 216, 77, 0.6);
  color: var(--text); font-size: 13px; display: none; }
#notice.show { display: block; }
#conjDays { display: flex; gap: 4px; align-items: flex-end; margin: 4px 0 6px; }
#conjDays .day { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 4px 2px;
  min-width: 0; background: transparent; border-color: transparent; }
#conjDays .day:hover { background: rgba(255, 255, 255, 0.08); }
#conjDays .day.current { border-color: var(--accent); background: rgba(78, 168, 255, 0.12); }
#conjDays .bar { width: 70%; background: #ff4d4d; border-radius: 2px; }
#conjDays .count { font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
#conjDays .label { font-size: 10.5px; color: var(--muted); white-space: nowrap; }
#conjDays .day.today .label { color: var(--text); font-weight: 600; }
#conjDays .day.unscreened .bar { background: rgba(140, 160, 200, 0.35); }
#conjDays .day.unscreened .count, #conjDays .day.unscreened .label { opacity: 0.55; }
.fresh { margin: 6px 0; padding: 6px 8px; border-radius: 6px; font-size: 11.5px;
  background: rgba(78, 168, 255, 0.10); border: 1px solid rgba(78, 168, 255, 0.35); }
.fresh.warn { background: rgba(255, 216, 77, 0.10); border-color: rgba(255, 216, 77, 0.45); }
.fresh.ready { background: rgba(61, 220, 151, 0.12); border-color: rgba(61, 220, 151, 0.5); }
.fresh button { margin-left: 6px; padding: 1px 8px; }
input[type=datetime-local] { color-scheme: dark; flex: 1; min-width: 0; }
#conjFocus { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 6px 0 0;
  padding: 4px 4px 4px 8px; border-radius: 6px; background: rgba(78, 168, 255, 0.15); border: 1px solid rgba(78, 168, 255, 0.4); }
#conjFocus button { padding: 0 7px; }
.check { margin-top: 10px; padding: 8px 10px; border-radius: 6px; border: 1px solid; }
.check.ok { background: rgba(61, 220, 151, 0.12); border-color: rgba(61, 220, 151, 0.45); }
.check.yellow { background: rgba(255, 216, 77, 0.12); border-color: rgba(255, 216, 77, 0.5); }
.check.red { background: rgba(255, 77, 77, 0.14); border-color: rgba(255, 77, 77, 0.55); }
.check.green { background: rgba(255, 216, 77, 0.07); border-color: rgba(255, 216, 77, 0.3); }
.check .title { font-weight: 600; margin-bottom: 2px; }
.check button { margin-top: 6px; }
#conjDetail .pair { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.dot { width: 9px; height: 9px; border-radius: 50%; flex: none; align-self: center; }
.dot.a { background: #ffd84d; }
.dot.b { background: #ff4d4d; }
#conjList { margin: 6px 0 8px; }
.conj-row { display: grid; grid-template-columns: 10px 1fr; column-gap: 8px; padding: 6px; border-radius: 6px; cursor: pointer; }
.conj-row:hover { background: rgba(255, 255, 255, 0.08); }
.conj-row.active { background: rgba(78, 168, 255, 0.18); }
.conj-row .badge { grid-row: span 2; width: 10px; height: 10px; border-radius: 50%; margin-top: 4px; }
.conj-names { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conj-meta { color: var(--muted); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.badge.red { background: #ff4d4d; }
.badge.yellow { background: #ffd84d; }
.badge.green { background: #3ddc97; }
.badge-text { padding: 1px 6px; border-radius: 4px; font-weight: 600; color: #05070d; }
.badge-text.red { background: #ff4d4d; }
.badge-text.yellow { background: #ffd84d; }
.badge-text.green { background: #3ddc97; }
/* ML risk tags and the avoidance manoeuvre box (riskAssessment.js) */
.conj-rank { display: inline-block; min-width: 18px; margin-right: 5px; padding: 0 4px; border-radius: 4px;
  background: rgba(255, 255, 255, 0.12); color: var(--text); font-size: 11px; text-align: center; }
.ml-tag { padding: 0 5px; border-radius: 4px; font-weight: 600; font-size: 10.5px; }
.ml-tag.yes { background: rgba(255, 77, 77, 0.25); color: #ff8a8a; }
.ml-tag.no { background: rgba(61, 220, 151, 0.18); color: #6ee7b5; }
.ml-warn { color: #ff8a8a; font-weight: 600; }
.man-box { margin-top: 10px; padding: 8px 10px; border-radius: 8px; border: 1px solid; }
.man-box.ok { background: rgba(61, 220, 151, 0.10); border-color: rgba(61, 220, 151, 0.5); }
.man-box.warn { background: rgba(255, 77, 77, 0.16); border-color: rgba(255, 77, 77, 0.7); }
.man-box.none { background: rgba(255, 255, 255, 0.05); border-color: var(--border); color: var(--muted); }
.man-box.warn .man-title { color: #ff8a8a; }
.man-title { font-weight: 600; margin-bottom: 4px; color: var(--text); }
.man-main { display: flex; align-items: center; gap: 12px; }
.man-dv { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
.man-dir { font-weight: 600; color: #6ee7b5; }
.man-dl { margin-top: 6px; }
.man-safe { color: #6ee7b5; }
.man-conf { margin: 2px 0 0; padding-left: 16px; }
.man-svg { flex: none; }
.man-go { margin-top: 4px; padding: 2px 8px; font-size: 11.5px; }
.man-ring { fill: rgba(255, 255, 255, 0.04); stroke: var(--border); }
.man-cross { stroke: rgba(140, 160, 200, 0.25); stroke-dasharray: 2 2; }
.man-lbl { fill: var(--muted); font-size: 9px; font-weight: 600; }
.man-arrow { stroke: #3ddc97; stroke-width: 3; stroke-linecap: round; }
.man-head, .man-dot { fill: #3ddc97; }
.man-vert { fill: #ffd84d; font-size: 9px; font-weight: 600; }
h1 { font-size: 15px; margin: 0 0 2px; }
.muted { color: var(--muted); }
.small { font-size: 11.5px; }
#clock { font: 600 14px ui-monospace, SFMono-Regular, Menlo, monospace; margin: 10px 0 6px; }
.row { display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0; align-items: center; }
button, select, input { font: inherit; color: var(--text); background: rgba(255,255,255,0.06);
  border: 1px solid var(--border); border-radius: 6px; padding: 4px 8px; }
button { cursor: pointer; }
button:hover { background: rgba(255,255,255,0.12); }
button.active { background: var(--accent); border-color: var(--accent); color: #05070d; font-weight: 600; }
input[type=search] { width: 100%; }
.section { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.section-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin-bottom: 6px; }
.legend-item { display: flex; align-items: center; gap: 8px; padding: 2px 0; cursor: pointer; user-select: none; }
.legend-item input { margin: 0; }
.swatch { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.legend-item .count { margin-left: auto; color: var(--muted); font-variant-numeric: tabular-nums; }
#gradient { height: 8px; border-radius: 4px; margin: 4px 0 2px; display: none; }
#gradient-labels { display: none; justify-content: space-between; }
#suggestions { margin-top: 4px; }
#suggestions div { padding: 3px 6px; border-radius: 4px; cursor: pointer; }
#suggestions div:hover { background: rgba(255,255,255,0.1); }
dl { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin: 8px 0 0; }
dt { color: var(--muted); }
dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
#info h2 { font-size: 14px; margin: 0; padding-right: 24px; }
#close { position: absolute; top: 8px; right: 8px; padding: 0 7px; }
#loading { position: fixed; inset: 0; display: grid; place-items: center; font-size: 15px; color: var(--muted); }
@media (max-width: 640px) {
  #panel { width: auto; right: 16px; max-height: 45%; }
  #conj { top: auto; bottom: 16px; left: 16px; width: auto; max-height: 35%; }
  #info, #conjDetail { bottom: calc(35% + 24px); left: 16px; width: auto; max-height: 30%; }
  #zoneAlert { top: calc(45% + 24px); left: 16px; right: 16px; }
  #planHud { display: none !important; }   /* no room: the same details are in the conjunction card */
}

/* Link styled as a button (e.g. "Satellite communication" to the crosslink simulation). */
a.button-link { display: block; margin: 8px 0 4px; padding: 6px 10px; border-radius: 6px; text-align: center;
  font-weight: 600; color: var(--text); text-decoration: none; background: rgba(92, 225, 230, 0.15);
  border: 1px solid rgba(92, 225, 230, 0.55); }
a.button-link:hover { background: rgba(92, 225, 230, 0.28); }