@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 in every app toolbar button. Applies to both and