First run now lands on a step-by-step guide instead of the overview: create a Sia Storage account (link out, Pithos never sees the password), install s3d, choose or generate the recovery phrase, connect, start the gateway and create the first access key, with Back/Next on every step. The connect step opens the indexer's approval page on its own and moves on as soon as the approval lands; where a browser blocks the pop-up it says so and makes the button the primary action. Hosts without node-pty (the Theseus add-on) now fetch the one platform package they need from the npm registry on first login, pinned to its published sha512 integrity, so the approval link can be read there too. The console-window login stays only as the fallback when that fails. A retry after a failed connect with an existing phrase goes back to the phrase step: the phrase is not kept, and a blank one would make s3d generate a new one.
228 lines
11 KiB
CSS
228 lines
11 KiB
CSS
:root {
|
|
--bg: #f6f7f8;
|
|
--surface: #ffffff;
|
|
--surface-2: #f0f2f4;
|
|
--border: #dfe3e7;
|
|
--text: #15191d;
|
|
--muted: #5d6873;
|
|
--accent: #1e9e72;
|
|
--accent-ink: #ffffff;
|
|
--accent-soft: #e2f5ed;
|
|
--danger: #c93a3a;
|
|
--danger-soft: #fbe9e9;
|
|
--warn: #b7791f;
|
|
--warn-soft: #fdf3e1;
|
|
--mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, monospace;
|
|
--radius: 10px;
|
|
color-scheme: light;
|
|
}
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--bg: #0f1214;
|
|
--surface: #171b1f;
|
|
--surface-2: #1e2328;
|
|
--border: #2a3036;
|
|
--text: #e6eaee;
|
|
--muted: #8d98a3;
|
|
--accent: #3ddc97;
|
|
--accent-ink: #06231a;
|
|
--accent-soft: #123327;
|
|
--danger: #ef6b6b;
|
|
--danger-soft: #3a1c1c;
|
|
--warn: #e0a84a;
|
|
--warn-soft: #3a2c14;
|
|
color-scheme: dark;
|
|
}
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
html, body { margin: 0; height: 100%; }
|
|
body {
|
|
background: var(--bg); color: var(--text);
|
|
font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
}
|
|
[hidden] { display: none !important; }
|
|
a { color: var(--accent); }
|
|
h1 { font-size: 22px; margin: 0 0 4px; font-weight: 650; }
|
|
h2 { font-size: 16px; margin: 0 0 12px; font-weight: 600; }
|
|
h3 { font-size: 14px; margin: 0 0 8px; font-weight: 600; }
|
|
code, .mono { font-family: var(--mono); font-size: 12.5px; }
|
|
.muted { color: var(--muted); }
|
|
.error { color: var(--danger); }
|
|
.small { font-size: 12.5px; }
|
|
|
|
/* layout */
|
|
.app { display: grid; grid-template-columns: 220px 1fr; min-height: 100%; }
|
|
.sidebar {
|
|
background: var(--surface); border-right: 1px solid var(--border);
|
|
display: flex; flex-direction: column; padding: 16px 12px; gap: 16px;
|
|
position: sticky; top: 0; height: 100vh;
|
|
}
|
|
.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 17px; padding: 0 8px; }
|
|
nav { display: flex; flex-direction: column; gap: 2px; }
|
|
nav a {
|
|
color: var(--text); text-decoration: none; padding: 8px 10px; border-radius: 8px;
|
|
}
|
|
nav a:hover { background: var(--surface-2); }
|
|
nav a.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
|
|
.daemon-pill {
|
|
margin-top: auto; display: flex; align-items: center; gap: 8px;
|
|
padding: 8px 10px; border-radius: 8px; background: var(--surface-2); font-size: 13px;
|
|
}
|
|
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; }
|
|
.dot.running { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
|
|
.dot.starting, .dot.stopping { background: var(--warn); }
|
|
.dot.crashed { background: var(--danger); }
|
|
|
|
main { padding: 28px 32px 48px; max-width: 1100px; width: 100%; min-width: 0; }
|
|
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
|
|
.page-head p { margin: 0; }
|
|
|
|
.grid { display: grid; gap: 16px; }
|
|
.grid.two { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
|
|
.card {
|
|
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
|
|
padding: 18px 20px;
|
|
}
|
|
.card + .card { margin-top: 16px; }
|
|
.grid > .card + .card { margin-top: 0; }
|
|
|
|
.row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
.row.spread { justify-content: space-between; }
|
|
.stack { display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
dl.kv { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0; }
|
|
dl.kv dt { color: var(--muted); }
|
|
dl.kv dd { margin: 0; overflow-wrap: anywhere; }
|
|
|
|
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); gap: 12px; }
|
|
.stat { background: var(--surface-2); border-radius: 8px; padding: 12px 14px; }
|
|
.stat .v { font-size: 22px; font-weight: 650; font-variant-numeric: tabular-nums; }
|
|
.stat .l { color: var(--muted); font-size: 12.5px; }
|
|
.stat.bad .v { color: var(--danger); }
|
|
|
|
/* controls */
|
|
.btn {
|
|
appearance: none; border: 1px solid var(--border); background: var(--surface);
|
|
color: var(--text); padding: 7px 14px; border-radius: 8px; font: inherit; cursor: pointer;
|
|
display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
|
|
}
|
|
.btn:hover:not(:disabled) { background: var(--surface-2); }
|
|
.btn:disabled { opacity: .5; cursor: default; }
|
|
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
|
|
.btn.primary:hover:not(:disabled) { filter: brightness(1.06); background: var(--accent); }
|
|
.btn.danger { color: var(--danger); }
|
|
.btn.danger:hover:not(:disabled) { background: var(--danger-soft); }
|
|
.btn.small { padding: 3px 9px; font-size: 12.5px; }
|
|
.btn.link { border: none; background: none; color: var(--accent); padding: 0; }
|
|
|
|
input[type=text], input[type=password], input[type=number], input[type=url], select, textarea {
|
|
font: inherit; color: var(--text); background: var(--surface); border: 1px solid var(--border);
|
|
border-radius: 8px; padding: 7px 10px; width: 100%;
|
|
}
|
|
textarea { resize: vertical; min-height: 70px; }
|
|
input:focus, select:focus, textarea:focus, .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
|
|
label.field { display: flex; flex-direction: column; gap: 4px; }
|
|
label.field > span { font-weight: 550; font-size: 13px; }
|
|
label.field > small { color: var(--muted); }
|
|
label.check { display: flex; align-items: center; gap: 8px; }
|
|
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 14px; }
|
|
|
|
/* tables */
|
|
table { width: 100%; border-collapse: collapse; }
|
|
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; }
|
|
th { color: var(--muted); font-weight: 550; font-size: 12.5px; }
|
|
tr:last-child td { border-bottom: none; }
|
|
td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
td.actions { text-align: right; white-space: nowrap; }
|
|
tr.clickable { cursor: pointer; }
|
|
tr.clickable:hover td { background: var(--surface-2); }
|
|
.empty { text-align: center; color: var(--muted); padding: 28px 10px; }
|
|
|
|
.badge { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 12px; background: var(--surface-2); color: var(--muted); }
|
|
.badge.ok { background: var(--accent-soft); color: var(--accent); }
|
|
.badge.warn { background: var(--warn-soft); color: var(--warn); }
|
|
|
|
.banner { border-radius: var(--radius); padding: 12px 16px; margin-bottom: 16px; display: flex; gap: 12px; align-items: center; justify-content: space-between; flex-wrap: wrap; }
|
|
.banner.warn { background: var(--warn-soft); color: var(--text); border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent); }
|
|
.banner.info { background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); }
|
|
|
|
.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: 15px; }
|
|
.crumbs button { border: none; background: none; color: var(--accent); cursor: pointer; font: inherit; padding: 2px 4px; border-radius: 4px; }
|
|
.crumbs button:hover { background: var(--surface-2); }
|
|
.crumbs .sep { color: var(--muted); }
|
|
|
|
.dropzone { position: relative; }
|
|
.dropzone.over::after {
|
|
content: "Drop files to upload"; position: absolute; inset: 0; display: grid; place-items: center;
|
|
background: color-mix(in srgb, var(--accent-soft) 85%, transparent); border: 2px dashed var(--accent);
|
|
border-radius: var(--radius); font-weight: 600; color: var(--accent);
|
|
}
|
|
|
|
.uploads { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
|
|
.upload { display: grid; grid-template-columns: 1fr 160px 70px; gap: 10px; align-items: center; font-size: 13px; }
|
|
.bar { height: 6px; background: var(--surface-2); border-radius: 3px; overflow: hidden; }
|
|
.bar > i { display: block; height: 100%; background: var(--accent); width: 0; transition: width .2s; }
|
|
|
|
.logs {
|
|
font-family: var(--mono); font-size: 12px; background: var(--surface); border: 1px solid var(--border);
|
|
border-radius: var(--radius); padding: 12px; height: calc(100vh - 170px); overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere;
|
|
}
|
|
.logs .err { color: var(--danger); }
|
|
.logs .sys { color: var(--muted); font-style: italic; }
|
|
|
|
.secret { display: flex; gap: 6px; align-items: center; }
|
|
.secret code { background: var(--surface-2); padding: 3px 8px; border-radius: 6px; overflow-wrap: anywhere; }
|
|
pre.snippet { background: var(--surface-2); padding: 10px 12px; border-radius: 8px; overflow: auto; margin: 0; font-family: var(--mono); font-size: 12px; }
|
|
|
|
.phrase { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; counter-reset: w; }
|
|
.phrase span { background: var(--surface-2); padding: 6px 8px; border-radius: 6px; font-family: var(--mono); counter-increment: w; }
|
|
.phrase span::before { content: counter(w) ". "; color: var(--muted); }
|
|
|
|
.steps { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
|
|
.steps span { padding: 3px 10px; border-radius: 999px; background: var(--surface-2); color: var(--muted); font-size: 12.5px; }
|
|
.steps span.on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
|
|
|
|
/* modal + toasts */
|
|
.modal-backdrop { position: fixed; inset: 0; background: rgb(0 0 0 / .45); display: grid; place-items: center; padding: 16px; z-index: 10; }
|
|
.modal { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 22px; width: min(560px, 100%); max-height: 90vh; overflow: auto; }
|
|
.modal h2 { margin-bottom: 14px; }
|
|
.modal .foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
|
|
|
|
.toasts { position: fixed; right: 16px; bottom: 16px; display: flex; flex-direction: column; gap: 8px; z-index: 20; }
|
|
.toast { background: var(--text); color: var(--bg); padding: 10px 14px; border-radius: 8px; max-width: 380px; box-shadow: 0 6px 20px rgb(0 0 0 / .2); }
|
|
.toast.error { background: var(--danger); color: #fff; }
|
|
|
|
.signin { display: grid; place-items: center; min-height: 100%; padding: 16px; }
|
|
.signin-card { width: min(340px, 100%); display: flex; flex-direction: column; gap: 12px; align-items: stretch; text-align: center; }
|
|
.signin-card img { align-self: center; }
|
|
|
|
.spinner { width: 14px; height: 14px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .8s linear infinite; display: inline-block; }
|
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
|
|
@media (max-width: 760px) {
|
|
.app { grid-template-columns: 1fr; }
|
|
.sidebar { position: static; height: auto; flex-direction: row; flex-wrap: wrap; align-items: center; padding: 10px 16px; }
|
|
nav { flex-direction: row; flex-wrap: wrap; }
|
|
.daemon-pill { margin-top: 0; margin-left: auto; }
|
|
main { padding: 20px 16px 40px; }
|
|
.upload { grid-template-columns: 1fr 80px 50px; }
|
|
.hide-sm { display: none; }
|
|
}
|
|
|
|
/* Theseus sidebar: widen / open-in-tab controls */
|
|
.host-controls { display: flex; gap: 6px; flex-wrap: wrap; margin-top: auto; }
|
|
.host-controls + .daemon-pill { margin-top: 0; }
|
|
@media (max-width: 760px) { .host-controls { margin-top: 0; } }
|
|
|
|
/* Narrow hosts (Theseus sidebar): never scroll sideways. */
|
|
html, body { overflow-x: hidden; }
|
|
.card { min-width: 0; }
|
|
|
|
/* Get started wizard */
|
|
.wizard { max-width: 720px; }
|
|
.wizard h2 { margin-top: 6px; }
|
|
.wizard-progress { margin-bottom: 18px; }
|
|
.wizard-progress .bar { margin-top: 6px; }
|
|
.wizard-nav { margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--border); }
|
|
.wizard-list { margin: 0 0 8px 1.2em; padding: 0; display: grid; gap: 4px; }
|