File size: 12,280 Bytes
9f21d0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
@import "tailwindcss";
@import "@nuxt/ui";

html,
body,
#cesiumContainer {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  position: fixed;
  overflow: hidden;
  font-family: sans-serif;
  color: #edffff;
  background-color: black;
}

body {
  -webkit-touch-callout: none;
  user-select: none;
}

/* Hides #app until Vue mounts. The `dark` class index.html sets alongside it forces
   Nuxt UI onto its dark palette, since Vue mode has no color-mode switch and
   defaults to light while this app is a dark globe ui throughout. */
[v-cloak] {
  display: none;
}

/* The safe area, named once. `viewport-fit=cover` in index.html is what makes these
   report anything: without it iOS keeps them 0 even where the page already reaches
   under the home indicator. The top is 0 on every iOS layout, and is carried for an
   Android install, which is edge to edge. */
:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);

  /* Cesium's credit line in the bottom-left corner: the inset lifts it off the home
     indicator, and the screen's rounded corner then cuts into the left. The same inset
     scales how much of 12px that costs, so a square screen keeps Cesium's own 5/3. */
  --credit-corner-bottom: calc(3px + var(--safe-bottom));
  --credit-corner-left: calc(5px + var(--safe-left) + min(12px, var(--safe-bottom)));

  /* With no deck to clear, the corner. `body.clock-deck` moves the line up. */
  --credit-bottom: var(--credit-corner-bottom);
  --credit-left: var(--credit-corner-left);
}

/* Above the sky view's HUD (z-4) and the entity info panel (z-5), so the control
   that leaves the sky view stays reachable while it is up. Sideways the notch is
   beside these rows, and without the inset they slide under it. */
#toolbarLeft {
  position: absolute;
  top: calc(5px + var(--safe-top));
  left: calc(2px + var(--safe-left));
  z-index: 6;
}

#toolbarRight {
  position: absolute;
  top: calc(5px + var(--safe-top));
  right: calc(2px + var(--safe-right));
  z-index: 6;
}

/* Cesium styles these buttons for a mouse, and on iOS a tap leaves `:hover` and
   `:focus` behind on whatever it touched last. The lit state is bound to `menu` in
   Satvis.vue instead; these put the pointer states back to base. */
#toolbarLeft .cesium-button:not(.toolbarButton--open):focus,
#toolbarRight .cesium-button:not(.toolbarButton--open):focus {
  border-color: #444;
}

/* Only where a pointer can actually rest on a button. Elsewhere :hover is whatever
   was tapped last. */
@media (hover: none) {
  #toolbarLeft .cesium-button:not(.toolbarButton--open):hover,
  #toolbarRight .cesium-button:not(.toolbarButton--open):hover {
    background: #303336;
    border-color: #444;
    color: #edffff;
    fill: #edffff;
    box-shadow: none;
  }
}

/* The propagation panel deliberately reuses Satvis's compact toolbar language
   instead of creating a competing application shell. */
.propagation-panel {
  width: min(330px, calc(100vw - 20px));
  max-height: min(76vh, 760px);
  overflow: auto;
  padding-bottom: 10px;
}

.propagation-panel__intro,
.propagation-panel__note,
.propagation-panel__status {
  margin: 7px 12px 10px;
  color: #bfd0d8;
  font-size: 12px;
  line-height: 1.35;
}

.propagation-panel__note {
  color: #9eacb4;
  font-size: 11px;
}

.propagation-panel__status {
  min-height: 32px;
  color: #82e6f4;
}

.propagation-panel__status--error {
  color: #ffac99;
}

.propagation-panel__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 0 12px 12px;
}

.propagation-panel__grid label {
  display: grid;
  gap: 4px;
  color: #d8e4e9;
  font-size: 11px;
}

.propagation-panel__grid span {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #92acb9;
}

.propagation-panel__grid input {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  border: 1px solid #58676f;
  border-radius: 3px;
  background: #1d2428;
  color: #e7fbff;
  font: inherit;
  padding: 5px 6px;
}

.propagation-panel__details {
  margin: 8px 12px 12px;
  color: #d8e4e9;
  font-size: 12px;
}

