This commit is contained in:
root
2026-09-20 14:16:41 +02:00
parent 0798933b05
commit b6d1909d7f
56 changed files with 3752 additions and 1989 deletions
+63 -49
View File
@@ -26,7 +26,7 @@ body {
margin: 0;
min-height: 100vh;
color: var(--ink);
background: linear-gradient(180deg, #07030f 0%, #0f0626 40%, #2a0a4d 72%, #6a1268 100%) fixed;
background: #07030f;
font-family: var(--mono);
font-size: 17px;
line-height: 1.5;
@@ -35,50 +35,21 @@ body {
/* ---- backdrop ------------------------------------------------------------ */
#stars { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; }
.horizon {
position: fixed; left: 0; right: 0; bottom: 0; height: 46vh;
z-index: 1; pointer-events: none; overflow: hidden;
--sun: clamp(180px, 34vmin, 400px);
--floor: 17vh;
/* The whole backdrop is one canvas. It is a fixed box of 100vh anchored to the
bottom of the screen, so it never resizes when a phone's toolbar comes and goes
and the floor always sits at the visible bottom. */
#backdrop {
position: fixed; left: 0; bottom: 0; width: 100%; height: 100vh; height: 100lvh; z-index: 0;
background: linear-gradient(180deg, #07030f 0%, #0f0626 40%, #2a0a4d 72%, #6a1268 100%);
}
.sun {
position: absolute; left: 50%; margin-left: calc(var(--sun) / -2);
bottom: calc(var(--floor) - var(--sun) * 0.34);
width: var(--sun); height: var(--sun); border-radius: 50%;
background: linear-gradient(180deg, #fff27a 0%, #ffb62e 32%, #ff3ad8 72%, #8a2cff 100%);
box-shadow: 0 0 70px 12px rgba(255, 58, 216, 0.5);
-webkit-mask-image: linear-gradient(#000 0 46%, transparent 46% 49%, #000 49% 56%, transparent 56% 60%, #000 60% 67%, transparent 67% 72%, #000 72% 79%, transparent 79% 85%, #000 85% 91%, transparent 91% 98%, #000 98%);
mask-image: linear-gradient(#000 0 46%, transparent 46% 49%, #000 49% 56%, transparent 56% 60%, #000 60% 67%, transparent 67% 72%, #000 72% 79%, transparent 79% 85%, #000 85% 91%, transparent 91% 98%, #000 98%);
}
.floor {
position: absolute; left: 0; right: 0; bottom: 0; height: var(--floor);
overflow: hidden; background: linear-gradient(#22093f, #0c0420);
border-top: 2px solid var(--cyan);
box-shadow: 0 -2px 26px rgba(40, 245, 255, 0.7);
}
.floor::before {
content: ""; position: absolute; left: -60%; right: -60%; top: 0; height: 400%;
transform-origin: 50% 0; transform: perspective(240px) rotateX(64deg);
background-image:
linear-gradient(rgba(255, 58, 216, 0.8) 2px, transparent 2px),
linear-gradient(90deg, rgba(255, 58, 216, 0.8) 2px, transparent 2px);
background-size: 64px 64px;
animation: grid-move 2.6s linear infinite;
}
@keyframes grid-move { to { background-position: 0 64px; } }
/* Static scanlines and vignette. (They used to flicker; that was the flicker.) */
.crt {
position: fixed; inset: 0; z-index: 100; pointer-events: none;
background:
repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0) 0 2px, rgba(0, 0, 0, 0.17) 3px, rgba(0, 0, 0, 0) 4px),
radial-gradient(ellipse at center, transparent 58%, rgba(0, 0, 0, 0.5) 100%);
animation: flicker 7s infinite;
}
@keyframes flicker { 0%, 100% { opacity: 1; } 47% { opacity: 1; } 48% { opacity: 0.86; } 50% { opacity: 1; } 83% { opacity: 0.93; } 84% { opacity: 1; } }
#app, dialog, #toasts { position: relative; z-index: 10; }
@@ -120,20 +91,23 @@ a:hover { color: var(--mag); }
position: sticky; top: 0; z-index: 20;
display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1.4rem;
padding: 0.6rem 1.2rem;
background: rgba(7, 3, 15, 0.88); backdrop-filter: blur(6px);
background: rgba(7, 3, 15, 0.96);
border-bottom: 1px solid var(--line); box-shadow: 0 2px 24px rgba(40, 245, 255, 0.12);
}
.top-brand { display: flex; align-items: baseline; gap: 0.9rem; letter-spacing: 0.25em; font-size: 0.85rem; }
.top-stats { display: flex; flex-wrap: wrap; gap: 0.5rem; flex: 1; }
.top-user { display: flex; align-items: center; gap: 0.6rem; margin-left: auto; }
.callsign { color: var(--lime); letter-spacing: 0.15em; text-shadow: 0 0 8px rgba(125, 255, 138, 0.6); }
/* Callsigns can be 40 characters: truncate them, never the buttons beside them. */
.top-user { min-width: 0; max-width: 100%; }
.callsign { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.top-user .btn { flex: none; }
.chip { border: 1px solid var(--faint); padding: 0.05rem 0.65rem; font-size: 0.9rem; letter-spacing: 0.08em; background: rgba(0, 0, 0, 0.3); }
.chip b { color: var(--amber); font-weight: 700; }
.chip.ore b { color: var(--cyan); }
.navbar { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 0.6rem; max-width: 1100px; margin: 1rem auto 0; padding: 0 1rem; }
.tabs { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.tabs { display: flex; flex-wrap: nowrap; gap: 0.3rem; min-width: 0; }
.tab {
font-family: var(--display); font-size: 0.85rem; letter-spacing: 0.22em; text-transform: uppercase; text-decoration: none;
padding: 0.6rem 1.2rem; color: var(--dim); background: rgba(13, 6, 34, 0.7);
@@ -233,9 +207,28 @@ textarea { resize: vertical; }
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0.6rem 0; }
.toolbar.pad { margin: 0; }
.sealrow { justify-content: space-between; margin-top: 0.8rem; }
.sealrow .grow { flex: 1 1 260px; }
.panel-title .dim { white-space: nowrap; }
/* Button bars in the code editor: one control height and style throughout. */
.bar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 1rem; margin: 0.8rem 0; }
.bar-label { flex: none; width: 4.2rem; font-size: 0.72rem; letter-spacing: 0.24em; color: var(--dim); }
.bar-buttons { display: flex; flex: 1; flex-wrap: wrap; gap: 0.5rem; min-width: 0; }
.bar .btn, .bar select {
height: 2.5rem; margin: 0; padding: 0 1.1rem; font-size: 0.82rem; line-height: 1; white-space: nowrap;
display: inline-flex; align-items: center; justify-content: center;
}
.bar .push { margin-left: auto; }
.bar select { min-width: 0; max-width: 100%; text-overflow: ellipsis; }
.stack-lg > * { min-width: 0; }
/* The example chooser looks like the buttons beside it. */
.bar select {
-webkit-appearance: none; appearance: none; width: auto; cursor: pointer;
font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--cyan);
background: rgba(40, 245, 255, 0.06) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%2328f5ff' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 0.9rem center / 0.65rem;
border: 1px solid var(--cyan); box-shadow: 0 0 10px rgba(40, 245, 255, 0.25); padding-right: 2.4rem;
}
.bar select:hover { background-color: rgba(40, 245, 255, 0.16); }
.nowrap { white-space: nowrap; }
.panel-title .dim { min-width: 0; text-align: right; overflow-wrap: anywhere; }
.badge { display: inline-block; padding: 0.05rem 0.7rem; font-size: 0.8rem; letter-spacing: 0.15em; border: 1px solid currentColor; text-shadow: 0 0 8px currentColor; white-space: nowrap; }
.badge.amber { color: var(--amber); }
@@ -315,15 +308,13 @@ textarea { resize: vertical; }
.drop.disabled { opacity: 0.4; cursor: not-allowed; border-color: var(--faint); }
.uplink-grid { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
.fleet-grid { grid-template-columns: minmax(0, 1fr) 330px; }
.uplink-preview .hx-body { font-size: 13px; }
.uplink-preview .hx-row { gap: 0.9rem; }
.panel-body > .hint, .panel-body > .hx-inspector + .hint { margin-top: 0.7rem; }
.uplink-preview:empty::before { content: "NOTHING TO SEND YET."; color: var(--dim); letter-spacing: 0.15em; }
/* ---- hex viewer ---------------------------------------------------------- */
.hx-body { background: #05020c; border: 1px solid var(--faint); padding: 0.7rem 0.9rem; overflow-x: auto; font-size: 15px; line-height: 1.55; }
.hx-row { display: flex; gap: 1.4rem; white-space: pre; width: max-content; }
.hx-row { display: flex; gap: 1.2ch; white-space: pre; width: max-content; }
.hx-off { color: var(--amber); }
.hx-b { display: inline-block; width: 2ch; text-align: center; cursor: default; }
.hx-hex .hx-b { margin-right: 1ch; }
@@ -333,6 +324,7 @@ textarea { resize: vertical; }
.hx-b:hover { background: rgba(40, 245, 255, 0.4); color: #fff; }
.hx-b.sel { background: var(--mag); color: #fff; }
.hx-gap { display: inline-block; width: 1ch; }
.hx-probe { position: absolute; visibility: hidden; font-size: 100px; white-space: pre; }
.hx-inspector { margin-top: 0.7rem; padding: 0.5rem 0.9rem; min-height: 2.6rem; border: 1px solid var(--line); color: var(--cyan); font-size: 0.95rem; letter-spacing: 0.06em; overflow-wrap: anywhere; }
.nosignal { text-align: center; padding: 2.5rem 1rem; }
@@ -360,6 +352,12 @@ dialog::backdrop { background: rgba(3, 1, 10, 0.78); backdrop-filter: blur(3px);
.dialog { width: min(480px, 92vw); }
.dialog.danger { border-color: var(--red); }
.dialog .panel-body p + p { margin-top: 0.7rem; }
.dialog select, .dialog input[type="text"] { width: 100%; }
.dialog select { color: var(--cyan); border-color: var(--line); }
.launch-status { min-height: 1.5em; letter-spacing: 0.04em; }
.launch-status.ok { color: var(--lime); }
.launch-status.bad { color: var(--red); }
.slot-status { margin: 0.2rem 0 0.7rem; }
.dialog .actions { display: flex; justify-content: flex-end; gap: 0.6rem; padding: 0 1rem 1rem; }
/* ---- small screens ------------------------------------------------------- */
@@ -372,8 +370,15 @@ dialog::backdrop { background: rgba(3, 1, 10, 0.78); backdrop-filter: blur(3px);
body { font-size: 16px; }
.topbar { position: static; }
.toolbar .btn { padding: 0.4rem 0.8rem; font-size: 0.9rem; letter-spacing: 0.08em; }
.sealrow .btn { width: 100%; }
.panel-title { letter-spacing: 0.16em; }
/* phones: a tidy two-column grid; the chooser and the primary action span the row */
.bar { flex-direction: column; align-items: stretch; gap: 0.3rem; }
.bar-label { width: auto; }
.bar-buttons { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.bar select { width: 100%; }
.bar .span2 { grid-column: 1 / -1; }
.bar .push { margin-left: 0; }
.bar .btn, .bar select { padding: 0 0.6rem; }
.panel-title { letter-spacing: 0.16em; flex-wrap: wrap; row-gap: 0.15rem; }
.auth { padding-bottom: 10rem; }
.top-user { margin-left: 0; }
.manifest thead { display: none; }
@@ -382,10 +387,19 @@ dialog::backdrop { background: rgba(3, 1, 10, 0.78); backdrop-filter: blur(3px);
.manifest td::before { content: attr(data-label); color: var(--dim); font-size: 0.75rem; letter-spacing: 0.2em; }
.manifest td.actions { justify-content: flex-end; }
.manifest td.actions::before { content: none; }
.tab { padding: 0.5rem 0.8rem; letter-spacing: 0.12em; }
.navbar { flex-direction: column; align-items: stretch; gap: 0.6rem; }
.tabs { width: 100%; gap: 0.2rem; }
.tab { flex: 1 1 auto; min-width: 0; padding: 0.55rem 0.2rem; font-size: 0.68rem; letter-spacing: 0.05em; text-align: center; white-space: nowrap; }
.shipsel { justify-content: space-between; }
.hx-body { padding: 0.6rem 0.5rem; }
.editor { height: 52vh; }
}
@media (max-width: 360px) {
.bar .btn, .bar select { font-size: 0.7rem; letter-spacing: 0.05em; padding: 0 0.4rem; }
.tab { font-size: 0.62rem; letter-spacing: 0.02em; padding-left: 0.1rem; padding-right: 0.1rem; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation: none !important; transition: none !important; }
}