sirius/portal.html
Local Dev 8ee9fc1a63 fix(studio): open the page the name actually serves, not an empty folder
Sirius Studio only looked in its own folder, bns/<name>/. Every site
published the conventional way lives at bns/<label>/ (the s3 record),
or inline in the h record, so the editor opened those names as "new
site" with a template picker instead of the current build.

The gateway's site read gains a read-only ?src=live view that follows
the on-chain record: list and fetch from whatever bucket s3 points at,
or serve the h HTML as index.html. Writes are unchanged and still
confined to bns/<name>/.

The editor now starts from the live page when there is no draft:
relative image and link URLs are resolved against the public site URL,
stylesheets are inlined (cross-origin ones such as font CDNs are kept
as links and re-emitted on export), scripts dropped. When a draft
exists but the name serves something else, or index.html on Sia is
newer than the draft, a notice says so with a one-click import. An
"Import live site" button is always available. Verified with
aloevera.test, which is hosted at bns/aloevera/.
2026-09-20 01:22:21 +02:00

687 lines
45 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dashboard — your names on Sirius.X</title>
<meta name="description" content="Manage every BCNR name and TLD your wallet holds: DNS records, content, redirects, transfers, TLD pricing. Your keys never leave the browser.">
<link rel="icon" href="./assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="./assets/favicon.svg" color="#d6ff3d">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Sirius.X">
<meta property="og:title" content="Sirius.X dashboard — your BCNR names">
<meta property="og:description" content="Manage DNS, content, redirects and TLD policy for every name your wallet holds. Keys never leave the browser.">
<meta property="og:url" content="https://silentmode.st/sirius-x/portal.html">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta name="twitter:card" content="summary">
<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&family=Ubuntu:wght@400;500;700&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;
--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)}
html[data-font-cmp="ubuntu"] body,
html[data-font-cmp="ubuntu"] h1, html[data-font-cmp="ubuntu"] h2, html[data-font-cmp="ubuntu"] h3,
html[data-font-cmp="ubuntu"] p, html[data-font-cmp="ubuntu"] a, html[data-font-cmp="ubuntu"] button,
html[data-font-cmp="ubuntu"] span, html[data-font-cmp="ubuntu"] div,
html[data-font-cmp="ubuntu"] label, html[data-font-cmp="ubuntu"] input, html[data-font-cmp="ubuntu"] li{
font-family:'Ubuntu',system-ui,sans-serif !important
}
html[data-font-cmp="ubuntu"] code, html[data-font-cmp="ubuntu"] .mono{font-family:var(--mono) !important}
.font-picker{display:inline-flex;align-items:center;gap:2px;padding:2px;margin:0 10px;
background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:999px;
font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase}
.font-picker button{background:transparent;border:none;color:var(--dim);
padding:4px 10px;border-radius:999px;cursor:pointer;font-family:inherit;font-size:inherit;
letter-spacing:inherit;text-transform:inherit;transition:color .12s}
.font-picker button:hover{color:var(--ink)}
.font-picker button.active{background:var(--acid);color:var(--bg);font-weight:600}
a{color:var(--acid)}
.wrap{max-width:820px;margin:0 auto;padding:0 1.2rem}
.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);border-bottom:1px solid var(--line)}
.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}
.topnav a.portal:hover{background:rgba(214,255,61,.18)}
header.hero{text-align:center;padding:3rem 1.2rem 1rem}
.mark{font-size:44px;line-height:1}
h1{font-size:clamp(1.6rem,4.5vw,2.2rem);margin:.3rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1rem;max-width:580px;margin:0 auto}
h2{font-size:1.35rem;margin:0 0 .3rem}
h3{font-size:1.05rem;margin:0 0 .3rem}
section{padding:2rem 0;border-top:1px solid var(--line);margin-top:2rem}
section:first-of-type{border-top:none;margin-top:1rem}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:20px 22px;margin-top:1rem}
label{display:block;font-size:13px;color:var(--mut);margin:14px 0 5px}
textarea,input[type=password],input[type=text],input[type=number],select{
width:100%;padding:10px 12px;border-radius:10px;border:1px solid #ffffff22;background:#0e131b;
color:var(--ink);font-size:14px;font-family:inherit;outline:none
}
select{appearance:auto}
textarea{min-height:74px;resize:vertical;font-family:var(--mono);font-size:13px}
textarea:focus,input:focus,select:focus{border-color:#4b7bec}
.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}
.row{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px;align-items:center}
.row.end{justify-content:flex-end}
.row.between{justify-content:space-between}
.muted{color:var(--mut);font-size:13px}
.dim{color:var(--dim);font-size:12.5px}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:var(--mono);font-size:12.5px;word-break:break-all}
.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)}
.err{color:var(--taken);font-size:13.5px;margin-top:10px}
.status{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 14px;font-size:13px;color:var(--mut);margin-top:12px}
.status.ok{border-left:3px solid var(--ok)}
.status.err{border-left:3px solid var(--taken);color:var(--taken)}
.hidden{display:none !important}
/* ---------- 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}
/* wide screens: let the dashboard use the width — wider sidebar, card
grids for the lists, two-column settings / TLD detail. Text blocks keep
a readable measure via .ph p max-width. */
@media (min-width:1280px){
.dash{max-width:1720px;grid-template-columns:260px minmax(0,1fr);gap:34px;padding:1.6rem 2rem 3rem}
.list.cols{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:10px;margin-top:8px}
.list.cols .drow{margin-top:0;align-content:start}
.list.cols > .empty,.list.cols > .status{grid-column:1/-1}
.grid2{grid-template-columns:repeat(auto-fit,minmax(340px,1fr))}
.pane[data-pane="settings"]:not([hidden]),.pane[data-pane="tld"]:not([hidden]){display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-content:start}
.pane[data-pane="settings"] > .ph,.pane[data-pane="tld"] > .crumbs,.pane[data-pane="tld"] > .dhead,.pane[data-pane="tld"] > .msg,.pane[data-pane="tld"] > .grid2{grid-column:1/-1}
.pane[data-pane="settings"] > .card,.pane[data-pane="tld"] > .card{margin-top:0}
.pane[data-pane="tld"] > .msg:empty{display:none}
.pane[data-pane="domain"] .sub[data-sub="summary"] > .grid2{grid-template-columns:repeat(2,minmax(0,1fr))}
.pane[data-pane="newtld"] .card{max-width:760px !important}
}
@media (min-width:1700px){
.list.cols{grid-template-columns:repeat(auto-fill,minmax(400px,1fr))}
.pane[data-pane="settings"]:not([hidden]){grid-template-columns:repeat(3,minmax(0,1fr))}
}
.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 .who .net.pending{color:var(--warn);font-size:11px}
.side .who .refresh{background:none;border:0;color:var(--dim);cursor:pointer;font-size:13px;padding:0 4px;line-height:1;vertical-align:middle}
.side .who .refresh:hover{color:var(--acid)}
.side .who .refresh.spin{animation:spin .8s linear infinite;display:inline-block}
@keyframes spin{to{transform:rotate(360deg)}}
.side .grp{font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);padding:12px 14px 4px}
.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)}
.side .sep{height:1px;background:var(--line);margin:8px 0}
.content{min-width:0}
.pane{animation:paneIn .18s ease-out}
.pane[hidden]{display:none}
@keyframes paneIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.ph{display:flex;align-items:flex-end;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:.6rem}
.ph p{margin:.2rem 0 0;color:var(--mut);font-size:13.5px;max-width:720px}
.crumbs{font-size:13px;color:var(--dim);margin-bottom:8px}
.crumbs a{color:var(--mut);text-decoration:none}
.crumbs a:hover{color:var(--ink)}
/* stats */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px;margin-top:1rem}
.stat{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px 18px}
.stat .lbl{font-family:var(--mono);font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--dim);margin-bottom:8px;display:flex;align-items:center;gap:6px}
.stat .lbl:before{content:"";width:5px;height:5px;background:var(--acid);border-radius:50%}
.stat .val{font-family:var(--serif);font-size:30px;font-weight:600;color:var(--ink);letter-spacing:-.01em;line-height:1}
.stat .sub{color:var(--mut);font-size:12.5px;margin-top:4px}
/* toolbar + lists */
.toolbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:10px 0 6px}
.toolbar input[type=text]{max-width:320px}
.toolbar select{width:auto;padding:8px 30px 8px 10px;font-size:13px}
.list{margin-top:6px}
.drow{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px 14px;align-items:center;padding:13px 16px;
background:var(--panel2);border:1px solid var(--line);border-radius:12px;margin-top:8px;cursor:pointer;transition:border-color .12s,background .12s}
.drow:hover{border-color:rgba(214,255,61,.3);background:#0c1220}
.drow .n{font-family:var(--mono);font-size:15px;color:var(--ink);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.drow .n .tld{color:var(--acid)}
.drow .meta{grid-column:1/-1;display:flex;gap:6px;flex-wrap:wrap;align-items:center;color:var(--mut);font-size:12px}
.drow .acts{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.empty{padding:26px 20px;text-align:center;color:var(--mut);border:1px dashed var(--line);border-radius:12px;margin-top:10px}
/* detail */
.dhead{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.dhead h2{font-family:var(--mono);font-size:1.5rem;margin:0}
.subtabs{display:flex;gap:4px;flex-wrap:wrap;border-bottom:1px solid var(--line);margin:14px 0 16px}
.subtabs button{background:transparent;border:0;border-bottom:2px solid transparent;color:var(--mut);padding:9px 12px;font:inherit;font-size:13.5px;cursor:pointer;margin-bottom:-1px}
.subtabs button:hover{color:var(--ink)}
.subtabs button.active{color:var(--acid);border-bottom-color:var(--acid)}
.kv{display:grid;grid-template-columns:160px minmax(0,1fr);gap:8px 14px;font-size:13.5px;margin-top:10px}
.kv .k{color:var(--dim)}
.kv .v{word-break:break-all}
.kv .v code{font-size:12px}
.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px}
.card h3{margin-top:0}
.card .hint{color:var(--dim);font-size:12.5px;margin:2px 0 0}
.field-hint{color:var(--dim);font-size:11.5px;margin-left:8px;text-transform:none;letter-spacing:0}
.budget{display:flex;justify-content:space-between;align-items:center;font-size:12px;color:var(--mut);margin-top:14px;padding:8px 12px;background:var(--panel2);border-radius:8px}
.budget.over{background:rgba(246,118,138,.15);color:var(--taken)}
.steps-log{margin-top:12px;font-family:var(--mono);font-size:12px;color:var(--mut);background:#0e131b;border:1px solid var(--line);border-radius:8px;padding:10px 12px;max-height:140px;overflow-y:auto;display:none}
.steps-log.on{display:block}
.steps-log div::before{content:" ";color:var(--acid)}
.msg{font-size:13px;margin-top:12px}
.msg.err{color:var(--taken)} .msg.ok{color:var(--ok)}
/* DNS table */
.tbl{width:100%;border-collapse:separate;border-spacing:0;margin-top:10px;font-size:13px}
.tbl th{font-family:var(--mono);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);text-align:left;padding:8px 10px;border-bottom:1px solid var(--line)}
.tbl td{padding:9px 10px;border-bottom:1px solid var(--line);vertical-align:middle}
.tbl td.t{font-family:var(--mono);color:var(--acid);width:80px}
.tbl td.v{font-family:var(--mono);word-break:break-all}
.tbl td.p{color:var(--mut);white-space:nowrap}
.tbl td.a{text-align:right;white-space:nowrap}
.tbl .x{background:none;border:0;color:var(--dim);cursor:pointer;font-size:16px;padding:2px 6px}
.tbl .x:hover{color:var(--taken)}
.addrow{display:grid;grid-template-columns:110px minmax(0,1fr) 90px 90px 90px auto;gap:8px;align-items:end;margin-top:12px;padding:12px;background:var(--panel2);border:1px solid var(--line);border-radius:10px}
.addrow label{margin:0 0 4px;font-size:11px;text-transform:uppercase;letter-spacing:.08em}
.addrow input,.addrow select{padding:8px 10px;font-size:13px}
.addrow .opt[hidden]{display:none}
.toggle{display:flex;align-items:flex-start;gap:12px;padding:12px 0;border-bottom:1px solid var(--line)}
.toggle:last-child{border-bottom:0}
.toggle .txt b{display:block;font-weight:600;font-size:14px}
.toggle .txt span{color:var(--mut);font-size:12.5px}
.toggle input[type=checkbox]{width:18px;height:18px;margin-top:3px;accent-color:var(--acid);flex:none}
.pill{display:inline-block;font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;padding:2px 8px;border-radius:999px;background:rgba(255,255,255,.06);color:var(--dim);margin-left:8px;vertical-align:middle}
/* modals kept for policy editing */
.modal{position:fixed;inset:0;background:rgba(6,9,14,.82);backdrop-filter:blur(3px);
display:none;align-items:flex-start;justify-content:center;padding:3vh 1rem;overflow-y:auto;z-index:50}
.modal.open{display:flex}
.sheet{background:var(--panel);border:1px solid var(--line);border-radius:16px;max-width:620px;width:100%;padding:24px 26px;position:relative}
.sheet h3{margin:0 0 .3rem;font-size:1.15rem;font-family:var(--mono)}
.sheet .sub{color:var(--mut);font-size:13px;margin:0 0 1.2rem}
.sheet .x{position:absolute;top:14px;right:16px;background:none;border:none;color:var(--dim);font-size:22px;cursor:pointer;line-height:1}
.sheet label{display:block;font-size:12px;color:var(--mut);margin:12px 0 4px;text-transform:uppercase;letter-spacing:.4px}
.sheet input[type=text],.sheet textarea,.sheet select{width:100%;padding:9px 12px;border-radius:8px;border:1px solid #ffffff22;background:#0e131b;color:var(--ink);font-size:13px;font-family:var(--mono);outline:none}
.sheet textarea{min-height:60px;resize:vertical}
.sheet .actions{display:flex;gap:10px;justify-content:flex-end;margin-top:16px}
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
@media (max-width:900px){
/* minmax(0,…) + min-width:0: the nowrap address must never widen the page */
.dash{grid-template-columns:minmax(0,1fr);gap:14px}
.side{position:static;flex-direction:row;flex-wrap:wrap;gap:6px;align-items:center;min-width:0}
/* one slim line: short address + live balance + refresh */
.side .who{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;margin:0 0 4px}
.side .who .lbl,.side .who .net.pending{display:none}
.side .who .addr{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0;font-size:11.5px}
.side .who .net{margin:0;white-space:nowrap}
.side .grp,.side .sep{display:none}
/* the menu becomes a row of pills (the wide-screen rule sets width:100% with higher specificity) */
.side button.item,.side a.item{width:auto;padding:7px 11px;font-size:13px;border-color:var(--line)}
.side .item .cnt{margin-left:4px}
.subtabs{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.subtabs::-webkit-scrollbar{display:none}
.subtabs button{white-space:nowrap}
.dhead h2{font-size:1.25rem}
.kv{grid-template-columns:1fr}
.addrow{grid-template-columns:1fr 1fr}
}
</style>
<script src="./js/i18n.js?v=20260920b"></script>
</head>
<body>
<nav class="topnav">
<a class="brand" href="./"><span class="g">Sirius.X</span></a>
<a href="./#try">Try it</a>
<a href="./#search-input">✏️ Register</a>
<a href="./tld.html">🌐 TLD</a>
<a href="./market.html">🛒 Market</a>
<a href="./theseus/"><svg width="14" height="14" viewBox="0 0 64 64" style="vertical-align:-2px;margin-right:4px" aria-hidden="true"><rect width="64" height="64" rx="12" fill="#0b0e14"/><path d="M32 6 L38 32 L26 32 Z" fill="#e04e4e"/><path d="M38 32 L32 58 L26 32 Z" fill="#d6ff3d"/><path d="M6 32 L32 27 L58 32 L32 37 Z" fill="#d6ff3d" opacity=".55"/><circle cx="32" cy="32" r="3" fill="#0b0e14"/></svg>Theseus</a>
<a href="./portal.html" class="portal here">🔑 Sign in</a>
</nav>
<!-- ============ signed-out: hero + inline sign-in ============ -->
<div id="signed-out">
<header class="hero">
<div class="mark">🔑</div>
<h1>Your <span class="g">names</span> dashboard</h1>
<p class="tag">Sign in once with your Bitcoin Cash seed phrase or connect an external wallet. This device
stays signed in until you sign out — no passwords on every visit. Your keys never leave this browser.</p>
</header>
<div class="wrap">
<section id="signin">
<h2>Sign in or create a wallet</h2>
<p class="muted">The same wallet that will hold your names does the signing. Pick a tab —
everything happens on this page; keys never leave your browser.</p>
<div id="signin-inline" style="margin-top:1rem"></div>
<div id="signin-err" class="err hidden"></div>
</section>
</div>
</div>
<!-- ============ signed-in: dashboard ============ -->
<div id="me" class="dash hidden">
<aside class="side" aria-label="Dashboard menu">
<div class="who">
<div class="lbl">Signed in</div>
<div class="addr" id="side-addr"></div>
<div class="net">chipnet · <span id="side-balance"></span> sat <button class="refresh" id="side-refresh" title="Refresh balance" aria-label="Refresh balance"></button></div>
<div class="net pending" id="side-pending" hidden>incl. <span id="side-pending-sats">0</span> sat unconfirmed · spendable now</div>
</div>
<button class="item" data-go="studio"><span class="ic">🎨</span>Web-Builder</button>
<button class="item active" data-go="domains"><span class="ic">🌐</span>Domain names<span class="cnt" id="cnt-names">0</span></button>
<button class="item" data-go="tlds"><span class="ic">🏷</span>My TLDs<span class="cnt" id="cnt-tlds">0</span></button>
<div class="sep"></div>
<button class="item" data-go="settings"><span class="ic"></span>Settings</button>
<a class="item hidden" id="side-admin" href="./admin/"><span class="ic">🛠</span>Admin panel</a>
<button class="item" id="side-signout"><span class="ic">🚪</span>Sign out</button>
</aside>
<main class="content">
<!-- WEB-BUILDER -->
<div class="pane" data-pane="studio" hidden>
<div class="ph"><div><h2>Web-Builder</h2><p>Sirius Studio builds a site for any name you hold: drag blocks, edit text, publish. Pages live in the name's own folder on Sia and the name points at them — no host, no renewal.</p></div>
<div class="row" style="margin:0"><button class="btn ghost small" id="refresh-btn">↻ Refresh</button></div></div>
<div class="status" id="studio-status">Loading names from the chain…</div>
<div id="studio-list" class="list cols"></div>
</div>
<!-- DOMAINS -->
<div class="pane" data-pane="domains">
<div class="ph"><div><h2>Domain names</h2><p>Every BCNR name this wallet holds. Open one to manage DNS, content, redirects or transfer it.</p></div>
<div class="row" style="margin:0"><button class="btn ghost small" id="names-refresh">↻ Refresh</button><a class="btn acid small" href="./#search-input"> Register a name</a></div></div>
<div id="ov-attention" class="list" style="margin-bottom:6px"></div>
<div class="toolbar">
<input type="text" id="dom-search" placeholder="Filter names…" autocomplete="off">
<select id="dom-sort"><option value="name">Sort: name</option><option value="tld">Sort: TLD</option><option value="height">Sort: newest</option></select>
<select id="dom-tld"><option value="">All TLDs</option></select>
<span class="dim" id="dom-count"></span>
</div>
<div class="status" id="names-status">Loading names from the chain…</div>
<div id="names-list" class="list cols"></div>
</div>
<!-- DOMAIN DETAIL -->
<div class="pane" data-pane="domain" hidden>
<div class="crumbs"><a href="#domains" data-go="domains">Domain names</a> <span id="dd-crumb"></span></div>
<div class="dhead">
<h2 id="dd-name"></h2>
<span class="badge b-x">on chain</span>
<span class="badge b-dim" id="dd-dnsbadge">no DNS</span>
<span style="margin-left:auto" class="row" style="margin:0">
<a class="btn ghost small" id="dd-view" href="#" target="_blank" rel="noopener">Open site →</a>
</span>
</div>
<div class="subtabs" role="tablist">
<button data-sub="summary" class="active">Summary</button>
<button data-sub="dns">DNS records</button>
<button data-sub="content">Content &amp; hosting</button>
<button data-sub="redirect">Redirect</button>
<button data-sub="transfer">Transfer</button>
<button data-sub="sell">Sell</button>
<button data-sub="export">Export</button>
</div>
<div class="sub" data-sub="sell" hidden>
<div class="card" style="margin-top:0">
<h3>Sell this name</h3>
<p class="hint">You sign an offer once: "whoever pays me this price gets the certificate". The offer is stored by the gateway and shown on the <a href="./market.html" target="_blank" rel="noopener">market</a>. A buyer completes it in one transaction — you are paid in the same transaction that moves the name, or not at all. No escrow, nothing to trust.</p>
<div class="status" id="sell-status">Checking the market…</div>
<div id="sell-form">
<div class="row" style="align-items:flex-end">
<div><label style="margin-top:0">Price (USD)</label><input type="text" id="sell-usd" placeholder="25" inputmode="decimal" style="max-width:160px"></div>
<div><label style="margin-top:0">Price (sat)</label><input type="text" id="sell-sats" placeholder="6250000" inputmode="numeric" style="max-width:200px"></div>
<span class="dim" id="sell-rate"></span>
</div>
<div class="row end"><button class="btn acid" id="sell-list">List for sale →</button></div>
</div>
<div id="sell-active" class="hidden">
<div class="kv" id="sell-kv"></div>
<div class="row end">
<button class="btn danger" id="sell-cancel">Cancel listing →</button>
</div>
<p class="hint">Cancelling removes the offer from the market and moves your certificate once (a no-op update, a few cents), so the signed offer can never be completed later.</p>
</div>
<div class="steps-log" id="sell-log"></div>
<div class="msg" id="sell-msg"></div>
</div>
</div>
<div class="sub" data-sub="summary">
<div class="grid2">
<div class="card" style="margin-top:0">
<h3>Certificate</h3>
<div class="kv" id="dd-kv"></div>
</div>
<div class="card" style="margin-top:0">
<h3>Where it points</h3>
<p class="hint">On-chain records decide what a resolver serves. Change them under Content &amp; hosting.</p>
<div class="kv" id="dd-records"></div>
</div>
</div>
<div class="card">
<h3>DNS at a glance</h3>
<p class="hint">Signed off-chain records for mail, verification and classic DNS interop.</p>
<div id="dd-dns-summary" class="muted" style="margin-top:8px"></div>
</div>
</div>
<div class="sub" data-sub="dns" hidden>
<div class="card" style="margin-top:0">
<div class="row between" style="margin:0">
<div><h3 style="margin:0">DNS records</h3>
<p class="hint">Standard records, signed by your key and stored in a manifest on Sia. Free to edit, no chain transaction. Resolvers and the gateway verify the signature against the current NFT holder.</p></div>
<span class="badge b-dim" id="dns-seq">seq —</span>
</div>
<table class="tbl" id="dns-table">
<thead><tr><th>Type</th><th>Value</th><th>Priority / extra</th><th></th></tr></thead>
<tbody></tbody>
</table>
<div class="empty hidden" id="dns-empty">No DNS records yet. Add the first one below.</div>
<div class="addrow">
<div><label>Type</label>
<select id="dns-type">
<option>A</option><option>AAAA</option><option>CNAME</option><option>MX</option>
<option>TXT</option><option>NS</option><option>SRV</option><option>CAA</option>
</select></div>
<div><label id="dns-value-label">Value</label><input type="text" id="dns-value" placeholder="1.2.3.4" autocomplete="off" spellcheck="false"></div>
<div class="opt" data-for="MX SRV"><label>Priority</label><input type="number" id="dns-prio" min="0" placeholder="10"></div>
<div class="opt" data-for="SRV"><label>Weight</label><input type="number" id="dns-weight" min="0" placeholder="0"></div>
<div class="opt" data-for="SRV"><label>Port</label><input type="number" id="dns-port" min="0" placeholder="443"></div>
<div class="opt" data-for="CAA"><label>Tag</label><select id="dns-tag"><option>issue</option><option>issuewild</option><option>iodef</option></select></div>
<div><label>&nbsp;</label><button class="btn small" id="dns-add"> Add</button></div>
</div>
<div class="dim" id="dns-help" style="margin-top:8px"></div>
<div class="steps-log" id="dns-log"></div>
<div class="msg" id="dns-msg"></div>
<div class="row end">
<button class="btn ghost" id="dns-reload">Discard changes</button>
<button class="btn acid" id="dns-publish">Sign &amp; publish →</button>
</div>
</div>
<div class="card">
<h3>Nameservers</h3>
<p class="hint">BCNR names do not need nameservers — resolvers read the chain and this manifest directly. Add NS records above only if you also delegate this name in classic DNS.</p>
</div>
</div>
<div class="sub" data-sub="content" hidden>
<div class="card" style="margin-top:0">
<h3>Content &amp; hosting</h3>
<p class="hint">On-chain records, published as one signed UPD transaction (a few cents of chain dust). Leave a field blank to drop that record. Precedence for resolvers: h, then s3, then p, then ip.</p>
<label>h <span class="field-hint">inline HTML — served as-is at the site root (~150 bytes)</span></label>
<textarea id="ct-h" placeholder="&lt;h1&gt;My site&lt;/h1&gt;"></textarea>
<label>s3 <span class="field-hint">Sia bucket key, trailing slash for directories — also where DNS manifests live</span></label>
<input type="text" id="ct-s3" placeholder="bns/myname/">
<label>p <span class="field-hint">reverse proxy: full upstream URL the gateway mirrors</span></label>
<input type="text" id="ct-p" placeholder="https://origin.example.com">
<label>ip <span class="field-hint">IPv4 that serves this name over Host header</span></label>
<input type="text" id="ct-ip" placeholder="1.2.3.4">
<label>tls <span class="field-hint">SHA-256 of your leaf cert — chain-pinned TLS trust</span></label>
<input type="text" id="ct-tls" placeholder="hex — 64 chars, no separators">
<div class="budget" id="ct-budget">payload: <b><span id="ct-budget-used">0</span></b> / <span id="ct-budget-max">?</span> bytes</div>
<div class="steps-log" id="ct-log"></div>
<div class="msg" id="ct-msg"></div>
<div class="row end">
<button class="btn ghost" id="ct-reset">Reset</button>
<button class="btn acid" id="ct-save">Save records →</button>
</div>
</div>
</div>
<div class="sub" data-sub="redirect" hidden>
<div class="card" style="margin-top:0">
<h3>Redirect</h3>
<p class="hint">Forward this name to any web address. Stored on chain as the <b>u</b> record; resolvers and the gateway issue the redirect. Clear it to stop forwarding.</p>
<label>Destination URL</label>
<input type="text" id="rd-url" placeholder="https://example.com/">
<div class="steps-log" id="rd-log"></div>
<div class="msg" id="rd-msg"></div>
<div class="row end">
<button class="btn ghost" id="rd-clear">Remove redirect</button>
<button class="btn acid" id="rd-save">Save redirect →</button>
</div>
</div>
</div>
<div class="sub" data-sub="transfer" hidden>
<div class="card" style="margin-top:0">
<h3>Transfer ownership</h3>
<p class="hint">Moves the name's certificate to another Bitcoin Cash address in one transaction. Records stay as they are. The new holder controls the name from that moment — this cannot be undone from here.</p>
<label>Recipient address <span class="field-hint">bchtest:… (chipnet)</span></label>
<input type="text" id="tr-addr" placeholder="bchtest:q…" autocomplete="off" spellcheck="false">
<label style="display:flex;align-items:center;gap:8px;margin-top:12px"><input type="checkbox" id="tr-ack" style="width:16px;height:16px;accent-color:var(--acid)"> I understand this hands the name to that address permanently.</label>
<div class="steps-log" id="tr-log"></div>
<div class="msg" id="tr-msg"></div>
<div class="row end"><button class="btn danger" id="tr-send" disabled>Transfer name →</button></div>
</div>
</div>
<div class="sub" data-sub="export" hidden>
<div class="card" style="margin-top:0">
<h3>Export</h3>
<p class="hint">Download this name's DNS as a BIND-style zone file, or its full record set as JSON, for backups or importing elsewhere.</p>
<div class="row">
<button class="btn ghost small" id="ex-zone">⬇ Zone file (.txt)</button>
<button class="btn ghost small" id="ex-json">⬇ Records (.json)</button>
<button class="btn ghost small" id="ex-copy">Copy DNS manifest</button>
</div>
<pre class="mono" id="ex-preview" style="margin-top:12px;padding:12px;white-space:pre-wrap;font-size:12px;max-height:280px;overflow:auto"></pre>
</div>
</div>
</div>
<!-- TLDs -->
<div class="pane" data-pane="tlds" hidden>
<div class="ph"><div><h2>My TLDs</h2><p>Every per-TLD registry NFT this wallet holds. Set the price every name under a TLD sells for, switch it on or off (off = private: only you can register under it), and tune policy. Each change is one signed TUPD on chain; you receive 90% of every sale.</p></div>
<button class="btn acid small" data-go="newtld"> Register a TLD</button></div>
<div class="status" id="tlds-status">Loading TLDs from the chain…</div>
<div id="tlds-list" class="list cols"></div>
</div>
<!-- TLD DETAIL -->
<div class="pane" data-pane="tld" hidden>
<div class="crumbs"><a href="#tlds" data-go="tlds">My TLDs</a> <span id="td-crumb"></span></div>
<div class="dhead">
<h2 id="td-name">.—</h2>
<span class="badge" id="td-state">on</span>
<span class="badge b-x" id="td-price">tier pricing</span>
<span style="margin-left:auto"></span>
<button class="btn ghost small" id="td-toggle">Switch off</button>
<button class="btn acid small" id="td-policy">Price &amp; policy</button>
</div>
<div class="msg" id="td-msg"></div>
<div class="grid2" style="margin-top:14px">
<div class="card" style="margin-top:0">
<h3>Registry</h3>
<div class="kv" id="td-kv"></div>
</div>
<div class="card" style="margin-top:0">
<h3>Register a name under this TLD</h3>
<p class="hint">Works whether the TLD is on or off. As the owner you pay only the platform's 10% share.</p>
<div class="row" style="margin-top:10px">
<input type="text" id="td-label" placeholder="label" maxlength="32" autocomplete="off" spellcheck="false" style="max-width:220px">
<span class="mono" id="td-suffix">.—</span>
<button class="btn small acid" id="td-register">Register →</button>
</div>
</div>
</div>
<div class="card" id="td-cosign-card">
<h3>Pending approvals</h3>
<p class="hint">Registrations under this TLD that wait for your co-signature. Approving signs your TLD certificate into the buyer's transaction and broadcasts it; the certificate returns to you in the same transaction. Nothing can be registered under a co-sign or private TLD without this step.</p>
<div id="td-cosign" class="list"></div>
<div class="msg" id="td-cosign-msg"></div>
</div>
<div class="card">
<h3>Names registered under this TLD</h3>
<p class="hint">Everyone's registrations, from the public registry.</p>
<div id="td-names" class="list cols"></div>
</div>
</div>
<!-- NEW TLD -->
<div class="pane" data-pane="newtld" hidden>
<div class="ph"><div><h2>Register a TLD</h2><p>TLDs are per-registry NFTs on the chipnet TLD beacon. Public mints pay a service fee that funds the registry. Chipnet uses a placeholder rate; mainnet prices by label length via a real oracle.</p></div></div>
<div class="card" id="tld-register-card" style="margin-top:0;max-width:640px">
<label>Label <span class="dim" style="margin-left:6px">116 chars, [a-z0-9-]</span></label>
<input type="text" id="tld-label" placeholder="myregistry" autocomplete="off" spellcheck="false" maxlength="16">
<label style="margin-top:12px">Service fee (USD) <span class="dim" style="margin-left:6px">chipnet test rate</span></label>
<input type="text" id="tld-usd" value="5">
<div class="status" id="tld-price">= <b>0</b> sats · rate <b>0</b> sats/USD</div>
<div class="row">
<button class="btn ghost small" id="tld-check" disabled>Check availability</button>
<button class="btn acid small" id="tld-submit" disabled>Register (~0 sats)</button>
</div>
<div id="tld-log" class="status" style="display:none;font-family:var(--mono);font-size:12.5px;margin-top:12px"></div>
<div id="tld-msg" style="margin-top:10px;font-size:13.5px"></div>
</div>
</div>
<!-- SETTINGS -->
<div class="pane" data-pane="settings" hidden>
<div class="ph"><div><h2>Settings</h2><p>Session, security and wallet details for this browser. Nothing here changes what is on chain.</p></div></div>
<div class="card" style="margin-top:0">
<h3>Session</h3>
<div class="toggle"><input type="checkbox" id="set-stay"><div class="txt"><b>Stay signed in on this device</b><span>Your recovery phrase is kept encrypted under a key this browser holds and cannot export. Next visits open the dashboard straight away. Turn off to be asked for your password or PIN every time.</span></div></div>
<div class="toggle"><input type="checkbox" id="set-pinpay"><div class="txt"><b>Ask for PIN before payments</b><span>Adds a PIN prompt when registering a name or TLD. Off by default so signed-in sessions run uninterrupted.</span></div></div>
<div class="row">
<button class="btn ghost small" id="set-setpin">Set / change PIN</button>
<button class="btn ghost small" id="set-clearpin">Remove PIN</button>
<span class="dim" id="set-pinstate"></span>
</div>
</div>
<div class="card">
<h3>Wallet</h3>
<p class="hint">Your addresses and current balance. Keys stay in this browser.</p>
<label>Receive address <span class="dim" style="margin-left:6px">chipnet</span></label>
<div><code id="me-addr"></code> <button class="btn ghost small" data-copy="me-addr">Copy</button></div>
<label style="margin-top:14px">Token address <span class="dim" style="margin-left:6px">holds your name certificates</span></label>
<div><code id="me-taddr"></code> <button class="btn ghost small" data-copy="me-taddr">Copy</button></div>
<div class="row between">
<span class="dim" id="me-info"></span>
<span class="row" style="margin:0">
<a class="btn ghost small" href="https://tbch.googol.cash/" target="_blank" rel="noopener">Faucet →</a>
<a class="btn ghost small" href="https://chipnet.imaginary.cash/faucet" target="_blank" rel="noopener">Faucet 2 →</a>
</span>
</div>
<div class="kv" style="margin-top:14px"><div class="k">Spendable</div><div class="v" id="w-sats"></div><div class="k">UTXOs</div><div class="v" id="w-utxos"></div><div class="k">Watched addresses</div><div class="v" id="w-watched"></div><div class="k">Chain height</div><div class="v" id="stat-height"></div></div>
</div>
<div class="card">
<h3>Reading, language &amp; help</h3>
<p class="hint">Font pill and language picker live in the top bar; both are remembered per browser. The technical documentation is at <a href="./docs/" target="_blank" rel="noopener">sirius-x/docs</a>.</p>
</div>
<div class="card">
<h3>This device</h3>
<p class="hint">Sign out keeps the encrypted wallet on this device so you can unlock it later. Forget removes it entirely — you will need your recovery phrase to come back.</p>
<div class="row">
<button class="btn ghost small" id="set-signout">Sign out</button>
<button class="btn danger small" id="set-forget">Forget wallet on this device</button>
</div>
<div class="msg" id="set-msg"></div>
</div>
</div>
</main>
</div>
<!-- TLD-policy editor modal — signs a TUPD against the TREG NFT. -->
<div class="modal" id="tld-editor">
<div class="sheet">
<button class="x" id="tld-ed-close" title="close">×</button>
<h3>Policy for <span id="tld-ed-name" style="color:var(--acid);font-family:var(--mono)">.—</span></h3>
<p class="sub">Set policy for names registered under this TLD. Only your key can sign this TUPD;
the transaction fee is a few cents in chain dust. Leave a field blank to omit that policy
(defaults apply — open policy, tier pricing).</p>
<label>price <span class="field-hint">USD per name — flat, shown to every buyer; blank = length tiers. You receive 90% of each sale.</span></label>
<input type="text" id="tld-ed-price" placeholder="7" inputmode="decimal">
<label>listing <span class="field-hint">off hides the TLD from search and blocks new registrations until you switch it back on</span></label>
<select id="tld-ed-hidden">
<option value="">On — listed, names for sale</option>
<option value="1">Off — hidden, not for sale</option>
</select>
<label>min_len <span class="field-hint">reject names shorter than N chars</span></label>
<input type="text" id="tld-ed-minlen" placeholder="1">
<label>fee_bps <span class="field-hint">service fee owner takes, in basis points (500 = 5%)</span></label>
<input type="text" id="tld-ed-feebps" placeholder="500">
<label>policy <span class="field-hint">open · frozen · reserved-only</span></label>
<input type="text" id="tld-ed-policy" placeholder="open">
<label>reserved <span class="field-hint">space-separated labels only owner can mint</span></label>
<input type="text" id="tld-ed-reserved" placeholder="admin root bank">
<label>renewal_period <span class="field-hint">days between renewals, 0 = never expire</span></label>
<input type="text" id="tld-ed-renewal" placeholder="0">
<label>renewal_fee <span class="field-hint">renewal price in sats, 0 = free</span></label>
<input type="text" id="tld-ed-renewalfee" placeholder="0">
<label>site <span class="field-hint">where the TLD's own landing lives</span></label>
<input type="text" id="tld-ed-site" placeholder="https://silentmode.st/…">
<div class="budget" id="tld-ed-budget">payload: <b><span id="tld-ed-budget-used">0</span></b> / <span id="tld-ed-budget-max">?</span> bytes</div>
<div class="steps-log" id="tld-ed-log"></div>
<div class="msg" id="tld-ed-msg"></div>
<div class="actions">
<button class="btn ghost" id="tld-ed-cancel">Cancel</button>
<button class="btn acid" id="tld-ed-save">Save policy →</button>
</div>
</div>
</div>
<!-- PIN setup modal (Settings) -->
<div class="modal" id="pin-modal">
<div class="sheet" style="max-width:440px">
<button class="x" id="pin-close" title="close">×</button>
<h3>Set a PIN</h3>
<p class="sub">46 digits. Encrypts your recovery phrase under this PIN on this device. Three wrong PINs clear it and fall back to your password.</p>
<label>PIN</label><input type="text" id="pin-1" inputmode="numeric" pattern="[0-9]*" maxlength="6" autocomplete="off">
<label>Repeat PIN</label><input type="text" id="pin-2" inputmode="numeric" pattern="[0-9]*" maxlength="6" autocomplete="off">
<div class="msg" id="pin-msg"></div>
<div class="actions"><button class="btn ghost" id="pin-cancel">Cancel</button><button class="btn acid" id="pin-save">Save PIN →</button></div>
</div>
</div>
<footer id="site-footer"></footer>
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
<script src="./js/session.js?v=20260917dash"></script>
<script src="./js/pin-escrow.js?v=20260909pin"></script>
<script src="./js/pricing.js?v=20260917market"></script>
<script type="module" src="./js/dashboard.js?v=20260917bal"></script>
<script defer src="./js/theme.js?v=20260910font"></script>
<script defer src="./js/site-footer.js?v=20260917market"></script>
<script type="module" src="./js/register-flow.js?v=20260917bal"></script>
<script defer src="./js/profile-menu.js?v=20260920m"></script>
</body>
</html>