.propagation-panel__details summary {
  cursor: pointer;
  margin-bottom: 10px;
}

.propagation-panel__details .propagation-panel__grid {
  padding: 0;
}

.propagation-panel__run {
  display: block;
  width: calc(100% - 24px);
  margin: 12px;
  border: 1px solid #5cd8ec;
  border-radius: 4px;
  background: #176274;
  color: #f2ffff;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  padding: 9px 10px;
}

.propagation-panel__run:hover,
.propagation-panel__run:focus-visible {
  background: #23899e;
}

/* Cesium's `outline: none` leaves keyboard focus with nothing to show for it. */
#toolbarLeft .cesium-button:focus-visible,
#toolbarRight .cesium-button:focus-visible {
  outline: 2px solid #7fd2ea;
  outline-offset: 2px;
}

/* The button whose panel is open. The shadow is cleared so it looks the same whether
   or not a pointer also happens to be resting on it. */
#toolbarLeft .toolbarButton--open,
#toolbarRight .toolbarButton--open {
  background: #3d4348;
  border-color: #7fd2ea;
  color: #7fd2ea;
  fill: #7fd2ea;
  box-shadow: none;
}

.toolbarSwitches {
  display: flex;
  flex-direction: column;
  margin: 2px 3px;
  /* Carries the group titles, which have no surface of their own — the rows do,
     so the panel is what has to hold them legible against a bright globe. */
  background-color: #303336d9;
  border-radius: 8px;
}

/* The satellite catalog panel is a dense text list; a more opaque surface
   keeps globe labels from bleeding through the rows. */
.toolbarSwitches--catalog {
  background-color: #303336e6;
}

.toolbarTitle {
  text-align: center;
  height: 24px;
  line-height: 24px;
  margin-top: 5px;
}

.toolbarContent {
  margin: 5px;
}

/* A control whose selection a surface model has taken over, so it is no longer
   describing what is on screen. Dimming says only that; whether the row is still
   the user's to change is a separate question the markup answers per group (a
   hidden globe leaves the choice theirs, an imposed terrain does not).
   Opacity only, deliberately. A `grayscale` filter here read as a broken panel
   rather than an inert one: the red/green dot is the only state a row carries,
   and draining its colour left a column of switches saying nothing at all. */
.toolbarSwitch--inert {
  opacity: 0.3;
}

.toolbarTitle--inert {
  opacity: 0.5;
}

/* Why nothing happened, for a surface model that cannot apply in this view mode.
   Zero width with a full-width minimum so the sentence wraps inside the panel
   instead of widening it: these panels are sized by their content, and the
   longest row is what should set that width. */
.toolbarNote {
  width: 0;
  min-width: 100%;
  box-sizing: border-box;
  padding: 2px 8px 3px 8px;
  font-size: 11px;
  line-height: 14px;
  opacity: 0.6;
}

.toolbarSwitch {
  /* Lighter than the panel it sits on, not the same colour. These were both
     #303336, which was invisible while the panel was translucent enough to show
     the globe through the gaps — and once the panel was made opaque, the rows and
     their surface merged into one flat slab with no edges at all. */
  background-color: #464b50;
  border-radius: 8px;
  cursor: pointer;
  display: inline-block;
  height: 24px;
  line-height: 24px;
  margin: 1px 0px 1px 0px;
  opacity: 0.85;
  padding-left: 50px;
  position: relative;
}

.toolbarSwitch input {
  display: none;
}

/* Waiting on the device — a location fix, or the orientation sensor answering a
   probe. Not clickable, so a second tap cannot queue a second request while the
   first is still out. */
.toolbarSwitch:has(input:disabled) {
  cursor: default;
}

/* Sits exactly where the slider's dot does, and is positioned rather than inline
   so that showing it costs no width: these panels are sized by their content, so
   anything that grows a row reflows the whole menu. That is why the wait is not
   said in the label. */
.toolbarSpinner {
  position: absolute;
  left: 4px;
  bottom: 4px;
  box-sizing: border-box;
  height: 16px;
  width: 16px;
  border: 2px solid #ffffff40;
  border-top-color: #ffffff;
  border-radius: 50%;
  animation: toolbarSpin 0.8s linear infinite;
}

