Brand button was wrapping the whole "Sirius.X" label in <span class="g">, so the entire name rendered acid green. Consistency across the ecosystem is Sirius (ink) + .X (acid), like Theseus.X and Hephaestus.X. Split the span across every page (index, tld, portal, admin, brand, docs, market, storage, theseus/) so only the .X tail carries the acid tint.
576 lines
30 KiB
HTML
576 lines
30 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Storage — Sirius.X (wireframe)</title>
|
||
<meta name="description" content="Wireframe for the Sirius.X portal Storage tab. Per-user Sia storage on Hephaestus. Not wired to a backend.">
|
||
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">
|
||
<link rel="mask-icon" href="../assets/favicon.svg" color="#d6ff3d">
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300;9..144,400;9..144,500;9..144,600;9..144,700&family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root{
|
||
--bg:#050810; --panel:#141a24; --panel2:#0a0f1c; --line:rgba(255,255,255,.06);
|
||
--sky-mid:#0a0f1c; --sky-rim:#131a2a;
|
||
--ink:#f1f4fa; --mut:#b8c2d4; --dim:#6a7488; --acid:#d6ff3d;
|
||
--chain-native:#0AC18E; --forge:#ff8c00;
|
||
--ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
|
||
--serif:'Fraunces',Georgia,serif;
|
||
--sans:'DM Sans','Inter',system-ui,sans-serif;
|
||
--mono:'JetBrains Mono',ui-monospace,monospace;
|
||
}
|
||
*{box-sizing:border-box}
|
||
body{margin:0;
|
||
background:radial-gradient(ellipse 1200px 600px at 50% -5%,var(--sky-rim) 0%,transparent 60%),
|
||
radial-gradient(ellipse 900px 500px at 100% 100%,var(--sky-mid) 0%,transparent 55%),
|
||
radial-gradient(ellipse 900px 500px at 0% 100%,#0c1424 0%,transparent 55%),
|
||
var(--bg);
|
||
background-attachment:fixed;
|
||
color:var(--ink);font:15px/1.55 var(--sans);min-height:100vh;font-feature-settings:"ss01","ss02"}
|
||
h1,h2,h3{font-family:var(--serif);font-feature-settings:"ss01","ss02"}
|
||
code,.mono{font-family:var(--mono)}
|
||
a{color:var(--acid);text-decoration:none}
|
||
|
||
/* topnav (matches portal) */
|
||
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
|
||
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px)}
|
||
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px}
|
||
.topnav .brand .g{color:var(--acid)}
|
||
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
|
||
.topnav a:hover{color:var(--ink);background:var(--panel)}
|
||
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
|
||
.topnav a.portal{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
|
||
|
||
/* dashboard shell */
|
||
.dash{display:grid;grid-template-columns:236px minmax(0,1fr);gap:26px;max-width:1200px;margin:0 auto;padding:1.4rem 1.2rem 3rem}
|
||
@media (min-width:1280px){
|
||
.dash{max-width:1720px;grid-template-columns:260px minmax(0,1fr);gap:34px;padding:1.6rem 2rem 3rem}
|
||
}
|
||
@media (max-width:800px){
|
||
.dash{grid-template-columns:1fr;gap:14px}
|
||
.side{position:static}
|
||
}
|
||
|
||
.side{position:sticky;top:68px;align-self:start;display:flex;flex-direction:column;gap:4px}
|
||
.side .who{padding:12px 14px;border-radius:12px;background:var(--panel);border:1px solid var(--line);margin-bottom:8px}
|
||
.side .who .lbl{font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--dim)}
|
||
.side .who .addr{font-family:var(--mono);font-size:12px;color:var(--ink);word-break:break-all;margin-top:4px}
|
||
.side .who .net{font-size:11.5px;color:var(--dim);margin-top:4px}
|
||
.side .grp{font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);padding:12px 14px 4px}
|
||
.side .sep{height:1px;background:var(--line);margin:8px 6px}
|
||
.side button.item,.side a.item{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:9px 12px;border-radius:10px;
|
||
background:transparent;border:1px solid transparent;color:var(--mut);font:inherit;font-size:14px;cursor:pointer;text-decoration:none;transition:all .12s}
|
||
.side .item .ic{width:20px;text-align:center;flex:none;opacity:.9}
|
||
.side .item .cnt{margin-left:auto;font-family:var(--mono);font-size:11px;padding:1px 7px;border-radius:999px;background:rgba(255,255,255,.08);color:var(--ink)}
|
||
.side .item:hover{color:var(--ink);background:rgba(255,255,255,.04)}
|
||
.side .item.active{color:var(--acid);background:rgba(214,255,61,.08);border-color:rgba(214,255,61,.18)}
|
||
.side .item.active .cnt{background:rgba(214,255,61,.2);color:var(--acid)}
|
||
|
||
/* content shared */
|
||
.content{min-width:0}
|
||
.ph{display:flex;flex-wrap:wrap;gap:14px;justify-content:space-between;align-items:flex-start;margin-bottom:14px}
|
||
.ph h2{font-size:1.35rem;margin:0}
|
||
.ph p{color:var(--mut);margin:.3rem 0 0;max-width:640px}
|
||
|
||
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:20px 22px}
|
||
.card + .card{margin-top:14px}
|
||
|
||
.btn{display:inline-flex;align-items:center;gap:6px;text-decoration:none;padding:9px 16px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit;line-height:1.2}
|
||
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
|
||
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
|
||
.btn.danger{background:rgba(246,118,138,.14);color:var(--taken);border:1px solid rgba(246,118,138,.35)}
|
||
.btn.small{padding:6px 11px;font-size:12.5px}
|
||
.btn:hover{filter:brightness(1.12)}
|
||
.btn:disabled{opacity:.45;cursor:not-allowed;filter:none}
|
||
|
||
.badge{display:inline-block;font-size:11px;padding:2px 9px;border-radius:999px;font-weight:600;line-height:1.6}
|
||
.b-x{background:rgba(214,255,61,.14);color:var(--acid)}
|
||
.b-warn{background:rgba(255,199,95,.14);color:var(--warn)}
|
||
.b-ok{background:rgba(79,209,165,.14);color:var(--ok)}
|
||
.b-off{background:rgba(246,118,138,.14);color:var(--taken)}
|
||
.b-dim{background:rgba(255,255,255,.06);color:var(--mut)}
|
||
.b-native{background:rgba(10,193,142,.14);color:var(--chain-native)}
|
||
.b-forge{background:rgba(255,140,0,.14);color:var(--forge)}
|
||
|
||
.muted{color:var(--mut);font-size:13px}
|
||
.dim{color:var(--dim);font-size:12.5px}
|
||
.hidden{display:none !important}
|
||
|
||
/* ---------- storage layout ---------- */
|
||
.quota{display:flex;flex-direction:column;gap:14px}
|
||
.quota-hdr{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
|
||
.quota-hdr .tier-name{font-family:var(--serif);font-size:1.35rem;font-weight:500}
|
||
.quota-hdr .quota-line{font-family:var(--mono);color:var(--mut);font-size:14px}
|
||
.quota-hdr .quota-line b{color:var(--ink);font-weight:500}
|
||
.quota-hdr .renew{font-size:12.5px;color:var(--dim);margin-left:auto}
|
||
|
||
.bar{width:100%;height:10px;border-radius:999px;background:rgba(255,255,255,.04);overflow:hidden;border:1px solid var(--line)}
|
||
.bar > .fill{height:100%;background:linear-gradient(90deg,var(--acid),#a8e600);border-radius:999px;transition:width .3s}
|
||
.bar.warn > .fill{background:linear-gradient(90deg,var(--warn),#f59d00)}
|
||
.bar.over > .fill{background:linear-gradient(90deg,var(--taken),#e04e4e)}
|
||
|
||
.quota-detail{display:flex;gap:20px;flex-wrap:wrap;font-size:12.5px;color:var(--dim)}
|
||
.quota-detail b{color:var(--mut);font-weight:500;font-family:var(--mono)}
|
||
|
||
/* file browser */
|
||
.browser{display:grid;grid-template-columns:180px minmax(0,1fr);gap:16px;margin-top:14px}
|
||
@media (max-width:640px){.browser{grid-template-columns:1fr}}
|
||
|
||
.folders{display:flex;flex-direction:column;gap:2px;padding:4px 0}
|
||
.folders .fh{font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);padding:6px 10px 4px}
|
||
.folders button{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:8px;background:transparent;border:1px solid transparent;color:var(--mut);font:inherit;font-size:13.5px;cursor:pointer;text-align:left;width:100%}
|
||
.folders button .ic{width:16px;text-align:center;opacity:.85}
|
||
.folders button:hover{color:var(--ink);background:rgba(255,255,255,.04)}
|
||
.folders button.active{color:var(--acid);background:rgba(214,255,61,.06);border-color:rgba(214,255,61,.15)}
|
||
.folders button .cnt{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--dim)}
|
||
|
||
.files{display:flex;flex-direction:column;gap:1px;background:var(--panel2);border:1px solid var(--line);border-radius:12px;overflow:hidden}
|
||
.files .toolbar{display:flex;gap:8px;padding:10px 14px;border-bottom:1px solid var(--line);align-items:center;background:rgba(255,255,255,.02)}
|
||
.files .toolbar .path{font-family:var(--mono);font-size:12.5px;color:var(--mut);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.files .toolbar .path .sep{color:var(--dim);margin:0 4px}
|
||
.files .toolbar .path .lock{color:var(--acid);margin-right:6px}
|
||
.files .toolbar .path .globe{color:var(--chain-native);margin-right:6px}
|
||
.files .row{display:grid;grid-template-columns:1fr 90px 110px 40px;gap:12px;align-items:center;padding:10px 14px;transition:background .1s}
|
||
.files .row:hover{background:rgba(255,255,255,.03)}
|
||
.files .row + .row{border-top:1px solid rgba(255,255,255,.03)}
|
||
.files .row.head{color:var(--dim);font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;padding:8px 14px}
|
||
.files .row.head:hover{background:transparent}
|
||
.files .row .name{display:flex;gap:8px;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.files .row .name .ic{width:18px;text-align:center;flex:none}
|
||
.files .row .size{font-family:var(--mono);font-size:12px;color:var(--mut);text-align:right}
|
||
.files .row .date{font-family:var(--mono);font-size:12px;color:var(--dim)}
|
||
.files .row .more{color:var(--dim);cursor:pointer;text-align:right;padding:0 4px;user-select:none}
|
||
.files .row .more:hover{color:var(--ink)}
|
||
|
||
.drop{margin:12px 14px 14px;border:1.5px dashed rgba(255,255,255,.12);border-radius:10px;padding:22px;text-align:center;color:var(--mut);font-size:13.5px;transition:all .15s}
|
||
.drop.active{border-color:var(--acid);background:rgba(214,255,61,.03);color:var(--ink)}
|
||
.drop b{color:var(--acid);font-weight:500}
|
||
.drop .k{font-family:var(--mono);color:var(--dim);font-size:12px;display:block;margin-top:4px}
|
||
|
||
/* upgrade modal */
|
||
.modal-scrim{position:fixed;inset:0;z-index:100;background:rgba(4,6,11,.72);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;padding:20px}
|
||
.modal-scrim.show{display:flex}
|
||
.modal{background:var(--panel);border:1px solid var(--line);border-radius:16px;max-width:640px;width:100%;max-height:calc(100vh - 40px);overflow:auto;padding:22px 26px}
|
||
.modal h2{margin:0 0 6px;font-size:1.4rem}
|
||
.modal .close{float:right;background:none;border:0;color:var(--dim);font-size:22px;cursor:pointer;line-height:1;padding:0 4px;margin:-4px -8px 0 0}
|
||
.modal .close:hover{color:var(--ink)}
|
||
.plans{display:flex;flex-direction:column;gap:10px;margin:14px 0 18px}
|
||
.plan{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:12px;border:1px solid var(--line);cursor:pointer;transition:all .12s;background:var(--panel2)}
|
||
.plan:hover{border-color:rgba(214,255,61,.28)}
|
||
.plan.sel{border-color:var(--acid);background:rgba(214,255,61,.05)}
|
||
.plan .radio{width:16px;height:16px;border-radius:50%;border:1.5px solid var(--dim);flex:none;position:relative}
|
||
.plan.sel .radio{border-color:var(--acid)}
|
||
.plan.sel .radio::after{content:'';position:absolute;inset:3px;background:var(--acid);border-radius:50%}
|
||
.plan .nm{flex:1;font-family:var(--serif);font-size:1.05rem;font-weight:500}
|
||
.plan .size{font-family:var(--mono);font-size:12.5px;color:var(--mut);width:130px}
|
||
.plan .price{font-family:var(--mono);font-size:14px;color:var(--ink);font-weight:500;width:80px;text-align:right}
|
||
.plan.current{opacity:.6;cursor:default}
|
||
.plan.current .nm::after{content:' — current';color:var(--dim);font-family:var(--sans);font-size:12px;font-weight:400}
|
||
.plan .save{font-family:var(--mono);font-size:10.5px;color:var(--acid);letter-spacing:.1em;margin-left:8px}
|
||
|
||
.pay-box{padding:18px 20px;border-radius:12px;background:linear-gradient(135deg,rgba(214,255,61,.04),rgba(10,193,142,.02));border:1px solid rgba(214,255,61,.16)}
|
||
.pay-box .amt{font-family:var(--serif);font-size:2rem;color:var(--acid);font-weight:400;letter-spacing:-.02em}
|
||
.pay-box .amt sub{font-family:var(--mono);font-size:12px;color:var(--mut);letter-spacing:0;vertical-align:baseline;margin-left:6px}
|
||
.pay-box .oracle{font-family:var(--mono);font-size:11.5px;color:var(--dim);margin-top:4px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
||
.pay-box .dot{width:6px;height:6px;border-radius:50%;background:var(--ok);animation:pulse 2s infinite ease-in-out}
|
||
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
|
||
|
||
.modal .actions{display:flex;gap:10px;margin-top:16px;flex-wrap:wrap;align-items:center}
|
||
.modal .actions .btn{flex:1;justify-content:center;padding:12px 18px;font-size:14.5px}
|
||
.modal .actions .btn.acid{flex:2}
|
||
.modal .alt{font-size:12px;color:var(--dim);margin-top:12px;text-align:center}
|
||
.modal .alt a{color:var(--mut)}
|
||
|
||
/* confirmation banner */
|
||
.banner{padding:14px 18px;border-radius:12px;background:rgba(79,209,165,.06);border:1px solid rgba(79,209,165,.24);color:var(--ink);margin-bottom:14px;display:flex;gap:12px;align-items:center}
|
||
.banner.warn{background:rgba(255,199,95,.06);border-color:rgba(255,199,95,.24)}
|
||
.banner.err{background:rgba(246,118,138,.06);border-color:rgba(246,118,138,.24)}
|
||
.banner .ic{font-size:20px;flex:none}
|
||
.banner .txt{flex:1;font-size:13.5px;color:var(--mut)}
|
||
.banner .txt b{color:var(--ink);font-weight:500}
|
||
.banner .close{background:none;border:0;color:var(--dim);font-size:18px;cursor:pointer;padding:0 4px}
|
||
.banner .close:hover{color:var(--ink)}
|
||
|
||
/* wireframe state picker (dev-only) */
|
||
.wf-picker{position:fixed;bottom:16px;right:16px;z-index:50;padding:8px 10px;border-radius:12px;background:rgba(20,26,36,.94);border:1px solid var(--line);font-family:var(--mono);font-size:11px;color:var(--dim);display:flex;flex-direction:column;gap:4px;backdrop-filter:blur(10px)}
|
||
.wf-picker .h{color:var(--acid);text-transform:uppercase;letter-spacing:.15em;font-size:9.5px;margin-bottom:2px}
|
||
.wf-picker button{background:transparent;border:0;color:var(--mut);cursor:pointer;font-family:inherit;font-size:11.5px;padding:3px 6px;border-radius:6px;text-align:left}
|
||
.wf-picker button:hover{color:var(--ink);background:rgba(255,255,255,.04)}
|
||
.wf-picker button.active{color:var(--acid);background:rgba(214,255,61,.08)}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="topnav">
|
||
<a class="brand" href="../"><svg width="18" height="18" viewBox="0 0 64 64" style="vertical-align:-4px;margin-right:6px" aria-hidden="true"><rect width="64" height="64" rx="12" fill="#0b0e14"/><path d="M32 4 L36.4 27.6 L60 32 L36.4 36.4 L32 60 L27.6 36.4 L4 32 L27.6 27.6 Z" fill="#d6ff3d"/></svg>Sirius<span class="g">.X</span></a>
|
||
<a href="../tld.html">🌐 TLD</a>
|
||
<a href="../market/">🛒 Market</a>
|
||
<a href="../portal.html" class="portal here">🔑 Storage</a>
|
||
</nav>
|
||
|
||
<div class="dash">
|
||
|
||
<!-- ============ sidebar ============ -->
|
||
<aside class="side" aria-label="Dashboard menu">
|
||
<div class="who">
|
||
<div class="lbl">Signed in</div>
|
||
<div class="addr">bitcoincash:qzrp…4qtx</div>
|
||
<div class="net">chipnet · 42,180 sat</div>
|
||
</div>
|
||
<button class="item"><span class="ic">🎨</span>Web-Builder</button>
|
||
<button class="item"><span class="ic">🌐</span>Domain names<span class="cnt">3</span></button>
|
||
<button class="item"><span class="ic">🏷</span>My TLDs<span class="cnt">1</span></button>
|
||
<button class="item active"><span class="ic">📦</span>Storage<span class="cnt" id="side-quota">120M</span></button>
|
||
<div class="sep"></div>
|
||
<button class="item"><span class="ic">⚙</span>Settings</button>
|
||
<button class="item"><span class="ic">🚪</span>Sign out</button>
|
||
</aside>
|
||
|
||
<!-- ============ content ============ -->
|
||
<main class="content">
|
||
|
||
<!-- Confirmation banners appear here based on wireframe state -->
|
||
<div id="banner-confirming" class="banner warn hidden">
|
||
<div class="ic">⏳</div>
|
||
<div class="txt"><b>Confirming payment.</b> 0.0462 BCH received — waiting for 1 confirmation (~10 min). Your plan activates automatically.</div>
|
||
<button class="close" onclick="dismissBanner(this)">×</button>
|
||
</div>
|
||
|
||
<div id="banner-upgraded" class="banner hidden">
|
||
<div class="ic">✓</div>
|
||
<div class="txt"><b>Silent Max is active.</b> Quota bumped to 50 GB private. Renews 2026-10-20.</div>
|
||
<button class="close" onclick="dismissBanner(this)">×</button>
|
||
</div>
|
||
|
||
<div id="banner-grace" class="banner err hidden">
|
||
<div class="ic">⚠</div>
|
||
<div class="txt"><b>Over quota.</b> Files are read-only for 27 more days. Upgrade or delete files to restore write access.</div>
|
||
<button class="close" onclick="dismissBanner(this)">×</button>
|
||
</div>
|
||
|
||
<div class="ph">
|
||
<div>
|
||
<h2>Storage</h2>
|
||
<p id="hdr-sub">Files you host on Silent Mode's Sia backend. Public files get a URL anyone can open;
|
||
private files are encrypted in your browser with a key only your wallet can derive.</p>
|
||
</div>
|
||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||
<button class="btn ghost small">↻ Refresh</button>
|
||
<button class="btn acid small" id="upgrade-btn" onclick="openModal()">Upgrade</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Quota card -->
|
||
<section class="card">
|
||
<div class="quota">
|
||
<div class="quota-hdr">
|
||
<span class="tier-name" id="tier-name">Silent Free</span>
|
||
<span class="badge b-dim" id="tier-badge">Free</span>
|
||
<span class="quota-line"><b id="q-used">120 MB</b> / <span id="q-cap">500 MB</span> private</span>
|
||
<span class="renew" id="renew-line" style="display:none">renews <b id="renew-date">2026-10-20</b></span>
|
||
</div>
|
||
<div class="bar" id="q-bar"><div class="fill" id="q-fill" style="width:24%"></div></div>
|
||
<div class="quota-detail">
|
||
<span>Public: <b>2.4 GB</b> · unlimited</span>
|
||
<span>Files: <b>47</b></span>
|
||
<span>Encryption: <b>on</b> for private</span>
|
||
<span id="credit-line" style="display:none">Credit: <b>$0.00</b></span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- File browser -->
|
||
<section class="card" style="padding:14px 14px 0">
|
||
<div class="browser">
|
||
<nav class="folders">
|
||
<div class="fh">Folders</div>
|
||
<button class="active" data-folder="private">
|
||
<span class="ic" style="color:var(--acid)">🔒</span>Private
|
||
<span class="cnt">12</span>
|
||
</button>
|
||
<button data-folder="public">
|
||
<span class="ic" style="color:var(--chain-native)">🌐</span>Public
|
||
<span class="cnt">35</span>
|
||
</button>
|
||
<button data-folder="shared">
|
||
<span class="ic">🔗</span>Shared
|
||
<span class="cnt">2</span>
|
||
</button>
|
||
<div class="fh" style="margin-top:8px">Actions</div>
|
||
<button><span class="ic">+</span>New folder</button>
|
||
<button><span class="ic">↑</span>Upload</button>
|
||
</nav>
|
||
|
||
<div class="files">
|
||
<div class="toolbar">
|
||
<div class="path">
|
||
<span class="lock">🔒</span>
|
||
<span>private</span>
|
||
<span class="sep">/</span>
|
||
<span>projects</span>
|
||
</div>
|
||
<button class="btn ghost small">Share</button>
|
||
</div>
|
||
|
||
<div class="row head">
|
||
<span>Name</span>
|
||
<span class="size" style="text-align:right">Size</span>
|
||
<span class="date">Modified</span>
|
||
<span></span>
|
||
</div>
|
||
|
||
<div class="row">
|
||
<span class="name"><span class="ic">📁</span>silentmode-notes</span>
|
||
<span class="size">—</span>
|
||
<span class="date">3d ago</span>
|
||
<span class="more">⋯</span>
|
||
</div>
|
||
<div class="row">
|
||
<span class="name"><span class="ic">📁</span>contracts</span>
|
||
<span class="size">—</span>
|
||
<span class="date">1w ago</span>
|
||
<span class="more">⋯</span>
|
||
</div>
|
||
<div class="row">
|
||
<span class="name"><span class="ic">📄</span>hestia-outline.md</span>
|
||
<span class="size">14 KB</span>
|
||
<span class="date">just now</span>
|
||
<span class="more">⋯</span>
|
||
</div>
|
||
<div class="row">
|
||
<span class="name"><span class="ic">📄</span>oracle-notes.txt</span>
|
||
<span class="size">4 KB</span>
|
||
<span class="date">2h ago</span>
|
||
<span class="more">⋯</span>
|
||
</div>
|
||
<div class="row">
|
||
<span class="name"><span class="ic">🗄</span>backup-2026-09-18.tar.gz</span>
|
||
<span class="size">86 MB</span>
|
||
<span class="date">2d ago</span>
|
||
<span class="more">⋯</span>
|
||
</div>
|
||
<div class="row">
|
||
<span class="name"><span class="ic">🖼</span>diagram.png</span>
|
||
<span class="size">220 KB</span>
|
||
<span class="date">4d ago</span>
|
||
<span class="more">⋯</span>
|
||
</div>
|
||
<div class="row">
|
||
<span class="name"><span class="ic">🔑</span>keys.json.gpg</span>
|
||
<span class="size">2 KB</span>
|
||
<span class="date">2w ago</span>
|
||
<span class="more">⋯</span>
|
||
</div>
|
||
|
||
<div class="drop" id="drop">
|
||
Drag files here, or <b>click to browse</b>
|
||
<span class="k">Encrypted in your browser before upload · max 100 MB per file on Free</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- CLI hint -->
|
||
<section class="card" style="margin-top:14px">
|
||
<div style="display:flex;gap:10px;align-items:baseline;justify-content:space-between;flex-wrap:wrap">
|
||
<div>
|
||
<h3 style="margin:0 0 4px">CLI access</h3>
|
||
<p class="muted" style="margin:0">Upload from a script or CI with your Silent Mode PAT.
|
||
Encryption still happens client-side.</p>
|
||
</div>
|
||
<span class="badge b-dim" id="cli-tier">Free — via gateway</span>
|
||
</div>
|
||
<pre style="margin:12px 0 0;padding:12px 14px;background:var(--panel2);border:1px solid var(--line);border-radius:10px;font-family:var(--mono);font-size:12.5px;color:var(--mut);overflow:auto;line-height:1.6"><span style="color:var(--dim)"># upload a private file</span>
|
||
curl -H "Authorization: token $HESTIA_PAT" \
|
||
--data-binary @notes.md \
|
||
https://storage.silentmode.st/u/48291/private/notes.md
|
||
|
||
<span style="color:var(--dim)"># list your files</span>
|
||
curl -H "Authorization: token $HESTIA_PAT" \
|
||
https://storage.silentmode.st/u/48291/list</pre>
|
||
<p class="muted" id="cli-hint" style="margin:10px 0 0;font-size:12.5px">
|
||
<span class="badge b-warn">Pro / Max</span> get their own S3 credentials for direct
|
||
<code>rclone</code> / <code>aws s3</code> use.
|
||
</p>
|
||
</section>
|
||
|
||
</main>
|
||
</div>
|
||
|
||
<!-- ============ upgrade modal ============ -->
|
||
<div class="modal-scrim" id="modal">
|
||
<div class="modal">
|
||
<button class="close" onclick="closeModal()">×</button>
|
||
<h2>Plans</h2>
|
||
<p class="muted">Priced in USD, paid in BCH at the live oracle rate. All plans include unlimited public storage. Encryption is client-side, wallet-derived, always on for private files.</p>
|
||
|
||
<div class="plans" id="plans">
|
||
<div class="plan current" data-tier="free">
|
||
<span class="radio"></span>
|
||
<span class="nm">Silent Free</span>
|
||
<span class="size">500 MB private</span>
|
||
<span class="price">$0</span>
|
||
</div>
|
||
<div class="plan" data-tier="pro" onclick="selectPlan('pro')">
|
||
<span class="radio"></span>
|
||
<span class="nm">Silent Pro</span>
|
||
<span class="size">2 GB private</span>
|
||
<span class="price">$3<span class="save">·25% off GH</span></span>
|
||
</div>
|
||
<div class="plan sel" data-tier="max" onclick="selectPlan('max')">
|
||
<span class="radio"></span>
|
||
<span class="nm">Silent Max</span>
|
||
<span class="size">50 GB private</span>
|
||
<span class="price">$16<span class="save">·24% off GH</span></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pay-box">
|
||
<div style="display:flex;justify-content:space-between;align-items:baseline">
|
||
<div>
|
||
<div class="dim" style="font-family:var(--mono);letter-spacing:.1em;text-transform:uppercase;font-size:10px">Pay for 1 month</div>
|
||
<div class="amt" id="pay-amt">0.0462 BCH<sub>≈ $16.00</sub></div>
|
||
</div>
|
||
<span class="badge b-native" id="pay-tier">Silent Max</span>
|
||
</div>
|
||
<div class="oracle">
|
||
<span class="dot"></span>
|
||
<span>live oracle at <b style="color:var(--mut)" id="oracle-rate">$346.40</b> / BCH</span>
|
||
<span>·</span>
|
||
<span id="oracle-age">quoted 00:14 ago</span>
|
||
<span>·</span>
|
||
<span>refreshes in <span id="oracle-refresh">04:46</span></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button class="btn ghost" onclick="closeModal()">Cancel</button>
|
||
<button class="btn acid" onclick="mockPay()">Pay from wallet →</button>
|
||
</div>
|
||
<div class="alt">
|
||
also accepts: <a href="#">QR code</a> · <a href="#">external wallet</a> · <a href="#">on-chain address</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ wireframe state picker (dev only) ============ -->
|
||
<div class="wf-picker">
|
||
<div class="h">Wireframe state</div>
|
||
<button class="active" onclick="setState('free')">Free · default</button>
|
||
<button onclick="setState('confirming')">Free · confirming</button>
|
||
<button onclick="setState('max-fresh')">Max · just upgraded</button>
|
||
<button onclick="setState('max-half')">Max · half full</button>
|
||
<button onclick="setState('grace')">Free · over quota</button>
|
||
</div>
|
||
|
||
<script>
|
||
const PLAN = {
|
||
free: {name:'Silent Free', badge:'Free', badgeCls:'b-dim', used:120, cap:500, capUnit:'MB', price:0, bch:0},
|
||
pro: {name:'Silent Pro', badge:'Pro', badgeCls:'b-forge', used:1200, cap:2, capUnit:'GB', price:3, bch:0.00866},
|
||
max: {name:'Silent Max', badge:'Max', badgeCls:'b-native',used:24800, cap:50, capUnit:'GB', price:16, bch:0.04620},
|
||
};
|
||
let currentTier = 'free';
|
||
let selectedTier = 'max';
|
||
|
||
function selectPlan(t){
|
||
selectedTier = t;
|
||
document.querySelectorAll('.plan').forEach(p=>p.classList.toggle('sel', p.dataset.tier === t));
|
||
const p = PLAN[t];
|
||
document.getElementById('pay-amt').innerHTML = p.bch.toFixed(5) + ' BCH<sub>≈ $' + p.price.toFixed(2) + '</sub>';
|
||
document.getElementById('pay-tier').className = 'badge ' + p.badgeCls;
|
||
document.getElementById('pay-tier').textContent = p.name;
|
||
}
|
||
|
||
function openModal(){ document.getElementById('modal').classList.add('show'); }
|
||
function closeModal(){ document.getElementById('modal').classList.remove('show'); }
|
||
function dismissBanner(el){ el.parentElement.classList.add('hidden'); }
|
||
|
||
function mockPay(){
|
||
closeModal();
|
||
setState('confirming');
|
||
// fake the SSE flow: confirming → upgraded after 3s
|
||
setTimeout(() => setState('max-fresh'), 3000);
|
||
}
|
||
|
||
function fmtBytes(x, unit){
|
||
if (unit === 'MB') return x < 1024 ? x + ' MB' : (x/1024).toFixed(1) + ' GB';
|
||
if (unit === 'GB') return x < 1 ? Math.round(x*1024) + ' MB' : x + ' GB';
|
||
return x + ' ' + unit;
|
||
}
|
||
|
||
function setState(s){
|
||
// reset banners
|
||
['confirming','upgraded','grace'].forEach(k =>
|
||
document.getElementById('banner-' + k).classList.add('hidden'));
|
||
|
||
// reset state-picker button
|
||
document.querySelectorAll('.wf-picker button').forEach(b => b.classList.remove('active'));
|
||
(document.querySelector(`.wf-picker button[onclick*="${s}"]`) || {classList:{add:()=>{}}}).classList.add('active');
|
||
|
||
let tier='free', usedMB=120, capMB=500, capLabel='500 MB', tierLabel='Silent Free',
|
||
badgeCls='b-dim', badgeLbl='Free', renew=false, credit=false, cliBadge='Free — via gateway';
|
||
|
||
if (s === 'confirming') {
|
||
document.getElementById('banner-confirming').classList.remove('hidden');
|
||
}
|
||
if (s === 'max-fresh') {
|
||
tier='max'; usedMB=120; capMB=50*1024; capLabel='50 GB'; tierLabel='Silent Max';
|
||
badgeCls='b-native'; badgeLbl='Max'; renew=true;
|
||
cliBadge='Max — direct S3';
|
||
document.getElementById('banner-upgraded').classList.remove('hidden');
|
||
}
|
||
if (s === 'max-half') {
|
||
tier='max'; usedMB=25*1024; capMB=50*1024; capLabel='50 GB'; tierLabel='Silent Max';
|
||
badgeCls='b-native'; badgeLbl='Max'; renew=true;
|
||
cliBadge='Max — direct S3';
|
||
}
|
||
if (s === 'grace') {
|
||
tier='free'; usedMB=580; capMB=500; capLabel='500 MB'; tierLabel='Silent Free';
|
||
badgeCls='b-dim'; badgeLbl='Free (over quota)'; credit=true;
|
||
document.getElementById('banner-grace').classList.remove('hidden');
|
||
}
|
||
|
||
currentTier = tier;
|
||
document.getElementById('tier-name').textContent = tierLabel;
|
||
document.getElementById('tier-badge').className = 'badge ' + badgeCls;
|
||
document.getElementById('tier-badge').textContent = badgeLbl;
|
||
|
||
const pct = Math.min(100, Math.round((usedMB / capMB) * 100));
|
||
document.getElementById('q-used').textContent = usedMB < 1024 ? usedMB + ' MB' : (usedMB/1024).toFixed(1) + ' GB';
|
||
document.getElementById('q-cap').textContent = capLabel;
|
||
document.getElementById('q-fill').style.width = pct + '%';
|
||
document.getElementById('q-bar').className = 'bar' + (pct >= 100 ? ' over' : pct >= 85 ? ' warn' : '');
|
||
document.getElementById('side-quota').textContent = usedMB < 1024 ? usedMB + 'M' : (usedMB/1024).toFixed(1) + 'G';
|
||
|
||
document.getElementById('renew-line').style.display = renew ? '' : 'none';
|
||
document.getElementById('credit-line').style.display = credit ? '' : 'none';
|
||
document.getElementById('cli-tier').textContent = cliBadge;
|
||
document.getElementById('cli-tier').className = 'badge ' + (tier === 'free' ? 'b-dim' : tier === 'pro' ? 'b-forge' : 'b-native');
|
||
|
||
// update available plans in modal (highlight current, remove .current from others)
|
||
document.querySelectorAll('.plan').forEach(p => {
|
||
p.classList.toggle('current', p.dataset.tier === tier);
|
||
if (p.dataset.tier === tier) p.classList.remove('sel');
|
||
});
|
||
if (tier === 'free') selectPlan('max');
|
||
else if (tier === 'pro') selectPlan('max');
|
||
else selectPlan('max');
|
||
}
|
||
|
||
// fake oracle refresh countdown (visual only)
|
||
let refreshLeft = 286;
|
||
setInterval(() => {
|
||
refreshLeft = refreshLeft > 0 ? refreshLeft - 1 : 300;
|
||
const m = Math.floor(refreshLeft / 60);
|
||
const s = refreshLeft % 60;
|
||
const el = document.getElementById('oracle-refresh');
|
||
if (el) el.textContent = String(m).padStart(2,'0') + ':' + String(s).padStart(2,'0');
|
||
}, 1000);
|
||
|
||
setState('free');
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|