@keyframes toolbarSpin {
  to {
    transform: rotate(1turn);
  }
}

/* Still a ring rather than a dot, so it reads as busy without moving. */
@media (prefers-reduced-motion: reduce) {
  .toolbarSpinner {
    animation: none;
  }
}

.slider::before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 4px;
  bottom: 4px;
  border-radius: 50%;
  background-color: red;
  transition: 0.4s;
}

input:checked + .slider::before {
  background-color: green;
  transform: translateX(20px);
}

.cesium-toolbar-button {
  font-size: 22px;
  color: #ffffff;
}

/* Center the Nuxt UI <svg> in every app toolbar button. Applies to both <a> and
   <button>; without flex the block-level Iconify SVGs hug the button's left
   edge. */
#toolbarLeft .cesium-toolbar-button,
#toolbarRight .cesium-toolbar-button {
  align-items: center;
  justify-content: center;
  display: inline-flex;
}

/* Cesium's ion logo at 80%. Its guide allows placement and presentation to be
   adjusted while the logo stays prominent, and the line's width is what the deck's
   breakpoints are measured against.
   https://cesium.com/learn/ion/content-usage-and-attribution-guide/ */
.cesium-credit-logoContainer img {
  height: 22px;
  width: auto;
}

/* The clock deck shares the bottom of the screen with Cesium's credit line: how much
   room the deck claims, and where the credits go around it. */
body.clock-deck {
  /* Every offset below is in terms of this, or a notch grows the deck past the line. */
  --clock-deck-safe: max(6px, var(--safe-bottom));
  /* What the deck occupies, for the sky view's cards. Constant across the fold. */
  --clock-deck-height: calc(88px + var(--clock-deck-safe));
  /* Clear of the deck: the default, and where a phone puts them. Far enough up that
     the corner is no concern, so the left goes back to Cesium's own. */
  --credit-bottom: calc(var(--clock-deck-height) + 4px);
  --credit-left: calc(5px + var(--safe-left));
}

/* In the control row beside the surface: 28 px of credit centred in its 46. */
body.clock-deck[data-clock-deck="beside"] {
  --credit-bottom: calc(51px + var(--clock-deck-safe));
}

/* Folded, the reserved scale row is more room than the credit line needs, which
   leaves the rounded corner as the only thing to clear. */
body.clock-deck[data-clock-deck="folded"] {
  --credit-bottom: var(--credit-corner-bottom);
  --credit-left: var(--credit-corner-left);
}

/* `!important` because Cesium rewrites this element's `bottom` inline on every
   resize. Unscoped: the corner is the viewport's, deck or no deck. */
.cesium-viewer-bottom {
  bottom: var(--credit-bottom) !important;
  left: var(--credit-left) !important;
}

/* The width cap stops its full-row container swallowing taps meant for the deck. */
body.clock-deck .cesium-viewer-bottom {
  right: auto !important;
  width: max-content !important;
}

/* Below the cap the scale row covers the corner Cesium puts the fullscreen button in.
   Hidden, not unbuilt, so it returns with the gutter. `!important` for the reason
   above. */
@media (max-width: 999px) {
  body.clock-deck .cesium-viewer-fullscreenContainer {
    display: none !important;
  }
}

/* Room for a phone-width deck and the line side by side: 560 plus twice the 206 px
   box it ends at, plus air. The box, not its 196 px of content. Both with the logo at
   22 px; 236 and 226 at Cesium's own 28. */
@media (min-width: 1000px) {
  /* On `:root`, not `body.clock-deck`: the class arrives in the deck's `onMounted`,
     and the timeline measures its own width in that same tick. */
  :root {
    --clock-deck-max: 560px;
  }

  /* Cesium's own corner, for the two cases that hold the line above the deck: the
     deck caps and centres at this width and stops sharing the row. */
  body.clock-deck[data-clock-deck="clear"],
  body.clock-deck[data-clock-deck="beside"] {
    --credit-bottom: var(--credit-corner-bottom);
    --credit-left: var(--credit-corner-left);
  }
}