Compare commits

...

No commits in common. "cc4e36d7fb47ef2f5fe97153d4095c8b8e39ffa7" and "1b52c8dd83ac0f71838fba010adc8ffd78ff916d" have entirely different histories.

68 changed files with 11555 additions and 753 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
# Regenerated on each publish; the source of truth is the working repo itself.
repo/silent-mode.bundle
repo/silent-mode.git/
docs/INSTRUCTIONS.md

394
admin/index.html Normal file
View file

@ -0,0 +1,394 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Admin — Sirius.X</title>
<meta name="description" content="Sirius.x operator admin — mint TLDs, manage the registry, verify chain health. Operator-key gated.">
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="../assets/favicon.svg" color="#d6ff3d">
<meta name="robots" content="noindex,nofollow">
<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);
--ink:#f1f4fa; --mut:#b8c2d4; --dim:#6a7488; --acid:#d6ff3d;
--ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
}
*{box-sizing:border-box}
body{margin:0;background:radial-gradient(ellipse 1200px 600px at 50% -5%,#131a2a 0%,transparent 60%),radial-gradient(ellipse 900px 500px at 100% 100%,#0a0f1c 0%,transparent 55%),radial-gradient(ellipse 900px 500px at 0% 100%,#0c1424 0%,transparent 55%),var(--bg);
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:900px;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)}
.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:2.8rem 1.2rem 1rem}
.mark{font-size:40px;line-height:1}
h1{font-size:clamp(1.5rem,4vw,2rem);margin:.3rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:.98rem;max-width:600px;margin:0 auto}
h2{font-size:1.2rem;margin:0 0 .35rem}
h3{font-size:.98rem;margin:0 0 .3rem;font-family:ui-monospace,monospace}
section{padding:1.8rem 0;border-top:1px solid var(--line);margin-top:1.6rem}
section:first-of-type{border-top:none;margin-top:.8rem}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px 18px;margin-top:.8rem}
label{display:block;font-size:11.5px;color:var(--mut);margin:12px 0 4px;text-transform:uppercase;letter-spacing:.4px}
.field-hint{color:var(--dim);font-size:11px;margin-left:8px;text-transform:none;letter-spacing:0}
input[type=text],textarea{
width:100%;padding:9px 12px;border-radius:8px;border:1px solid #ffffff22;background:#0e131b;
color:var(--ink);font-size:13px;font-family:ui-monospace,monospace;outline:none
}
textarea{min-height:68px;resize:vertical}
input:focus,textarea:focus{border-color:#4b7bec}
.btn{display:inline-block;text-decoration:none;padding:9px 16px;border-radius:9px;background:#4b7bec;color:#fff;font-size:13px;border:none;cursor:pointer;font-family:inherit}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn.small{padding:5px 10px;font-size:12px}
.btn:hover{filter:brightness(1.12)}
.btn:disabled{opacity:.45;cursor:not-allowed}
.row{display:flex;gap:9px;flex-wrap:wrap;margin-top:12px;align-items:center}
code{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:12.5px;word-break:break-all}
.status{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 14px;font-size:13px;color:var(--mut);margin-top:10px}
.status.ok{border-left:3px solid var(--ok)}
.status.err{border-left:3px solid var(--taken);color:var(--taken)}
.status.warn{border-left:3px solid var(--warn);color:var(--warn)}
.hidden{display:none}
.badge{display:inline-block;font-size:10.5px;padding:2px 8px;border-radius:999px;font-weight:600;letter-spacing:.3px}
.b-op{background:rgba(214,255,61,.14);color:var(--acid)}
.b-other{background:rgba(139,152,169,.14);color:var(--mut)}
.b-mem{background:rgba(255,199,95,.14);color:var(--warn)}
table.tlds{width:100%;border-collapse:collapse;margin-top:1rem;font-size:13px}
table.tlds th,table.tlds td{padding:8px 10px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
table.tlds th{color:var(--mut);font-weight:500;font-size:11.5px;text-transform:uppercase;letter-spacing:.4px}
table.tlds .tld{font-family:ui-monospace,monospace;color:var(--acid);font-size:13.5px;font-weight:600}
table.tlds .cat{font-family:ui-monospace,monospace;color:var(--mut);font-size:11.5px}
table.tlds .records{font-family:ui-monospace,monospace;color:var(--dim);font-size:11.5px;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.steps-log{margin-top:10px;font-family:ui-monospace,monospace;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:10px}
.msg.ok{color:var(--ok)} .msg.err{color:var(--taken)}
footer{border-top:1px solid var(--line);padding:1.8rem 0 3rem;color:var(--dim);font-size:12.5px;text-align:center;margin-top:2rem}
/* Deviant-family fonts + Fraunces/Ubuntu reader toggle. */
h1,h2,h3{font-family:'Fraunces',Georgia,serif;font-feature-settings:"ss01","ss02"}
code,.mono{font-family:'JetBrains Mono',ui-monospace,monospace}
body{font-family:'DM Sans','Inter',system-ui,sans-serif !important;font-feature-settings:"ss01","ss02"}
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:'JetBrains Mono',ui-monospace,monospace !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:'JetBrains Mono',monospace;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}
.font-picker button:hover{color:var(--ink)}
.font-picker button.active{background:var(--acid);color:var(--bg);font-weight:600}
</style>
</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="../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"/><circle cx="32" cy="32" r="3" fill="#0b0e14"/></svg>Theseus</a>
<a href="./" class="here">🛠 Admin</a>
<a href="../portal.html" class="portal">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">🛠</div>
<h1><span class="g">Admin</span> panel</h1>
<p class="tag">Operator-side tools: mint new TLDs, browse the registry, verify chain health.
Sign in with the wallet the ecosystem knows as the operator; unfamiliar wallets get
read-only access to the registry.</p>
</header>
<div class="wrap">
<section id="signin">
<h2>Sign in</h2>
<p class="status">Chipnet-only. Keys stay in this browser tab; a mint transaction is signed
locally and broadcast direct to the electrum. Operator gate is client-side — the covenant
that enforces it on-chain is a mainnet requirement (Decentralized.DNS/DESIGN-tld-registry.md §5.2).</p>
<div class="card">
<label for="seed">Recovery phrase</label>
<textarea id="seed" placeholder="word1 word2 … word12" spellcheck="false" autocomplete="off"></textarea>
<div class="row">
<button class="btn acid" id="signin-btn">Sign in →</button>
<span class="field-hint" id="signin-hint">seed stays in memory only</span>
</div>
<div id="signin-err" class="msg err hidden"></div>
</div>
</section>
<section id="me" class="hidden">
<h2>Signed in <span class="badge b-op" id="me-role" style="margin-left:8px">operator</span></h2>
<div class="card">
<label>Address</label>
<div><code id="me-addr">—</code></div>
<label style="margin-top:12px">Token address (holds the TLD certificates)</label>
<div><code id="me-taddr">—</code></div>
<div class="row">
<button class="btn ghost small" id="signout-btn">Sign out</button>
</div>
</div>
</section>
<section id="mint" class="hidden">
<h2>Mint a new TLD</h2>
<p class="tag" style="max-width:none">Adds a per-TLD certificate to the TLD beacon. The cert
lands in your token address. Cost is chain fees + beacon dust (~1,300 chipnet sats).</p>
<div class="card">
<label>TLD label <span class="field-hint">1–16 chars, [a-z0-9-]</span></label>
<input type="text" id="mint-tld" placeholder="e.g. shop, dao, wiki" maxlength="16">
<label>Records JSON <span class="field-hint">optional; leave empty for defaults</span></label>
<textarea id="mint-records" placeholder='e.g. {"policy":"open","fee_bps":500}'>{}</textarea>
<div class="row">
<button class="btn acid" id="mint-btn">Mint TLD →</button>
<span class="field-hint" id="mint-hint"></span>
</div>
<div class="steps-log" id="mint-log"></div>
<div class="msg" id="mint-msg"></div>
</div>
</section>
<section id="registry">
<h2>TLD registry</h2>
<p class="tag" style="max-width:none;font-size:.92rem">Every TLD registered on the beacon. Operators
(signed-in) can toggle a TLD's visibility on the public /api/tlds listing — hidden TLDs stop
appearing in the name-search UIs, but on-chain registrations under them keep resolving.</p>
<div class="card" id="op-token-card" style="margin-top:.8rem">
<label>Operator token <span class="field-hint">stored per browser tab, not sent anywhere except the /api/tld-visibility POST</span></label>
<input type="password" id="op-token" placeholder="paste BNS_OPERATOR_TOKEN">
<div class="row">
<button class="btn ghost small" id="op-token-save">Save token</button>
<span id="op-token-msg" class="dim"></span>
</div>
</div>
<div class="status" id="registry-status">Loading current registry…</div>
<div id="registry-table"></div>
</section>
</div>
<footer id="site-footer"></footer>
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
<script type="module">
// Cache-buster bump when the bundle changes (Chrome's ES-module map caches
// aggressively per plain URL). Portal.html has the same pattern.
import * as BNS from "https://silentmode.st/js/bns-register.js?v=20260908split";
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s).replace(/[&<>"']/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[c]));
// Operator gate: address that owns the chipnet TLD beacon + seeded TLDs.
// Client-side only — the covenant that enforces this on-chain lands with the
// mainnet TLD-registry work. For chipnet this is honour-system; a curious
// visitor can bypass by pasting any seed, but non-operator UPDs/TREGs won't
// carry the countersignature future clients will check.
const OPERATOR_ADDRESS = "bchtest:qzew3dqcsj0guwe5y3uxf9q2xs5ajgy9lca4z093cu";
let wallet = null;
let isOperator = false;
// ---------- sign in ----------
$("signin-btn").addEventListener("click", async () => {
const btn = $("signin-btn");
const errBox = $("signin-err");
errBox.classList.add("hidden");
const raw = $("seed").value.trim();
if (!raw) { errBox.textContent = "Enter your seed phrase."; errBox.classList.remove("hidden"); return; }
btn.disabled = true; btn.textContent = "Unlocking…";
try {
wallet = await BNS.BuiltInWallet.fromMnemonic(raw);
} catch (e) {
errBox.textContent = "Could not unlock: " + (e.message || e);
errBox.classList.remove("hidden");
btn.disabled = false; btn.textContent = "Sign in →";
return;
}
$("seed").value = "";
btn.disabled = false; btn.textContent = "Sign in →";
isOperator = wallet.address === OPERATOR_ADDRESS;
await enterAdmin();
});
$("signout-btn").addEventListener("click", () => {
wallet = null; isOperator = false;
$("me").classList.add("hidden");
$("mint").classList.add("hidden");
$("signin").classList.remove("hidden");
});
async function enterAdmin() {
$("signin").classList.add("hidden");
$("me").classList.remove("hidden");
$("me-addr").textContent = wallet.address;
$("me-taddr").textContent = wallet.tokenAddress;
const role = $("me-role");
role.textContent = isOperator ? "operator" : "read-only";
role.className = "badge " + (isOperator ? "b-op" : "b-other");
if (isOperator) {
$("mint").classList.remove("hidden");
}
}
// ---------- operator token ----------
// Stored in sessionStorage so refreshing the tab keeps the token for the
// session but a full browser close forgets it. Not localStorage — the
// weaker persistence is the right default for a POST-write credential.
const opToken = () => { try { return sessionStorage.getItem("bnsOperatorToken") || ""; } catch { return ""; } };
function setOpTokenMsg(text, ok) {
const el = $("op-token-msg"); el.textContent = text;
el.style.color = ok === true ? "var(--ok)" : ok === false ? "var(--taken)" : "var(--dim)";
}
$("op-token").value = opToken();
$("op-token-save").addEventListener("click", () => {
try { sessionStorage.setItem("bnsOperatorToken", $("op-token").value.trim()); } catch {}
setOpTokenMsg(opToken() ? "saved for this session" : "cleared", opToken() ? true : null);
});
// ---------- TLD registry with hide/unhide ----------
// Fetches BOTH /api/tlds?include_hidden=1 (so we see the hidden ones the
// public listing filters out) and the current /api/tld-visibility. Renders
// one row per TLD with a checkbox for the hidden flag — flipping it POSTs
// to /api/tld-visibility with the operator token.
async function loadRegistry() {
const status = $("registry-status");
const table = $("registry-table");
status.className = "status";
status.textContent = "Loading current registry from the chain…";
table.innerHTML = "";
try {
const [rTlds, rVis] = await Promise.all([
fetch("https://silentmode.st/api/tlds?include_hidden=1"),
fetch("https://silentmode.st/api/tld-visibility"),
]);
if (!rTlds.ok) throw new Error("api/tlds " + rTlds.status);
if (!rVis.ok) throw new Error("api/tld-visibility " + rVis.status);
const body = await rTlds.json();
const vis = await rVis.json();
const hidden = new Set(vis.hidden || []);
const tlds = (body.tlds || []).sort((a, b) => a.tld.localeCompare(b.tld));
status.className = "status ok";
status.textContent = `${tlds.length} TLDs on the beacon · ${hidden.size} hidden from public listing`;
let html = '<table class="tlds"><thead><tr><th>TLD</th><th>Names</th><th>Advertised</th><th>Hidden from public</th></tr></thead><tbody>';
for (const t of tlds) {
const isHidden = hidden.has(t.tld);
html += `<tr>
<td class="tld">.${esc(t.tld)}</td>
<td class="cat">${t.registered_count ?? 0}</td>
<td class="cat">${t.in_advertised ? "yes" : ""}</td>
<td><label class="row" style="gap:6px;margin:0;font-size:12.5px;color:var(--mut)">
<input type="checkbox" data-hide-tld="${esc(t.tld)}" ${isHidden ? "checked" : ""}>
${isHidden ? '<span class="badge b-mem">hidden</span>' : '<span class="dim">public</span>'}
</label></td>
</tr>`;
}
html += "</tbody></table>";
table.innerHTML = html;
// Wire visibility checkboxes.
table.querySelectorAll("input[data-hide-tld]").forEach((cb) => {
cb.addEventListener("change", async (e) => {
const tld = e.target.getAttribute("data-hide-tld");
const hide = e.target.checked;
if (!opToken()) {
e.target.checked = !hide;
setOpTokenMsg("paste your operator token first — required for /api/tld-visibility writes", false);
return;
}
e.target.disabled = true;
try {
const r = await fetch("https://silentmode.st/api/tld-visibility", {
method: "POST",
headers: { "content-type": "application/json", authorization: "Bearer " + opToken() },
body: JSON.stringify({ tld, hide }),
});
if (!r.ok) {
const j = await r.json().catch(() => ({}));
throw new Error(j.error || "http " + r.status);
}
setOpTokenMsg(`.${tld} is now ${hide ? "hidden" : "public"}`, true);
setTimeout(loadRegistry, 400); // refresh row states + counts
} catch (err) {
e.target.checked = !hide;
setOpTokenMsg("update failed: " + err.message, false);
} finally {
e.target.disabled = false;
}
});
});
} catch (e) {
status.className = "status err";
status.textContent = "Could not load registry: " + (e.message || e);
}
}
loadRegistry();
// ---------- mint a new TLD ----------
$("mint-btn").addEventListener("click", async () => {
if (!wallet || !isOperator) return;
const tld = $("mint-tld").value.trim().toLowerCase();
if (!/^[a-z0-9-]{1,16}$/.test(tld)) {
$("mint-msg").className = "msg err";
$("mint-msg").textContent = "TLD label must be 1–16 chars [a-z0-9-]";
return;
}
let records = {};
const rawRecords = $("mint-records").value.trim();
if (rawRecords) {
try { records = JSON.parse(rawRecords); }
catch (e) { $("mint-msg").className = "msg err"; $("mint-msg").textContent = "Records JSON is invalid: " + e.message; return; }
}
const btn = $("mint-btn");
const msg = $("mint-msg");
const log = $("mint-log");
log.className = "steps-log on"; log.innerHTML = "";
msg.textContent = ""; msg.className = "msg";
const push = (t) => { const d = document.createElement("div"); d.textContent = t; log.appendChild(d); log.scrollTop = log.scrollHeight; };
btn.disabled = true; btn.textContent = "Signing…";
let el = null;
try {
el = await BNS.connect();
push("connected to chipnet");
const res = await BNS.registerTldWithBuiltInWallet(el, {
wallet, tld, records,
onProgress: (step) => push(step),
});
push("broadcast: " + (res.txid || res.txId || "(unknown)"));
msg.className = "msg ok";
msg.textContent = "Minted .${tld}. Category " + (res.category || "unknown") + ". Registry refresh below in ~30s.";
btn.textContent = "Mint TLD →"; btn.disabled = false;
$("mint-tld").value = "";
$("mint-records").value = "{}";
setTimeout(loadRegistry, 3000);
} catch (e) {
msg.className = "msg err";
msg.textContent = "Mint failed: " + (e.message || e);
push("error: " + (e.message || e));
btn.disabled = false; btn.textContent = "Mint TLD →";
} finally {
try { el?.close?.(); } catch {}
}
});
</script>
<script src="../js/pin-escrow.js?v=20260909pin"></script>
<script src="../js/pricing.js?v=20260909tldhigh"></script>
<script defer src="../js/site-footer.js?v=20260907rel"></script>
<script defer src="../js/theme.js?v=20260910font"></script>
<script defer src="../js/profile-menu.js?v=20260908tabs"></script>
</body>
</html>

View file

@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<!-- sirius.x — brightest-star favicon. Rounded dark square + 4-point sparkle
<!-- Sirius.X — brightest-star favicon. Rounded dark square + 4-point sparkle
in the Silent Mode acid green so it reads clearly at 16x16 tab-icon size
while staying legible against both light and dark browser chromes. -->
<rect width="64" height="64" rx="12" fill="#0b0e14"/>

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 473 B

View file

@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="sirius.x">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="Sirius.X">
<path d="M32 12 L35.3 30.7 L54 34 L35.3 37.3 L32 56 L28.7 37.3 L10 34 L28.7 30.7 Z"
fill="#d6ff3d"/>
<text x="72" y="42" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="28" font-weight="600" fill="#e7eaf1" letter-spacing=".5">
sirius<tspan fill="#d6ff3d">.x</tspan>
Sirius<tspan fill="#d6ff3d">.X</tspan>
</text>
</svg>

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 434 B

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-label="sirius.x avatar">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-label="Sirius.X avatar">
<!-- Square profile-picture avatar. Full-bleed dark background, single star
centered and enlarged so it reads at 24px in a social feed. Corners are
square (not rounded) so the platform can apply its own mask (Twitter,

Before

Width:  |  Height:  |  Size: 579 B

After

Width:  |  Height:  |  Size: 579 B

View file

@ -1,34 +1,38 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" role="img" aria-label="sirius.x banner">
<!-- 1200x630 = the OpenGraph / Twitter Card canonical size. Left half is the
wordmark + tagline; right half is a large decorative star that survives
aggressive cropping (Facebook, Slack and Discord all crop differently). -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" role="img" aria-label="Sirius.X banner">
<!-- 1200x630 = the OpenGraph / Twitter Card canonical size. Centered
layout: "Sirius.X" wordmark above; a horizontal divider that is the
star's own horizontal arm, extended edge-to-edge; tagline below. -->
<defs>
<radialGradient id="glow" cx="70%" cy="50%" r="55%">
<radialGradient id="glow" cx="50%" cy="55%" r="65%">
<stop offset="0%" stop-color="#16202e"/>
<stop offset="100%" stop-color="#0b0e14"/>
</radialGradient>
</defs>
<rect width="1200" height="630" fill="url(#glow)"/>
<!-- decorative giant star, right side -->
<g opacity="0.95">
<path d="M900 90 L950 300 L1160 315 L950 330 L900 540 L850 330 L640 315 L850 300 Z"
fill="#d6ff3d"/>
</g>
<!-- The horizontal divider IS the star's horizontal arm. Left tip at (0,315),
right tip at (1200,315), so the arm crosses the full banner width. The
vertical arm is short and centered (top 230, bottom 400) so the star
body reads as a compact 4-point mark sitting on the divider line. -->
<path d="M600 230 L620 310 L1200 315 L620 320 L600 400 L580 320 L0 315 L580 310 Z"
fill="#d6ff3d"/>
<!-- wordmark, left column -->
<g transform="translate(80, 250)">
<text font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="110" font-weight="700" fill="#e7eaf1" letter-spacing="-1">
sirius<tspan fill="#d6ff3d">.x</tspan>
</text>
<text y="70" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="30" font-weight="400" fill="#8b98a9">
The home for names on Bitcoin Cash.
</text>
<text y="115" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="18" font-weight="500" fill="#5e6678" letter-spacing="1.5">
REGISTER · RESOLVE · VERIFY
</text>
</g>
<!-- Wordmark, centered above the divider -->
<text x="600" y="185" text-anchor="middle"
font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="120" font-weight="700" fill="#e7eaf1" letter-spacing="-1">
Sirius<tspan fill="#d6ff3d">.X</tspan>
</text>
<!-- Tagline, centered below the divider -->
<text x="600" y="475" text-anchor="middle"
font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="34" font-weight="400" fill="#8b98a9">
The home for names on Bitcoin Cash.
</text>
<text x="600" y="525" text-anchor="middle"
font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="20" font-weight="500" fill="#5e6678" letter-spacing="4">
REGISTER · RESOLVE · VERIFY
</text>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -3,29 +3,32 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Brand — sirius.x</title>
<meta name="description" content="sirius.x brand kit — logo, wordmark, avatar, banner, favicon, colour palette, and usage guidance. All assets served as SVG so they stay crisp at any size.">
<title>Brand — Sirius.X</title>
<meta name="description" content="Sirius.X brand kit — logo, wordmark, avatar, banner, favicon, colour palette, and usage guidance. All assets served as SVG so they stay crisp at any size.">
<link rel="icon" href="./favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="./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 brand kit">
<meta property="og:site_name" content="Sirius.X">
<meta property="og:title" content="Sirius.X brand kit">
<meta property="og:description" content="Logo, wordmark, avatar, banner, favicon, colour palette. All SVG, downloadable, MIT.">
<meta property="og:url" content="https://silentmode.st/sirius-x/brand/">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta name="twitter:card" content="summary_large_image">
<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:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--bg:#050810; --panel:#141a24; --panel2:#0a0f1c; --line:rgba(255,255,255,.06);
--ink:#f1f4fa; --mut:#b8c2d4; --dim:#6a7488; --acid:#d6ff3d;
}
*{box-sizing:border-box}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
body{margin:0;background:radial-gradient(ellipse 1200px 600px at 50% -5%,#131a2a 0%,transparent 60%),radial-gradient(ellipse 900px 500px at 100% 100%,#0a0f1c 0%,transparent 55%),radial-gradient(ellipse 900px 500px at 0% 100%,#0c1424 0%,transparent 55%),var(--bg);
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:1040px;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)}
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}
@ -71,24 +74,35 @@
.note b{color:var(--ink)}
code{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:12.5px;word-break:break-all}
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
/* Deviant-family fonts + Fraunces/Ubuntu reader toggle. */
h1,h2,h3{font-family:'Fraunces',Georgia,serif;font-feature-settings:"ss01","ss02"}
code,.mono{font-family:'JetBrains Mono',ui-monospace,monospace}
body{font-family:'DM Sans','Inter',system-ui,sans-serif !important;font-feature-settings:"ss01","ss02"}
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:'JetBrains Mono',ui-monospace,monospace !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:'JetBrains Mono',monospace;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}
.font-picker button:hover{color:var(--ink)}
.font-picker button.active{background:var(--acid);color:var(--bg);font-weight:600}
</style>
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">⭐ <span class="g">sirius.x</span></a>
<a class="brand" href="../">⭐ <span class="g">Sirius.X</span></a>
<a href="../#try">Try it</a>
<a href="../docs/">📚 Docs</a>
<a href="../theseus/">🧭 Theseus</a>
<a href="../#roadmap">Roadmap</a>
<a href="./" class="here">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</a>
<a href="../#search-input">✏️ Register</a>
<a href="../tld.html">🌐 TLD</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"/><circle cx="32" cy="32" r="3" fill="#0b0e14"/></svg>Theseus</a>
<a href="../portal.html" class="portal">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">🎨</div>
<h1>sirius.x <span class="g">brand kit</span></h1>
<h1>Sirius.X <span class="g">brand kit</span></h1>
<p class="tag">Logo, wordmark, avatar, banner, favicon, and the colour palette. Every asset ships as
SVG so it stays crisp at any size and reads correctly in light and dark contexts. Free to reuse
with attribution.</p>
@ -98,7 +112,7 @@
<section>
<h2>Logo &amp; wordmark</h2>
<p class="lede">A 4-point sparkle star plus <b>sirius.x</b>, with the <code>.x</code> TLD picked out
<p class="lede">A 4-point sparkle star plus <b>Sirius.X</b>, with the <code>.x</code> TLD picked out
in acid green. The star alone works when you have no room for the wordmark; the full lockup is
the default choice everywhere else.</p>
<div class="grid">
@ -142,7 +156,7 @@
<div class="preview favicon"><img src="./favicon.svg" alt="sirius.x favicon"></div>
<h3>Favicon <span class="meta">SVG · 64×64, 12px radius</span></h3>
<p class="lede" style="margin-bottom:.6rem">Rounded browser-tab icon. Scales down to 16×16
cleanly; used on every sirius.x page.</p>
cleanly; used on every Sirius.X page.</p>
<div class="row">
<a class="btn acid" href="./favicon.svg" download>Download SVG</a>
<a class="btn" href="./favicon.svg" target="_blank">Open</a>
@ -168,7 +182,7 @@
<section>
<h2>Colour palette</h2>
<p class="lede">Silent Mode family colours. Dark chromes are the default; acid green is the
single accent that consistently signals "this is sirius.x".</p>
single accent that consistently signals "this is Sirius.X".</p>
<div class="swatches">
<div class="sw"><div class="chip" style="background:#d6ff3d"></div><div class="info"><b>Acid</b>#d6ff3d — accent, links, active nav</div></div>
<div class="sw"><div class="chip" style="background:#0b0e14"></div><div class="info"><b>Background</b>#0b0e14 — page canvas</div></div>
@ -191,7 +205,7 @@
<p style="margin:0;font-family:system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
font-size:36px;font-weight:600;letter-spacing:-.5px">The quick brown fox</p>
<p style="margin:.4rem 0 0;color:var(--mut);font-family:system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
font-size:16px">jumps over the lazy dog · 0123456789 · sirius.x</p>
font-size:16px">jumps over the lazy dog · 0123456789 · Sirius.X</p>
<div class="meta" style="margin-top:12px">system-ui, -apple-system, Segoe UI, Roboto, sans-serif</div>
</div>
<div class="note">The wordmark's <code>.x</code> is a <code>&lt;tspan fill="#d6ff3d"&gt;</code> —
@ -201,12 +215,12 @@
<section>
<h2>Usage &amp; licence</h2>
<p class="lede">All assets are MIT. Reuse them for third-party tools that integrate with sirius.x
<p class="lede">All assets are MIT. Reuse them for third-party tools that integrate with Sirius.X
(wallets, indexers, explorers, blog posts about BCNR). Keep the star's proportions intact and
don't recolour the acid to a similar-but-different green — palette drift is what makes brands
look untrustworthy over time.</p>
<ul style="color:var(--mut);font-size:14px;padding-left:1.2rem">
<li><b style="color:var(--ink)">Do</b> use the mark to indicate "supports sirius.x" or "hosted on sirius.x".</li>
<li><b style="color:var(--ink)">Do</b> use the mark to indicate "supports Sirius.X" or "hosted on Sirius.X".</li>
<li><b style="color:var(--ink)">Do</b> shrink to the favicon at 16×16 — the SVG scales cleanly.</li>
<li><b style="color:var(--ink)">Don't</b> imply endorsement of a specific product without asking.</li>
<li><b style="color:var(--ink)">Don't</b> stretch, skew, or re-tint the star.</li>
@ -215,11 +229,12 @@
</div>
<footer>
Brand kit for sirius.x ·
<a href="../">back to sirius.x</a> ·
<a href="https://silentmode.st/">silentmode.st</a>
</footer>
<footer id="site-footer"></footer>
<script src="../js/pin-escrow.js?v=20260909pin"></script>
<script src="../js/pricing.js?v=20260909tldhigh"></script>
<script defer src="../js/site-footer.js?v=20260907rel"></script>
<script defer src="../js/theme.js?v=20260910font"></script>
<script defer src="../js/profile-menu.js?v=20260908tabs"></script>
</body>
</html>

View file

@ -1,10 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="sirius.x (monochrome)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="Sirius.X (monochrome)">
<!-- Single-fill variant for print, embossing, one-colour merch. currentColor
so the SVG inherits the surrounding text colour when inlined; pass
style="color: #d6ff3d" to force the acid green. -->
<g fill="currentColor">
<path d="M32 12 L35.3 30.7 L54 34 L35.3 37.3 L32 56 L28.7 37.3 L10 34 L28.7 30.7 Z"/>
<text x="72" y="42" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="28" font-weight="600" letter-spacing=".5">sirius.x</text>
font-size="28" font-weight="600" letter-spacing=".5">Sirius.X</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 623 B

After

Width:  |  Height:  |  Size: 623 B

View file

@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="sirius.x">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 64" role="img" aria-label="Sirius.X">
<path d="M32 12 L35.3 30.7 L54 34 L35.3 37.3 L32 56 L28.7 37.3 L10 34 L28.7 30.7 Z"
fill="#d6ff3d"/>
<text x="72" y="42" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="28" font-weight="600" fill="#e7eaf1" letter-spacing=".5">
sirius<tspan fill="#d6ff3d">.x</tspan>
Sirius<tspan fill="#d6ff3d">.X</tspan>
</text>
</svg>

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 434 B

View file

@ -0,0 +1,154 @@
# Signed records manifest (BNS records v1)
**Status:** shipped v1 — gateway `GET/POST /api/records/<name>` and
verified `GET /api/dns/<name>` live on `silentmode.st/navigate.st`;
owner-tracking in the indexer live; portal DNS editor + wallet-side
`signMessage` + `signRecordsManifest` shipped. Native DNS server
(UDP :53 → BCDN name → verified records) is a v2 follow-up.
**Related:** `DESIGN-tld-registry.md`, `PROTOCOL.md`, public explainer at
`silentmode.st/sirius-x/docs/#signed-records`. Mirrored to
`site-sirius-x/docs/DESIGN-signed-records-manifest.md` so it rides the
next push-split to the sirius forge.
## Problem
Every records edit today is a chain UPD:
- costs ~1,300 sat + service fee
- caps records at ~150 bytes of payload
- rules out DNS-style records (A/AAAA/MX/TXT/CNAME/NS) at any useful scale
- makes TXT-verification churn (ACME, DKIM, DMARC) actively expensive
We want records to be:
- **free to edit** — no chain tx per change
- **unlimited size** — accommodate whole DNS record sets
- **trustless** — no operator can substitute their own records for the owner's
- **backwards compatible** — existing on-chain `h` / `s3` / `p` / `u` records keep working
## Design
The chain says *who owns the name*. A signed manifest says *what the owner's
records are*. Resolvers verify both.
### The manifest — `_records.json`
Lives at the Sia bucket the name's on-chain `records.s3` already points at,
under the fixed filename `_records.json`. Shape:
```json
{
"v": 1,
"name": "bitcoin.cash",
"seq": 42,
"updated_at": "2026-09-12T00:00:00Z",
"dns": {
"A": ["1.2.3.4"],
"AAAA": ["2001:db8::1"],
"MX": [{"pref": 10, "host": "mail.example.com"}],
"TXT": ["v=spf1 include:_spf.silentmode.st -all"],
"CNAME": null,
"NS": []
},
"meta": { "note": "optional free-form" },
"sig": "H3n… (BCH message signature, base64)"
}
```
**Rules:**
- `v`: schema version, currently `1`.
- `name`: the fully-qualified name the manifest belongs to. Resolver rejects
a manifest whose `name` field doesn't match the URL it was fetched from.
- `seq`: monotonic integer. Resolvers cache the highest seen; blobs with an
older or equal `seq` are rejected as replays.
- `updated_at`: ISO-8601 UTC. Human-readable only — verification is on `seq`.
- `dns.*`: DNS record slots. `null` or `[]` means "not set". `A`/`AAAA`/`TXT`
are string arrays. `MX` is objects `{pref, host}`. `NS` is a string array
of host names. Additional slots (`CAA`, `SRV`) reserved for v2.
- `meta`: unstructured; ignored by DNS resolvers, useful for portal UI.
- `sig`: BCH-style message signature (same format `libauth.signMessage`
produces) over the canonical bytes of the envelope (see below).
### Canonicalisation and signing
The signable bytes are the JSON serialisation of the manifest **without the
`sig` field**, with:
- keys sorted lexicographically at every level
- no insignificant whitespace (`JSON.stringify` with no `space` arg)
- `\u`-escape every non-ASCII character
- `null` fields OMITTED (`"CNAME": null` becomes absent)
The signature is `sign(sha256(canonical_bytes))` with the wallet key whose
address currently holds the name's NFT certificate.
Verification, at the resolver:
1. Read the name's chain record. Follow `records.s3` to the Sia bucket.
2. Fetch `_records.json` from that bucket.
3. Extract `sig`, recompute `sha256(canonical_bytes)` over the rest.
4. Recover the signing pubkey → derive the CashAddress → compare to the
current NFT owner address from the chain.
5. Compare `seq` to the cached last-seen `seq` for this name. Reject if not
strictly greater.
6. If everything matches: cache the new `seq`, apply the DNS records.
Any step failing means "no records" — the resolver falls back to whatever
was already on the chain (`h`, `s3` for content, etc.).
### Endpoints (gateway)
**GET `/api/records/<name>`** — read-through of the signed manifest.
Returns 200 with the JSON if present, 404 if missing, 5xx on Sia errors.
Cacheable for a minute. Anyone can call this; it's public.
**POST `/api/records/<name>`** — write. Body IS the manifest JSON.
The gateway:
1. Verifies the signature matches the current on-chain NFT owner.
2. Verifies `seq` is strictly greater than the last-seen `seq` (from
`GET`ing the current manifest if any).
3. Uploads the JSON to the name's Sia bucket at `_records.json`.
4. Returns 200 with `{seq, bytes, sia_key}`.
Rate-limit: 1 write / 5 s per name. Refuses if the on-chain record has no
`s3` pointer yet — the name has no storage location, no place to write.
### Precedence and interaction with existing records
The signed manifest **complements** the on-chain records — it doesn't replace
them:
- **Content** (`h`, `s3`, `p`, `u`, `ip`) still comes from chain.
- **DNS records** come from the manifest — chain has never carried them.
A future extension (v2) could allow the manifest to override `h`/`s3`/etc.
for owners who want everything off-chain. Not shipped in v1 because the
existing content model already works.
### Threat model
- **Operator tampers with the manifest.** Signature verification catches it —
the resolver rejects and falls back to on-chain records.
- **Replay of an old manifest.** `seq` monotonicity catches it — resolvers
keep the highest-seen `seq`.
- **Owner's key compromised.** Same as chain-side compromise: attacker
controls the NFT and can sign whatever. Move the name to a new key.
- **Sia object deleted.** The name still resolves via chain records; DNS
records disappear until the manifest is republished.
- **Gateway hostility.** The gateway signs nothing itself — it only relays
and enforces `seq` monotonicity. A hostile gateway can refuse to accept
writes but cannot forge them; users can bypass it entirely by writing
directly to Sia with their own credentials (v2 flow).
### What ships in v1
- The spec (this doc).
- Gateway `/api/records/<name>` (GET + POST) with signature verification and
Sia read-through.
- Portal DNS editor that composes a manifest, asks the wallet to sign, and
POSTs to the gateway.
- Resolver support in Theseus + Ariadne staged behind a flag until the
portal-side has been in production for a week.
### What ships in v2
- Direct-to-Sia write flow for users who hold their own S3 credentials.
- Owner-controlled manifest that overrides `h`/`s3`/etc. entirely.
- CAA/SRV/HTTPS records.
- Federated resolver caches for `seq` (mitigates the case where two writes
race and each thinks its `seq` is winning).

View file

@ -1,363 +0,0 @@
# How to do things — Silent Mode runbook
Operational companion to [`SESSION-CONTEXT.md`](SESSION-CONTEXT.md). That file is
*what the product is*; this one is *how to do a thing*. Every command below was
run on 2026-07-30 and works.
All commands run from `D:\Dev\SilentMode\Argus` unless stated. Prefix with `rtk`
per project convention. **Everything is chipnet.**
> **Before you touch a `.js` in `Argus/src/lib/`, grep for it first.** Two
> sessions have written here concurrently and `registry-lifecycle.js`,
> `portfolio.js` and `ElectrumPool` were each independently rebuilt once. If a
> test file exists for a module you are about to create, implement to the test —
> the test is the contract.
---
## 1. Read the registry
```bash
node src/resolve.js # list every name, with records and category
node src/resolve.js demo.p2p # resolve one
```
Real output today (abridged):
```
silentmode.bch -> {"s3":"bns/silentmode/"}
theseus.bch -> {"h":"<h1>Theseus</h1>…"}
coinspectrum.bch-> {"ip":"195.184.247.106","p":"https://…","tls":"84e4cd…"}
demo.p2p -> {"h":"<h1>demo.p2p</h1>…"}
syskypo.de -> {"s3":"bns/syskypo.de/"}
```
Zero-dependency alternative (the resolver clients actually ship):
```bash
node --input-type=module -e "
import WebSocket from 'ws';
import { resolveName } from './src/lib/resolver-web.js';
console.log(await resolveName('silentmode.bch', { WebSocket }));
process.exit(0);"
```
---
## 2. Register a name
```bash
node src/register.js <name> <url-or-json>
```
```bash
node src/register.js mysite https://example.org # shorthand → {"u": …}
node src/register.js mysite '{"h":"<h1>Hello</h1>"}' # explicit records
node src/register.js mysite.nav '{"s3":"bns/mysite/"}' # any TLD, same command
```
Registers from the project wallet (`wallets.json`). It mints the certificate,
publishes the records and pays the beacon in **one transaction**.
Verify:
```bash
node src/resolve.js mysite.nav
```
Records can be omitted at registration and set later — see §4.
**Buyer-facing registration** (built-in wallet, pay-by-QR) goes through
`site/register.html`, not the CLI. The CLI is for operator-held names and testing.
---
## 3. Add a new TLD
**Superseded 2026-08-29.** The old "TLDs are just a convention, no registry
change needed" model is retired. The per-TLD registry
([`Decentralized.DNS/DESIGN-tld-registry.md`](Decentralized.DNS/DESIGN-tld-registry.md))
is now the source of truth: **a name REG under a TLD that has no on-chain TLD
certificate will be rejected by conforming clients once enforcement is on** (the
code is in `buildIndex({enforceTld:true})` in both `bns.js` and
`resolver-web.js`; default is still off during the mainnet migration, but the
registrar treats the on-chain list as authoritative today).
So adding a TLD is now **three steps: TREG on the beacon, UI, deploy.**
**1. Register the TLD on the TLD beacon (chipnet).**
The idempotent way — the operator wallet holds the seed for the TLD-beacon
address and the seed script skips anything already present:
```bash
cd Argus
# Edit src/seed-tld-beacon.mjs SEED_TLDS[] — append your new TLD label
node src/seed-tld-beacon.mjs
```
Or a one-off from a Node REPL if you don't want to touch the script:
```bash
node --input-type=module -e "
import { loadWallet } from './src/lib/wallet.js';
import { registerTld } from './src/lib/bns.js';
const w = await loadWallet('main');
console.log(await registerTld(w, 'newtld', {}));
process.exit(0);"
```
Either way you get `{tld, txid, category}`. The TLD certificate is minted to
the operator wallet — that address becomes the TLD's owner and can UPD the
records with `updateTld(wallet, tld, records, category)` later.
Cost: ~1,300 chipnet sats per TREG. Empty records `{}` mean "defaults apply"
per the design doc §3.
**2. Add the TLD to the registrar UI.**
The dropdown is gone. `site/sirius/register.html` now uses a `TLDS` array
(around line 275). Append your new TLD with `onchain: true`:
```js
const TLDS = [
...,
{ tld: "newtld", onchain: true },
];
```
If you registered the cert but want to *hold* the TLD without offering it in
the registrar (the `.com` pattern — cert on-chain so nobody else claims it, but
no second-level names offered), just leave it out of the `TLDS` array. The
cert stays valid on the beacon.
**3. Deploy `site/sirius/register.html` to the VPS.**
silentmode.st is nginx-served from `/opt/silent-mode/site/`, NOT Sia
(see [`DEPLOY-split-st-from-bch.md`](DEPLOY-split-st-from-bch.md)):
```bash
scp D:/Dev/SilentMode/site/sirius/register.html silentmode:/opt/silent-mode/site/sirius/register.html
```
(silentmode.bch — the Sia mirror — takes a full `sia-upload.js` of `site/`.
Only touch that if you also want the on-chain-hosted copy refreshed.)
**4. Republish the TLD snapshot (optional, updates mirrors).**
If a downstream is reading from the Sia mirror or the Nostr replaceable event
rather than doing its own chain scan, refresh the snapshot:
```bash
cd Argus
node src/publish-tld-mirror.mjs
```
Uploads `bns/tld-list.json` (floating) and `bns/tld-list-<root>.json`
(immutable content-addressed) to Sia, and publishes NIP-33 kind 30078 (d-tag
`bns-tld-list`) to the configured relays. Dry-run: `BNS_MIRROR_DRY_RUN=1`.
### The thing to think about before adding one
Under the per-TLD registry the operator's key is the countersignature gate —
so **you're the registrar** for any TLD you mint. On mainnet the covenant will
enforce a price floor and an operator-countersig for public mints
([`Decentralized.DNS/DESIGN-tld-registry.md`](Decentralized.DNS/DESIGN-tld-registry.md) §5).
On chipnet nothing enforces this; a rogue script could TREG anything under a
different key. Only the operator's key produces TLD certs that clients trust
once the enforcement rules ship.
`.bch` is special in one way only: its on-chain commitment is the **bare label**
(`silentmode`, not `silentmode.bch`) for backward compatibility. Every other TLD
stores the full `label.tld`. `normalizeName` handles this; don't hand-roll it.
### Current chipnet TLD set (2026-08-29)
Bench-checkable via `node src/seed-tld-beacon.mjs` (idempotent verify) or by
fetching the mirror at `https://s3.silentmode.st:8600/bns/tld-list.json` (403
to anon today; the Nostr replaceable event `kind:30078` `d:bns-tld-list` from
pubkey `f2c925194c531c7c398017e35b2396df64a61a613aa5fadebdf1f4990f2267f4` on
`wss://nos.lol` / `wss://relay.damus.io` is publicly readable).
Live: `bch p2p bit nav test x asm neo gt sc sia com dex cex nt` (15 total).
`.com` is **held** by the operator — cert on-chain, excluded from the public
registrar UI so nobody else can claim it.
---
## 4. Set or change records
```bash
node src/update.js <name> <url-or-json>
```
```bash
node src/update.js mysite '{"ip":"203.0.113.9"}'
node src/update.js mysite.nav '{"s3":"bns/mysite/","tls":"a1b2c3…"}'
```
Proves ownership by moving the certificate — only the holder can do it.
### Record types
| Key | Meaning | Example |
|---|---|---|
| `h` | inline HTML, stored on-chain | `{"h":"<h1>Hi</h1>"}` |
| `u` | redirect to a URL | `{"u":"https://example.org"}` |
| `ip` | IPv4 of your server | `{"ip":"203.0.113.9"}` |
| `p` | reverse-proxy upstream (address bar stays on the name) | `{"p":"https://backend.example"}` |
| `s3` | Sia object or prefix | `{"s3":"bns/mysite/"}` |
| `tls` | SHA-256 fingerprint of the name's TLS cert (hex, over DER) | `{"tls":"84e4cd…"}` |
### The 200-byte ceiling
The whole payload — `"BNS1"` + the JSON — must be **≤ 200 bytes**. For
`sirius.nav` that leaves about 161 bytes for records. An oversized payload throws
at build time rather than producing a broken registration.
Check before you commit to a long `h`:
```bash
node --input-type=module -e "
import { payloadBudget } from './src/lib/register-tx.js';
console.log('bytes free for records:', payloadBudget('sirius.nav'));
process.exit(0);"
```
`h` is for a page, a profile, a link hub. Anything real goes on Sia or a server.
---
## 5. Put a site on Sia storage
Two steps: upload the bytes, then point the name at them.
```bash
# from D:\Dev\SilentMode
node Argus/src/lib/sia-upload.js <file-or-dir> <bucket[/prefix]>
```
```bash
node Argus/src/lib/sia-upload.js D:/Dev/SilentMode/site/mysite bns/mysite
node Argus/src/lib/sia-upload.js ./page.html bns/mysite
```
Then the record — a **trailing slash means "site root"**, no slash means a single
object:
```bash
cd Argus
node src/update.js mysite '{"s3":"bns/mysite/"}' # directory → site
node src/update.js mysite '{"s3":"bns/page.html"}' # one file
```
Verify through the public gateway:
```bash
curl -s -o /dev/null -w "%{http_code}\n" https://navigate.st/bns/mysite.bch/
```
Upload the **whole directory** if the page has assets — `sia-upload.js` walks it
and preserves relative paths, which is what makes `/js/…` and `/vendor/…` resolve.
**`sia-s3.json` is a secret** (SECURITY.md rule 0). Never print it, commit it, or
copy its values into a bundle. The build refuses to emit a bundle containing them.
---
## 6. Build and deploy the site
```bash
cd Argus && node build-web.mjs # bundles
cd .. && node Argus/src/lib/sia-upload.js D:/Dev/SilentMode/site bns/silentmode
```
Two rules that will bite otherwise:
- **Run the upload from the repo root**, not from `site/`. The path is relative
to cwd and `site/Argus/...` does not exist.
- **Upload the whole `site/` directory.** `register.html` depends on `site/js/`
and `site/vendor/`; a page-only upload leaves a broken live page.
`build-web.mjs` refuses to write a bundle that contains a live secret **value**
(it reads `wallets.json`/`sia-s3.json` and greps for their contents) or a
build-machine path. Do not weaken those checks.
libauth is **one shared module behind an import map** (`site/js/libauth.js`).
Do not bundle it per-file: its WASM init uses top-level await, and a second copy
hands out `undefined` for `secp256k1` on cold load. The build verifies every
import the other bundles emit is satisfied.
Verify what is actually live:
```bash
curl -s https://navigate.st/bns/silentmode.bch/register.html | grep -c 'bns-register.js'
```
---
## 7. Tests
```bash
cd Argus
node --test test/*.test.mjs # offline; no network, no coins
```
Live scripts spend real chipnet coins and are run deliberately:
```bash
node test/chipnet-acceptance.mjs # built-in wallet, full registration
node test/chipnet-paybyqr.mjs # registrar mints to a buyer
node test/chipnet-escrow-refund.mjs # unsigned order → refund, name never minted
```
They **exit 2** when the chain is unreachable, so an environment failure is
distinguishable from a product failure. Add `--keep` to the acceptance test to
print the throwaway wallet's phrase.
---
## 8. Gotchas that have actually cost time
**Node cannot resolve some hostnames on the dev machine.** `getaddrinfo` returns
`EAI_FAIL` for `coinspectrum.duckdns.org` and the chipnet electrum hosts while
`nslookup` and c-ares resolve them fine. Symptom: uploads and live tests fail
instantly with a DNS error. Workaround is a `--require` shim that falls back to
`dns.resolve4`; the real fix is on the machine. **If a network command fails
instantly, suspect this before suspecting the code.**
**Electrum uses ports 50004/62002**, which corporate networks and some VPNs block
outright — and every configured server shares those ports, so one firewall rule
takes the whole resolver down. `REGISTRAR.selfHosted` puts your own Fulcrum on
443 first; see `Argus/OPERATIONS-electrum.md`.
**Two resolvers must stay in lockstep.** `resolver-web.js` (zero-dep, shipped in
clients) and `bns.js` (mainnet-js). Change one, change both. A disagreement is a
consensus split between clients.
**Terminology is enforced.** It is a **certificate / registration record /
title** — never an "NFT" in code, comments or UI. `NFTCapability` and `.nft` are
mainnet-js API names and stay.
**The certificate lives in a 1,000-sat UTXO.** A wallet that does not understand
CashTokens sees dust; a "sweep all funds" would destroy the name. This is why
destinations are normalised to the token-aware `z…` form.
**`h` records are HTML you are publishing permanently.** There is no edit — only
an update transaction, and the old payload stays on-chain forever.
**Never register a name you cannot spell twice.** Registration is irreversible and
there is no expiry on chipnet today, so a typo is a permanently burned name.
---
## 9. What not to do
- Do not touch `D:\Dev\NameCoin` — separate live system.
- Do not flip anything to mainnet. It is a deliberate switch (new electrum
servers, `bitcoincash:` prefix, a new beacon, real money), not a config change.
- Do not commit or print `wallets.json`, `sia-s3.json`, `ca/root-ca.key`, or any
seed phrase.
- Do not put the operator's name or email in any file (SECURITY.md rule 3).
- Do not add a TLD to the dropdown without registering a test name on it first.
- Do not weaken the build's secret scan or the LGPL licence checks.

View file

@ -3,31 +3,34 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Docs — sirius.x</title>
<title>Docs — Sirius.X</title>
<meta name="description" content="How BCNR works: the TLD registry, name registration, records, resolver, and how to verify anything against the Bitcoin Cash chain.">
<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 docs — how BCNR works">
<meta property="og:site_name" content="Sirius.X">
<meta property="og:title" content="Sirius.X docs — how BCNR works">
<meta property="og:description" content="The TLD registry, name registration, records, resolver, mainnet pricing, and how to verify anything against the chain.">
<meta property="og:url" content="https://silentmode.st/sirius-x/docs/">
<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:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--bg:#050810; --panel:#141a24; --panel2:#0a0f1c; --line:rgba(255,255,255,.06);
--ink:#f1f4fa; --mut:#b8c2d4; --dim:#6a7488; --acid:#d6ff3d;
--ok:#4fd1a5; --warn:#ffc75f;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
body{margin:0;background:radial-gradient(ellipse 1200px 600px at 50% -5%,#131a2a 0%,transparent 60%),radial-gradient(ellipse 900px 500px at 100% 100%,#0a0f1c 0%,transparent 55%),radial-gradient(ellipse 900px 500px at 0% 100%,#0c1424 0%,transparent 55%),var(--bg);
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:900px;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)}
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}
@ -75,24 +78,37 @@
.verify dt:first-of-type{margin-top:0}
.verify dd{margin:2px 0 0;font-family:ui-monospace,monospace;font-size:12.5px;word-break:break-all;color:var(--ink)}
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
/* Deviant-family fonts + Fraunces/Ubuntu reader toggle. */
h1,h2,h3{font-family:'Fraunces',Georgia,serif;font-feature-settings:"ss01","ss02"}
code,.mono{font-family:'JetBrains Mono',ui-monospace,monospace}
body{font-family:'DM Sans','Inter',system-ui,sans-serif !important;font-feature-settings:"ss01","ss02"}
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:'JetBrains Mono',ui-monospace,monospace !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:'JetBrains Mono',monospace;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}
.font-picker button:hover{color:var(--ink)}
.font-picker button.active{background:var(--acid);color:var(--bg);font-weight:600}
</style>
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
<script src="../js/i18n.js?v=20260920d"></script>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">⭐ <span class="g">sirius.x</span></a>
<a class="brand" href="../">⭐ <span class="g">Sirius.X</span></a>
<a href="../#try">Try it</a>
<a href="./" class="here">📚 Docs</a>
<a href="../theseus/">🧭 Theseus</a>
<a href="../#roadmap">Roadmap</a>
<a href="../brand/">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</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">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">📚</div>
<h1>sirius.x <span class="g">docs</span></h1>
<h1>Sirius.X <span class="g">docs</span></h1>
<p class="tag">How the pieces fit together: the TLD registry, name registration, records that
tell the resolver where a site lives, the resolver itself, and how anyone can verify anything
against the chain.</p>
@ -105,7 +121,10 @@
<h4>Contents</h4>
<a href="#tld-registry">TLD registry</a>
<a href="#register-name">Register a name</a>
<a href="#private-tlds">Private &amp; co-sign TLDs</a>
<a href="#market">Buying &amp; selling names</a>
<a href="#records">Records &amp; hosting</a>
<a href="#signed-records">Signed off-chain records</a>
<a href="#host">Host your name</a>
<a href="#resolver">Resolver / gateway</a>
<a href="#pricing">Pricing (mainnet)</a>
@ -156,6 +175,82 @@
</ol>
</section>
<section id="private-tlds">
<h2>Private &amp; co-sign TLDs</h2>
<p class="lede">A TLD owner decides who may register names under it, and the decision is
enforced by every resolver, not just by the shop. Three switches live in the TLD's
on-chain records (a <code>TUPD</code> signed by the owner's key):</p>
<table class="pricing">
<tr><th>Record</th><th>Who can register</th><th>How it is enforced</th></tr>
<tr><td><code>hidden: 1</code> (switched off)</td>
<td>Only the owner, from the dashboard. Off the public list.</td>
<td>Co-sign rule (below).</td></tr>
<tr><td><code>policy: "cosign"</code></td>
<td>Anyone, but every registration needs the owner's approval.</td>
<td>Co-sign rule (below).</td></tr>
<tr><td><code>policy: "frozen"</code></td>
<td>Nobody, owner included.</td>
<td>Resolvers drop every new registration.</td></tr>
</table>
<h3 style="margin-top:1.4rem">The co-sign rule</h3>
<p>A registration under a <code>cosign</code> or <code>hidden</code> TLD is only recognised
when the same transaction also <b>carries the TLD's own certificate</b> — the TLD NFT
goes in as an input and comes back out to its owner. Only the owner's key can spend that
NFT, so its presence is a signature nobody can forge, and nothing is consumed: the
certificate returns in the same transaction. Every conforming client (gateway, Theseus,
Ariadne desktop and mobile) applies the rule when it builds its index, judging each
registration against the TLD policy <b>in force at that block</b>, so switching a TLD
off later never invalidates names registered while it was open.</p>
<ol class="steps">
<li><b>Owner registering under a private TLD.</b>
<span>Open the TLD in the dashboard, type a label, register. The certificate is added
from your own wallet; you pay only the platform share of the name price.</span></li>
<li><b>Anyone registering under a co-sign TLD.</b>
<span>The normal register flow builds the full transaction with the owner's certificate
as its last input, you sign your part, and the request waits in the gateway's approval
queue (<code>POST /api/cosign</code>). Nothing leaves your wallet until the owner
acts; requests expire after 7 days.</span></li>
<li><b>Owner approving.</b>
<span>Dashboard → the TLD → <b>Pending approvals</b>. Approve signs the certificate
input and broadcasts; Decline removes the request. The wallet refuses to sign any
request that would not return the certificate to you.</span></li>
</ol>
<div class="note"><b>Why not a covenant?</b> A covenant-gated mint is the mainnet plan for
fee enforcement; the co-sign rule needs no new script, works today with plain P2PKH
certificates, and gives the owner a human veto rather than a formula.</div>
</section>
<section id="market">
<h2>Buying &amp; selling names</h2>
<p class="lede">Any name can be sold to anyone, in <b>one transaction, with no escrow</b>.
The seller is paid exactly when the certificate moves — or not at all.</p>
<ol class="steps">
<li><b>Seller lists.</b>
<span>Dashboard → the name → <b>Sell</b>, set a price. Your wallet signs a partial
transaction — your certificate as input 0, the price to you as output 0 — with
<code>SIGHASH_SINGLE | ANYONECANPAY</code>. That signature says "whoever completes this
pays me this much"; it constrains nothing else. The gateway stores it and shows it on
the <a href="../market.html">market</a> after checking the signature, the on-chain
owner and that the certificate is still unspent.</span></li>
<li><b>Buyer completes.</b>
<span>Verify the offer locally, add your coins, add the certificate output to your own
token address plus a registry update so every resolver learns the new owner, sign your
inputs, broadcast. The seller's signature is already in place.</span></li>
<li><b>Seller cancels.</b>
<span>Cancelling removes the offer from the market and moves the certificate once (a
no-op update, a few cents), so the signed offer can never be completed afterwards.</span></li>
</ol>
<div class="note"><b>Trust model.</b> The gateway is a bulletin board. A forged or stale
listing fails the buyer's local check or the broadcast; a buyer can never pay without
receiving the certificate in the same transaction, and a seller can never lose the
certificate without being paid. Endpoints: <code>GET /api/market</code>,
<code>GET /api/market/&lt;name&gt;</code>, <code>POST /api/market</code> (a signed listing),
<code>DELETE /api/market/&lt;name&gt;</code> (owner-signed
<code>BNS-MARKET1
&lt;name&gt;
&lt;ts&gt;</code>).</div>
</section>
<section id="records">
<h2>Records &amp; hosting</h2>
<p class="lede">A registered name carries a small JSON records object. Every record is
@ -179,6 +274,89 @@
(Host-header semantics). Full rule is in <code>Argus/src/lib/record-picker.js</code>.</p>
</section>
<section id="signed-records">
<h2>Free edits — signed off-chain records</h2>
<p class="lede">The on-chain records above (<code>h</code>, <code>s3</code>, <code>ip</code>, <code>u</code>,
<code>tls</code>, <code>np</code>, <code>el</code>) cost a chain transaction to change and are capped
at 200 bytes of OP_RETURN. For DNS-style records (A / AAAA / MX / TXT / CNAME / NS) and any records
you edit often, Sirius.X uses a companion mechanism: a <b>signed off-chain manifest</b> that costs
nothing per change and has no size cap.</p>
<p class="lede" style="margin-top:1rem"><b>The chain says who owns the name. A signed blob says what
the records are. Resolvers verify both.</b> No third party is trusted for records: the manifest is
signed by the same key that holds the on-chain NFT certificate, so an operator (or Sia farmer, or
anyone else in the middle) can't rewrite records without breaking the signature.</p>
<table class="pricing" style="margin-top:1.2rem">
<thead><tr><th>Concern</th><th>Where it lives</th><th>Cost per change</th></tr></thead>
<tbody>
<tr><td>Who owns the name</td><td>Bitcoin Cash chain (NFT certificate)</td><td>1 tx to transfer</td></tr>
<tr><td>Where the site lives</td><td>Chain record: <code>s3</code>, <code>ip</code>, <code>u</code>, <code>h</code></td><td>1 tx per change</td></tr>
<tr><td>DNS records, meta, TXT churn, etc.</td><td>Sia at <code>&lt;s3-bucket&gt;/_records.json</code></td><td><b style="color:var(--acid)">free</b></td></tr>
</tbody>
</table>
<h3 style="margin-top:1.4rem">How the manifest is verified</h3>
<ol class="steps" style="counter-reset:s">
<li><b>Resolver reads</b> the name's chain record, follows <code>records.s3</code> to the Sia bucket,
fetches <code>_records.json</code>.</li>
<li><b>Signature check</b> — recovers the signing pubkey from the manifest's <code>sig</code> field,
derives the CashAddress, compares to the current NFT-holder address from the chain. Mismatch = reject.</li>
<li><b>Replay check</b> — the manifest carries a monotonic <code>seq</code> number. Resolvers cache the
highest seen and reject anything less-or-equal. An old signed blob can't be re-served.</li>
<li><b>Fall-back</b> — if the manifest is missing, invalid, or its signature doesn't match, the resolver
silently falls back to the on-chain records. Signed records never override a name; they extend it.</li>
</ol>
<h3 style="margin-top:1.4rem">The manifest shape</h3>
<pre style="background:#0e131b;border:1px solid var(--line);border-radius:10px;padding:14px 16px;overflow-x:auto;font-family:ui-monospace,monospace;font-size:12.5px;line-height:1.6;color:var(--ink);white-space:pre;margin-top:.6rem">{
"v": 1,
"name": "bitcoin.cash",
"seq": 42,
"updated_at": "2026-09-15T00:00:00Z",
"dns": {
"A": ["1.2.3.4"],
"AAAA": ["2001:db8::1"],
"MX": [{"pref": 10, "host": "mail.example.com"}],
"TXT": ["v=spf1 include:_spf.silentmode.st -all"],
"CNAME": null,
"NS": []
},
"sig": "&lt;BCH message signature over sha256(canonical bytes)&gt;"
}</pre>
<p class="lede" style="margin-top:.8rem">Canonicalisation: sorted keys, no whitespace, <code>null</code>
fields omitted. The signable bytes are the manifest with the <code>sig</code> field removed. Full
spec: <a href="./DESIGN-signed-records-manifest.md"><code>DESIGN-signed-records-manifest.md</code></a>
— signable byte order, seq-monotonicity rules, threat model, v2 roadmap.</p>
<h3 style="margin-top:1.4rem">Endpoints</h3>
<table class="pricing">
<thead><tr><th>Method</th><th>Path</th><th>Effect</th></tr></thead>
<tbody>
<tr><td><b>GET</b></td><td><code>/api/records/&lt;name&gt;</code></td><td>Fetches the raw signed manifest from the name's Sia bucket. Public, cacheable.</td></tr>
<tr><td><b>POST</b></td><td><code>/api/records/&lt;name&gt;</code></td><td>Accepts a signed manifest, verifies against the on-chain owner + seq monotonicity, uploads to Sia.</td></tr>
<tr><td><b>GET</b></td><td><code>/api/dns/&lt;name&gt;</code></td><td><b>Resolver read.</b> Fetches the manifest, verifies the signature against the on-chain owner and rejects rollback of the seq, then returns <em>only</em> the verified <code>dns</code> block. Callers can trust the response without doing their own signature or chain lookups. 30-second cache hint.</td></tr>
</tbody>
</table>
<p class="lede" style="margin-top:.8rem">The distinction between <code>/api/records/&lt;name&gt;</code>
and <code>/api/dns/&lt;name&gt;</code> is deliberate: the former is transparent (raw manifest as
uploaded, including the signature so clients can re-verify), the latter is opinionated (only the
verified DNS records, with the gateway having done the sig + seq work). Bridges and shims should
use <code>/api/dns/</code>; wallets and tools that want to see the full signed blob should use
<code>/api/records/</code>.</p>
<p class="lede" style="margin-top:.8rem">A name needs <code>records.s3</code> set on chain first —
without a storage pointer, the manifest has nowhere to live. Portal and CLI both refuse to
publish a manifest until <code>s3</code> is present.</p>
<div class="note" style="margin-top:1.2rem">
<b>Threat model at a glance.</b> Operator tampers → sig check fails, resolver falls back to chain
records. Replay of an old blob → seq check fails. Owner's key compromised → same as chain-side
compromise; move the name to a new key. Sia object deleted → name still resolves via chain
records, DNS records disappear until republished. Hostile gateway can refuse writes but cannot
forge them; users can PUT directly to Sia with their own credentials to bypass.
</div>
</section>
<section id="host">
<h2>Host your name</h2>
<p class="lede">The end-to-end recipe for putting a static site under a BCNR name. Chipnet
@ -207,7 +385,7 @@ node Argus/src/update.js myname.x '{"s3":"bns/myname/"}'</pre>
node Argus/src/update.js myname.x '{"ip":"1.2.3.4","tls":"&lt;sha256-of-leaf-cert&gt;"}'</pre>
<h3>Pattern C — Dual host (Sia primary, VPS mirror)</h3>
<p class="lede">What sirius.x itself uses. Sia is the chain-authoritative source (survives
<p class="lede">What Sirius.X itself uses. Sia is the chain-authoritative source (survives
if the VPS is down); the VPS serves the same content on <code>silentmode.st/&lt;path&gt;</code>
for users without a BCNR resolver installed. On the VPS side, extend the nginx vhost
serving <code>silentmode.st</code> with a new <code>location</code> block that aliases
@ -222,6 +400,71 @@ node Argus/src/update.js myname.x '{"ip":"1.2.3.4","tls":"&lt;sha256-of-leaf-cer
<code>https://silentmode.st/myname-x/</code> (VPS-direct) and the chain-authoritative
<code>https://myname.x/</code> via any BCNR resolver.</p>
<h3>The dual-host recipe, end to end</h3>
<p class="lede">This is the exact sequence Sirius.X itself uses on every publish. The
chain record stays constant; only file contents change, so no per-publish UPD is
needed.</p>
<ol class="steps">
<li><b>Edit locally.</b>
<span>Site source lives at <code>site-myname-x/</code> in your working repo. Any
static generator works (or plain HTML) — the deploy is content-agnostic.</span></li>
<li><b>Push VPS mirror (fast path).</b>
<span>Serves at <code>silentmode.st/myname-x/</code> within seconds. Users without a
BCNR resolver hit this route.
<pre>scp -r site-myname-x/* silentmode:/opt/silent-mode/site-myname-x/</pre></span></li>
<li><b>Push Sia mirror (durable copy).</b>
<span>Serves at <code>sirius.x/</code> via any BCNR gateway. Survives VPS outage.
<pre>node Argus/src/lib/sia-upload.js site-myname-x/ bns/myname/</pre></span></li>
<li><b>Verify both.</b>
<span><code>curl -so /dev/null -w "%{http_code}\n" https://silentmode.st/myname-x/</code>
and <code>curl -so /dev/null -w "%{http_code}\n" https://silentmode.st/bns/myname.x/</code>
— both should return 200.</span></li>
</ol>
<h3>Auto-backup: one command, both mirrors</h3>
<p class="lede">Wrap the two commands into a script so every publish reaches both mirrors
without extra thought. This is exactly what a two-liner deploy hook looks like:</p>
<pre># scripts/deploy-myname-x.sh
#!/usr/bin/env bash
set -eu
SRC="$(dirname "$0")/../site-myname-x"
VPS_DEST="silentmode:/opt/silent-mode/site-myname-x/"
SIA_BUCKET="bns/myname/"
echo "→ VPS mirror"
scp -qr "$SRC"/. "$VPS_DEST"
echo "→ Sia mirror"
node "$(dirname "$0")/../Argus/src/lib/sia-upload.js" "$SRC" "$SIA_BUCKET"
echo "✓ deployed; verifying"
for url in "https://silentmode.st/myname-x/" "https://silentmode.st/bns/myname.x/"; do
code=$(curl -so /dev/null -w '%{http_code}' "$url")
printf ' %s → %s\n' "$url" "$code"
done</pre>
<p class="lede">Wire it into git: <code>chmod +x scripts/deploy-myname-x.sh</code>, add a
<code>.git/hooks/post-commit</code> that runs it if the site subtree changed, or invoke
manually. Sia uploads that fail (network hiccup, quota) leave the VPS mirror ahead until
the next run — same failure mode as any staged deploy.</p>
<h3>Automate the reverse — VPS → Sia periodic backup</h3>
<p class="lede">If your primary publish path is straight-to-VPS (nginx-direct, no Sia
step per publish), a cron job can pull the VPS state and push to Sia on a schedule:</p>
<pre># /etc/cron.d/sirius-x-sia-backup (on the operator's VPS)
17 * * * * root cd /opt/silent-mode && node Argus/src/lib/sia-upload.js \
/opt/silent-mode/site-myname-x/ bns/myname/ &gt;/var/log/sia-backup.log 2&gt;&amp;1</pre>
<p class="lede">Runs hourly at :17 (offset from the top of the hour so it doesn't collide
with everyone else's cron traffic). The tradeoff: up to an hour of drift between VPS
and Sia after a publish — usually fine, since the chain record still resolves
correctly either way and BCNR gateways cache Sia content.</p>
<div class="note"><b>Which mirror is authoritative?</b> The one your chain record points
at. If <code>s3</code> is set, gateways fetch from Sia; the VPS mirror is just a
convenience URL. If only <code>ip</code> is set, gateways fetch from the VPS; Sia is
just backup. If BOTH are set, gateways pick per the priority in the "Records" section
(subdomain-aware; see <code>record-picker.js</code>). Set both for durability, but be
deliberate about which is primary.</div>
<h3>Verify records changed correctly</h3>
<pre>node --input-type=module -e "
import { loadWallet } from './Argus/src/lib/wallet.js';
@ -279,6 +522,7 @@ process.exit(0);"</pre>
owner collects a share (<code>fee_bps</code>, default 5%, cap 50%). Chain-enforced when
the TLD's policy is <code>covenant</code>; honour-system otherwise. Name registration is
yearly and priced separately.</p>
<p class="lede" style="margin-top:1rem">The TLD owner also sets what names under it <b>sell for</b> and whether the TLD is <b>on or off</b>, straight from the portal: a <code>price</code> record (flat USD per name, replaces the length tiers for every buyer) and a <code>hidden</code> record (<code>1</code> makes it a <b>private TLD</b>: off the public list, nobody but the owner can register names under it — the owner still can from the portal, paying only the platform share — until it is switched back on). Both ride the same signed <code>TUPD</code>, so every client reads them from the chain; the owner keeps 90% of each sale.</p>
</section>
<section id="tracker">
@ -356,12 +600,13 @@ process.exit(0);"</pre>
</div>
</div>
<footer>
Documentation for BCNR + the sirius.x stack ·
<a href="../">back to sirius.x</a> ·
<a href="https://silentmode.st/tlds/">TLD registry snapshot</a> ·
<a href="https://silentmode.st/sirius/register.html">register a name</a>
</footer>
<footer id="site-footer"></footer>
<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 defer src="../js/site-footer.js?v=20260917market"></script>
<script defer src="../js/theme.js?v=20260910font"></script>
<script defer src="../js/profile-menu.js?v=20260920m"></script>
</body>
</html>

612
i18n/de.json Normal file
View file

@ -0,0 +1,612 @@
{
"Sirius.X — the home for names on Bitcoin Cash": "Sirius.X — das Zuhause für Namen auf Bitcoin Cash",
"Portal — your names on Sirius.X": "Portal — deine Namen auf Sirius.X",
"Register a TLD — Sirius.X": "TLD registrieren — Sirius.X",
"Try it": "Ausprobieren",
"✏️ Register": "✏️ Registrieren",
"🌐 TLD": "🌐 TLD",
"🔑 Sign in": "🔑 Anmelden",
"type a name — e.g. hello": "Namen eingeben — z. B. hallo",
"Search a name across every BCNR TLD": "Einen Namen in allen BCNR-TLDs suchen",
"Names on the": "Namen auf der",
"chain": "Kette",
"Sirius.X is the entry point for BCNR — Bitcoin Cash Name Registry. Register a top-level domain, register a name under one, look up records, verify anything against the chain.": "Sirius.X ist der Einstieg in BCNR — die Bitcoin Cash Name Registry. Registriere eine Top-Level-Domain, registriere einen Namen darunter, schlage Einträge nach und prüfe alles gegen die Kette.",
"One search checks the label across every TLD in the registry. Available names appear first.": "Eine Suche prüft das Label in jeder TLD des Registers. Verfügbare Namen erscheinen zuerst.",
"Or browse what you can do →": "Oder sieh dir an, was du tun kannst →",
"Read the docs": "Dokumentation lesen",
"Three things you can do right now. The registrar and TLD-registry UIs live at silentmode.st today; Sirius.X is the canonical home and will consolidate them here.": "Drei Dinge, die du sofort tun kannst. Registrar und TLD-Register laufen heute auf silentmode.st; Sirius.X ist das eigentliche Zuhause und führt sie hier zusammen.",
"Register a name": "Namen registrieren",
"Pick a label, search across every TLD in the registry at once, mint the name certificate straight into your own wallet. No yearly renewal.": "Wähle ein Label, durchsuche alle TLDs des Registers auf einmal und präge das Namenszertifikat direkt in dein eigenes Wallet. Keine jährliche Verlängerung.",
"≈ 10,000 sat service fee · 1,300 sat chain dust · < 1 ¢": "≈ 10.000 sat Servicegebühr · 1.300 sat Chain-Dust · < 1 ¢",
"Chipnet placeholder. 90 % of the service fee flows to the TLD owner, 10 % to the platform.": "Chipnet-Platzhalter. 90 % der Servicegebühr gehen an den TLD-Inhaber, 10 % an die Plattform.",
"Search a name →": "Namen suchen →",
"Register a TLD": "TLD registrieren",
"A TLD is itself a certificate on the chain. Anyone can mint one — you become the registry operator for every second-level name under it, and earn 90 % of the fee on every name registered under it. Renewals are per-TLD policy set by the owner.": "Eine TLD ist selbst ein Zertifikat auf der Kette. Jeder kann eine prägen — du wirst Registerbetreiber für jeden Second-Level-Namen darunter und verdienst 90 % der Gebühr jedes darunter registrierten Namens. Verlängerungen legt der Inhaber pro TLD fest.",
"≈ 1,250,000 sat service fee (≈ $5) · 1,300 sat chain dust": "≈ 1.250.000 sat Servicegebühr (≈ 5 $) · 1.300 sat Chain-Dust",
"Chipnet placeholder rate — mainnet will price by label length via an on-chain oracle.": "Chipnet-Platzhalterkurs — im Mainnet richtet sich der Preis per On-Chain-Orakel nach der Label-Länge.",
"Search a TLD →": "TLD suchen →",
"Operator admin →": "Betreiber-Admin →",
"Look up & verify": "Nachschlagen & prüfen",
"Resolve any BCNR name, compare records across mirrors, and check the TLD registry snapshot against the chain. Everything is publicly verifiable.": "Löse jeden BCNR-Namen auf, vergleiche Einträge über Spiegel hinweg und prüfe den Snapshot des TLD-Registers gegen die Kette. Alles ist öffentlich nachprüfbar.",
"How to verify →": "So prüfst du →",
"🔑 Sign in — your names portal": "🔑 Anmelden — dein Namensportal",
"Import your seed phrase or connect a wallet (Cashonize / Paytaca via WizardConnect) to see every name you own, review records, and update them. Your keys never leave your browser.": "Importiere deine Seed-Phrase oder verbinde ein Wallet (Cashonize / Paytaca über WizardConnect), um jeden Namen zu sehen, den du besitzt, Einträge zu prüfen und zu ändern. Deine Schlüssel verlassen nie deinen Browser.",
"Open the portal →": "Portal öffnen →",
"🧭 Theseus Navigator": "🧭 Theseus Navigator",
"The browser that speaks BCNR natively. Open": "Der Browser, der BCNR nativ spricht. Öffne",
"in the address bar — it just resolves. TLS verified against on-chain fingerprints, no OS trust-store install.": "in der Adressleiste — es löst einfach auf. TLS wird gegen On-Chain-Fingerabdrücke geprüft, keine Installation im Zertifikatspeicher des Systems.",
"Download →": "Herunterladen →",
"Documentation": "Dokumentation",
"The full docs — TLD registry model, record types, resolver & gateway paths, mainnet pricing, verification, and the operator runbook pointer — live on their own page so they can grow without cluttering the landing.": "Die vollständige Dokumentation — TLD-Registermodell, Eintragstypen, Resolver- und Gateway-Pfade, Mainnet-Preise, Verifikation und der Verweis aufs Betreiber-Runbook — hat ihre eigene Seite, damit sie wachsen kann, ohne die Startseite zu überladen.",
"📚 Open the docs →": "📚 Dokumentation öffnen →",
"Current TLD list": "Aktuelle TLD-Liste",
"Propose a new TLD": "Neue TLD vorschlagen",
"The per-TLD registry means minting a TLD is a real, paid action — not a namespace land-grab. During the alpha, all TLD mints are operator-signed. To propose a TLD, get in touch via the channels below. The design (mainnet) adds an on-chain covenant with countersignature + tiered USD price floors: 1-char $100k, 2-char $50k, 3-char $15k, 4-char $5k, 5–8-char $1k, 9+-char $250; one-time payment (not annual). See the design doc for the full model.": "Das Register pro TLD bedeutet: Eine TLD zu prägen ist eine echte, bezahlte Handlung — kein Landraub im Namensraum. Während der Alpha werden alle TLD-Prägungen vom Betreiber signiert. Um eine TLD vorzuschlagen, melde dich über die Kanäle unten. Das Design (Mainnet) ergänzt einen On-Chain-Covenant mit Gegensignatur und gestaffelten USD-Mindestpreisen: 1 Zeichen 100 k$, 2 Zeichen 50 k$, 3 Zeichen 15 k$, 4 Zeichen 5 k$, 5–8 Zeichen 1 k$, 9+ Zeichen 250 $; Einmalzahlung (nicht jährlich). Das vollständige Modell steht im Design-Dokument.",
"ICANN-adjacent TLDs are not open for public mint.": "ICANN-nahe TLDs sind nicht öffentlich prägbar.",
"A TLD registry is only useful if it does not immediately collapse into an ICANN-shadow — the mainnet covenant enforces this; on chipnet the operator's countersignature is the gate.": "Ein TLD-Register ist nur nützlich, wenn es nicht sofort zu einem ICANN-Schatten zusammenfällt — im Mainnet erzwingt das der Covenant; im Chipnet ist die Gegensignatur des Betreibers die Schranke.",
"The pantheon": "Das Pantheon",
"Sirius.x is one of seven sibling": "Sirius.x ist einer von sieben verwandten",
"names — the Silent Mode pantheon. Each project is its own on-chain certificate; each site is reachable through any BCNR resolver, plus the silentmode.st gateway for browsers without one.": "-Namen — das Silent-Mode-Pantheon. Jedes Projekt ist ein eigenes On-Chain-Zertifikat; jede Seite ist über jeden BCNR-Resolver erreichbar, plus das silentmode.st-Gateway für Browser ohne Resolver.",
"⛓️ Silentmode.X": "⛓️ Silentmode.X",
"The project umbrella. Redirects to": "Das Dach des Projekts. Leitet weiter zu",
"where every pillar has its own landing page + download hub.": "wo jede Säule ihre eigene Startseite und Downloads hat.",
"Open →": "Öffnen →",
"⭐ Sirius.X": "⭐ Sirius.X",
"you're here": "du bist hier",
"Names on Bitcoin Cash — register, resolve, verify, manage. This site.": "Namen auf Bitcoin Cash — registrieren, auflösen, prüfen, verwalten. Diese Seite.",
"Home →": "Start →",
"🧭 Theseus.X": "🧭 Theseus.X",
"The browser that speaks BCNR natively — Chromium build with the resolver baked in, no OS-level daemon or root-store install.": "Der Browser, der BCNR nativ spricht — ein Chromium-Build mit eingebautem Resolver, ohne System-Daemon oder Root-Zertifikat.",
"Learn more →": "Mehr erfahren →",
"🔥 Hephaestus.X": "🔥 Hephaestus.X",
"The forge. Forgejo instance for the ecosystem's git repos, backed by BCH wallet auth. Sirius's own source lives here.": "Die Schmiede. Forgejo-Instanz für die Git-Repos des Ökosystems, mit BCH-Wallet-Login. Der Quellcode von Sirius liegt hier.",
"🔮 Prometheus.X": "🔮 Prometheus.X",
"Fire from the chain. The project's foresight / experimentation layer. Redirects to": "Feuer aus der Kette. Die Ebene für Vorausschau und Experimente. Leitet weiter zu",
"today.": "(heute).",
"☀️ Helios.X": "☀️ Helios.X",
"The public gaze. Analytics, dashboards, transparency reports. Redirects to": "Der öffentliche Blick. Analysen, Dashboards, Transparenzberichte. Leitet weiter zu",
"✉️ Hermes.X": "✉️ Hermes.X",
"Messenger. Nostr-based messaging bound to a BCNR name via the": "Messenger. Nostr-basierte Nachrichten, an einen BCNR-Namen gebunden über die",
"records. Redirects to": "-Einträge. Leitet weiter zu",
"What's coming": "Was kommt",
"Sirius.X consolidates docs and registration today; three larger pieces are on the roadmap.": "Sirius.X bündelt heute Dokumentation und Registrierung; drei größere Bausteine stehen auf der Roadmap.",
"Wallet & name portal": "Wallet- & Namensportal",
"next": "als Nächstes",
"Sign in with your Bitcoin Cash wallet, see every name you own, edit records inline, mint or renew from one place. Same self-custody as today — the portal never handles your keys.": "Melde dich mit deinem Bitcoin-Cash-Wallet an, sieh jeden Namen, den du besitzt, bearbeite Einträge direkt, präge oder verlängere an einem Ort. Dieselbe Selbstverwahrung wie heute — das Portal fasst deine Schlüssel nie an.",
"Sirius Studio": "Sirius Studio",
"planned": "geplant",
"An in-browser site editor for names you already own — the WordPress / Tilda / Wix pattern, but the whole site persists to Sia and the name's": "Ein Website-Editor im Browser für Namen, die du bereits besitzt — das Muster von WordPress / Tilda / Wix, nur dass die ganze Seite auf Sia liegt und der",
"record updates on save. Sites live where the name says they live.": "-Eintrag des Namens beim Speichern aktualisiert wird. Seiten liegen dort, wo der Name es sagt.",
"Decentralized git remote": "Dezentrales Git-Remote",
"MVP live": "MVP läuft",
"The Silent Mode repo is served as a bare git tree over dumb-HTTP from the VPS. Clone it with any git client, no login. Forgejo + Sia sync for a proper decentralized backend is the next track.": "Das Silent-Mode-Repo wird als bare Git-Baum über dumb-HTTP vom VPS ausgeliefert. Klone es mit jedem Git-Client, ohne Login. Forgejo + Sia-Sync als richtig dezentrales Backend ist der nächste Schritt.",
"One-shot snapshot as a downloadable git bundle (works when dumb-HTTP is blocked):": "Einmaliger Snapshot als herunterladbares Git-Bundle (funktioniert, wenn dumb-HTTP blockiert ist):",
"Verify this page against the chain": "Diese Seite gegen die Kette prüfen",
"You do not have to trust that": "Du musst nicht darauf vertrauen, dass",
"is served by anyone specific. The name's certificate is on the Bitcoin Cash chain; the records point to Sia; every path is independently checkable.": "von jemand Bestimmtem ausgeliefert wird. Das Zertifikat des Namens liegt auf der Bitcoin-Cash-Kette; die Einträge zeigen auf Sia; jeder Pfad ist unabhängig prüfbar.",
"1. Confirm the certificate exists on chain": "1. Bestätige, dass das Zertifikat auf der Kette existiert",
"2. Fetch the TLD-registry snapshot from Nostr": "2. Hole den Snapshot des TLD-Registers von Nostr",
"The operator-signed snapshot of the TLD list is published as a Nostr replaceable event. Any relay carries it; the event's content field carries the current snapshot root.": "Der vom Betreiber signierte Snapshot der TLD-Liste wird als ersetzbares Nostr-Event veröffentlicht. Jedes Relay trägt es; das Content-Feld des Events enthält die aktuelle Snapshot-Wurzel.",
"Kind / d-tag": "Kind / d-Tag",
"Pubkey (x-only, hex)": "Pubkey (x-only, hex)",
"Relays": "Relays",
"3. Reach this site via more than one route": "3. Erreiche diese Seite über mehr als einen Weg",
"The same content should be served from at least two independent paths. If one mirror is unavailable, the others still work. If two mirrors disagree, the on-chain record is the tiebreaker.": "Derselbe Inhalt sollte über mindestens zwei unabhängige Pfade ausgeliefert werden. Fällt ein Spiegel aus, funktionieren die anderen weiter. Widersprechen sich zwei Spiegel, entscheidet der On-Chain-Eintrag.",
"Via any BCNR resolver:": "Über jeden BCNR-Resolver:",
"(requires the local root CA)": "(braucht die lokale Root-CA)",
"Via the public gateway:": "Über das öffentliche Gateway:",
"Via silentmode.st mirror:": "Über den silentmode.st-Spiegel:",
"Direct from Sia (content-addressed): the": "Direkt von Sia (inhaltsadressiert): der",
"record on": "-Eintrag auf",
"names the exact bucket key": "nennt den exakten Bucket-Schlüssel",
"Register a": "Registriere eine",
"A TLD is a certificate on the Bitcoin Cash chain. You mint it, you own it — any second-level name registered under it lives in your TLD's registry. One BCH transaction, no ICANN. Renewals? Your TLD, your policy.": "Eine TLD ist ein Zertifikat auf der Bitcoin-Cash-Kette. Du prägst sie, du besitzt sie — jeder darunter registrierte Second-Level-Name lebt im Register deiner TLD. Eine BCH-Transaktion, keine ICANN. Verlängerungen? Deine TLD, deine Regeln.",
"Search a TLD": "TLD suchen",
"Type a label (a–z, 0–9, hyphen; up to 16 chars). Available TLDs get a Register button that opens the shared wallet-choice modal — the same flow name registration uses. As TLD owner you earn": "Gib ein Label ein (a–z, 0–9, Bindestrich; bis 16 Zeichen). Verfügbare TLDs bekommen einen Registrieren-Button, der den gemeinsamen Wallet-Dialog öffnet — derselbe Ablauf wie bei der Namensregistrierung. Als TLD-Inhaber verdienst du",
"of every name registered under your TLD. Renewals are your call — set them per TLD, or don't.": "jedes unter deiner TLD registrierten Namens. Verlängerungen bestimmst du — pro TLD, oder gar nicht.",
"Register minting to your token address; you become the registry operator.": "Die Registrierung prägt an deine Token-Adresse; du wirst Registerbetreiber.",
"Registered TLDs": "Registrierte TLDs",
"Fetched from the on-chain TLD registry via the public gateway. Refresh the page for the latest.": "Aus dem On-Chain-TLD-Register über das öffentliche Gateway geladen. Seite neu laden für den aktuellen Stand.",
"Loading…": "Lädt…",
"Mint price": "Prägepreis",
"Category": "Kategorie",
"Portal sections": "Portalbereiche",
"Your": "Dein",
"names": "Namen",
"portal": "Portal",
"Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see every BCNR name your wallet holds. Your keys never leave this browser tab.": "Melde dich mit deiner Bitcoin-Cash-Seed-Phrase an oder verbinde ein externes Wallet, um jeden BCNR-Namen zu sehen, den dein Wallet hält. Deine Schlüssel verlassen nie diesen Browser-Tab.",
"Sign in or create a wallet": "Anmelden oder Wallet erstellen",
"The same wallet that will hold your names does the signing. Pick a tab — everything happens on this page; keys never leave your browser.": "Dasselbe Wallet, das deine Namen halten wird, signiert. Wähle einen Tab — alles passiert auf dieser Seite; Schlüssel verlassen nie deinen Browser.",
"Overview": "Übersicht",
"Names": "Namen",
"TLDs": "TLDs",
"Wallet": "Wallet",
"Settings": "Einstellungen",
"A snapshot of what this wallet holds on chain.": "Ein Überblick, was dieses Wallet auf der Kette hält.",
"Names held": "Gehaltene Namen",
"CashTokens NFT certificates": "CashTokens-NFT-Zertifikate",
"TLDs owned": "Eigene TLDs",
"Per-TLD registry NFTs": "Register-NFTs pro TLD",
"Wallet balance": "Wallet-Guthaben",
"chipnet sats": "Chipnet-Sats",
"Chain height": "Kettenhöhe",
"Last seen block": "Zuletzt gesehener Block",
"+ Register a name": "+ Namen registrieren",
"+ Register a TLD": "+ TLD registrieren",
"Names you hold": "Deine Namen",
"Every BCNR name your wallet's addresses currently hold a CashTokens NFT for. Edit records inline to publish an on-chain UPD.": "Jeder BCNR-Name, für den die Adressen deines Wallets gerade ein CashTokens-NFT halten. Bearbeite Einträge direkt, um ein On-Chain-UPD zu veröffentlichen.",
"Loading names from the chain…": "Namen werden von der Kette geladen…",
"TLDs you own": "Deine TLDs",
"Every per-TLD registry NFT held by this wallet. Set the": "Jedes Register-NFT, das dieses Wallet hält. Lege den",
"price": "Preis",
"every name under your TLD sells for, switch the TLD": "fest, zu dem jeder Name unter deiner TLD verkauft wird, schalte die TLD im öffentlichen Register",
"on or off": "ein oder aus",
"in the public registry (off = a": "(aus = eine",
"private TLD": "private TLD",
": nobody else can buy names under it, you still can from here), and tune policy —": ": niemand sonst kann Namen darunter kaufen, du von hier aus schon) und stimme die Regeln ab —",
"fee": "Gebühr",
"min length": "Mindestlänge",
"reserved labels": "reservierte Labels",
"renewal period": "Verlängerungszeitraum",
". Every change is one signed TUPD on chain; you receive 90% of each sale.": ". Jede Änderung ist ein signiertes TUPD auf der Kette; du erhältst 90 % jedes Verkaufs.",
"Loading TLDs from the chain…": "TLDs werden von der Kette geladen…",
"Register a new TLD": "Neue TLD registrieren",
"TLDs are per-registry NFTs on the chipnet TLD beacon. Public mints go through a service-fee output to fund the registry. Chipnet uses a placeholder rate; mainnet will price by label length via a real oracle.": "TLDs sind Register-NFTs auf dem Chipnet-TLD-Beacon. Öffentliche Prägungen zahlen eine Servicegebühr, die das Register finanziert. Chipnet nutzt einen Platzhalterkurs; im Mainnet bestimmt ein echtes Orakel den Preis nach Label-Länge.",
"Label": "Label",
"1–16 chars, [a-z0-9-]": "1–16 Zeichen, [a-z0-9-]",
"Service fee (USD)": "Servicegebühr (USD)",
"chipnet test rate": "Chipnet-Testkurs",
"sats · rate": "sats · Kurs",
"sats/USD": "sats/USD",
"Check availability": "Verfügbarkeit prüfen",
"Register (~0 sats)": "Registrieren (~0 sats)",
"Your addresses and current balance. Keys stay in this browser.": "Deine Adressen und dein aktuelles Guthaben. Schlüssel bleiben in diesem Browser.",
"Receive address": "Empfangsadresse",
"Token address": "Token-Adresse",
"holds your name certificates": "hält deine Namenszertifikate",
"Faucet →": "Faucet →",
"Reader preferences live per-browser; wallet changes require a signature.": "Leseeinstellungen gelten pro Browser; Wallet-Änderungen brauchen eine Signatur.",
"Reading font": "Leseschrift",
"Fraunces (Silent Mode family) or Ubuntu (Bitcoin Cash brand font). The pill lives in the top nav.": "Fraunces (Silent-Mode-Familie) oder Ubuntu (Bitcoin-Cash-Markenschrift). Der Umschalter sitzt oben in der Navigation.",
"Session PIN": "Sitzungs-PIN",
"PIN unlocks the wallet without re-typing your password. Wipes after 3 wrong attempts.": "Die PIN entsperrt das Wallet, ohne das Passwort erneut einzugeben. Wird nach 3 Fehlversuchen gelöscht.",
"Sign out": "Abmelden",
"Clears the signed-in state in this browser. Your on-chain names are unaffected.": "Löscht den Anmeldestatus in diesem Browser. Deine On-Chain-Namen bleiben unberührt.",
"Edit records. Only your key can sign this UPD; the transaction fee is a few cents in chain fees plus the beacon dust. Leave a field blank to omit that record.": "Einträge bearbeiten. Nur dein Schlüssel kann dieses UPD signieren; die Transaktion kostet ein paar Cent Kettengebühr plus Beacon-Dust. Lass ein Feld leer, um den Eintrag wegzulassen.",
"inline HTML — served as-is at the site root": "Inline-HTML — wird unverändert im Seiten-Root ausgeliefert",
"Sia bucket key, trailing slash for directories": "Sia-Bucket-Schlüssel, Schrägstrich am Ende für Verzeichnisse",
"IPv4 that serves this name over Host header": "IPv4, die diesen Namen über den Host-Header ausliefert",
"SHA-256 of your leaf cert — chain-pinned TLS trust": "SHA-256 deines Leaf-Zertifikats — an die Kette gepinntes TLS-Vertrauen",
"redirect target": "Weiterleitungsziel",
"payload:": "Payload:",
"bytes": "Bytes",
"Cancel": "Abbrechen",
"Save records →": "Einträge speichern →",
"DNS records for": "DNS-Einträge für",
"DNS-style records live in a signed manifest on Sia — not on chain.": "DNS-Einträge liegen in einem signierten Manifest auf Sia — nicht auf der Kette.",
"Free per edit": "Kostenlos pro Änderung",
", no size cap. The signature proves you own the name; the gateway rejects anything not signed by the current NFT holder. See": ", ohne Größenlimit. Die Signatur beweist, dass der Name dir gehört; das Gateway lehnt alles ab, was nicht vom aktuellen NFT-Inhaber signiert ist. Siehe",
"docs": "Doku",
"IPv4 addresses, one per line": "IPv4-Adressen, eine pro Zeile",
"IPv6 addresses, one per line": "IPv6-Adressen, eine pro Zeile",
"one string per line (SPF, DKIM, verification tokens…)": "eine Zeichenkette pro Zeile (SPF, DKIM, Verifizierungs-Tokens…)",
"one target host, or blank": "ein Zielhost, oder leer",
"nameservers, one per line": "Nameserver, einer pro Zeile",
"Sign & publish →": "Signieren & veröffentlichen →",
"Policy for": "Regeln für",
"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).": "Lege die Regeln für Namen unter dieser TLD fest. Nur dein Schlüssel kann dieses TUPD signieren; die Transaktion kostet ein paar Cent Chain-Dust. Lass ein Feld leer, um die Regel wegzulassen (Standard: offene Regel, Staffelpreise).",
"USD per name — flat, shown to every buyer; blank = length tiers. You receive 90% of each sale.": "USD pro Name — pauschal, wird jedem Käufer angezeigt; leer = Längenstaffel. Du erhältst 90 % jedes Verkaufs.",
"listing": "Listung",
"off hides the TLD from search and blocks new registrations until you switch it back on": "aus versteckt die TLD in der Suche und blockiert neue Registrierungen, bis du sie wieder einschaltest",
"On — listed, names for sale": "Ein — gelistet, Namen zum Verkauf",
"Off — hidden, not for sale": "Aus — versteckt, nicht zum Verkauf",
"reject names shorter than N chars": "Namen kürzer als N Zeichen ablehnen",
"service fee owner takes, in basis points (500 = 5%)": "Anteil des Inhabers an der Servicegebühr, in Basispunkten (500 = 5 %)",
"open · frozen · reserved-only": "open · frozen · reserved-only",
"space-separated labels only owner can mint": "durch Leerzeichen getrennte Labels, die nur der Inhaber prägen kann",
"days between renewals, 0 = never expire": "Tage zwischen Verlängerungen, 0 = läuft nie ab",
"renewal price in sats, 0 = free": "Verlängerungspreis in Sats, 0 = kostenlos",
"where the TLD's own landing lives": "wo die eigene Startseite der TLD liegt",
"Save policy →": "Regeln speichern →",
"Signed in": "Angemeldet",
"You are signed in as": "Du bist angemeldet als",
"Done": "Fertig",
"Close": "Schließen",
"Unlock my browser wallet": "Mein Browser-Wallet entsperren",
"You already created one on this device.": "Du hast auf diesem Gerät bereits eines erstellt.",
"Create a new wallet": "Neues Wallet erstellen",
"easiest": "am einfachsten",
"Made here in your browser. You get a recovery phrase to write down — it is the only key.": "Direkt hier im Browser erstellt. Du bekommst eine Wiederherstellungsphrase zum Aufschreiben — sie ist der einzige Schlüssel.",
"Import a recovery phrase": "Wiederherstellungsphrase importieren",
"Restore a wallet you already have, from its 12-word phrase.": "Stelle ein vorhandenes Wallet aus seiner 12-Wort-Phrase wieder her.",
"Connect a wallet — WizardConnect": "Wallet verbinden — WizardConnect",
"most private": "am privatesten",
"Cashonize 0.9+ or Paytaca. Encrypted end-to-end over Nostr; the relay sees only ciphertext. Your keys never leave your wallet.": "Cashonize 0.9+ oder Paytaca. Ende-zu-Ende verschlüsselt über Nostr; das Relay sieht nur Chiffretext. Deine Schlüssel verlassen nie dein Wallet.",
"Everything below runs on": "Alles hier unten läuft auf",
", Bitcoin Cash's test network. The coins are free and worth nothing — this is an alpha, and it is the honest place to try it before real money is involved.": ", dem Testnetz von Bitcoin Cash. Die Coins sind kostenlos und wertlos — das ist eine Alpha und der ehrliche Ort, es auszuprobieren, bevor echtes Geld im Spiel ist.",
"Starting the connection…": "Verbindung wird aufgebaut…",
"Back": "Zurück",
"Open your wallet": "Öffne dein Wallet",
"Copy": "Kopieren",
"Waiting for your wallet… The link stays valid until you close this page.": "Warte auf dein Wallet… Der Link bleibt gültig, bis du diese Seite schließt.",
"Connected": "Verbunden",
"Reading your wallet and building the registration…": "Wallet wird gelesen und die Registrierung vorbereitet…",
"That wallet is empty": "Dieses Wallet ist leer",
"Two approvals needed.": "Zwei Freigaben nötig.",
"Register — approve in your wallet": "Registrieren — in deinem Wallet bestätigen",
"Approve in your wallet": "In deinem Wallet bestätigen",
"Create your wallet": "Erstelle dein Wallet",
"Generated in this browser. The phrase is never sent anywhere — not to us, not to anyone.": "In diesem Browser erzeugt. Die Phrase wird nirgendwohin gesendet — nicht an uns, an niemanden.",
"Password (encrypts the wallet on this device)": "Passwort (verschlüsselt das Wallet auf diesem Gerät)",
"Repeat password": "Passwort wiederholen",
"There is no reset.": "Es gibt kein Zurücksetzen.",
"Generate phrase →": "Phrase erzeugen →",
"Write this down. Now.": "Schreib das auf. Jetzt.",
"These 12 words are your wallet. Anyone who has them owns your names; if you lose them, nobody — including us — can recover anything.": "Diese 12 Wörter sind dein Wallet. Wer sie hat, besitzt deine Namen; verlierst du sie, kann niemand — auch wir nicht — irgendetwas wiederherstellen.",
"Copy phrase": "Phrase kopieren",
"I have written the phrase down somewhere safe and offline. I understand it cannot be reset.": "Ich habe die Phrase sicher und offline aufgeschrieben. Ich verstehe, dass sie nicht zurückgesetzt werden kann.",
"Continue →": "Weiter →",
"12 words, separated by spaces. It stays in this browser.": "12 Wörter, durch Leerzeichen getrennt. Sie bleiben in diesem Browser.",
"Recovery phrase": "Wiederherstellungsphrase",
"Password to encrypt it on this device": "Passwort zum Verschlüsseln auf diesem Gerät",
"Import →": "Importieren →",
"No wallet on this device": "Kein Wallet auf diesem Gerät",
"📥 Import a wallet →": "📥 Wallet importieren →",
"🆕 Create a wallet →": "🆕 Wallet erstellen →",
"Enter your PIN": "PIN eingeben",
"Use password instead": "Stattdessen Passwort verwenden",
"Unlock →": "Entsperren →",
"PIN reset": "PIN zurückgesetzt",
"3 wrong attempts — the PIN has been cleared. Enter your password to unlock and set a new PIN if you like.": "3 Fehlversuche — die PIN wurde gelöscht. Gib dein Passwort ein, um zu entsperren, und lege bei Bedarf eine neue PIN fest.",
"Continue with password →": "Mit Passwort fortfahren →",
"Unlock your wallet": "Wallet entsperren",
"Decrypts the wallet stored in this browser. After unlocking you can set a PIN so future sessions ask for 4–6 digits instead of the full password.": "Entschlüsselt das in diesem Browser gespeicherte Wallet. Nach dem Entsperren kannst du eine PIN festlegen, damit künftige Sitzungen nur 4–6 Ziffern statt des ganzen Passworts abfragen.",
"Password": "Passwort",
"Set a PIN": "PIN festlegen",
"optional": "optional",
"Repeat PIN": "PIN wiederholen",
"Not now": "Jetzt nicht",
"Save PIN →": "PIN speichern →",
"Fund your wallet": "Wallet aufladen",
"Send test coins to this address. It is yours — derived from your phrase.": "Sende Test-Coins an diese Adresse. Sie gehört dir — abgeleitet aus deiner Phrase.",
"checking balance…": "Guthaben wird geprüft…",
"Preparing…": "Vorbereitung…",
"Building your registration transaction.": "Deine Registrierungstransaktion wird gebaut.",
"One transaction. It mints the certificate to": "Eine Transaktion. Sie prägt das Zertifikat an",
"your": "deine",
"address and pays the fees.": "Adresse und zahlt die Gebühren.",
"The certificate will be minted to": "Das Zertifikat wird geprägt an",
"— your key, your name. You can set where it points immediately afterwards.": "— dein Schlüssel, dein Name. Direkt danach kannst du festlegen, wohin er zeigt.",
"Register — sign & broadcast": "Registrieren — signieren & senden",
"Could not prepare": "Vorbereitung fehlgeschlagen",
"Confirm": "Bestätigen",
"Beacon dust + chain fee": "Beacon-Dust + Kettengebühr",
"(covered by wallet)": "(vom Wallet gedeckt)",
"Minted to": "Geprägt an",
"Service fee waived on chipnet": "Servicegebühr im Chipnet erlassen",
"Approve payment": "Zahlung freigeben",
"Approve →": "Freigeben →",
"Signing in your browser and broadcasting to the chain. Do not close this tab.": "Wird in deinem Browser signiert und an die Kette gesendet. Schließe diesen Tab nicht.",
"Transaction": "Transaktion",
"Certificate ID": "Zertifikats-ID",
"Operator": "Betreiber",
"The certificate is on the chain, held by your key. Nobody can take it back.": "Das Zertifikat ist auf der Kette, gehalten von deinem Schlüssel. Niemand kann es zurücknehmen.",
"Owner": "Inhaber",
"Point it somewhere": "Lass ihn irgendwohin zeigen",
"Optional, and changeable any time — only your key can.": "Optional und jederzeit änderbar — nur mit deinem Schlüssel.",
"Record type": "Eintragstyp",
"A tiny site stored on the chain itself (h)": "Eine winzige Seite direkt auf der Kette (h)",
"Redirect to a web address (u)": "Weiterleitung zu einer Webadresse (u)",
"Your own server's IPv4 address (ip)": "IPv4-Adresse deines eigenen Servers (ip)",
"TLS certificate fingerprint (tls)": "Fingerabdruck des TLS-Zertifikats (tls)",
"Done for now": "Vorerst fertig",
"Publish record": "Eintrag veröffentlichen",
"Publishing record": "Eintrag wird veröffentlicht",
"Update transaction": "Update-Transaktion",
"Finish": "Fertigstellen",
"My names": "Meine Namen",
"records & holdings": "Einträge & Bestände",
"Admin panel": "Admin-Bereich",
"operator tools": "Betreiber-Werkzeuge",
"clear this browser": "diesen Browser leeren",
"Unlock my wallet": "Mein Wallet entsperren",
"one you already created on this device": "eines, das du auf diesem Gerät schon erstellt hast",
"Locked wallet on this device": "Gesperrtes Wallet auf diesem Gerät",
"Unlock or pick another action": "Entsperren oder etwas anderes wählen",
"No wallet yet": "Noch kein Wallet",
"Pick how to sign in": "Wähle, wie du dich anmeldest",
"Create a wallet": "Wallet erstellen",
"generate a fresh 12-word phrase (sign up)": "eine neue 12-Wort-Phrase erzeugen (registrieren)",
"Import a wallet": "Wallet importieren",
"seed phrase you already have (sign in)": "eine Seed-Phrase, die du schon hast (anmelden)",
"Cashonize / Paytaca via QR": "Cashonize / Paytaca per QR",
"The home for names on Bitcoin Cash. Register a TLD, register a name, verify anything against the chain.": "Das Zuhause für Namen auf Bitcoin Cash. Registriere eine TLD, registriere einen Namen, prüfe alles gegen die Kette.",
"Product": "Produkt",
"✏️ Register a name": "✏️ Namen registrieren",
"🌐 Register a TLD": "🌐 TLD registrieren",
"🔑 My names portal": "🔑 Mein Namensportal",
"🧭 Theseus browser": "🧭 Theseus-Browser",
"Learn": "Lernen",
"📚 Docs": "📚 Doku",
"🗺 Roadmap": "🗺 Roadmap",
"🏛 The Pantheon": "🏛 Das Pantheon",
"🎨 Brand kit": "🎨 Markenkit",
"Alpha": "Alpha",
"Chipnet only. You hold your own keys; verify everything against the chain.": "Nur Chipnet. Du hältst deine eigenen Schlüssel; prüfe alles gegen die Kette.",
"brand assets": "Markenmaterial",
"available": "verfügbar",
"taken": "vergeben",
"checking…": "wird geprüft…",
"Register →": "Registrieren →",
"loading…": "lädt…",
"(no records set)": "(keine Einträge gesetzt)",
"on chain": "auf der Kette",
"Edit": "Bearbeiten",
"tier pricing": "Staffelpreis",
"(default policy — open, tier pricing)": "(Standardregel — offen, Staffelpreise)",
"Price & policy": "Preis & Regeln",
"Register a name under": "Namen registrieren unter",
"Preparing your addresses…": "Deine Adressen werden vorbereitet…",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.": "Keine BCNR-Namen für dieses Wallet gefunden. Wenn du gerade registriert hast, warte eine Minute auf die Bestätigung und lade neu.",
"Off-chain DNS records — free per edit": "Off-Chain-DNS-Einträge — kostenlos pro Änderung",
"Signing…": "Signiere…",
"Saved ✓": "Gespeichert ✓",
"Registered ✓": "Registriert ✓",
"Switch on": "Einschalten",
"Switch off": "Ausschalten",
"Switch on: list the TLD and sell names again": "Einschalten: TLD listen und wieder Namen verkaufen",
"Switch off: hide the TLD, stop new registrations": "Ausschalten: TLD verstecken, keine neuen Registrierungen",
"no owner price set — buyers pay the length tier": "kein Inhaberpreis gesetzt — Käufer zahlen die Längenstaffel",
"hidden from the public registry; no new names until you switch it on": "im öffentlichen Register versteckt; keine neuen Namen, bis du sie einschaltest",
"listed in the public registry": "im öffentlichen Register gelistet",
"label": "Label",
"🔓 Unlock": "🔓 Entsperren",
"🆕 Create": "🆕 Erstellen",
"📥 Import": "📥 Importieren",
"Dashboard — your names on Sirius.X": "Dashboard — deine Namen auf Sirius.X",
"dashboard": "Dashboard",
"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.": "Melde dich einmal mit deiner Bitcoin-Cash-Seed-Phrase an oder verbinde ein externes Wallet. Dieses Gerät bleibt angemeldet, bis du dich abmeldest — kein Passwort bei jedem Besuch. Deine Schlüssel verlassen nie diesen Browser.",
"Manage": "Verwalten",
"Domain names": "Domainnamen",
"My TLD list": "Meine TLDs",
"Get more": "Mehr holen",
"Docs": "Doku",
"What this wallet holds on chain, and where to go next.": "Was dieses Wallet auf der Kette hält, und was als Nächstes ansteht.",
"↻ Refresh": "↻ Aktualisieren",
"Recent names": "Neueste Namen",
"The last few certificates that landed in this wallet.": "Die letzten Zertifikate, die in diesem Wallet gelandet sind.",
"Attention": "Achtung",
"Names that point nowhere yet, or have no DNS.": "Namen, die noch nirgendwohin zeigen oder kein DNS haben.",
"Every BCNR name this wallet holds. Open one to manage DNS, content, redirects or transfer it.": "Jeder BCNR-Name in diesem Wallet. Öffne einen, um DNS, Inhalt, Weiterleitungen zu verwalten oder ihn zu übertragen.",
"Filter names…": "Namen filtern…",
"Sort: name": "Sortieren: Name",
"Sort: TLD": "Sortieren: TLD",
"Sort: newest": "Sortieren: neueste",
"All TLDs": "Alle TLDs",
"no DNS": "kein DNS",
"DNS …": "DNS …",
"DNS needs s3": "DNS braucht s3",
"Open site →": "Seite öffnen →",
"Summary": "Übersicht",
"DNS records": "DNS-Einträge",
"Content & hosting": "Inhalt & Hosting",
"Redirect": "Weiterleitung",
"Transfer": "Übertragen",
"Export": "Export",
"Certificate": "Zertifikat",
"Where it points": "Wohin er zeigt",
"On-chain records decide what a resolver serves. Change them under Content & hosting.": "On-Chain-Einträge entscheiden, was ein Resolver ausliefert. Ändere sie unter Inhalt & Hosting.",
"DNS at a glance": "DNS auf einen Blick",
"Signed off-chain records for mail, verification and classic DNS interop.": "Signierte Off-Chain-Einträge für Mail, Verifizierung und klassisches DNS.",
"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.": "Standardeinträge, mit deinem Schlüssel signiert und in einem Manifest auf Sia gespeichert. Kostenlos änderbar, keine Kettentransaktion. Resolver und Gateway prüfen die Signatur gegen den aktuellen NFT-Inhaber.",
"Type": "Typ",
"Value": "Wert",
"Priority / extra": "Priorität / Extra",
"No DNS records yet. Add the first one below.": "Noch keine DNS-Einträge. Füge unten den ersten hinzu.",
"Priority": "Priorität",
"Weight": "Gewicht",
"Port": "Port",
"Tag": "Tag",
"+ Add": "+ Hinzufügen",
"Discard changes": "Änderungen verwerfen",
"Nameservers": "Nameserver",
"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.": "BCNR-Namen brauchen keine Nameserver — Resolver lesen die Kette und dieses Manifest direkt. Füge NS-Einträge nur hinzu, wenn du den Namen auch im klassischen DNS delegierst.",
"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.": "On-Chain-Einträge, veröffentlicht als eine signierte UPD-Transaktion (ein paar Cent Chain-Dust). Feld leer lassen entfernt den Eintrag. Reihenfolge für Resolver: h, dann s3, dann p, dann ip.",
"inline HTML — served as-is at the site root (~150 bytes)": "Inline-HTML — unverändert im Seiten-Root ausgeliefert (~150 Bytes)",
"Sia bucket key, trailing slash for directories — also where DNS manifests live": "Sia-Bucket-Schlüssel, Schrägstrich am Ende für Verzeichnisse — dort liegen auch die DNS-Manifeste",
"reverse proxy: full upstream URL the gateway mirrors": "Reverse-Proxy: vollständige Upstream-URL, die das Gateway spiegelt",
"Reset": "Zurücksetzen",
"Forward this name to any web address. Stored on chain as the": "Leite diesen Namen an eine beliebige Webadresse weiter. Auf der Kette gespeichert als",
"record; resolvers and the gateway issue the redirect. Clear it to stop forwarding.": "-Eintrag; Resolver und Gateway führen die Weiterleitung aus. Leeren beendet sie.",
"Destination URL": "Ziel-URL",
"Remove redirect": "Weiterleitung entfernen",
"Save redirect →": "Weiterleitung speichern →",
"Transfer ownership": "Eigentum übertragen",
"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.": "Überträgt das Zertifikat des Namens in einer Transaktion an eine andere Bitcoin-Cash-Adresse. Einträge bleiben erhalten. Ab dann kontrolliert der neue Inhaber den Namen — von hier aus nicht rückgängig zu machen.",
"Recipient address": "Empfängeradresse",
"I understand this hands the name to that address permanently.": "Ich verstehe, dass der Name damit dauerhaft an diese Adresse übergeht.",
"Transfer name →": "Namen übertragen →",
"Download this name's DNS as a BIND-style zone file, or its full record set as JSON, for backups or importing elsewhere.": "Lade das DNS dieses Namens als BIND-Zonendatei oder alle Einträge als JSON herunter — für Backups oder den Import anderswo.",
"⬇ Zone file (.txt)": "⬇ Zonendatei (.txt)",
"⬇ Records (.json)": "⬇ Einträge (.json)",
"Copy DNS manifest": "DNS-Manifest kopieren",
"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.": "Jedes Register-NFT in diesem Wallet. Lege den Preis fest, zu dem jeder Name unter einer TLD verkauft wird, schalte sie ein oder aus (aus = privat: nur du kannst darunter registrieren) und stimme die Regeln ab. Jede Änderung ist ein signiertes TUPD auf der Kette; du erhältst 90 % jedes Verkaufs.",
"Registry": "Register",
"Register a name under this TLD": "Namen unter dieser TLD registrieren",
"Works whether the TLD is on or off. As the owner you pay only the platform's 10% share.": "Funktioniert, ob die TLD ein- oder ausgeschaltet ist. Als Inhaber zahlst du nur den 10-%-Anteil der Plattform.",
"Names registered under this TLD": "Unter dieser TLD registrierte Namen",
"Everyone's registrations, from the public registry.": "Alle Registrierungen, aus dem öffentlichen Register.",
"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.": "TLDs sind Register-NFTs auf dem Chipnet-TLD-Beacon. Öffentliche Prägungen zahlen eine Servicegebühr, die das Register finanziert. Chipnet nutzt einen Platzhalterkurs; im Mainnet bestimmt ein echtes Orakel den Preis nach Label-Länge.",
"Faucet 2 →": "Faucet 2 →",
"Balance": "Guthaben",
"Spendable": "Verfügbar",
"UTXOs": "UTXOs",
"Watched addresses": "Beobachtete Adressen",
"Session and security choices for this browser. Nothing here changes what is on chain.": "Sitzungs- und Sicherheitseinstellungen für diesen Browser. Nichts davon ändert etwas auf der Kette.",
"Session": "Sitzung",
"Stay signed in on this device": "Auf diesem Gerät angemeldet bleiben",
"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.": "Deine Wiederherstellungsphrase bleibt verschlüsselt unter einem Schlüssel, den dieser Browser hält und nicht exportieren kann. Nächste Besuche öffnen das Dashboard sofort. Ausschalten, um jedes Mal nach Passwort oder PIN gefragt zu werden.",
"Ask for PIN before payments": "Vor Zahlungen nach PIN fragen",
"Adds a PIN prompt when registering a name or TLD. Off by default so signed-in sessions run uninterrupted.": "Fragt beim Registrieren eines Namens oder einer TLD nach der PIN. Standardmäßig aus, damit angemeldete Sitzungen ohne Unterbrechung laufen.",
"Set / change PIN": "PIN festlegen / ändern",
"Remove PIN": "PIN entfernen",
"Reading & language": "Lesen & Sprache",
"Font pill and language picker live in the top bar; both are remembered per browser.": "Schriftumschalter und Sprachwahl sitzen oben in der Leiste; beide werden pro Browser gemerkt.",
"This device": "Dieses Gerät",
"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.": "Abmelden lässt das verschlüsselte Wallet auf dem Gerät, damit du es später entsperren kannst. Vergessen entfernt es ganz — du brauchst dann deine Wiederherstellungsphrase.",
"Forget wallet on this device": "Wallet auf diesem Gerät vergessen",
"4–6 digits. Encrypts your recovery phrase under this PIN on this device. Three wrong PINs clear it and fall back to your password.": "4–6 Ziffern. Verschlüsselt deine Wiederherstellungsphrase auf diesem Gerät unter dieser PIN. Drei falsche PINs löschen sie; dann gilt wieder dein Passwort.",
"No names yet.": "Noch keine Namen.",
"Register your first one →": "Registriere deinen ersten →",
"Everything points somewhere and has DNS. Nice.": "Alles zeigt irgendwohin und hat DNS. Schön.",
"Nothing matches that filter.": "Nichts passt zu diesem Filter.",
"Status": "Status",
"point it somewhere →": "lass ihn irgendwohin zeigen →",
"Add some →": "Welche hinzufügen →",
"Register one →": "Eine registrieren →",
"yours": "deins",
"Copied": "Kopiert",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and refresh.": "Keine BCNR-Namen für dieses Wallet gefunden. Wenn du gerade registriert hast, warte eine Minute auf die Bestätigung und aktualisiere.",
"Remove": "Entfernen",
"Transferring…": "Übertrage…",
"Transferred ✓": "Übertragen ✓",
"off · private": "aus · privat",
"on · public": "ein · öffentlich",
"Signing you in…": "Du wirst angemeldet…",
"Restoring your session on this device.": "Deine Sitzung auf diesem Gerät wird wiederhergestellt.",
"Dashboard": "Dashboard",
"names, TLDs, DNS, settings": "Namen, TLDs, DNS, Einstellungen",
"site on chain": "Seite auf der Kette",
"site on Sia": "Seite auf Sia",
"reverse proxy": "Reverse-Proxy",
"own server": "eigener Server",
"redirect": "Weiterleitung",
"not pointed": "zeigt nirgendwohin",
"points nowhere yet": "zeigt noch nirgendwohin",
"no DNS records": "keine DNS-Einträge",
"DNS needs an s3 pointer": "DNS braucht einen s3-Eintrag",
"block": "Block",
"Web-Builder": "Web-Builder",
"My TLDs": "Meine TLDs",
"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.": "Sirius Studio baut eine Seite für jeden Namen, den du hältst: Blöcke ziehen, Text ändern, veröffentlichen. Seiten liegen im eigenen Ordner des Namens auf Sia und der Name zeigt darauf — kein Hoster, keine Verlängerung.",
"Session, security and wallet details for this browser. Nothing here changes what is on chain.": "Sitzung, Sicherheit und Wallet-Details für diesen Browser. Nichts davon ändert etwas auf der Kette.",
"Reading, language & help": "Lesen, Sprache & Hilfe",
"Font pill and language picker live in the top bar; both are remembered per browser. The technical documentation is at": "Schriftumschalter und Sprachwahl sitzen oben in der Leiste; beide werden pro Browser gemerkt. Die technische Dokumentation liegt unter",
"Start from a template": "Mit einer Vorlage starten",
"Preview the exported page in a new tab": "Exportierte Seite in neuem Tab ansehen",
"Sirius Studio — build the site for your name": "Sirius Studio — baue die Seite für deinen Namen",
"Templates…": "Vorlagen…",
"Landing page": "Landingpage",
"Profile / link hub": "Profil / Link-Hub",
"Business one-pager": "Unternehmens-Onepager",
"Blank page": "Leere Seite",
"Preview": "Vorschau",
"Save draft": "Entwurf speichern",
"Publish to Sia →": "Auf Sia veröffentlichen →",
"View site →": "Seite ansehen →",
"Sign in first": "Erst anmelden",
"Sirius Studio publishes with your wallet's key. Sign in on the dashboard, then come back to this name.": "Sirius Studio veröffentlicht mit dem Schlüssel deines Wallets. Melde dich im Dashboard an und komm dann zu diesem Namen zurück.",
"Open the dashboard →": "Dashboard öffnen →",
"Build the site for": "Baue die Seite für",
"Pick a starting point. Everything is editable — drag blocks in from the right, click any text to change it. Nothing leaves your browser until you press Publish; then the page is stored on Sia and the name points at it.": "Wähle einen Ausgangspunkt. Alles ist editierbar — Blöcke von rechts hineinziehen, Text anklicken und ändern. Nichts verlässt deinen Browser, bis du Veröffentlichen drückst; dann liegt die Seite auf Sia und der Name zeigt darauf.",
"Hero, three features, call to action.": "Hero, drei Vorteile, Handlungsaufruf.",
"Avatar, bio and a stack of links.": "Avatar, Bio und eine Liste von Links.",
"About, services, hours, contact.": "Über uns, Leistungen, Öffnungszeiten, Kontakt.",
"Start from nothing.": "Von null anfangen.",
"Back to dashboard": "Zurück zum Dashboard",
"Publish": "Veröffentlichen",
"The page and its assets are uploaded to the name's folder on Sia, signed with your key. If the name does not point at that folder yet, one on-chain update sets it (a few cents of chain dust).": "Seite und Dateien werden in den Ordner des Namens auf Sia hochgeladen, signiert mit deinem Schlüssel. Zeigt der Name noch nicht dorthin, setzt ein On-Chain-Update das (ein paar Cent Chain-Dust).",
"Needs attention": "Braucht Aufmerksamkeit",
"View →": "Ansehen →",
"Edit in Studio": "Im Studio bearbeiten",
"Open in Studio": "Im Studio öffnen",
"built with Studio": "mit Studio gebaut",
"site on Sia (external)": "Seite auf Sia (extern)",
"inline HTML": "Inline-HTML",
"no site yet": "noch keine Seite",
"Pick a name to build or edit its site.": "Wähle einen Namen, um seine Seite zu bauen oder zu bearbeiten.",
"You need a name first.": "Du brauchst zuerst einen Namen.",
"— then come back here to build its site.": "— dann komm hierher zurück und baue seine Seite.",
"New site": "Neue Seite",
"Not signed in": "Nicht angemeldet",
"Loading name…": "Name wird geladen…",
"Published": "Veröffentlicht",
"Publish failed": "Veröffentlichung fehlgeschlagen",
"Template loaded — edit, then Publish": "Vorlage geladen — bearbeiten, dann veröffentlichen",
"Draft saved on Sia": "Entwurf auf Sia gespeichert",
"Saving draft…": "Entwurf wird gespeichert…",
"Copy address": "Adresse kopieren",
"receive coins or names here": "hier Coins oder Namen empfangen",
"Copy token address": "Token-Adresse kopieren",
"where name certificates are minted": "wohin Namenszertifikate geprägt werden",
"Get test coins": "Test-Coins holen",
"chipnet faucet": "Chipnet-Faucet",
"Wallet settings": "Wallet-Einstellungen",
"session, PIN, forget device": "Sitzung, PIN, Gerät vergessen",
"Holdings": "Bestände",
"open the dashboard to load": "Dashboard öffnen zum Laden",
"🛒 Market": "🛒 Markt",
"🛒 Names for sale": "🛒 Namen zum Verkauf",
"Market — names for sale on Sirius.X": "Markt — Namen zum Verkauf auf Sirius.X",
"for sale": "zum Verkauf",
"Every sale is a single Bitcoin Cash transaction. The seller signed an offer that pays them only when the certificate moves to you — you add your coins, sign, broadcast. No escrow, no middleman, no way for either side to cheat.": "Jeder Verkauf ist eine einzige Bitcoin-Cash-Transaktion. Der Verkäufer hat ein Angebot signiert, das ihn nur bezahlt, wenn das Zertifikat zu dir wechselt — du fügst deine Coins hinzu, signierst, sendest. Kein Treuhänder, kein Mittelsmann, keine Möglichkeit zu betrügen.",
"Sort: price": "Sortieren: Preis",
"Loading listings…": "Angebote werden geladen…",
"Selling a name?": "Einen Namen verkaufen?",
"Open it in your": "Öffne ihn in deinem",
", choose": ", wähle",
"Sell": "Verkaufen",
", set a price. The listing is a signed offer stored by the gateway; cancelling it moves your certificate once so the old offer can never be used.": ", lege einen Preis fest. Das Angebot ist eine signierte Offerte, die das Gateway speichert; beim Zurückziehen wird dein Zertifikat einmal bewegt, damit die alte Offerte nie mehr verwendet werden kann.",
"One transaction: your coins pay the seller, the certificate lands in your wallet, and the registry is told about the new owner. Records stay as they are — you can change them in the dashboard right after.": "Eine Transaktion: deine Coins bezahlen den Verkäufer, das Zertifikat landet in deiner Wallet, und das Register erfährt vom neuen Besitzer. Die Einträge bleiben wie sie sind — du kannst sie direkt danach im Dashboard ändern.",
"Sign in to buy →": "Zum Kauf anmelden →",
"Buy — sign & broadcast": "Kaufen — signieren & senden",
"Buy →": "Kaufen →",
"Nothing is for sale right now. Owners list names from their dashboard.": "Derzeit steht nichts zum Verkauf. Besitzer bieten Namen über ihr Dashboard an.",
"Sell this name": "Diesen Namen verkaufen",
"You sign an offer once: \"whoever pays me this price gets the certificate\". The offer is stored by the gateway and shown on the": "Du signierst einmal ein Angebot: „wer mir diesen Preis zahlt, bekommt das Zertifikat“. Das Angebot speichert das Gateway und zeigt es auf dem",
"market": "Markt",
". 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.": ". Ein Käufer schließt es in einer Transaktion ab — du wirst in derselben Transaktion bezahlt, die den Namen überträgt, oder gar nicht. Kein Treuhänder, nichts, dem man vertrauen muss.",
"Checking the market…": "Markt wird geprüft…",
"Price (USD)": "Preis (USD)",
"Price (sat)": "Preis (Sat)",
"List for sale →": "Zum Verkauf anbieten →",
"Cancel listing →": "Angebot zurückziehen →",
"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.": "Beim Zurückziehen wird das Angebot vom Markt entfernt und dein Zertifikat einmal bewegt (ein leeres Update, ein paar Cent), damit die signierte Offerte später nie mehr abgeschlossen werden kann.",
"Not for sale. Set a price to list it.": "Nicht zum Verkauf. Lege einen Preis fest, um ihn anzubieten.",
"This name is listed on the market.": "Dieser Name ist auf dem Markt gelistet.",
"Pending approvals": "Ausstehende Freigaben",
"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.": "Registrierungen unter dieser TLD, die auf deine Gegensignatur warten. Beim Freigeben wird dein TLD-Zertifikat in die Transaktion des Käufers signiert und gesendet; das Zertifikat kommt in derselben Transaktion zu dir zurück. Ohne diesen Schritt kann unter einer Co-Sign- oder privaten TLD nichts registriert werden.",
"No requests waiting.": "Keine Anfragen offen.",
"awaiting you": "wartet auf dich",
"Approve & broadcast": "Freigeben & senden",
"Decline": "Ablehnen",
"Request approval — sign": "Freigabe anfragen — signieren",
"Withdraw request": "Anfrage zurückziehen",
"Request declined": "Anfrage abgelehnt",
"Open dashboard →": "Dashboard öffnen →",
"incl.": "inkl.",
"sat unconfirmed · spendable now": "Sat unbestätigt · sofort verfügbar",
"Nothing is for sale right now": "Derzeit steht nichts zum Verkauf",
"Names go on sale when their owners list them from the dashboard. Have one to sell, or want a fresh one instead?": "Namen kommen in den Verkauf, wenn ihre Besitzer sie im Dashboard anbieten. Hast du einen zu verkaufen — oder lieber einen neuen registrieren?",
"Sell a name from your dashboard →": "Einen Namen im Dashboard verkaufen →",
"Register a new name": "Neuen Namen registrieren",
"↓ Import live site": "↓ Live-Seite importieren",
"Import the live site": "Live-Seite importieren",
"✨ Assistant": "✨ Assistent",
"Runs on your own device. Nothing you write or build is sent to Sirius.X or to any AI vendor.": "Läuft auf deinem eigenen Gerät. Nichts, was du schreibst oder baust, wird an Sirius.X oder einen KI-Anbieter gesendet.",
"Runs on": "Läuft auf",
"This browser — your GPU, private": "Dieser Browser — deine GPU, privat",
"Local endpoint — Ollama, LM Studio": "Lokaler Endpunkt — Ollama, LM Studio",
"Model": "Modell",
"Downloads once, then stays in the browser cache. Needs WebGPU (current Chrome, Edge, Firefox, Safari).": "Wird einmal geladen und bleibt im Browser-Cache. Braucht WebGPU (aktuelles Chrome, Edge, Firefox, Safari).",
"Load model": "Modell laden",
"Endpoint": "Endpunkt",
"Connect": "Verbinden",
"What do you want?": "Was möchtest du?",
"Make a section": "Abschnitt erstellen",
"Rewrite selected text": "Markierten Text umschreiben",
"Restyle selection": "Auswahl umgestalten",
"Nothing selected": "Nichts ausgewählt",
"Undo last change": "Letzte Änderung rückgängig",
"Stop": "Stopp"
}

612
i18n/el.json Normal file
View file

@ -0,0 +1,612 @@
{
"Sirius.X — the home for names on Bitcoin Cash": "Sirius.X — το σπίτι των ονομάτων στο Bitcoin Cash",
"Portal — your names on Sirius.X": "Πύλη — τα ονόματά σου στο Sirius.X",
"Register a TLD — Sirius.X": "Καταχώρηση TLD — Sirius.X",
"Try it": "Δοκίμασέ το",
"✏️ Register": "✏️ Καταχώρηση",
"🌐 TLD": "🌐 TLD",
"🔑 Sign in": "🔑 Σύνδεση",
"type a name — e.g. hello": "πληκτρολόγησε ένα όνομα — π.χ. hello",
"Search a name across every BCNR TLD": "Αναζήτηση ονόματος σε κάθε TLD του BCNR",
"Names on the": "Ονόματα τομέα στο",
"chain": "blockchain",
"Sirius.X is the entry point for BCNR — Bitcoin Cash Name Registry. Register a top-level domain, register a name under one, look up records, verify anything against the chain.": "Το Sirius.X είναι η είσοδος στο BCNR — το Μητρώο Ονομάτων του Bitcoin Cash. Καταχώρησε ένα domain ανώτατου επιπέδου, καταχώρησε ένα όνομα κάτω από αυτό, δες εγγραφές, επαλήθευσε τα πάντα στο blockchain.",
"One search checks the label across every TLD in the registry. Available names appear first.": "Μία αναζήτηση ελέγχει την ετικέτα σε κάθε TLD του μητρώου. Τα διαθέσιμα ονόματα εμφανίζονται πρώτα.",
"Or browse what you can do →": "Ή δες τι μπορείς να κάνεις →",
"Read the docs": "Διάβασε την τεκμηρίωση",
"Three things you can do right now. The registrar and TLD-registry UIs live at silentmode.st today; Sirius.X is the canonical home and will consolidate them here.": "Τρία πράγματα που μπορείς να κάνεις τώρα. Ο registrar και το μητρώο TLD ζουν σήμερα στο silentmode.st· το Sirius.X είναι το κανονικό τους σπίτι και θα τα ενοποιήσει εδώ.",
"Register a name": "Καταχώρηση ονόματος",
"Pick a label, search across every TLD in the registry at once, mint the name certificate straight into your own wallet. No yearly renewal.": "Διάλεξε μια ετικέτα, ψάξε ταυτόχρονα σε κάθε TLD του μητρώου, κόψε το πιστοποιητικό του ονόματος κατευθείαν στο δικό σου πορτοφόλι. Χωρίς ετήσια ανανέωση.",
"≈ 10,000 sat service fee · 1,300 sat chain dust · < 1 ¢": "≈ 10.000 sat τέλος υπηρεσίας · 1.300 sat σκόνη blockchain · < 1 ¢",
"Chipnet placeholder. 90 % of the service fee flows to the TLD owner, 10 % to the platform.": "Προσωρινή τιμή chipnet. Το 90 % του τέλους πάει στον κάτοχο του TLD, το 10 % στην πλατφόρμα.",
"Search a name →": "Αναζήτηση ονόματος →",
"Register a TLD": "Καταχώρηση TLD",
"A TLD is itself a certificate on the chain. Anyone can mint one — you become the registry operator for every second-level name under it, and earn 90 % of the fee on every name registered under it. Renewals are per-TLD policy set by the owner.": "Ένα TLD είναι κι αυτό πιστοποιητικό στο blockchain. Οποιοσδήποτε μπορεί να το κόψει — γίνεσαι διαχειριστής μητρώου για κάθε όνομα δεύτερου επιπέδου κάτω από αυτό και κερδίζεις το 90 % του τέλους κάθε ονόματος που καταχωρείται εκεί. Οι ανανεώσεις είναι πολιτική ανά TLD που ορίζει ο κάτοχος.",
"≈ 1,250,000 sat service fee (≈ $5) · 1,300 sat chain dust": "≈ 1.250.000 sat τέλος υπηρεσίας (≈ 5 $) · 1.300 sat σκόνη blockchain",
"Chipnet placeholder rate — mainnet will price by label length via an on-chain oracle.": "Προσωρινή ισοτιμία chipnet — στο mainnet η τιμή θα ορίζεται από το μήκος της ετικέτας μέσω on-chain oracle.",
"Search a TLD →": "Αναζήτηση TLD →",
"Operator admin →": "Διαχείριση operator →",
"Look up & verify": "Αναζήτηση & επαλήθευση",
"Resolve any BCNR name, compare records across mirrors, and check the TLD registry snapshot against the chain. Everything is publicly verifiable.": "Επίλυσε οποιοδήποτε όνομα BCNR, σύγκρινε εγγραφές μεταξύ mirrors και έλεγξε το snapshot του μητρώου TLD με το blockchain. Όλα επαληθεύονται δημόσια.",
"How to verify →": "Πώς να επαληθεύσεις →",
"🔑 Sign in — your names portal": "🔑 Σύνδεση — η πύλη των ονομάτων σου",
"Import your seed phrase or connect a wallet (Cashonize / Paytaca via WizardConnect) to see every name you own, review records, and update them. Your keys never leave your browser.": "Εισήγαγε τη seed φράση σου ή σύνδεσε ένα πορτοφόλι (Cashonize / Paytaca μέσω WizardConnect) για να δεις κάθε όνομα που κατέχεις, να ελέγξεις εγγραφές και να τις ενημερώσεις. Τα κλειδιά σου δεν φεύγουν ποτέ από τον browser.",
"Open the portal →": "Άνοιγμα πύλης →",
"🧭 Theseus Navigator": "🧭 Theseus Navigator",
"The browser that speaks BCNR natively. Open": "Ο browser που μιλά BCNR εγγενώς. Άνοιξε",
"in the address bar — it just resolves. TLS verified against on-chain fingerprints, no OS trust-store install.": "στη γραμμή διευθύνσεων — απλώς επιλύεται. Το TLS επαληθεύεται με on-chain αποτυπώματα, χωρίς εγκατάσταση στο trust-store του λειτουργικού.",
"Download →": "Λήψη →",
"Documentation": "Τεκμηρίωση",
"The full docs — TLD registry model, record types, resolver & gateway paths, mainnet pricing, verification, and the operator runbook pointer — live on their own page so they can grow without cluttering the landing.": "Η πλήρης τεκμηρίωση — μοντέλο μητρώου TLD, τύποι εγγραφών, διαδρομές resolver και gateway, τιμές mainnet, επαλήθευση και ο δείκτης στο runbook του operator — ζει σε δική της σελίδα για να μεγαλώνει χωρίς να φορτώνει την αρχική.",
"📚 Open the docs →": "📚 Άνοιγμα τεκμηρίωσης →",
"Current TLD list": "Τρέχουσα λίστα TLD",
"Propose a new TLD": "Πρότεινε νέο TLD",
"The per-TLD registry means minting a TLD is a real, paid action — not a namespace land-grab. During the alpha, all TLD mints are operator-signed. To propose a TLD, get in touch via the channels below. The design (mainnet) adds an on-chain covenant with countersignature + tiered USD price floors: 1-char $100k, 2-char $50k, 3-char $15k, 4-char $5k, 5–8-char $1k, 9+-char $250; one-time payment (not annual). See the design doc for the full model.": "Το μητρώο ανά TLD σημαίνει ότι η κοπή ενός TLD είναι πραγματική, πληρωμένη πράξη — όχι αρπαγή χώρου ονομάτων. Στη διάρκεια της alpha, όλες οι κοπές TLD υπογράφονται από τον operator. Για να προτείνεις TLD, επικοινώνησε μέσω των παρακάτω καναλιών. Ο σχεδιασμός (mainnet) προσθέτει on-chain covenant με αντυπογραφή και κλιμακωτές ελάχιστες τιμές σε USD: 1 χαρακτήρας $100k, 2 $50k, 3 $15k, 4 $5k, 5–8 $1k, 9+ $250· εφάπαξ πληρωμή (όχι ετήσια). Δες το έγγραφο σχεδιασμού για το πλήρες μοντέλο.",
"ICANN-adjacent TLDs are not open for public mint.": "TLD που συμπίπτουν με το ICANN δεν είναι ανοιχτά για δημόσια κοπή.",
"A TLD registry is only useful if it does not immediately collapse into an ICANN-shadow — the mainnet covenant enforces this; on chipnet the operator's countersignature is the gate.": "Ένα μητρώο TLD είναι χρήσιμο μόνο αν δεν καταρρέει αμέσως σε σκιά του ICANN — στο mainnet αυτό το επιβάλλει το covenant· στο chipnet η αντυπογραφή του operator είναι η πύλη.",
"The pantheon": "Το πάνθεον",
"Sirius.x is one of seven sibling": "Το Sirius.x είναι ένα από τα επτά αδελφά ονόματα",
"names — the Silent Mode pantheon. Each project is its own on-chain certificate; each site is reachable through any BCNR resolver, plus the silentmode.st gateway for browsers without one.": "— το πάνθεον του Silent Mode. Κάθε έργο είναι δικό του on-chain πιστοποιητικό· κάθε site είναι προσβάσιμο από οποιονδήποτε resolver BCNR, συν το gateway silentmode.st για browsers χωρίς resolver.",
"⛓️ Silentmode.X": "⛓️ Silentmode.X",
"The project umbrella. Redirects to": "Η ομπρέλα του έργου. Ανακατευθύνει στο",
"where every pillar has its own landing page + download hub.": "όπου κάθε πυλώνας έχει δική του σελίδα και λήψεις.",
"Open →": "Άνοιγμα →",
"⭐ Sirius.X": "⭐ Sirius.X",
"you're here": "είσαι εδώ",
"Names on Bitcoin Cash — register, resolve, verify, manage. This site.": "Ονόματα στο Bitcoin Cash — καταχώρηση, επίλυση, επαλήθευση, διαχείριση. Αυτό το site.",
"Home →": "Αρχική →",
"🧭 Theseus.X": "🧭 Theseus.X",
"The browser that speaks BCNR natively — Chromium build with the resolver baked in, no OS-level daemon or root-store install.": "Ο browser που μιλά BCNR εγγενώς — Chromium build με ενσωματωμένο resolver, χωρίς daemon συστήματος ή εγκατάσταση root πιστοποιητικού.",
"Learn more →": "Μάθε περισσότερα →",
"🔥 Hephaestus.X": "🔥 Hephaestus.X",
"The forge. Forgejo instance for the ecosystem's git repos, backed by BCH wallet auth. Sirius's own source lives here.": "Το σιδηρουργείο. Forgejo για τα git repos του οικοσυστήματος, με σύνδεση μέσω πορτοφολιού BCH. Εδώ ζει ο πηγαίος κώδικας του Sirius.",
"🔮 Prometheus.X": "🔮 Prometheus.X",
"Fire from the chain. The project's foresight / experimentation layer. Redirects to": "Φωτιά από το blockchain. Το επίπεδο πρόβλεψης και πειραματισμού του έργου. Ανακατευθύνει στο",
"today.": "(σήμερα).",
"☀️ Helios.X": "☀️ Helios.X",
"The public gaze. Analytics, dashboards, transparency reports. Redirects to": "Το δημόσιο βλέμμα. Αναλύσεις, πίνακες, αναφορές διαφάνειας. Ανακατευθύνει στο",
"✉️ Hermes.X": "✉️ Hermes.X",
"Messenger. Nostr-based messaging bound to a BCNR name via the": "Messenger. Μηνύματα μέσω Nostr, δεμένα σε όνομα BCNR μέσω των εγγραφών",
"records. Redirects to": ". Ανακατευθύνει στο",
"What's coming": "Τι έρχεται",
"Sirius.X consolidates docs and registration today; three larger pieces are on the roadmap.": "Το Sirius.X ενοποιεί σήμερα τεκμηρίωση και καταχώρηση· τρία μεγαλύτερα κομμάτια είναι στον οδικό χάρτη.",
"Wallet & name portal": "Πύλη πορτοφολιού & ονομάτων",
"next": "επόμενο",
"Sign in with your Bitcoin Cash wallet, see every name you own, edit records inline, mint or renew from one place. Same self-custody as today — the portal never handles your keys.": "Συνδέσου με το πορτοφόλι Bitcoin Cash, δες κάθε όνομα που κατέχεις, επεξεργάσου εγγραφές επιτόπου, κόψε ή ανανέωσε από ένα μέρος. Η ίδια αυτοφύλαξη όπως σήμερα — η πύλη δεν αγγίζει ποτέ τα κλειδιά σου.",
"Sirius Studio": "Sirius Studio",
"planned": "σχεδιάζεται",
"An in-browser site editor for names you already own — the WordPress / Tilda / Wix pattern, but the whole site persists to Sia and the name's": "Επεξεργαστής site μέσα στον browser για ονόματα που ήδη κατέχεις — το μοτίβο WordPress / Tilda / Wix, αλλά ολόκληρο το site αποθηκεύεται στο Sia και η εγγραφή",
"record updates on save. Sites live where the name says they live.": "του ονόματος ενημερώνεται στην αποθήκευση. Τα sites ζουν εκεί που λέει το όνομα.",
"Decentralized git remote": "Αποκεντρωμένο git remote",
"MVP live": "MVP σε λειτουργία",
"The Silent Mode repo is served as a bare git tree over dumb-HTTP from the VPS. Clone it with any git client, no login. Forgejo + Sia sync for a proper decentralized backend is the next track.": "Το repo του Silent Mode σερβίρεται ως bare git δέντρο μέσω dumb-HTTP από το VPS. Κλωνοποίησέ το με οποιονδήποτε git client, χωρίς σύνδεση. Το επόμενο βήμα είναι Forgejo + συγχρονισμός Sia για πραγματικά αποκεντρωμένο backend.",
"One-shot snapshot as a downloadable git bundle (works when dumb-HTTP is blocked):": "Στιγμιότυπο μίας χρήσης ως git bundle για λήψη (δουλεύει όταν το dumb-HTTP είναι μπλοκαρισμένο):",
"Verify this page against the chain": "Επαλήθευσε αυτή τη σελίδα με το blockchain",
"You do not have to trust that": "Δεν χρειάζεται να εμπιστεύεσαι ότι το",
"is served by anyone specific. The name's certificate is on the Bitcoin Cash chain; the records point to Sia; every path is independently checkable.": "σερβίρεται από κάποιον συγκεκριμένο. Το πιστοποιητικό του ονόματος είναι στο blockchain του Bitcoin Cash· οι εγγραφές δείχνουν στο Sia· κάθε διαδρομή ελέγχεται ανεξάρτητα.",
"1. Confirm the certificate exists on chain": "1. Επιβεβαίωσε ότι το πιστοποιητικό υπάρχει στο blockchain",
"2. Fetch the TLD-registry snapshot from Nostr": "2. Πάρε το snapshot του μητρώου TLD από το Nostr",
"The operator-signed snapshot of the TLD list is published as a Nostr replaceable event. Any relay carries it; the event's content field carries the current snapshot root.": "Το υπογεγραμμένο από τον operator snapshot της λίστας TLD δημοσιεύεται ως αντικαταστάσιμο συμβάν Nostr. Κάθε relay το μεταφέρει· το πεδίο content του συμβάντος περιέχει τη ρίζα του τρέχοντος snapshot.",
"Kind / d-tag": "Kind / d-tag",
"Pubkey (x-only, hex)": "Δημόσιο κλειδί (x-only, hex)",
"Relays": "Relays",
"3. Reach this site via more than one route": "3. Φτάσε σε αυτό το site από περισσότερες από μία διαδρομές",
"The same content should be served from at least two independent paths. If one mirror is unavailable, the others still work. If two mirrors disagree, the on-chain record is the tiebreaker.": "Το ίδιο περιεχόμενο πρέπει να σερβίρεται από τουλάχιστον δύο ανεξάρτητες διαδρομές. Αν ένα mirror δεν είναι διαθέσιμο, τα άλλα δουλεύουν. Αν δύο mirrors διαφωνούν, η on-chain εγγραφή αποφασίζει.",
"Via any BCNR resolver:": "Μέσω οποιουδήποτε resolver BCNR:",
"(requires the local root CA)": "(απαιτεί το τοπικό root CA)",
"Via the public gateway:": "Μέσω του δημόσιου gateway:",
"Via silentmode.st mirror:": "Μέσω του mirror silentmode.st:",
"Direct from Sia (content-addressed): the": "Απευθείας από το Sia (διεύθυνση βάσει περιεχομένου): η εγγραφή",
"record on": "στο",
"names the exact bucket key": "ονομάζει το ακριβές κλειδί bucket",
"Register a": "Καταχώρησε ένα",
"A TLD is a certificate on the Bitcoin Cash chain. You mint it, you own it — any second-level name registered under it lives in your TLD's registry. One BCH transaction, no ICANN. Renewals? Your TLD, your policy.": "Ένα TLD είναι πιστοποιητικό στο blockchain του Bitcoin Cash. Το κόβεις, το κατέχεις — κάθε όνομα δεύτερου επιπέδου κάτω από αυτό ζει στο μητρώο του TLD σου. Μία συναλλαγή BCH, καθόλου ICANN. Ανανεώσεις; Δικό σου TLD, δική σου πολιτική.",
"Search a TLD": "Αναζήτηση TLD",
"Type a label (a–z, 0–9, hyphen; up to 16 chars). Available TLDs get a Register button that opens the shared wallet-choice modal — the same flow name registration uses. As TLD owner you earn": "Πληκτρολόγησε μια ετικέτα (a–z, 0–9, παύλα· έως 16 χαρακτήρες). Τα διαθέσιμα TLD αποκτούν κουμπί καταχώρησης που ανοίγει το κοινό παράθυρο επιλογής πορτοφολιού — η ίδια ροή με την καταχώρηση ονόματος. Ως κάτοχος TLD κερδίζεις",
"of every name registered under your TLD. Renewals are your call — set them per TLD, or don't.": "κάθε ονόματος που καταχωρείται κάτω από το TLD σου. Οι ανανεώσεις είναι δική σου απόφαση — όρισέ τες ανά TLD, ή όχι.",
"Register minting to your token address; you become the registry operator.": "Η καταχώρηση κόβει στη διεύθυνση token σου· γίνεσαι διαχειριστής μητρώου.",
"Registered TLDs": "Καταχωρημένα TLD",
"Fetched from the on-chain TLD registry via the public gateway. Refresh the page for the latest.": "Από το on-chain μητρώο TLD μέσω του δημόσιου gateway. Ανανέωσε τη σελίδα για τα πιο πρόσφατα.",
"Loading…": "Φόρτωση…",
"Mint price": "Τιμή κοπής",
"Category": "Κατηγορία",
"Portal sections": "Ενότητες πύλης",
"Your": "Η πύλη",
"names": "των ονομάτων",
"portal": "σου",
"Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see every BCNR name your wallet holds. Your keys never leave this browser tab.": "Συνδέσου με τη seed φράση Bitcoin Cash ή σύνδεσε εξωτερικό πορτοφόλι για να δεις κάθε όνομα BCNR που κατέχει. Τα κλειδιά σου δεν φεύγουν ποτέ από αυτή την καρτέλα.",
"Sign in or create a wallet": "Σύνδεση ή δημιουργία πορτοφολιού",
"The same wallet that will hold your names does the signing. Pick a tab — everything happens on this page; keys never leave your browser.": "Το ίδιο πορτοφόλι που θα κρατά τα ονόματά σου κάνει την υπογραφή. Διάλεξε καρτέλα — όλα γίνονται σε αυτή τη σελίδα· τα κλειδιά δεν φεύγουν από τον browser.",
"Overview": "Επισκόπηση",
"Names": "Ονόματα",
"TLDs": "TLD",
"Wallet": "Πορτοφόλι",
"Settings": "Ρυθμίσεις",
"A snapshot of what this wallet holds on chain.": "Μια εικόνα του τι κατέχει αυτό το πορτοφόλι στο blockchain.",
"Names held": "Ονόματα που κατέχεις",
"CashTokens NFT certificates": "Πιστοποιητικά NFT CashTokens",
"TLDs owned": "TLD που κατέχεις",
"Per-TLD registry NFTs": "NFT μητρώου ανά TLD",
"Wallet balance": "Υπόλοιπο πορτοφολιού",
"chipnet sats": "sats chipnet",
"Chain height": "Ύψος blockchain",
"Last seen block": "Τελευταίο μπλοκ",
"+ Register a name": "+ Καταχώρηση ονόματος",
"+ Register a TLD": "+ Καταχώρηση TLD",
"Names you hold": "Τα ονόματά σου",
"Every BCNR name your wallet's addresses currently hold a CashTokens NFT for. Edit records inline to publish an on-chain UPD.": "Κάθε όνομα BCNR για το οποίο οι διευθύνσεις του πορτοφολιού σου κατέχουν τώρα NFT CashTokens. Επεξεργάσου εγγραφές επιτόπου για να δημοσιεύσεις on-chain UPD.",
"Loading names from the chain…": "Φόρτωση ονομάτων από το blockchain…",
"TLDs you own": "Τα TLD σου",
"Every per-TLD registry NFT held by this wallet. Set the": "Κάθε NFT μητρώου TLD που κατέχει αυτό το πορτοφόλι. Όρισε την",
"price": "τιμή",
"every name under your TLD sells for, switch the TLD": "πώλησης κάθε ονόματος κάτω από το TLD σου, άναψε ή σβήσε το TLD",
"on or off": "στο δημόσιο μητρώο",
"in the public registry (off = a": "(σβηστό = ένα",
"private TLD": "ιδιωτικό TLD",
": nobody else can buy names under it, you still can from here), and tune policy —": ": κανείς άλλος δεν αγοράζει ονόματα κάτω από αυτό, εσύ μπορείς από εδώ) και ρύθμισε την πολιτική —",
"fee": "τέλος",
"min length": "ελάχιστο μήκος",
"reserved labels": "δεσμευμένες ετικέτες",
"renewal period": "περίοδος ανανέωσης",
". Every change is one signed TUPD on chain; you receive 90% of each sale.": ". Κάθε αλλαγή είναι ένα υπογεγραμμένο TUPD στο blockchain· λαμβάνεις το 90 % κάθε πώλησης.",
"Loading TLDs from the chain…": "Φόρτωση TLD από το blockchain…",
"Register a new TLD": "Καταχώρηση νέου TLD",
"TLDs are per-registry NFTs on the chipnet TLD beacon. Public mints go through a service-fee output to fund the registry. Chipnet uses a placeholder rate; mainnet will price by label length via a real oracle.": "Τα TLD είναι NFT μητρώου στο TLD beacon του chipnet. Οι δημόσιες κοπές πληρώνουν τέλος υπηρεσίας που χρηματοδοτεί το μητρώο. Το chipnet χρησιμοποιεί προσωρινή ισοτιμία· στο mainnet ένα πραγματικό oracle θα ορίζει την τιμή από το μήκος της ετικέτας.",
"Label": "Ετικέτα",
"1–16 chars, [a-z0-9-]": "1–16 χαρακτήρες, [a-z0-9-]",
"Service fee (USD)": "Τέλος υπηρεσίας (USD)",
"chipnet test rate": "δοκιμαστική ισοτιμία chipnet",
"sats · rate": "sats · ισοτιμία",
"sats/USD": "sats/USD",
"Check availability": "Έλεγχος διαθεσιμότητας",
"Register (~0 sats)": "Καταχώρηση (~0 sats)",
"Your addresses and current balance. Keys stay in this browser.": "Οι διευθύνσεις σου και το τρέχον υπόλοιπο. Τα κλειδιά μένουν σε αυτόν τον browser.",
"Receive address": "Διεύθυνση λήψης",
"Token address": "Διεύθυνση token",
"holds your name certificates": "κρατά τα πιστοποιητικά των ονομάτων σου",
"Faucet →": "Faucet →",
"Reader preferences live per-browser; wallet changes require a signature.": "Οι προτιμήσεις ανάγνωσης είναι ανά browser· οι αλλαγές πορτοφολιού απαιτούν υπογραφή.",
"Reading font": "Γραμματοσειρά ανάγνωσης",
"Fraunces (Silent Mode family) or Ubuntu (Bitcoin Cash brand font). The pill lives in the top nav.": "Fraunces (οικογένεια Silent Mode) ή Ubuntu (γραμματοσειρά του Bitcoin Cash). Ο διακόπτης βρίσκεται στην πάνω πλοήγηση.",
"Session PIN": "PIN συνεδρίας",
"PIN unlocks the wallet without re-typing your password. Wipes after 3 wrong attempts.": "Το PIN ξεκλειδώνει το πορτοφόλι χωρίς να ξαναγράψεις τον κωδικό. Διαγράφεται μετά από 3 λάθος προσπάθειες.",
"Sign out": "Αποσύνδεση",
"Clears the signed-in state in this browser. Your on-chain names are unaffected.": "Καθαρίζει την κατάσταση σύνδεσης σε αυτόν τον browser. Τα on-chain ονόματά σου δεν επηρεάζονται.",
"Edit records. Only your key can sign this UPD; the transaction fee is a few cents in chain fees plus the beacon dust. Leave a field blank to omit that record.": "Επεξεργασία εγγραφών. Μόνο το κλειδί σου υπογράφει αυτό το UPD· η συναλλαγή κοστίζει λίγα λεπτά σε τέλη blockchain συν τη σκόνη του beacon. Άφησε ένα πεδίο κενό για να παραλείψεις την εγγραφή.",
"inline HTML — served as-is at the site root": "ενσωματωμένο HTML — σερβίρεται ως έχει στη ρίζα του site",
"Sia bucket key, trailing slash for directories": "κλειδί bucket Sia, κάθετος στο τέλος για καταλόγους",
"IPv4 that serves this name over Host header": "IPv4 που σερβίρει αυτό το όνομα μέσω κεφαλίδας Host",
"SHA-256 of your leaf cert — chain-pinned TLS trust": "SHA-256 του τελικού πιστοποιητικού σου — εμπιστοσύνη TLS καρφωμένη στο blockchain",
"redirect target": "προορισμός ανακατεύθυνσης",
"payload:": "φορτίο:",
"bytes": "bytes",
"Cancel": "Ακύρωση",
"Save records →": "Αποθήκευση εγγραφών →",
"DNS records for": "Εγγραφές DNS για",
"DNS-style records live in a signed manifest on Sia — not on chain.": "Οι εγγραφές τύπου DNS ζουν σε υπογεγραμμένο manifest στο Sia — όχι στο blockchain.",
"Free per edit": "Δωρεάν ανά αλλαγή",
", no size cap. The signature proves you own the name; the gateway rejects anything not signed by the current NFT holder. See": ", χωρίς όριο μεγέθους. Η υπογραφή αποδεικνύει ότι το όνομα είναι δικό σου· το gateway απορρίπτει ό,τι δεν υπογράφει ο τρέχων κάτοχος του NFT. Δες",
"docs": "τεκμηρίωση",
"IPv4 addresses, one per line": "διευθύνσεις IPv4, μία ανά γραμμή",
"IPv6 addresses, one per line": "διευθύνσεις IPv6, μία ανά γραμμή",
"one string per line (SPF, DKIM, verification tokens…)": "μία συμβολοσειρά ανά γραμμή (SPF, DKIM, tokens επαλήθευσης…)",
"one target host, or blank": "ένας host προορισμού, ή κενό",
"nameservers, one per line": "nameservers, ένας ανά γραμμή",
"Sign & publish →": "Υπογραφή & δημοσίευση →",
"Policy for": "Πολιτική για",
"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).": "Όρισε πολιτική για τα ονόματα κάτω από αυτό το TLD. Μόνο το κλειδί σου υπογράφει αυτό το TUPD· η συναλλαγή κοστίζει λίγα λεπτά σε σκόνη blockchain. Άφησε ένα πεδίο κενό για να παραλείψεις τον κανόνα (προεπιλογή — ανοιχτή πολιτική, κλιμακωτές τιμές).",
"USD per name — flat, shown to every buyer; blank = length tiers. You receive 90% of each sale.": "USD ανά όνομα — σταθερή, φαίνεται σε κάθε αγοραστή· κενό = κλίμακες μήκους. Λαμβάνεις το 90 % κάθε πώλησης.",
"listing": "εμφάνιση",
"off hides the TLD from search and blocks new registrations until you switch it back on": "σβηστό κρύβει το TLD από την αναζήτηση και μπλοκάρει νέες καταχωρήσεις μέχρι να το ανάψεις ξανά",
"On — listed, names for sale": "Αναμμένο — στη λίστα, ονόματα προς πώληση",
"Off — hidden, not for sale": "Σβηστό — κρυφό, δεν πωλείται",
"reject names shorter than N chars": "απόρριψη ονομάτων μικρότερων από N χαρακτήρες",
"service fee owner takes, in basis points (500 = 5%)": "μερίδιο του κατόχου στο τέλος, σε μονάδες βάσης (500 = 5 %)",
"open · frozen · reserved-only": "open · frozen · reserved-only",
"space-separated labels only owner can mint": "ετικέτες χωρισμένες με κενό που μόνο ο κάτοχος μπορεί να κόψει",
"days between renewals, 0 = never expire": "ημέρες μεταξύ ανανεώσεων, 0 = δεν λήγει ποτέ",
"renewal price in sats, 0 = free": "τιμή ανανέωσης σε sats, 0 = δωρεάν",
"where the TLD's own landing lives": "πού ζει η σελίδα του ίδιου του TLD",
"Save policy →": "Αποθήκευση πολιτικής →",
"Signed in": "Συνδεδεμένος",
"You are signed in as": "Είσαι συνδεδεμένος ως",
"Done": "Έγινε",
"Close": "Κλείσιμο",
"Unlock my browser wallet": "Ξεκλείδωμα του πορτοφολιού του browser",
"You already created one on this device.": "Έχεις ήδη δημιουργήσει ένα σε αυτή τη συσκευή.",
"Create a new wallet": "Δημιουργία νέου πορτοφολιού",
"easiest": "το πιο εύκολο",
"Made here in your browser. You get a recovery phrase to write down — it is the only key.": "Φτιάχνεται εδώ στον browser σου. Παίρνεις φράση ανάκτησης για να τη σημειώσεις — είναι το μόνο κλειδί.",
"Import a recovery phrase": "Εισαγωγή φράσης ανάκτησης",
"Restore a wallet you already have, from its 12-word phrase.": "Επανάφερε ένα πορτοφόλι που ήδη έχεις, από τη φράση 12 λέξεων.",
"Connect a wallet — WizardConnect": "Σύνδεση πορτοφολιού — WizardConnect",
"most private": "το πιο ιδιωτικό",
"Cashonize 0.9+ or Paytaca. Encrypted end-to-end over Nostr; the relay sees only ciphertext. Your keys never leave your wallet.": "Cashonize 0.9+ ή Paytaca. Κρυπτογράφηση από άκρο σε άκρο μέσω Nostr· το relay βλέπει μόνο κρυπτοκείμενο. Τα κλειδιά δεν φεύγουν ποτέ από το πορτοφόλι σου.",
"Everything below runs on": "Όλα τα παρακάτω τρέχουν στο",
", Bitcoin Cash's test network. The coins are free and worth nothing — this is an alpha, and it is the honest place to try it before real money is involved.": ", το δοκιμαστικό δίκτυο του Bitcoin Cash. Τα νομίσματα είναι δωρεάν και δεν αξίζουν τίποτα — είναι alpha, και είναι το τίμιο μέρος να το δοκιμάσεις πριν μπουν πραγματικά χρήματα.",
"Starting the connection…": "Έναρξη σύνδεσης…",
"Back": "Πίσω",
"Open your wallet": "Άνοιξε το πορτοφόλι σου",
"Copy": "Αντιγραφή",
"Waiting for your wallet… The link stays valid until you close this page.": "Αναμονή για το πορτοφόλι σου… Ο σύνδεσμος ισχύει μέχρι να κλείσεις τη σελίδα.",
"Connected": "Συνδέθηκε",
"Reading your wallet and building the registration…": "Ανάγνωση πορτοφολιού και δημιουργία της καταχώρησης…",
"That wallet is empty": "Αυτό το πορτοφόλι είναι άδειο",
"Two approvals needed.": "Χρειάζονται δύο εγκρίσεις.",
"Register — approve in your wallet": "Καταχώρηση — έγκρινε στο πορτοφόλι σου",
"Approve in your wallet": "Έγκρινε στο πορτοφόλι σου",
"Create your wallet": "Δημιούργησε το πορτοφόλι σου",
"Generated in this browser. The phrase is never sent anywhere — not to us, not to anyone.": "Δημιουργήθηκε σε αυτόν τον browser. Η φράση δεν στέλνεται πουθενά — ούτε σε εμάς, ούτε σε κανέναν.",
"Password (encrypts the wallet on this device)": "Κωδικός (κρυπτογραφεί το πορτοφόλι σε αυτή τη συσκευή)",
"Repeat password": "Επανάληψη κωδικού",
"There is no reset.": "Δεν υπάρχει επαναφορά.",
"Generate phrase →": "Δημιουργία φράσης →",
"Write this down. Now.": "Σημείωσέ το. Τώρα.",
"These 12 words are your wallet. Anyone who has them owns your names; if you lose them, nobody — including us — can recover anything.": "Αυτές οι 12 λέξεις είναι το πορτοφόλι σου. Όποιος τις έχει κατέχει τα ονόματά σου· αν τις χάσεις, κανείς — ούτε εμείς — δεν μπορεί να ανακτήσει τίποτα.",
"Copy phrase": "Αντιγραφή φράσης",
"I have written the phrase down somewhere safe and offline. I understand it cannot be reset.": "Έχω σημειώσει τη φράση σε ασφαλές μέρος, εκτός σύνδεσης. Καταλαβαίνω ότι δεν επαναφέρεται.",
"Continue →": "Συνέχεια →",
"12 words, separated by spaces. It stays in this browser.": "12 λέξεις, χωρισμένες με κενά. Μένει σε αυτόν τον browser.",
"Recovery phrase": "Φράση ανάκτησης",
"Password to encrypt it on this device": "Κωδικός για κρυπτογράφηση σε αυτή τη συσκευή",
"Import →": "Εισαγωγή →",
"No wallet on this device": "Δεν υπάρχει πορτοφόλι σε αυτή τη συσκευή",
"📥 Import a wallet →": "📥 Εισαγωγή πορτοφολιού →",
"🆕 Create a wallet →": "🆕 Δημιουργία πορτοφολιού →",
"Enter your PIN": "Πληκτρολόγησε το PIN",
"Use password instead": "Χρήση κωδικού αντί για PIN",
"Unlock →": "Ξεκλείδωμα →",
"PIN reset": "Επαναφορά PIN",
"3 wrong attempts — the PIN has been cleared. Enter your password to unlock and set a new PIN if you like.": "3 λάθος προσπάθειες — το PIN διαγράφηκε. Πληκτρολόγησε τον κωδικό για ξεκλείδωμα και όρισε νέο PIN αν θέλεις.",
"Continue with password →": "Συνέχεια με κωδικό →",
"Unlock your wallet": "Ξεκλείδωσε το πορτοφόλι σου",
"Decrypts the wallet stored in this browser. After unlocking you can set a PIN so future sessions ask for 4–6 digits instead of the full password.": "Αποκρυπτογραφεί το πορτοφόλι που είναι αποθηκευμένο στον browser. Μετά μπορείς να ορίσεις PIN, ώστε οι επόμενες συνεδρίες να ζητούν 4–6 ψηφία αντί για ολόκληρο τον κωδικό.",
"Password": "Κωδικός",
"Set a PIN": "Ορισμός PIN",
"optional": "προαιρετικό",
"Repeat PIN": "Επανάληψη PIN",
"Not now": "Όχι τώρα",
"Save PIN →": "Αποθήκευση PIN →",
"Fund your wallet": "Χρηματοδότησε το πορτοφόλι σου",
"Send test coins to this address. It is yours — derived from your phrase.": "Στείλε δοκιμαστικά νομίσματα σε αυτή τη διεύθυνση. Είναι δική σου — παράγεται από τη φράση σου.",
"checking balance…": "έλεγχος υπολοίπου…",
"Preparing…": "Προετοιμασία…",
"Building your registration transaction.": "Δημιουργία της συναλλαγής καταχώρησης.",
"One transaction. It mints the certificate to": "Μία συναλλαγή. Κόβει το πιστοποιητικό στη",
"your": "δική σου",
"address and pays the fees.": "διεύθυνση και πληρώνει τα τέλη.",
"The certificate will be minted to": "Το πιστοποιητικό θα κοπεί στη",
"— your key, your name. You can set where it points immediately afterwards.": "— δικό σου κλειδί, δικό σου όνομα. Αμέσως μετά μπορείς να ορίσεις πού δείχνει.",
"Register — sign & broadcast": "Καταχώρηση — υπογραφή & αποστολή",
"Could not prepare": "Αδυναμία προετοιμασίας",
"Confirm": "Επιβεβαίωση",
"Beacon dust + chain fee": "Σκόνη beacon + τέλος blockchain",
"(covered by wallet)": "(καλύπτεται από το πορτοφόλι)",
"Minted to": "Κόπηκε στη",
"Service fee waived on chipnet": "Το τέλος υπηρεσίας δεν χρεώνεται στο chipnet",
"Approve payment": "Έγκριση πληρωμής",
"Approve →": "Έγκριση →",
"Signing in your browser and broadcasting to the chain. Do not close this tab.": "Υπογραφή στον browser και αποστολή στο blockchain. Μην κλείσεις αυτή την καρτέλα.",
"Transaction": "Συναλλαγή",
"Certificate ID": "ID πιστοποιητικού",
"Operator": "Operator",
"The certificate is on the chain, held by your key. Nobody can take it back.": "Το πιστοποιητικό είναι στο blockchain, στο κλειδί σου. Κανείς δεν μπορεί να το πάρει πίσω.",
"Owner": "Κάτοχος",
"Point it somewhere": "Δείξε κάπου",
"Optional, and changeable any time — only your key can.": "Προαιρετικό και αλλάζει οποτεδήποτε — μόνο με το κλειδί σου.",
"Record type": "Τύπος εγγραφής",
"A tiny site stored on the chain itself (h)": "Ένα μικροσκοπικό site αποθηκευμένο στο ίδιο το blockchain (h)",
"Redirect to a web address (u)": "Ανακατεύθυνση σε διεύθυνση web (u)",
"Your own server's IPv4 address (ip)": "Η διεύθυνση IPv4 του δικού σου server (ip)",
"TLS certificate fingerprint (tls)": "Αποτύπωμα πιστοποιητικού TLS (tls)",
"Done for now": "Αρκετά για τώρα",
"Publish record": "Δημοσίευση εγγραφής",
"Publishing record": "Δημοσίευση εγγραφής σε εξέλιξη",
"Update transaction": "Συναλλαγή ενημέρωσης",
"Finish": "Τέλος",
"My names": "Τα ονόματά μου",
"records & holdings": "εγγραφές & κατοχές",
"Admin panel": "Πίνακας διαχείρισης",
"operator tools": "εργαλεία operator",
"clear this browser": "καθαρισμός αυτού του browser",
"Unlock my wallet": "Ξεκλείδωμα πορτοφολιού",
"one you already created on this device": "αυτό που ήδη δημιούργησες σε αυτή τη συσκευή",
"Locked wallet on this device": "Κλειδωμένο πορτοφόλι σε αυτή τη συσκευή",
"Unlock or pick another action": "Ξεκλείδωσε ή διάλεξε άλλη ενέργεια",
"No wallet yet": "Δεν υπάρχει ακόμα πορτοφόλι",
"Pick how to sign in": "Διάλεξε πώς θα συνδεθείς",
"Create a wallet": "Δημιουργία πορτοφολιού",
"generate a fresh 12-word phrase (sign up)": "δημιουργία νέας φράσης 12 λέξεων (εγγραφή)",
"Import a wallet": "Εισαγωγή πορτοφολιού",
"seed phrase you already have (sign in)": "seed φράση που ήδη έχεις (σύνδεση)",
"Cashonize / Paytaca via QR": "Cashonize / Paytaca μέσω QR",
"The home for names on Bitcoin Cash. Register a TLD, register a name, verify anything against the chain.": "Το σπίτι των ονομάτων στο Bitcoin Cash. Καταχώρησε TLD, καταχώρησε όνομα, επαλήθευσε τα πάντα στο blockchain.",
"Product": "Προϊόν",
"✏️ Register a name": "✏️ Καταχώρηση ονόματος",
"🌐 Register a TLD": "🌐 Καταχώρηση TLD",
"🔑 My names portal": "🔑 Η πύλη των ονομάτων μου",
"🧭 Theseus browser": "🧭 Browser Theseus",
"Learn": "Μάθε",
"📚 Docs": "📚 Τεκμηρίωση",
"🗺 Roadmap": "🗺 Οδικός χάρτης",
"🏛 The Pantheon": "🏛 Το Πάνθεον",
"🎨 Brand kit": "🎨 Brand kit",
"Alpha": "Alpha",
"Chipnet only. You hold your own keys; verify everything against the chain.": "Μόνο chipnet. Κρατάς τα δικά σου κλειδιά· επαλήθευσε τα πάντα στο blockchain.",
"brand assets": "υλικό brand",
"available": "διαθέσιμο",
"taken": "κατειλημμένο",
"checking…": "έλεγχος…",
"Register →": "Καταχώρηση →",
"loading…": "φόρτωση…",
"(no records set)": "(δεν έχουν οριστεί εγγραφές)",
"on chain": "στο blockchain",
"Edit": "Επεξεργασία",
"tier pricing": "κλιμακωτή τιμή",
"(default policy — open, tier pricing)": "(προεπιλεγμένη πολιτική — ανοιχτή, κλιμακωτές τιμές)",
"Price & policy": "Τιμή & πολιτική",
"Register a name under": "Καταχώρηση ονόματος κάτω από",
"Preparing your addresses…": "Προετοιμασία των διευθύνσεών σου…",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.": "Δεν βρέθηκαν ονόματα BCNR για αυτό το πορτοφόλι. Αν μόλις καταχώρησες, περίμενε ένα λεπτό για επιβεβαίωση και ανανέωσε.",
"Off-chain DNS records — free per edit": "Εγγραφές DNS εκτός blockchain — δωρεάν ανά αλλαγή",
"Signing…": "Υπογραφή…",
"Saved ✓": "Αποθηκεύτηκε ✓",
"Registered ✓": "Καταχωρήθηκε ✓",
"Switch on": "Άναμμα",
"Switch off": "Σβήσιμο",
"Switch on: list the TLD and sell names again": "Άναμμα: εμφάνιση του TLD και πώληση ονομάτων ξανά",
"Switch off: hide the TLD, stop new registrations": "Σβήσιμο: απόκρυψη του TLD, διακοπή νέων καταχωρήσεων",
"no owner price set — buyers pay the length tier": "δεν έχει οριστεί τιμή κατόχου — οι αγοραστές πληρώνουν την κλίμακα μήκους",
"hidden from the public registry; no new names until you switch it on": "κρυφό από το δημόσιο μητρώο· κανένα νέο όνομα μέχρι να το ανάψεις",
"listed in the public registry": "στο δημόσιο μητρώο",
"label": "ετικέτα",
"🔓 Unlock": "🔓 Ξεκλείδωμα",
"🆕 Create": "🆕 Δημιουργία",
"📥 Import": "📥 Εισαγωγή",
"Dashboard — your names on Sirius.X": "Πίνακας ελέγχου — τα ονόματά σου στο Sirius.X",
"dashboard": "",
"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.": "Συνδέσου μία φορά με τη seed φράση Bitcoin Cash ή σύνδεσε εξωτερικό πορτοφόλι. Η συσκευή μένει συνδεδεμένη μέχρι να αποσυνδεθείς — χωρίς κωδικούς σε κάθε επίσκεψη. Τα κλειδιά σου δεν φεύγουν ποτέ από αυτόν τον browser.",
"Manage": "Διαχείριση",
"Domain names": "Ονόματα τομέα",
"My TLD list": "Τα TLD μου",
"Get more": "Περισσότερα",
"Docs": "Τεκμηρίωση",
"What this wallet holds on chain, and where to go next.": "Τι κατέχει αυτό το πορτοφόλι στο blockchain και πού να πας μετά.",
"↻ Refresh": "↻ Ανανέωση",
"Recent names": "Πρόσφατα ονόματα",
"The last few certificates that landed in this wallet.": "Τα τελευταία πιστοποιητικά που έφτασαν σε αυτό το πορτοφόλι.",
"Attention": "Προσοχή",
"Names that point nowhere yet, or have no DNS.": "Ονόματα που δεν δείχνουν ακόμα πουθενά ή δεν έχουν DNS.",
"Every BCNR name this wallet holds. Open one to manage DNS, content, redirects or transfer it.": "Κάθε όνομα BCNR σε αυτό το πορτοφόλι. Άνοιξε ένα για DNS, περιεχόμενο, ανακατευθύνσεις ή μεταβίβαση.",
"Filter names…": "Φιλτράρισμα ονομάτων…",
"Sort: name": "Ταξινόμηση: όνομα",
"Sort: TLD": "Ταξινόμηση: TLD",
"Sort: newest": "Ταξινόμηση: νεότερα",
"All TLDs": "Όλα τα TLD",
"no DNS": "χωρίς DNS",
"DNS …": "DNS …",
"DNS needs s3": "DNS χρειάζεται s3",
"Open site →": "Άνοιγμα site →",
"Summary": "Σύνοψη",
"DNS records": "Εγγραφές DNS",
"Content & hosting": "Περιεχόμενο & φιλοξενία",
"Redirect": "Ανακατεύθυνση",
"Transfer": "Μεταβίβαση",
"Export": "Εξαγωγή",
"Certificate": "Πιστοποιητικό",
"Where it points": "Πού δείχνει",
"On-chain records decide what a resolver serves. Change them under Content & hosting.": "Οι on-chain εγγραφές ορίζουν τι σερβίρει ο resolver. Άλλαξέ τες στο Περιεχόμενο & φιλοξενία.",
"DNS at a glance": "DNS με μια ματιά",
"Signed off-chain records for mail, verification and classic DNS interop.": "Υπογεγραμμένες εγγραφές εκτός αλυσίδας για mail, επαλήθευση και κλασικό DNS.",
"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.": "Τυπικές εγγραφές, υπογεγραμμένες με το κλειδί σου και αποθηκευμένες σε manifest στο Sia. Δωρεάν αλλαγές, χωρίς συναλλαγή. Resolvers και gateway επαληθεύουν την υπογραφή με τον τρέχοντα κάτοχο του NFT.",
"Type": "Τύπος",
"Value": "Τιμή",
"Priority / extra": "Προτεραιότητα / επιπλέον",
"No DNS records yet. Add the first one below.": "Δεν υπάρχουν ακόμα εγγραφές DNS. Πρόσθεσε την πρώτη παρακάτω.",
"Priority": "Προτεραιότητα",
"Weight": "Βάρος",
"Port": "Θύρα",
"Tag": "Ετικέτα",
"+ Add": "+ Προσθήκη",
"Discard changes": "Απόρριψη αλλαγών",
"Nameservers": "Nameservers",
"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.": "Τα ονόματα BCNR δεν χρειάζονται nameservers — οι resolvers διαβάζουν το blockchain και αυτό το manifest απευθείας. Πρόσθεσε NS μόνο αν αναθέτεις το όνομα και σε κλασικό DNS.",
"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.": "On-chain εγγραφές, δημοσιευμένες ως μία υπογεγραμμένη συναλλαγή UPD (λίγα λεπτά σκόνη). Κενό πεδίο αφαιρεί την εγγραφή. Προτεραιότητα για resolvers: h, μετά s3, μετά p, μετά ip.",
"inline HTML — served as-is at the site root (~150 bytes)": "ενσωματωμένο HTML — σερβίρεται ως έχει στη ρίζα (~150 bytes)",
"Sia bucket key, trailing slash for directories — also where DNS manifests live": "κλειδί bucket Sia, κάθετος στο τέλος για καταλόγους — εκεί ζουν και τα manifests DNS",
"reverse proxy: full upstream URL the gateway mirrors": "reverse proxy: πλήρες URL προέλευσης που καθρεφτίζει το gateway",
"Reset": "Επαναφορά",
"Forward this name to any web address. Stored on chain as the": "Προώθησε αυτό το όνομα σε οποιαδήποτε διεύθυνση web. Αποθηκεύεται στο blockchain ως εγγραφή",
"record; resolvers and the gateway issue the redirect. Clear it to stop forwarding.": "· resolvers και gateway εκτελούν την ανακατεύθυνση. Καθάρισέ το για να σταματήσει.",
"Destination URL": "URL προορισμού",
"Remove redirect": "Αφαίρεση ανακατεύθυνσης",
"Save redirect →": "Αποθήκευση ανακατεύθυνσης →",
"Transfer ownership": "Μεταβίβαση κυριότητας",
"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.": "Μεταφέρει το πιστοποιητικό του ονόματος σε άλλη διεύθυνση Bitcoin Cash με μία συναλλαγή. Οι εγγραφές μένουν ως έχουν. Ο νέος κάτοχος ελέγχει το όνομα από εκείνη τη στιγμή — δεν αναιρείται από εδώ.",
"Recipient address": "Διεύθυνση παραλήπτη",
"I understand this hands the name to that address permanently.": "Καταλαβαίνω ότι αυτό παραδίδει το όνομα μόνιμα σε εκείνη τη διεύθυνση.",
"Transfer name →": "Μεταβίβαση ονόματος →",
"Download this name's DNS as a BIND-style zone file, or its full record set as JSON, for backups or importing elsewhere.": "Κατέβασε το DNS αυτού του ονόματος ως αρχείο ζώνης τύπου BIND ή όλες τις εγγραφές ως JSON, για αντίγραφα ή εισαγωγή αλλού.",
"⬇ Zone file (.txt)": "⬇ Αρχείο ζώνης (.txt)",
"⬇ Records (.json)": "⬇ Εγγραφές (.json)",
"Copy DNS manifest": "Αντιγραφή manifest DNS",
"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.": "Κάθε NFT μητρώου TLD σε αυτό το πορτοφόλι. Όρισε την τιμή κάθε ονόματος κάτω από ένα TLD, άναψέ το ή σβήσε το (σβηστό = ιδιωτικό: μόνο εσύ καταχωρείς) και ρύθμισε την πολιτική. Κάθε αλλαγή είναι ένα υπογεγραμμένο TUPD στο blockchain· λαμβάνεις το 90 % κάθε πώλησης.",
"Registry": "Μητρώο",
"Register a name under this TLD": "Καταχώρηση ονόματος κάτω από αυτό το TLD",
"Works whether the TLD is on or off. As the owner you pay only the platform's 10% share.": "Δουλεύει είτε το TLD είναι αναμμένο είτε σβηστό. Ως κάτοχος πληρώνεις μόνο το 10 % της πλατφόρμας.",
"Names registered under this TLD": "Ονόματα καταχωρημένα κάτω από αυτό το TLD",
"Everyone's registrations, from the public registry.": "Οι καταχωρήσεις όλων, από το δημόσιο μητρώο.",
"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.": "Τα TLD είναι NFT μητρώου στο TLD beacon του chipnet. Οι δημόσιες κοπές πληρώνουν τέλος που χρηματοδοτεί το μητρώο. Το chipnet έχει προσωρινή ισοτιμία· στο mainnet ένα πραγματικό oracle ορίζει τιμή από το μήκος.",
"Faucet 2 →": "Faucet 2 →",
"Balance": "Υπόλοιπο",
"Spendable": "Διαθέσιμο",
"UTXOs": "UTXOs",
"Watched addresses": "Παρακολουθούμενες διευθύνσεις",
"Session and security choices for this browser. Nothing here changes what is on chain.": "Επιλογές συνεδρίας και ασφάλειας για αυτόν τον browser. Τίποτα εδώ δεν αλλάζει το blockchain.",
"Session": "Συνεδρία",
"Stay signed in on this device": "Παραμονή σύνδεσης σε αυτή τη συσκευή",
"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.": "Η φράση ανάκτησης μένει κρυπτογραφημένη με κλειδί που κρατά ο browser και δεν μπορεί να εξάγει. Οι επόμενες επισκέψεις ανοίγουν κατευθείαν τον πίνακα. Απενεργοποίησέ το για να ζητείται κωδικός ή PIN κάθε φορά.",
"Ask for PIN before payments": "Ζήτα PIN πριν από πληρωμές",
"Adds a PIN prompt when registering a name or TLD. Off by default so signed-in sessions run uninterrupted.": "Προσθέτει ερώτηση PIN στην καταχώρηση ονόματος ή TLD. Απενεργοποιημένο εξ ορισμού ώστε οι συνεδρίες να τρέχουν χωρίς διακοπές.",
"Set / change PIN": "Ορισμός / αλλαγή PIN",
"Remove PIN": "Αφαίρεση PIN",
"Reading & language": "Ανάγνωση & γλώσσα",
"Font pill and language picker live in the top bar; both are remembered per browser.": "Ο διακόπτης γραμματοσειράς και η επιλογή γλώσσας είναι στην πάνω μπάρα· και τα δύο θυμούνται ανά browser.",
"This device": "Αυτή η συσκευή",
"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.": "Η αποσύνδεση κρατά το κρυπτογραφημένο πορτοφόλι στη συσκευή για να το ξεκλειδώσεις αργότερα. Η λήθη το αφαιρεί εντελώς — θα χρειαστείς τη φράση ανάκτησης.",
"Forget wallet on this device": "Λήθη πορτοφολιού σε αυτή τη συσκευή",
"4–6 digits. Encrypts your recovery phrase under this PIN on this device. Three wrong PINs clear it and fall back to your password.": "4–6 ψηφία. Κρυπτογραφεί τη φράση ανάκτησης με αυτό το PIN στη συσκευή. Τρία λάθος PIN το διαγράφουν και επιστρέφεις στον κωδικό.",
"No names yet.": "Δεν υπάρχουν ακόμα ονόματα.",
"Register your first one →": "Καταχώρησε το πρώτο σου →",
"Everything points somewhere and has DNS. Nice.": "Όλα δείχνουν κάπου και έχουν DNS. Ωραία.",
"Nothing matches that filter.": "Τίποτα δεν ταιριάζει με αυτό το φίλτρο.",
"Status": "Κατάσταση",
"point it somewhere →": "δείξε κάπου →",
"Add some →": "Πρόσθεσε →",
"Register one →": "Καταχώρησε ένα →",
"yours": "δικό σου",
"Copied": "Αντιγράφηκε",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and refresh.": "Δεν βρέθηκαν ονόματα BCNR για αυτό το πορτοφόλι. Αν μόλις καταχώρησες, περίμενε ένα λεπτό και ανανέωσε.",
"Remove": "Αφαίρεση",
"Transferring…": "Μεταβίβαση…",
"Transferred ✓": "Μεταβιβάστηκε ✓",
"off · private": "σβηστό · ιδιωτικό",
"on · public": "αναμμένο · δημόσιο",
"Signing you in…": "Σύνδεση…",
"Restoring your session on this device.": "Επαναφορά της συνεδρίας σου σε αυτή τη συσκευή.",
"Dashboard": "Πίνακας ελέγχου",
"names, TLDs, DNS, settings": "ονόματα, TLD, DNS, ρυθμίσεις",
"site on chain": "site στο blockchain",
"site on Sia": "site στο Sia",
"reverse proxy": "reverse proxy",
"own server": "δικός σου server",
"redirect": "ανακατεύθυνση",
"not pointed": "δεν δείχνει πουθενά",
"points nowhere yet": "δεν δείχνει ακόμα πουθενά",
"no DNS records": "χωρίς εγγραφές DNS",
"DNS needs an s3 pointer": "DNS χρειάζεται εγγραφή s3",
"block": "μπλοκ",
"Web-Builder": "Web-Builder",
"My TLDs": "Τα TLD μου",
"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.": "Το Sirius Studio φτιάχνει site για κάθε όνομα που κατέχεις: σύρε μπλοκ, άλλαξε κείμενο, δημοσίευσε. Οι σελίδες ζουν στον φάκελο του ονόματος στο Sia και το όνομα δείχνει εκεί — χωρίς host, χωρίς ανανέωση.",
"Session, security and wallet details for this browser. Nothing here changes what is on chain.": "Συνεδρία, ασφάλεια και στοιχεία πορτοφολιού για αυτόν τον browser. Τίποτα εδώ δεν αλλάζει το blockchain.",
"Reading, language & help": "Ανάγνωση, γλώσσα & βοήθεια",
"Font pill and language picker live in the top bar; both are remembered per browser. The technical documentation is at": "Ο διακόπτης γραμματοσειράς και η επιλογή γλώσσας είναι στην πάνω μπάρα· θυμούνται ανά browser. Η τεχνική τεκμηρίωση βρίσκεται στο",
"Start from a template": "Ξεκίνα από πρότυπο",
"Preview the exported page in a new tab": "Προεπισκόπηση της εξαγόμενης σελίδας σε νέα καρτέλα",
"Sirius Studio — build the site for your name": "Sirius Studio — φτιάξε το site για το όνομά σου",
"Templates…": "Πρότυπα…",
"Landing page": "Σελίδα προορισμού",
"Profile / link hub": "Προφίλ / σύνδεσμοι",
"Business one-pager": "Επιχείρηση σε μία σελίδα",
"Blank page": "Κενή σελίδα",
"Preview": "Προεπισκόπηση",
"Save draft": "Αποθήκευση προσχεδίου",
"Publish to Sia →": "Δημοσίευση στο Sia →",
"View site →": "Προβολή site →",
"Sign in first": "Πρώτα σύνδεση",
"Sirius Studio publishes with your wallet's key. Sign in on the dashboard, then come back to this name.": "Το Sirius Studio δημοσιεύει με το κλειδί του πορτοφολιού σου. Συνδέσου στον πίνακα και γύρνα σε αυτό το όνομα.",
"Open the dashboard →": "Άνοιγμα πίνακα →",
"Build the site for": "Φτιάξε το site για το",
"Pick a starting point. Everything is editable — drag blocks in from the right, click any text to change it. Nothing leaves your browser until you press Publish; then the page is stored on Sia and the name points at it.": "Διάλεξε αφετηρία. Όλα επεξεργάζονται — σύρε μπλοκ από δεξιά, κάνε κλικ σε κείμενο για να το αλλάξεις. Τίποτα δεν φεύγει από τον browser μέχρι να πατήσεις Δημοσίευση· τότε η σελίδα αποθηκεύεται στο Sia και το όνομα δείχνει εκεί.",
"Hero, three features, call to action.": "Hero, τρία χαρακτηριστικά, κάλεσμα σε δράση.",
"Avatar, bio and a stack of links.": "Avatar, βιογραφικό και λίστα συνδέσμων.",
"About, services, hours, contact.": "Σχετικά, υπηρεσίες, ωράριο, επικοινωνία.",
"Start from nothing.": "Ξεκίνα από το μηδέν.",
"Back to dashboard": "Πίσω στον πίνακα",
"Publish": "Δημοσίευση",
"The page and its assets are uploaded to the name's folder on Sia, signed with your key. If the name does not point at that folder yet, one on-chain update sets it (a few cents of chain dust).": "Η σελίδα και τα αρχεία της ανεβαίνουν στον φάκελο του ονόματος στο Sia, υπογεγραμμένα με το κλειδί σου. Αν το όνομα δεν δείχνει ακόμα εκεί, μία on-chain ενημέρωση το ορίζει (λίγα λεπτά σκόνη).",
"Needs attention": "Χρειάζεται προσοχή",
"View →": "Προβολή →",
"Edit in Studio": "Επεξεργασία στο Studio",
"Open in Studio": "Άνοιγμα στο Studio",
"built with Studio": "φτιαγμένο με Studio",
"site on Sia (external)": "site στο Sia (εξωτερικό)",
"inline HTML": "ενσωματωμένο HTML",
"no site yet": "χωρίς site ακόμα",
"Pick a name to build or edit its site.": "Διάλεξε όνομα για να φτιάξεις ή να επεξεργαστείς το site του.",
"You need a name first.": "Χρειάζεσαι πρώτα ένα όνομα.",
"— then come back here to build its site.": "— και γύρνα εδώ για να φτιάξεις το site του.",
"New site": "Νέο site",
"Not signed in": "Μη συνδεδεμένος",
"Loading name…": "Φόρτωση ονόματος…",
"Published": "Δημοσιεύτηκε",
"Publish failed": "Η δημοσίευση απέτυχε",
"Template loaded — edit, then Publish": "Το πρότυπο φορτώθηκε — επεξεργάσου, μετά δημοσίευσε",
"Draft saved on Sia": "Το προσχέδιο αποθηκεύτηκε στο Sia",
"Saving draft…": "Αποθήκευση προσχεδίου…",
"Copy address": "Αντιγραφή διεύθυνσης",
"receive coins or names here": "λάβε εδώ νομίσματα ή ονόματα",
"Copy token address": "Αντιγραφή διεύθυνσης token",
"where name certificates are minted": "εκεί κόβονται τα πιστοποιητικά ονομάτων",
"Get test coins": "Πάρε δοκιμαστικά νομίσματα",
"chipnet faucet": "faucet chipnet",
"Wallet settings": "Ρυθμίσεις πορτοφολιού",
"session, PIN, forget device": "συνεδρία, PIN, λήθη συσκευής",
"Holdings": "Κατοχές",
"open the dashboard to load": "άνοιξε τον πίνακα για φόρτωση",
"🛒 Market": "🛒 Αγορά",
"🛒 Names for sale": "🛒 Ονόματα προς πώληση",
"Market — names for sale on Sirius.X": "Αγορά — ονόματα προς πώληση στο Sirius.X",
"for sale": "προς πώληση",
"Every sale is a single Bitcoin Cash transaction. The seller signed an offer that pays them only when the certificate moves to you — you add your coins, sign, broadcast. No escrow, no middleman, no way for either side to cheat.": "Κάθε πώληση είναι μία μόνο συναλλαγή Bitcoin Cash. Ο πωλητής υπέγραψε μια προσφορά που τον πληρώνει μόνο όταν το πιστοποιητικό περάσει σε εσένα — προσθέτεις τα κέρματά σου, υπογράφεις, μεταδίδεις. Χωρίς μεσεγγύηση, χωρίς μεσάζοντα, χωρίς τρόπο να εξαπατήσει κανείς.",
"Sort: price": "Ταξινόμηση: τιμή",
"Loading listings…": "Φόρτωση αγγελιών…",
"Selling a name?": "Πουλάς ένα όνομα;",
"Open it in your": "Άνοιξέ το στον",
", choose": ", επίλεξε",
"Sell": "Πώληση",
", set a price. The listing is a signed offer stored by the gateway; cancelling it moves your certificate once so the old offer can never be used.": ", όρισε τιμή. Η αγγελία είναι μια υπογεγραμμένη προσφορά που αποθηκεύει η πύλη· η ακύρωση μετακινεί το πιστοποιητικό σου μία φορά ώστε η παλιά προσφορά να μην μπορεί ποτέ να χρησιμοποιηθεί.",
"One transaction: your coins pay the seller, the certificate lands in your wallet, and the registry is told about the new owner. Records stay as they are — you can change them in the dashboard right after.": "Μία συναλλαγή: τα κέρματά σου πληρώνουν τον πωλητή, το πιστοποιητικό φτάνει στο πορτοφόλι σου και το μητρώο ενημερώνεται για τον νέο ιδιοκτήτη. Οι εγγραφές μένουν ως έχουν — μπορείς να τις αλλάξεις αμέσως μετά στον πίνακα ελέγχου.",
"Sign in to buy →": "Σύνδεση για αγορά →",
"Buy — sign & broadcast": "Αγορά — υπογραφή & μετάδοση",
"Buy →": "Αγορά →",
"Nothing is for sale right now. Owners list names from their dashboard.": "Τίποτα δεν πωλείται αυτή τη στιγμή. Οι ιδιοκτήτες καταχωρούν ονόματα από τον πίνακα ελέγχου τους.",
"Sell this name": "Πώληση αυτού του ονόματος",
"You sign an offer once: \"whoever pays me this price gets the certificate\". The offer is stored by the gateway and shown on the": "Υπογράφεις μία προσφορά μία φορά: «όποιος μου πληρώσει αυτή την τιμή παίρνει το πιστοποιητικό». Η προσφορά αποθηκεύεται από την πύλη και εμφανίζεται στην",
"market": "αγορά",
". 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.": ". Ο αγοραστής την ολοκληρώνει σε μία συναλλαγή — πληρώνεσαι στην ίδια συναλλαγή που μεταφέρει το όνομα, ή καθόλου. Χωρίς μεσεγγύηση, τίποτα προς εμπιστοσύνη.",
"Checking the market…": "Έλεγχος της αγοράς…",
"Price (USD)": "Τιμή (USD)",
"Price (sat)": "Τιμή (sat)",
"List for sale →": "Καταχώρηση προς πώληση →",
"Cancel listing →": "Ακύρωση αγγελίας →",
"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.": "Η ακύρωση αφαιρεί την προσφορά από την αγορά και μετακινεί το πιστοποιητικό σου μία φορά (μια κενή ενημέρωση, λίγα λεπτά), ώστε η υπογεγραμμένη προσφορά να μην μπορεί ποτέ να ολοκληρωθεί αργότερα.",
"Not for sale. Set a price to list it.": "Δεν πωλείται. Όρισε τιμή για να το καταχωρήσεις.",
"This name is listed on the market.": "Αυτό το όνομα είναι καταχωρημένο στην αγορά.",
"Pending approvals": "Εκκρεμείς εγκρίσεις",
"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.": "Καταχωρήσεις κάτω από αυτό το TLD που περιμένουν τη συνυπογραφή σου. Η έγκριση υπογράφει το πιστοποιητικό TLD σου μέσα στη συναλλαγή του αγοραστή και τη μεταδίδει· το πιστοποιητικό επιστρέφει σε εσένα στην ίδια συναλλαγή. Τίποτα δεν μπορεί να καταχωρηθεί κάτω από ένα TLD συνυπογραφής ή ιδιωτικό χωρίς αυτό το βήμα.",
"No requests waiting.": "Δεν εκκρεμούν αιτήματα.",
"awaiting you": "περιμένει εσένα",
"Approve & broadcast": "Έγκριση & μετάδοση",
"Decline": "Απόρριψη",
"Request approval — sign": "Αίτημα έγκρισης — υπογραφή",
"Withdraw request": "Απόσυρση αιτήματος",
"Request declined": "Το αίτημα απορρίφθηκε",
"Open dashboard →": "Άνοιγμα πίνακα ελέγχου →",
"incl.": "συμπ.",
"sat unconfirmed · spendable now": "sat ανεπιβεβαίωτα · διαθέσιμα τώρα",
"Nothing is for sale right now": "Τίποτα δεν πωλείται αυτή τη στιγμή",
"Names go on sale when their owners list them from the dashboard. Have one to sell, or want a fresh one instead?": "Τα ονόματα βγαίνουν προς πώληση όταν οι ιδιοκτήτες τους τα καταχωρούν από τον πίνακα ελέγχου. Έχεις ένα να πουλήσεις ή προτιμάς ένα καινούργιο;",
"Sell a name from your dashboard →": "Πούλησε ένα όνομα από τον πίνακα ελέγχου →",
"Register a new name": "Καταχώρηση νέου ονόματος",
"↓ Import live site": "↓ Εισαγωγή ζωντανής σελίδας",
"Import the live site": "Εισαγωγή ζωντανής σελίδας",
"✨ Assistant": "✨ Βοηθός",
"Runs on your own device. Nothing you write or build is sent to Sirius.X or to any AI vendor.": "Τρέχει στη δική σου συσκευή. Τίποτα από όσα γράφεις ή φτιάχνεις δεν στέλνεται στο Sirius.X ή σε πάροχο AI.",
"Runs on": "Τρέχει σε",
"This browser — your GPU, private": "Αυτός ο browser — η GPU σου, ιδιωτικά",
"Local endpoint — Ollama, LM Studio": "Τοπικό endpoint — Ollama, LM Studio",
"Model": "Μοντέλο",
"Downloads once, then stays in the browser cache. Needs WebGPU (current Chrome, Edge, Firefox, Safari).": "Κατεβαίνει μία φορά και μένει στην cache του browser. Χρειάζεται WebGPU (σύγχρονο Chrome, Edge, Firefox, Safari).",
"Load model": "Φόρτωση μοντέλου",
"Endpoint": "Endpoint",
"Connect": "Σύνδεση",
"What do you want?": "Τι θέλεις;",
"Make a section": "Φτιάξε ενότητα",
"Rewrite selected text": "Ξαναγράψε το επιλεγμένο κείμενο",
"Restyle selection": "Άλλαξε στυλ στην επιλογή",
"Nothing selected": "Τίποτα επιλεγμένο",
"Undo last change": "Αναίρεση τελευταίας αλλαγής",
"Stop": "Στοπ"
}

612
i18n/es.json Normal file
View file

@ -0,0 +1,612 @@
{
"Sirius.X — the home for names on Bitcoin Cash": "Sirius.X — el hogar de los nombres en Bitcoin Cash",
"Portal — your names on Sirius.X": "Portal — tus nombres en Sirius.X",
"Register a TLD — Sirius.X": "Registrar un TLD — Sirius.X",
"Try it": "Pruébalo",
"✏️ Register": "✏️ Registrar",
"🌐 TLD": "🌐 TLD",
"🔑 Sign in": "🔑 Iniciar sesión",
"type a name — e.g. hello": "escribe un nombre — p. ej. hola",
"Search a name across every BCNR TLD": "Buscar un nombre en todos los TLD de BCNR",
"Names on the": "Nombres en la",
"chain": "cadena",
"Sirius.X is the entry point for BCNR — Bitcoin Cash Name Registry. Register a top-level domain, register a name under one, look up records, verify anything against the chain.": "Sirius.X es la puerta de entrada a BCNR — el registro de nombres de Bitcoin Cash. Registra un dominio de nivel superior, registra un nombre bajo uno, consulta registros y verifica cualquier cosa contra la cadena.",
"One search checks the label across every TLD in the registry. Available names appear first.": "Una sola búsqueda comprueba la etiqueta en todos los TLD del registro. Los nombres disponibles aparecen primero.",
"Or browse what you can do →": "O mira lo que puedes hacer →",
"Read the docs": "Leer la documentación",
"Three things you can do right now. The registrar and TLD-registry UIs live at silentmode.st today; Sirius.X is the canonical home and will consolidate them here.": "Tres cosas que puedes hacer ahora mismo. El registrador y el registro de TLD viven hoy en silentmode.st; Sirius.X es su hogar canónico y los consolidará aquí.",
"Register a name": "Registrar un nombre",
"Pick a label, search across every TLD in the registry at once, mint the name certificate straight into your own wallet. No yearly renewal.": "Elige una etiqueta, búscala en todos los TLD del registro a la vez y acuña el certificado del nombre directamente en tu propia cartera. Sin renovación anual.",
"≈ 10,000 sat service fee · 1,300 sat chain dust · < 1 ¢": "≈ 10 000 sat de tarifa de servicio · 1 300 sat de polvo de cadena · < 1 ¢",
"Chipnet placeholder. 90 % of the service fee flows to the TLD owner, 10 % to the platform.": "Valor provisional de chipnet. El 90 % de la tarifa va al dueño del TLD, el 10 % a la plataforma.",
"Search a name →": "Buscar un nombre →",
"Register a TLD": "Registrar un TLD",
"A TLD is itself a certificate on the chain. Anyone can mint one — you become the registry operator for every second-level name under it, and earn 90 % of the fee on every name registered under it. Renewals are per-TLD policy set by the owner.": "Un TLD es en sí mismo un certificado en la cadena. Cualquiera puede acuñar uno: te conviertes en operador del registro de cada nombre de segundo nivel bajo él y ganas el 90 % de la tarifa de cada nombre registrado. Las renovaciones son una política por TLD que fija el dueño.",
"≈ 1,250,000 sat service fee (≈ $5) · 1,300 sat chain dust": "≈ 1 250 000 sat de tarifa de servicio (≈ 5 $) · 1 300 sat de polvo de cadena",
"Chipnet placeholder rate — mainnet will price by label length via an on-chain oracle.": "Tasa provisional de chipnet — en mainnet el precio dependerá de la longitud de la etiqueta mediante un oráculo en cadena.",
"Search a TLD →": "Buscar un TLD →",
"Operator admin →": "Administración del operador →",
"Look up & verify": "Consultar y verificar",
"Resolve any BCNR name, compare records across mirrors, and check the TLD registry snapshot against the chain. Everything is publicly verifiable.": "Resuelve cualquier nombre BCNR, compara registros entre espejos y comprueba la instantánea del registro de TLD contra la cadena. Todo es verificable públicamente.",
"How to verify →": "Cómo verificar →",
"🔑 Sign in — your names portal": "🔑 Iniciar sesión — tu portal de nombres",
"Import your seed phrase or connect a wallet (Cashonize / Paytaca via WizardConnect) to see every name you own, review records, and update them. Your keys never leave your browser.": "Importa tu frase semilla o conecta una cartera (Cashonize / Paytaca vía WizardConnect) para ver todos los nombres que posees, revisar registros y actualizarlos. Tus claves nunca salen de tu navegador.",
"Open the portal →": "Abrir el portal →",
"🧭 Theseus Navigator": "🧭 Theseus Navigator",
"The browser that speaks BCNR natively. Open": "El navegador que habla BCNR de forma nativa. Abre",
"in the address bar — it just resolves. TLS verified against on-chain fingerprints, no OS trust-store install.": "en la barra de direcciones y simplemente resuelve. TLS verificado contra huellas en cadena, sin instalar nada en el almacén de confianza del sistema.",
"Download →": "Descargar →",
"Documentation": "Documentación",
"The full docs — TLD registry model, record types, resolver & gateway paths, mainnet pricing, verification, and the operator runbook pointer — live on their own page so they can grow without cluttering the landing.": "La documentación completa — modelo del registro de TLD, tipos de registro, rutas de resolvedor y pasarela, precios en mainnet, verificación y el enlace al runbook del operador — vive en su propia página para crecer sin recargar la portada.",
"📚 Open the docs →": "📚 Abrir la documentación →",
"Current TLD list": "Lista actual de TLD",
"Propose a new TLD": "Proponer un nuevo TLD",
"The per-TLD registry means minting a TLD is a real, paid action — not a namespace land-grab. During the alpha, all TLD mints are operator-signed. To propose a TLD, get in touch via the channels below. The design (mainnet) adds an on-chain covenant with countersignature + tiered USD price floors: 1-char $100k, 2-char $50k, 3-char $15k, 4-char $5k, 5–8-char $1k, 9+-char $250; one-time payment (not annual). See the design doc for the full model.": "El registro por TLD significa que acuñar un TLD es una acción real y de pago, no una apropiación del espacio de nombres. Durante la alfa, todas las acuñaciones de TLD las firma el operador. Para proponer un TLD, contacta por los canales de abajo. El diseño (mainnet) añade un covenant en cadena con contrafirma y precios mínimos escalonados en USD: 1 carácter 100 k$, 2 caracteres 50 k$, 3 caracteres 15 k$, 4 caracteres 5 k$, 5–8 caracteres 1 k$, 9+ caracteres 250 $; pago único (no anual). Consulta el documento de diseño para el modelo completo.",
"ICANN-adjacent TLDs are not open for public mint.": "Los TLD que coinciden con ICANN no están abiertos a acuñación pública.",
"A TLD registry is only useful if it does not immediately collapse into an ICANN-shadow — the mainnet covenant enforces this; on chipnet the operator's countersignature is the gate.": "Un registro de TLD solo es útil si no se convierte de inmediato en una sombra de ICANN: en mainnet lo impone el covenant; en chipnet la contrafirma del operador es la barrera.",
"The pantheon": "El panteón",
"Sirius.x is one of seven sibling": "Sirius.x es uno de los siete nombres hermanos",
"names — the Silent Mode pantheon. Each project is its own on-chain certificate; each site is reachable through any BCNR resolver, plus the silentmode.st gateway for browsers without one.": "— el panteón de Silent Mode. Cada proyecto es su propio certificado en cadena; cada sitio es accesible mediante cualquier resolvedor BCNR, además de la pasarela silentmode.st para navegadores sin uno.",
"⛓️ Silentmode.X": "⛓️ Silentmode.X",
"The project umbrella. Redirects to": "El paraguas del proyecto. Redirige a",
"where every pillar has its own landing page + download hub.": "donde cada pilar tiene su propia página y sus descargas.",
"Open →": "Abrir →",
"⭐ Sirius.X": "⭐ Sirius.X",
"you're here": "estás aquí",
"Names on Bitcoin Cash — register, resolve, verify, manage. This site.": "Nombres en Bitcoin Cash — registrar, resolver, verificar, gestionar. Este sitio.",
"Home →": "Inicio →",
"🧭 Theseus.X": "🧭 Theseus.X",
"The browser that speaks BCNR natively — Chromium build with the resolver baked in, no OS-level daemon or root-store install.": "El navegador que habla BCNR de forma nativa: una compilación de Chromium con el resolvedor integrado, sin demonio del sistema ni certificado raíz.",
"Learn more →": "Saber más →",
"🔥 Hephaestus.X": "🔥 Hephaestus.X",
"The forge. Forgejo instance for the ecosystem's git repos, backed by BCH wallet auth. Sirius's own source lives here.": "La forja. Instancia de Forgejo para los repositorios git del ecosistema, con acceso mediante cartera BCH. El código fuente de Sirius vive aquí.",
"🔮 Prometheus.X": "🔮 Prometheus.X",
"Fire from the chain. The project's foresight / experimentation layer. Redirects to": "Fuego de la cadena. La capa de prospectiva y experimentación del proyecto. Redirige a",
"today.": "(hoy).",
"☀️ Helios.X": "☀️ Helios.X",
"The public gaze. Analytics, dashboards, transparency reports. Redirects to": "La mirada pública. Analíticas, paneles, informes de transparencia. Redirige a",
"✉️ Hermes.X": "✉️ Hermes.X",
"Messenger. Nostr-based messaging bound to a BCNR name via the": "Mensajería. Mensajes sobre Nostr vinculados a un nombre BCNR mediante los registros",
"records. Redirects to": ". Redirige a",
"What's coming": "Lo que viene",
"Sirius.X consolidates docs and registration today; three larger pieces are on the roadmap.": "Hoy Sirius.X consolida documentación y registro; tres piezas mayores están en la hoja de ruta.",
"Wallet & name portal": "Portal de cartera y nombres",
"next": "siguiente",
"Sign in with your Bitcoin Cash wallet, see every name you own, edit records inline, mint or renew from one place. Same self-custody as today — the portal never handles your keys.": "Inicia sesión con tu cartera de Bitcoin Cash, ve todos los nombres que posees, edita registros en línea, acuña o renueva desde un solo lugar. La misma autocustodia de hoy: el portal nunca toca tus claves.",
"Sirius Studio": "Sirius Studio",
"planned": "planificado",
"An in-browser site editor for names you already own — the WordPress / Tilda / Wix pattern, but the whole site persists to Sia and the name's": "Un editor de sitios en el navegador para nombres que ya posees — el patrón de WordPress / Tilda / Wix, pero todo el sitio se guarda en Sia y el registro",
"record updates on save. Sites live where the name says they live.": "del nombre se actualiza al guardar. Los sitios viven donde dice el nombre.",
"Decentralized git remote": "Remoto git descentralizado",
"MVP live": "MVP en marcha",
"The Silent Mode repo is served as a bare git tree over dumb-HTTP from the VPS. Clone it with any git client, no login. Forgejo + Sia sync for a proper decentralized backend is the next track.": "El repositorio de Silent Mode se sirve como árbol git bare por dumb-HTTP desde el VPS. Clónalo con cualquier cliente git, sin cuenta. El siguiente paso es Forgejo + sincronización con Sia como backend realmente descentralizado.",
"One-shot snapshot as a downloadable git bundle (works when dumb-HTTP is blocked):": "Instantánea única como git bundle descargable (funciona cuando dumb-HTTP está bloqueado):",
"Verify this page against the chain": "Verifica esta página contra la cadena",
"You do not have to trust that": "No tienes que confiar en que",
"is served by anyone specific. The name's certificate is on the Bitcoin Cash chain; the records point to Sia; every path is independently checkable.": "lo sirva alguien en concreto. El certificado del nombre está en la cadena de Bitcoin Cash; los registros apuntan a Sia; cada ruta se puede comprobar de forma independiente.",
"1. Confirm the certificate exists on chain": "1. Confirma que el certificado existe en la cadena",
"2. Fetch the TLD-registry snapshot from Nostr": "2. Obtén la instantánea del registro de TLD desde Nostr",
"The operator-signed snapshot of the TLD list is published as a Nostr replaceable event. Any relay carries it; the event's content field carries the current snapshot root.": "La instantánea de la lista de TLD, firmada por el operador, se publica como evento reemplazable de Nostr. Cualquier relé la lleva; el campo content del evento contiene la raíz de la instantánea actual.",
"Kind / d-tag": "Kind / d-tag",
"Pubkey (x-only, hex)": "Clave pública (x-only, hex)",
"Relays": "Relés",
"3. Reach this site via more than one route": "3. Llega a este sitio por más de una ruta",
"The same content should be served from at least two independent paths. If one mirror is unavailable, the others still work. If two mirrors disagree, the on-chain record is the tiebreaker.": "El mismo contenido debería servirse desde al menos dos rutas independientes. Si un espejo no está disponible, los demás siguen funcionando. Si dos espejos discrepan, el registro en cadena desempata.",
"Via any BCNR resolver:": "Mediante cualquier resolvedor BCNR:",
"(requires the local root CA)": "(requiere la CA raíz local)",
"Via the public gateway:": "Mediante la pasarela pública:",
"Via silentmode.st mirror:": "Mediante el espejo silentmode.st:",
"Direct from Sia (content-addressed): the": "Directo desde Sia (direccionado por contenido): el registro",
"record on": "en",
"names the exact bucket key": "indica la clave exacta del bucket",
"Register a": "Registra un",
"A TLD is a certificate on the Bitcoin Cash chain. You mint it, you own it — any second-level name registered under it lives in your TLD's registry. One BCH transaction, no ICANN. Renewals? Your TLD, your policy.": "Un TLD es un certificado en la cadena de Bitcoin Cash. Lo acuñas, es tuyo: cualquier nombre de segundo nivel registrado bajo él vive en el registro de tu TLD. Una transacción BCH, sin ICANN. ¿Renovaciones? Tu TLD, tu política.",
"Search a TLD": "Buscar un TLD",
"Type a label (a–z, 0–9, hyphen; up to 16 chars). Available TLDs get a Register button that opens the shared wallet-choice modal — the same flow name registration uses. As TLD owner you earn": "Escribe una etiqueta (a–z, 0–9, guion; hasta 16 caracteres). Los TLD disponibles muestran un botón Registrar que abre el diálogo compartido de elección de cartera, el mismo flujo que el registro de nombres. Como dueño del TLD ganas",
"of every name registered under your TLD. Renewals are your call — set them per TLD, or don't.": "de cada nombre registrado bajo tu TLD. Las renovaciones las decides tú: fíjalas por TLD, o no.",
"Register minting to your token address; you become the registry operator.": "El registro acuña en tu dirección de tokens; te conviertes en operador del registro.",
"Registered TLDs": "TLD registrados",
"Fetched from the on-chain TLD registry via the public gateway. Refresh the page for the latest.": "Obtenido del registro de TLD en cadena mediante la pasarela pública. Recarga la página para ver lo último.",
"Loading…": "Cargando…",
"Mint price": "Precio de acuñación",
"Category": "Categoría",
"Portal sections": "Secciones del portal",
"Your": "Tu portal de",
"names": "nombres",
"portal": "",
"Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see every BCNR name your wallet holds. Your keys never leave this browser tab.": "Inicia sesión con tu frase semilla de Bitcoin Cash o conecta una cartera externa para ver todos los nombres BCNR que posee. Tus claves nunca salen de esta pestaña.",
"Sign in or create a wallet": "Inicia sesión o crea una cartera",
"The same wallet that will hold your names does the signing. Pick a tab — everything happens on this page; keys never leave your browser.": "La misma cartera que guardará tus nombres es la que firma. Elige una pestaña: todo ocurre en esta página; las claves nunca salen de tu navegador.",
"Overview": "Resumen",
"Names": "Nombres",
"TLDs": "TLD",
"Wallet": "Cartera",
"Settings": "Ajustes",
"A snapshot of what this wallet holds on chain.": "Una vista de lo que esta cartera posee en la cadena.",
"Names held": "Nombres en posesión",
"CashTokens NFT certificates": "Certificados NFT CashTokens",
"TLDs owned": "TLD en propiedad",
"Per-TLD registry NFTs": "NFT de registro por TLD",
"Wallet balance": "Saldo de la cartera",
"chipnet sats": "sats de chipnet",
"Chain height": "Altura de la cadena",
"Last seen block": "Último bloque visto",
"+ Register a name": "+ Registrar un nombre",
"+ Register a TLD": "+ Registrar un TLD",
"Names you hold": "Tus nombres",
"Every BCNR name your wallet's addresses currently hold a CashTokens NFT for. Edit records inline to publish an on-chain UPD.": "Todos los nombres BCNR para los que las direcciones de tu cartera poseen ahora un NFT CashTokens. Edita los registros en línea para publicar un UPD en cadena.",
"Loading names from the chain…": "Cargando nombres desde la cadena…",
"TLDs you own": "Tus TLD",
"Every per-TLD registry NFT held by this wallet. Set the": "Todos los NFT de registro de TLD de esta cartera. Fija el",
"price": "precio",
"every name under your TLD sells for, switch the TLD": "al que se vende cada nombre bajo tu TLD, enciende o apaga el TLD",
"on or off": "en el registro público",
"in the public registry (off = a": "(apagado = un",
"private TLD": "TLD privado",
": nobody else can buy names under it, you still can from here), and tune policy —": ": nadie más puede comprar nombres bajo él, tú sí desde aquí) y ajusta la política —",
"fee": "tarifa",
"min length": "longitud mínima",
"reserved labels": "etiquetas reservadas",
"renewal period": "periodo de renovación",
". Every change is one signed TUPD on chain; you receive 90% of each sale.": ". Cada cambio es un TUPD firmado en cadena; recibes el 90 % de cada venta.",
"Loading TLDs from the chain…": "Cargando TLD desde la cadena…",
"Register a new TLD": "Registrar un nuevo TLD",
"TLDs are per-registry NFTs on the chipnet TLD beacon. Public mints go through a service-fee output to fund the registry. Chipnet uses a placeholder rate; mainnet will price by label length via a real oracle.": "Los TLD son NFT de registro en el faro de TLD de chipnet. Las acuñaciones públicas pagan una tarifa de servicio que financia el registro. Chipnet usa una tasa provisional; en mainnet un oráculo real fijará el precio según la longitud de la etiqueta.",
"Label": "Etiqueta",
"1–16 chars, [a-z0-9-]": "1–16 caracteres, [a-z0-9-]",
"Service fee (USD)": "Tarifa de servicio (USD)",
"chipnet test rate": "tasa de prueba de chipnet",
"sats · rate": "sats · tasa",
"sats/USD": "sats/USD",
"Check availability": "Comprobar disponibilidad",
"Register (~0 sats)": "Registrar (~0 sats)",
"Your addresses and current balance. Keys stay in this browser.": "Tus direcciones y saldo actual. Las claves se quedan en este navegador.",
"Receive address": "Dirección de recepción",
"Token address": "Dirección de tokens",
"holds your name certificates": "guarda los certificados de tus nombres",
"Faucet →": "Grifo →",
"Reader preferences live per-browser; wallet changes require a signature.": "Las preferencias de lectura son por navegador; los cambios de cartera requieren firma.",
"Reading font": "Tipografía de lectura",
"Fraunces (Silent Mode family) or Ubuntu (Bitcoin Cash brand font). The pill lives in the top nav.": "Fraunces (familia Silent Mode) o Ubuntu (tipografía de marca de Bitcoin Cash). El selector está en la navegación superior.",
"Session PIN": "PIN de sesión",
"PIN unlocks the wallet without re-typing your password. Wipes after 3 wrong attempts.": "El PIN desbloquea la cartera sin volver a escribir la contraseña. Se borra tras 3 intentos fallidos.",
"Sign out": "Cerrar sesión",
"Clears the signed-in state in this browser. Your on-chain names are unaffected.": "Borra el estado de sesión en este navegador. Tus nombres en cadena no se ven afectados.",
"Edit records. Only your key can sign this UPD; the transaction fee is a few cents in chain fees plus the beacon dust. Leave a field blank to omit that record.": "Edita registros. Solo tu clave puede firmar este UPD; la transacción cuesta unos céntimos en tarifas de cadena más el polvo del faro. Deja un campo vacío para omitir ese registro.",
"inline HTML — served as-is at the site root": "HTML en línea — se sirve tal cual en la raíz del sitio",
"Sia bucket key, trailing slash for directories": "clave del bucket de Sia, barra final para directorios",
"IPv4 that serves this name over Host header": "IPv4 que sirve este nombre mediante la cabecera Host",
"SHA-256 of your leaf cert — chain-pinned TLS trust": "SHA-256 de tu certificado hoja — confianza TLS anclada en la cadena",
"redirect target": "destino de redirección",
"payload:": "carga:",
"bytes": "bytes",
"Cancel": "Cancelar",
"Save records →": "Guardar registros →",
"DNS records for": "Registros DNS de",
"DNS-style records live in a signed manifest on Sia — not on chain.": "Los registros tipo DNS viven en un manifiesto firmado en Sia, no en la cadena.",
"Free per edit": "Gratis por edición",
", no size cap. The signature proves you own the name; the gateway rejects anything not signed by the current NFT holder. See": ", sin límite de tamaño. La firma demuestra que el nombre es tuyo; la pasarela rechaza todo lo que no firme el titular actual del NFT. Ver",
"docs": "documentación",
"IPv4 addresses, one per line": "direcciones IPv4, una por línea",
"IPv6 addresses, one per line": "direcciones IPv6, una por línea",
"one string per line (SPF, DKIM, verification tokens…)": "una cadena por línea (SPF, DKIM, tokens de verificación…)",
"one target host, or blank": "un host de destino, o vacío",
"nameservers, one per line": "servidores de nombres, uno por línea",
"Sign & publish →": "Firmar y publicar →",
"Policy for": "Política de",
"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).": "Fija la política de los nombres registrados bajo este TLD. Solo tu clave puede firmar este TUPD; la transacción cuesta unos céntimos de polvo de cadena. Deja un campo vacío para omitir esa regla (por defecto: política abierta, precios por tramos).",
"USD per name — flat, shown to every buyer; blank = length tiers. You receive 90% of each sale.": "USD por nombre — fijo, visible para cada comprador; vacío = tramos por longitud. Recibes el 90 % de cada venta.",
"listing": "listado",
"off hides the TLD from search and blocks new registrations until you switch it back on": "apagado oculta el TLD de la búsqueda y bloquea nuevos registros hasta que lo vuelvas a encender",
"On — listed, names for sale": "Encendido — listado, nombres a la venta",
"Off — hidden, not for sale": "Apagado — oculto, no se vende",
"reject names shorter than N chars": "rechazar nombres de menos de N caracteres",
"service fee owner takes, in basis points (500 = 5%)": "parte de la tarifa que se lleva el dueño, en puntos básicos (500 = 5 %)",
"open · frozen · reserved-only": "open · frozen · reserved-only",
"space-separated labels only owner can mint": "etiquetas separadas por espacios que solo el dueño puede acuñar",
"days between renewals, 0 = never expire": "días entre renovaciones, 0 = nunca caduca",
"renewal price in sats, 0 = free": "precio de renovación en sats, 0 = gratis",
"where the TLD's own landing lives": "dónde vive la página propia del TLD",
"Save policy →": "Guardar política →",
"Signed in": "Sesión iniciada",
"You are signed in as": "Has iniciado sesión como",
"Done": "Hecho",
"Close": "Cerrar",
"Unlock my browser wallet": "Desbloquear la cartera de mi navegador",
"You already created one on this device.": "Ya creaste una en este dispositivo.",
"Create a new wallet": "Crear una cartera nueva",
"easiest": "lo más fácil",
"Made here in your browser. You get a recovery phrase to write down — it is the only key.": "Se crea aquí, en tu navegador. Recibes una frase de recuperación para anotar: es la única clave.",
"Import a recovery phrase": "Importar una frase de recuperación",
"Restore a wallet you already have, from its 12-word phrase.": "Restaura una cartera que ya tienes a partir de su frase de 12 palabras.",
"Connect a wallet — WizardConnect": "Conectar una cartera — WizardConnect",
"most private": "lo más privado",
"Cashonize 0.9+ or Paytaca. Encrypted end-to-end over Nostr; the relay sees only ciphertext. Your keys never leave your wallet.": "Cashonize 0.9+ o Paytaca. Cifrado de extremo a extremo sobre Nostr; el relé solo ve texto cifrado. Tus claves nunca salen de tu cartera.",
"Everything below runs on": "Todo lo de abajo funciona en",
", Bitcoin Cash's test network. The coins are free and worth nothing — this is an alpha, and it is the honest place to try it before real money is involved.": ", la red de pruebas de Bitcoin Cash. Las monedas son gratis y no valen nada: esto es una alfa y es el lugar honesto para probarlo antes de que haya dinero real.",
"Starting the connection…": "Iniciando la conexión…",
"Back": "Atrás",
"Open your wallet": "Abre tu cartera",
"Copy": "Copiar",
"Waiting for your wallet… The link stays valid until you close this page.": "Esperando a tu cartera… El enlace sigue válido hasta que cierres esta página.",
"Connected": "Conectado",
"Reading your wallet and building the registration…": "Leyendo tu cartera y preparando el registro…",
"That wallet is empty": "Esa cartera está vacía",
"Two approvals needed.": "Se necesitan dos aprobaciones.",
"Register — approve in your wallet": "Registrar — aprueba en tu cartera",
"Approve in your wallet": "Aprueba en tu cartera",
"Create your wallet": "Crea tu cartera",
"Generated in this browser. The phrase is never sent anywhere — not to us, not to anyone.": "Generada en este navegador. La frase nunca se envía a ningún sitio: ni a nosotros, ni a nadie.",
"Password (encrypts the wallet on this device)": "Contraseña (cifra la cartera en este dispositivo)",
"Repeat password": "Repite la contraseña",
"There is no reset.": "No hay restablecimiento.",
"Generate phrase →": "Generar frase →",
"Write this down. Now.": "Anótalo. Ahora.",
"These 12 words are your wallet. Anyone who has them owns your names; if you lose them, nobody — including us — can recover anything.": "Estas 12 palabras son tu cartera. Quien las tenga posee tus nombres; si las pierdes, nadie —ni nosotros— podrá recuperar nada.",
"Copy phrase": "Copiar frase",
"I have written the phrase down somewhere safe and offline. I understand it cannot be reset.": "He anotado la frase en un lugar seguro y sin conexión. Entiendo que no se puede restablecer.",
"Continue →": "Continuar →",
"12 words, separated by spaces. It stays in this browser.": "12 palabras separadas por espacios. Se queda en este navegador.",
"Recovery phrase": "Frase de recuperación",
"Password to encrypt it on this device": "Contraseña para cifrarla en este dispositivo",
"Import →": "Importar →",
"No wallet on this device": "No hay cartera en este dispositivo",
"📥 Import a wallet →": "📥 Importar una cartera →",
"🆕 Create a wallet →": "🆕 Crear una cartera →",
"Enter your PIN": "Introduce tu PIN",
"Use password instead": "Usar la contraseña",
"Unlock →": "Desbloquear →",
"PIN reset": "PIN restablecido",
"3 wrong attempts — the PIN has been cleared. Enter your password to unlock and set a new PIN if you like.": "3 intentos fallidos: el PIN se ha borrado. Introduce tu contraseña para desbloquear y fija un nuevo PIN si quieres.",
"Continue with password →": "Continuar con contraseña →",
"Unlock your wallet": "Desbloquea tu cartera",
"Decrypts the wallet stored in this browser. After unlocking you can set a PIN so future sessions ask for 4–6 digits instead of the full password.": "Descifra la cartera guardada en este navegador. Tras desbloquear puedes fijar un PIN para que las próximas sesiones pidan 4–6 dígitos en lugar de la contraseña completa.",
"Password": "Contraseña",
"Set a PIN": "Fijar un PIN",
"optional": "opcional",
"Repeat PIN": "Repite el PIN",
"Not now": "Ahora no",
"Save PIN →": "Guardar PIN →",
"Fund your wallet": "Añade fondos a tu cartera",
"Send test coins to this address. It is yours — derived from your phrase.": "Envía monedas de prueba a esta dirección. Es tuya: deriva de tu frase.",
"checking balance…": "comprobando saldo…",
"Preparing…": "Preparando…",
"Building your registration transaction.": "Construyendo tu transacción de registro.",
"One transaction. It mints the certificate to": "Una transacción. Acuña el certificado en",
"your": "tu",
"address and pays the fees.": "dirección y paga las tarifas.",
"The certificate will be minted to": "El certificado se acuñará en",
"— your key, your name. You can set where it points immediately afterwards.": "— tu clave, tu nombre. Justo después puedes fijar adónde apunta.",
"Register — sign & broadcast": "Registrar — firmar y difundir",
"Could not prepare": "No se pudo preparar",
"Confirm": "Confirmar",
"Beacon dust + chain fee": "Polvo del faro + tarifa de cadena",
"(covered by wallet)": "(lo cubre la cartera)",
"Minted to": "Acuñado en",
"Service fee waived on chipnet": "Tarifa de servicio exenta en chipnet",
"Approve payment": "Aprobar pago",
"Approve →": "Aprobar →",
"Signing in your browser and broadcasting to the chain. Do not close this tab.": "Firmando en tu navegador y difundiendo a la cadena. No cierres esta pestaña.",
"Transaction": "Transacción",
"Certificate ID": "ID del certificado",
"Operator": "Operador",
"The certificate is on the chain, held by your key. Nobody can take it back.": "El certificado está en la cadena, en poder de tu clave. Nadie puede quitártelo.",
"Owner": "Propietario",
"Point it somewhere": "Apúntalo a algún sitio",
"Optional, and changeable any time — only your key can.": "Opcional y modificable en cualquier momento — solo con tu clave.",
"Record type": "Tipo de registro",
"A tiny site stored on the chain itself (h)": "Un sitio diminuto guardado en la propia cadena (h)",
"Redirect to a web address (u)": "Redirigir a una dirección web (u)",
"Your own server's IPv4 address (ip)": "La dirección IPv4 de tu propio servidor (ip)",
"TLS certificate fingerprint (tls)": "Huella del certificado TLS (tls)",
"Done for now": "Listo por ahora",
"Publish record": "Publicar registro",
"Publishing record": "Publicando registro",
"Update transaction": "Transacción de actualización",
"Finish": "Terminar",
"My names": "Mis nombres",
"records & holdings": "registros y propiedades",
"Admin panel": "Panel de administración",
"operator tools": "herramientas del operador",
"clear this browser": "limpiar este navegador",
"Unlock my wallet": "Desbloquear mi cartera",
"one you already created on this device": "una que ya creaste en este dispositivo",
"Locked wallet on this device": "Cartera bloqueada en este dispositivo",
"Unlock or pick another action": "Desbloquea o elige otra acción",
"No wallet yet": "Aún no hay cartera",
"Pick how to sign in": "Elige cómo iniciar sesión",
"Create a wallet": "Crear una cartera",
"generate a fresh 12-word phrase (sign up)": "generar una frase nueva de 12 palabras (registrarse)",
"Import a wallet": "Importar una cartera",
"seed phrase you already have (sign in)": "una frase semilla que ya tienes (iniciar sesión)",
"Cashonize / Paytaca via QR": "Cashonize / Paytaca por QR",
"The home for names on Bitcoin Cash. Register a TLD, register a name, verify anything against the chain.": "El hogar de los nombres en Bitcoin Cash. Registra un TLD, registra un nombre, verifica cualquier cosa contra la cadena.",
"Product": "Producto",
"✏️ Register a name": "✏️ Registrar un nombre",
"🌐 Register a TLD": "🌐 Registrar un TLD",
"🔑 My names portal": "🔑 Mi portal de nombres",
"🧭 Theseus browser": "🧭 Navegador Theseus",
"Learn": "Aprender",
"📚 Docs": "📚 Documentación",
"🗺 Roadmap": "🗺 Hoja de ruta",
"🏛 The Pantheon": "🏛 El Panteón",
"🎨 Brand kit": "🎨 Kit de marca",
"Alpha": "Alfa",
"Chipnet only. You hold your own keys; verify everything against the chain.": "Solo chipnet. Tú guardas tus claves; verifica todo contra la cadena.",
"brand assets": "recursos de marca",
"available": "disponible",
"taken": "ocupado",
"checking…": "comprobando…",
"Register →": "Registrar →",
"loading…": "cargando…",
"(no records set)": "(sin registros)",
"on chain": "en cadena",
"Edit": "Editar",
"tier pricing": "precio por tramos",
"(default policy — open, tier pricing)": "(política por defecto — abierta, precios por tramos)",
"Price & policy": "Precio y política",
"Register a name under": "Registrar un nombre bajo",
"Preparing your addresses…": "Preparando tus direcciones…",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.": "No se encontraron nombres BCNR para esta cartera. Si acabas de registrar, espera un minuto a la confirmación y recarga.",
"Off-chain DNS records — free per edit": "Registros DNS fuera de la cadena — gratis por edición",
"Signing…": "Firmando…",
"Saved ✓": "Guardado ✓",
"Registered ✓": "Registrado ✓",
"Switch on": "Encender",
"Switch off": "Apagar",
"Switch on: list the TLD and sell names again": "Encender: listar el TLD y volver a vender nombres",
"Switch off: hide the TLD, stop new registrations": "Apagar: ocultar el TLD, detener nuevos registros",
"no owner price set — buyers pay the length tier": "sin precio del dueño — los compradores pagan el tramo por longitud",
"hidden from the public registry; no new names until you switch it on": "oculto del registro público; sin nombres nuevos hasta que lo enciendas",
"listed in the public registry": "listado en el registro público",
"label": "etiqueta",
"🔓 Unlock": "🔓 Desbloquear",
"🆕 Create": "🆕 Crear",
"📥 Import": "📥 Importar",
"Dashboard — your names on Sirius.X": "Panel — tus nombres en Sirius.X",
"dashboard": "",
"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.": "Inicia sesión una vez con tu frase semilla de Bitcoin Cash o conecta una cartera externa. Este dispositivo sigue conectado hasta que cierres sesión: sin contraseñas en cada visita. Tus claves nunca salen de este navegador.",
"Manage": "Gestionar",
"Domain names": "Nombres de dominio",
"My TLD list": "Mis TLD",
"Get more": "Más",
"Docs": "Documentación",
"What this wallet holds on chain, and where to go next.": "Lo que esta cartera posee en la cadena y qué hacer a continuación.",
"↻ Refresh": "↻ Actualizar",
"Recent names": "Nombres recientes",
"The last few certificates that landed in this wallet.": "Los últimos certificados que llegaron a esta cartera.",
"Attention": "Atención",
"Names that point nowhere yet, or have no DNS.": "Nombres que aún no apuntan a nada o no tienen DNS.",
"Every BCNR name this wallet holds. Open one to manage DNS, content, redirects or transfer it.": "Todos los nombres BCNR de esta cartera. Abre uno para gestionar DNS, contenido, redirecciones o transferirlo.",
"Filter names…": "Filtrar nombres…",
"Sort: name": "Orden: nombre",
"Sort: TLD": "Orden: TLD",
"Sort: newest": "Orden: más recientes",
"All TLDs": "Todos los TLD",
"no DNS": "sin DNS",
"DNS …": "DNS …",
"DNS needs s3": "DNS necesita s3",
"Open site →": "Abrir sitio →",
"Summary": "Resumen",
"DNS records": "Registros DNS",
"Content & hosting": "Contenido y alojamiento",
"Redirect": "Redirección",
"Transfer": "Transferir",
"Export": "Exportar",
"Certificate": "Certificado",
"Where it points": "Adónde apunta",
"On-chain records decide what a resolver serves. Change them under Content & hosting.": "Los registros en cadena deciden qué sirve un resolvedor. Cámbialos en Contenido y alojamiento.",
"DNS at a glance": "DNS de un vistazo",
"Signed off-chain records for mail, verification and classic DNS interop.": "Registros firmados fuera de la cadena para correo, verificación y DNS clásico.",
"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.": "Registros estándar, firmados con tu clave y guardados en un manifiesto en Sia. Editar es gratis, sin transacción en cadena. Los resolvedores y la pasarela verifican la firma contra el titular actual del NFT.",
"Type": "Tipo",
"Value": "Valor",
"Priority / extra": "Prioridad / extra",
"No DNS records yet. Add the first one below.": "Aún no hay registros DNS. Añade el primero abajo.",
"Priority": "Prioridad",
"Weight": "Peso",
"Port": "Puerto",
"Tag": "Etiqueta",
"+ Add": "+ Añadir",
"Discard changes": "Descartar cambios",
"Nameservers": "Servidores de nombres",
"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.": "Los nombres BCNR no necesitan servidores de nombres: los resolvedores leen la cadena y este manifiesto directamente. Añade NS solo si también delegas el nombre en DNS clásico.",
"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.": "Registros en cadena, publicados en una transacción UPD firmada (unos céntimos de polvo). Un campo vacío elimina ese registro. Precedencia para resolvedores: h, luego s3, luego p, luego ip.",
"inline HTML — served as-is at the site root (~150 bytes)": "HTML en línea — se sirve tal cual en la raíz (~150 bytes)",
"Sia bucket key, trailing slash for directories — also where DNS manifests live": "clave del bucket de Sia, barra final para directorios — ahí viven también los manifiestos DNS",
"reverse proxy: full upstream URL the gateway mirrors": "proxy inverso: URL completa del origen que la pasarela replica",
"Reset": "Restablecer",
"Forward this name to any web address. Stored on chain as the": "Reenvía este nombre a cualquier dirección web. Se guarda en cadena como el registro",
"record; resolvers and the gateway issue the redirect. Clear it to stop forwarding.": "; los resolvedores y la pasarela emiten la redirección. Bórralo para dejar de reenviar.",
"Destination URL": "URL de destino",
"Remove redirect": "Quitar redirección",
"Save redirect →": "Guardar redirección →",
"Transfer ownership": "Transferir la propiedad",
"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.": "Mueve el certificado del nombre a otra dirección de Bitcoin Cash en una transacción. Los registros se mantienen. El nuevo titular controla el nombre desde ese momento: no se puede deshacer desde aquí.",
"Recipient address": "Dirección del destinatario",
"I understand this hands the name to that address permanently.": "Entiendo que esto entrega el nombre a esa dirección de forma permanente.",
"Transfer name →": "Transferir nombre →",
"Download this name's DNS as a BIND-style zone file, or its full record set as JSON, for backups or importing elsewhere.": "Descarga el DNS de este nombre como archivo de zona tipo BIND, o todos sus registros como JSON, para copias o importarlo en otro sitio.",
"⬇ Zone file (.txt)": "⬇ Archivo de zona (.txt)",
"⬇ Records (.json)": "⬇ Registros (.json)",
"Copy DNS manifest": "Copiar manifiesto DNS",
"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.": "Todos los NFT de registro de TLD de esta cartera. Fija el precio de cada nombre bajo un TLD, enciéndelo o apágalo (apagado = privado: solo tú puedes registrar) y ajusta la política. Cada cambio es un TUPD firmado en cadena; recibes el 90 % de cada venta.",
"Registry": "Registro",
"Register a name under this TLD": "Registrar un nombre bajo este TLD",
"Works whether the TLD is on or off. As the owner you pay only the platform's 10% share.": "Funciona con el TLD encendido o apagado. Como dueño solo pagas el 10 % de la plataforma.",
"Names registered under this TLD": "Nombres registrados bajo este TLD",
"Everyone's registrations, from the public registry.": "Los registros de todos, desde el registro público.",
"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.": "Los TLD son NFT de registro en el faro de TLD de chipnet. Las acuñaciones públicas pagan una tarifa que financia el registro. Chipnet usa una tasa provisional; en mainnet un oráculo real fija el precio por longitud.",
"Faucet 2 →": "Grifo 2 →",
"Balance": "Saldo",
"Spendable": "Disponible",
"UTXOs": "UTXOs",
"Watched addresses": "Direcciones observadas",
"Session and security choices for this browser. Nothing here changes what is on chain.": "Opciones de sesión y seguridad para este navegador. Nada de esto cambia lo que hay en la cadena.",
"Session": "Sesión",
"Stay signed in on this device": "Mantener la sesión en este dispositivo",
"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.": "Tu frase de recuperación se guarda cifrada con una clave que este navegador guarda y no puede exportar. Las próximas visitas abren el panel directamente. Desactívalo para que se pida contraseña o PIN cada vez.",
"Ask for PIN before payments": "Pedir PIN antes de los pagos",
"Adds a PIN prompt when registering a name or TLD. Off by default so signed-in sessions run uninterrupted.": "Añade una petición de PIN al registrar un nombre o TLD. Desactivado por defecto para que las sesiones no se interrumpan.",
"Set / change PIN": "Fijar / cambiar PIN",
"Remove PIN": "Quitar PIN",
"Reading & language": "Lectura e idioma",
"Font pill and language picker live in the top bar; both are remembered per browser.": "El selector de fuente y el de idioma están en la barra superior; ambos se recuerdan por navegador.",
"This device": "Este dispositivo",
"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.": "Cerrar sesión conserva la cartera cifrada en este dispositivo para desbloquearla después. Olvidar la elimina por completo: necesitarás tu frase de recuperación.",
"Forget wallet on this device": "Olvidar la cartera en este dispositivo",
"4–6 digits. Encrypts your recovery phrase under this PIN on this device. Three wrong PINs clear it and fall back to your password.": "4–6 dígitos. Cifra tu frase de recuperación con este PIN en este dispositivo. Tres PIN erróneos lo borran y vuelves a la contraseña.",
"No names yet.": "Aún no hay nombres.",
"Register your first one →": "Registra el primero →",
"Everything points somewhere and has DNS. Nice.": "Todo apunta a algún sitio y tiene DNS. Bien.",
"Nothing matches that filter.": "Nada coincide con ese filtro.",
"Status": "Estado",
"point it somewhere →": "apúntalo a algún sitio →",
"Add some →": "Añade algunos →",
"Register one →": "Registra uno →",
"yours": "tuyo",
"Copied": "Copiado",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and refresh.": "No se encontraron nombres BCNR para esta cartera. Si acabas de registrar, espera un minuto y actualiza.",
"Remove": "Quitar",
"Transferring…": "Transfiriendo…",
"Transferred ✓": "Transferido ✓",
"off · private": "apagado · privado",
"on · public": "encendido · público",
"Signing you in…": "Iniciando sesión…",
"Restoring your session on this device.": "Restaurando tu sesión en este dispositivo.",
"Dashboard": "Panel",
"names, TLDs, DNS, settings": "nombres, TLD, DNS, ajustes",
"site on chain": "sitio en cadena",
"site on Sia": "sitio en Sia",
"reverse proxy": "proxy inverso",
"own server": "servidor propio",
"redirect": "redirección",
"not pointed": "sin apuntar",
"points nowhere yet": "aún no apunta a nada",
"no DNS records": "sin registros DNS",
"DNS needs an s3 pointer": "DNS necesita un registro s3",
"block": "bloque",
"Web-Builder": "Web-Builder",
"My TLDs": "Mis TLD",
"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.": "Sirius Studio crea un sitio para cualquier nombre que tengas: arrastra bloques, edita texto, publica. Las páginas viven en la carpeta del nombre en Sia y el nombre apunta a ellas: sin alojamiento ni renovación.",
"Session, security and wallet details for this browser. Nothing here changes what is on chain.": "Sesión, seguridad y datos de la cartera para este navegador. Nada de esto cambia lo que hay en la cadena.",
"Reading, language & help": "Lectura, idioma y ayuda",
"Font pill and language picker live in the top bar; both are remembered per browser. The technical documentation is at": "El selector de fuente y el de idioma están en la barra superior; ambos se recuerdan por navegador. La documentación técnica está en",
"Start from a template": "Empezar desde una plantilla",
"Preview the exported page in a new tab": "Previsualizar la página exportada en una pestaña nueva",
"Sirius Studio — build the site for your name": "Sirius Studio — crea el sitio de tu nombre",
"Templates…": "Plantillas…",
"Landing page": "Página de aterrizaje",
"Profile / link hub": "Perfil / enlaces",
"Business one-pager": "Negocio en una página",
"Blank page": "Página en blanco",
"Preview": "Vista previa",
"Save draft": "Guardar borrador",
"Publish to Sia →": "Publicar en Sia →",
"View site →": "Ver sitio →",
"Sign in first": "Inicia sesión primero",
"Sirius Studio publishes with your wallet's key. Sign in on the dashboard, then come back to this name.": "Sirius Studio publica con la clave de tu cartera. Inicia sesión en el panel y vuelve a este nombre.",
"Open the dashboard →": "Abrir el panel →",
"Build the site for": "Crea el sitio de",
"Pick a starting point. Everything is editable — drag blocks in from the right, click any text to change it. Nothing leaves your browser until you press Publish; then the page is stored on Sia and the name points at it.": "Elige un punto de partida. Todo es editable: arrastra bloques desde la derecha, haz clic en cualquier texto para cambiarlo. Nada sale de tu navegador hasta que pulses Publicar; entonces la página se guarda en Sia y el nombre apunta a ella.",
"Hero, three features, call to action.": "Cabecera, tres ventajas, llamada a la acción.",
"Avatar, bio and a stack of links.": "Avatar, biografía y una lista de enlaces.",
"About, services, hours, contact.": "Sobre nosotros, servicios, horario, contacto.",
"Start from nothing.": "Empezar desde cero.",
"Back to dashboard": "Volver al panel",
"Publish": "Publicar",
"The page and its assets are uploaded to the name's folder on Sia, signed with your key. If the name does not point at that folder yet, one on-chain update sets it (a few cents of chain dust).": "La página y sus archivos se suben a la carpeta del nombre en Sia, firmados con tu clave. Si el nombre aún no apunta a esa carpeta, una actualización en cadena lo hace (unos céntimos de polvo).",
"Needs attention": "Necesita atención",
"View →": "Ver →",
"Edit in Studio": "Editar en Studio",
"Open in Studio": "Abrir en Studio",
"built with Studio": "hecho con Studio",
"site on Sia (external)": "sitio en Sia (externo)",
"inline HTML": "HTML en línea",
"no site yet": "aún sin sitio",
"Pick a name to build or edit its site.": "Elige un nombre para crear o editar su sitio.",
"You need a name first.": "Primero necesitas un nombre.",
"— then come back here to build its site.": "— luego vuelve aquí para crear su sitio.",
"New site": "Sitio nuevo",
"Not signed in": "Sin sesión",
"Loading name…": "Cargando nombre…",
"Published": "Publicado",
"Publish failed": "Error al publicar",
"Template loaded — edit, then Publish": "Plantilla cargada: edita y luego publica",
"Draft saved on Sia": "Borrador guardado en Sia",
"Saving draft…": "Guardando borrador…",
"Copy address": "Copiar dirección",
"receive coins or names here": "recibe monedas o nombres aquí",
"Copy token address": "Copiar dirección de tokens",
"where name certificates are minted": "donde se acuñan los certificados de nombres",
"Get test coins": "Conseguir monedas de prueba",
"chipnet faucet": "grifo de chipnet",
"Wallet settings": "Ajustes de la cartera",
"session, PIN, forget device": "sesión, PIN, olvidar dispositivo",
"Holdings": "Propiedades",
"open the dashboard to load": "abre el panel para cargar",
"🛒 Market": "🛒 Mercado",
"🛒 Names for sale": "🛒 Nombres en venta",
"Market — names for sale on Sirius.X": "Mercado — nombres en venta en Sirius.X",
"for sale": "en venta",
"Every sale is a single Bitcoin Cash transaction. The seller signed an offer that pays them only when the certificate moves to you — you add your coins, sign, broadcast. No escrow, no middleman, no way for either side to cheat.": "Cada venta es una única transacción de Bitcoin Cash. El vendedor firmó una oferta que solo le paga cuando el certificado pasa a ti — añades tus monedas, firmas, transmites. Sin custodia, sin intermediarios, sin forma de que nadie haga trampa.",
"Sort: price": "Ordenar: precio",
"Loading listings…": "Cargando anuncios…",
"Selling a name?": "¿Vendes un nombre?",
"Open it in your": "Ábrelo en tu",
", choose": ", elige",
"Sell": "Vender",
", set a price. The listing is a signed offer stored by the gateway; cancelling it moves your certificate once so the old offer can never be used.": ", fija un precio. El anuncio es una oferta firmada que guarda la pasarela; cancelarlo mueve tu certificado una vez para que la oferta antigua nunca pueda usarse.",
"One transaction: your coins pay the seller, the certificate lands in your wallet, and the registry is told about the new owner. Records stay as they are — you can change them in the dashboard right after.": "Una transacción: tus monedas pagan al vendedor, el certificado llega a tu billetera y el registro conoce al nuevo dueño. Los registros quedan como están — puedes cambiarlos en el panel justo después.",
"Sign in to buy →": "Inicia sesión para comprar →",
"Buy — sign & broadcast": "Comprar — firmar y transmitir",
"Buy →": "Comprar →",
"Nothing is for sale right now. Owners list names from their dashboard.": "Ahora mismo no hay nada en venta. Los dueños publican nombres desde su panel.",
"Sell this name": "Vender este nombre",
"You sign an offer once: \"whoever pays me this price gets the certificate\". The offer is stored by the gateway and shown on the": "Firmas una oferta una vez: «quien me pague este precio se queda con el certificado». La pasarela guarda la oferta y la muestra en el",
"market": "mercado",
". 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.": ". Un comprador la completa en una transacción — cobras en la misma transacción que mueve el nombre, o no cobras. Sin custodia, nada en lo que confiar.",
"Checking the market…": "Consultando el mercado…",
"Price (USD)": "Precio (USD)",
"Price (sat)": "Precio (sat)",
"List for sale →": "Poner en venta →",
"Cancel listing →": "Cancelar anuncio →",
"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.": "Cancelar retira la oferta del mercado y mueve tu certificado una vez (una actualización vacía, unos céntimos), para que la oferta firmada nunca pueda completarse después.",
"Not for sale. Set a price to list it.": "No está en venta. Fija un precio para publicarlo.",
"This name is listed on the market.": "Este nombre está publicado en el mercado.",
"Pending approvals": "Aprobaciones pendientes",
"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.": "Registros bajo este TLD que esperan tu cofirma. Aprobar firma tu certificado de TLD dentro de la transacción del comprador y la transmite; el certificado vuelve a ti en la misma transacción. Nada puede registrarse bajo un TLD de cofirma o privado sin este paso.",
"No requests waiting.": "No hay solicitudes en espera.",
"awaiting you": "te espera",
"Approve & broadcast": "Aprobar y transmitir",
"Decline": "Rechazar",
"Request approval — sign": "Solicitar aprobación — firmar",
"Withdraw request": "Retirar solicitud",
"Request declined": "Solicitud rechazada",
"Open dashboard →": "Abrir panel →",
"incl.": "incl.",
"sat unconfirmed · spendable now": "sat sin confirmar · disponibles ya",
"Nothing is for sale right now": "Ahora mismo no hay nada en venta",
"Names go on sale when their owners list them from the dashboard. Have one to sell, or want a fresh one instead?": "Los nombres salen a la venta cuando sus dueños los publican desde el panel. ¿Tienes uno para vender, o prefieres uno nuevo?",
"Sell a name from your dashboard →": "Vender un nombre desde tu panel →",
"Register a new name": "Registrar un nombre nuevo",
"↓ Import live site": "↓ Importar el sitio en vivo",
"Import the live site": "Importar el sitio en vivo",
"✨ Assistant": "✨ Asistente",
"Runs on your own device. Nothing you write or build is sent to Sirius.X or to any AI vendor.": "Funciona en tu propio dispositivo. Nada de lo que escribes o construyes se envía a Sirius.X ni a ningún proveedor de IA.",
"Runs on": "Se ejecuta en",
"This browser — your GPU, private": "Este navegador — tu GPU, privado",
"Local endpoint — Ollama, LM Studio": "Servidor local — Ollama, LM Studio",
"Model": "Modelo",
"Downloads once, then stays in the browser cache. Needs WebGPU (current Chrome, Edge, Firefox, Safari).": "Se descarga una vez y queda en la caché del navegador. Requiere WebGPU (Chrome, Edge, Firefox, Safari actuales).",
"Load model": "Cargar modelo",
"Endpoint": "Endpoint",
"Connect": "Conectar",
"What do you want?": "¿Qué quieres?",
"Make a section": "Crear una sección",
"Rewrite selected text": "Reescribir el texto seleccionado",
"Restyle selection": "Cambiar estilo de la selección",
"Nothing selected": "Nada seleccionado",
"Undo last change": "Deshacer el último cambio",
"Stop": "Detener"
}

612
i18n/fr.json Normal file
View file

@ -0,0 +1,612 @@
{
"Sirius.X — the home for names on Bitcoin Cash": "Sirius.X — la maison des noms sur Bitcoin Cash",
"Portal — your names on Sirius.X": "Portail — vos noms sur Sirius.X",
"Register a TLD — Sirius.X": "Enregistrer un TLD — Sirius.X",
"Try it": "Essayer",
"✏️ Register": "✏️ Enregistrer",
"🌐 TLD": "🌐 TLD",
"🔑 Sign in": "🔑 Connexion",
"type a name — e.g. hello": "tapez un nom — p. ex. bonjour",
"Search a name across every BCNR TLD": "Chercher un nom dans tous les TLD BCNR",
"Names on the": "Des noms sur la",
"chain": "chaîne",
"Sirius.X is the entry point for BCNR — Bitcoin Cash Name Registry. Register a top-level domain, register a name under one, look up records, verify anything against the chain.": "Sirius.X est la porte d'entrée de BCNR — le registre de noms de Bitcoin Cash. Enregistrez un domaine de premier niveau, enregistrez un nom sous l'un d'eux, consultez les enregistrements, vérifiez tout sur la chaîne.",
"One search checks the label across every TLD in the registry. Available names appear first.": "Une seule recherche vérifie le libellé dans tous les TLD du registre. Les noms disponibles apparaissent en premier.",
"Or browse what you can do →": "Ou découvrez ce que vous pouvez faire →",
"Read the docs": "Lire la documentation",
"Three things you can do right now. The registrar and TLD-registry UIs live at silentmode.st today; Sirius.X is the canonical home and will consolidate them here.": "Trois choses à faire dès maintenant. Le registrar et le registre des TLD vivent aujourd'hui sur silentmode.st ; Sirius.X est leur maison canonique et les regroupera ici.",
"Register a name": "Enregistrer un nom",
"Pick a label, search across every TLD in the registry at once, mint the name certificate straight into your own wallet. No yearly renewal.": "Choisissez un libellé, cherchez-le dans tous les TLD du registre d'un coup, frappez le certificat du nom directement dans votre propre portefeuille. Sans renouvellement annuel.",
"≈ 10,000 sat service fee · 1,300 sat chain dust · < 1 ¢": "≈ 10 000 sat de frais de service · 1 300 sat de poussière de chaîne · < 1 ¢",
"Chipnet placeholder. 90 % of the service fee flows to the TLD owner, 10 % to the platform.": "Valeur provisoire chipnet. 90 % des frais vont au propriétaire du TLD, 10 % à la plateforme.",
"Search a name →": "Chercher un nom →",
"Register a TLD": "Enregistrer un TLD",
"A TLD is itself a certificate on the chain. Anyone can mint one — you become the registry operator for every second-level name under it, and earn 90 % of the fee on every name registered under it. Renewals are per-TLD policy set by the owner.": "Un TLD est lui-même un certificat sur la chaîne. N'importe qui peut en frapper un : vous devenez l'opérateur du registre pour chaque nom de second niveau en dessous, et gagnez 90 % des frais de chaque nom enregistré. Les renouvellements sont une politique par TLD fixée par le propriétaire.",
"≈ 1,250,000 sat service fee (≈ $5) · 1,300 sat chain dust": "≈ 1 250 000 sat de frais de service (≈ 5 $) · 1 300 sat de poussière de chaîne",
"Chipnet placeholder rate — mainnet will price by label length via an on-chain oracle.": "Taux provisoire chipnet — sur mainnet, le prix dépendra de la longueur du libellé via un oracle on-chain.",
"Search a TLD →": "Chercher un TLD →",
"Operator admin →": "Administration opérateur →",
"Look up & verify": "Consulter et vérifier",
"Resolve any BCNR name, compare records across mirrors, and check the TLD registry snapshot against the chain. Everything is publicly verifiable.": "Résolvez n'importe quel nom BCNR, comparez les enregistrements entre miroirs et vérifiez l'instantané du registre des TLD sur la chaîne. Tout est vérifiable publiquement.",
"How to verify →": "Comment vérifier →",
"🔑 Sign in — your names portal": "🔑 Connexion — votre portail de noms",
"Import your seed phrase or connect a wallet (Cashonize / Paytaca via WizardConnect) to see every name you own, review records, and update them. Your keys never leave your browser.": "Importez votre phrase de récupération ou connectez un portefeuille (Cashonize / Paytaca via WizardConnect) pour voir tous les noms que vous possédez, relire les enregistrements et les mettre à jour. Vos clés ne quittent jamais votre navigateur.",
"Open the portal →": "Ouvrir le portail →",
"🧭 Theseus Navigator": "🧭 Theseus Navigator",
"The browser that speaks BCNR natively. Open": "Le navigateur qui parle BCNR nativement. Ouvrez",
"in the address bar — it just resolves. TLS verified against on-chain fingerprints, no OS trust-store install.": "dans la barre d'adresse : ça se résout, tout simplement. TLS vérifié contre les empreintes on-chain, rien à installer dans le magasin de confiance du système.",
"Download →": "Télécharger →",
"Documentation": "Documentation",
"The full docs — TLD registry model, record types, resolver & gateway paths, mainnet pricing, verification, and the operator runbook pointer — live on their own page so they can grow without cluttering the landing.": "La documentation complète — modèle du registre des TLD, types d'enregistrements, chemins résolveur et passerelle, tarifs mainnet, vérification et le lien vers le runbook opérateur — a sa propre page pour grandir sans encombrer l'accueil.",
"📚 Open the docs →": "📚 Ouvrir la documentation →",
"Current TLD list": "Liste actuelle des TLD",
"Propose a new TLD": "Proposer un nouveau TLD",
"The per-TLD registry means minting a TLD is a real, paid action — not a namespace land-grab. During the alpha, all TLD mints are operator-signed. To propose a TLD, get in touch via the channels below. The design (mainnet) adds an on-chain covenant with countersignature + tiered USD price floors: 1-char $100k, 2-char $50k, 3-char $15k, 4-char $5k, 5–8-char $1k, 9+-char $250; one-time payment (not annual). See the design doc for the full model.": "Le registre par TLD signifie que frapper un TLD est un acte réel et payant, pas une razzia sur l'espace de noms. Pendant l'alpha, toutes les frappes de TLD sont signées par l'opérateur. Pour proposer un TLD, contactez-nous via les canaux ci-dessous. Le design (mainnet) ajoute un covenant on-chain avec contre-signature et des prix planchers échelonnés en USD : 1 caractère 100 k$, 2 caractères 50 k$, 3 caractères 15 k$, 4 caractères 5 k$, 5–8 caractères 1 k$, 9+ caractères 250 $ ; paiement unique (non annuel). Voir le document de design pour le modèle complet.",
"ICANN-adjacent TLDs are not open for public mint.": "Les TLD proches de l'ICANN ne sont pas ouverts à la frappe publique.",
"A TLD registry is only useful if it does not immediately collapse into an ICANN-shadow — the mainnet covenant enforces this; on chipnet the operator's countersignature is the gate.": "Un registre de TLD n'est utile que s'il ne s'effondre pas aussitôt en ombre de l'ICANN — sur mainnet le covenant l'impose ; sur chipnet la contre-signature de l'opérateur fait barrière.",
"The pantheon": "Le panthéon",
"Sirius.x is one of seven sibling": "Sirius.x est l'un des sept noms frères",
"names — the Silent Mode pantheon. Each project is its own on-chain certificate; each site is reachable through any BCNR resolver, plus the silentmode.st gateway for browsers without one.": "— le panthéon Silent Mode. Chaque projet est son propre certificat on-chain ; chaque site est accessible via n'importe quel résolveur BCNR, plus la passerelle silentmode.st pour les navigateurs qui n'en ont pas.",
"⛓️ Silentmode.X": "⛓️ Silentmode.X",
"The project umbrella. Redirects to": "Le parapluie du projet. Redirige vers",
"where every pillar has its own landing page + download hub.": "où chaque pilier a sa propre page et ses téléchargements.",
"Open →": "Ouvrir →",
"⭐ Sirius.X": "⭐ Sirius.X",
"you're here": "vous êtes ici",
"Names on Bitcoin Cash — register, resolve, verify, manage. This site.": "Des noms sur Bitcoin Cash — enregistrer, résoudre, vérifier, gérer. Ce site.",
"Home →": "Accueil →",
"🧭 Theseus.X": "🧭 Theseus.X",
"The browser that speaks BCNR natively — Chromium build with the resolver baked in, no OS-level daemon or root-store install.": "Le navigateur qui parle BCNR nativement — une build Chromium avec le résolveur intégré, sans démon système ni certificat racine.",
"Learn more →": "En savoir plus →",
"🔥 Hephaestus.X": "🔥 Hephaestus.X",
"The forge. Forgejo instance for the ecosystem's git repos, backed by BCH wallet auth. Sirius's own source lives here.": "La forge. Instance Forgejo pour les dépôts git de l'écosystème, avec connexion par portefeuille BCH. Le code source de Sirius vit ici.",
"🔮 Prometheus.X": "🔮 Prometheus.X",
"Fire from the chain. The project's foresight / experimentation layer. Redirects to": "Le feu de la chaîne. La couche de prospective et d'expérimentation du projet. Redirige vers",
"today.": "(aujourd'hui).",
"☀️ Helios.X": "☀️ Helios.X",
"The public gaze. Analytics, dashboards, transparency reports. Redirects to": "Le regard public. Analyses, tableaux de bord, rapports de transparence. Redirige vers",
"✉️ Hermes.X": "✉️ Hermes.X",
"Messenger. Nostr-based messaging bound to a BCNR name via the": "Messagerie. Messages sur Nostr liés à un nom BCNR via les enregistrements",
"records. Redirects to": ". Redirige vers",
"What's coming": "Ce qui arrive",
"Sirius.X consolidates docs and registration today; three larger pieces are on the roadmap.": "Sirius.X regroupe aujourd'hui documentation et enregistrement ; trois pièces plus grandes sont sur la feuille de route.",
"Wallet & name portal": "Portail portefeuille et noms",
"next": "prochain",
"Sign in with your Bitcoin Cash wallet, see every name you own, edit records inline, mint or renew from one place. Same self-custody as today — the portal never handles your keys.": "Connectez-vous avec votre portefeuille Bitcoin Cash, voyez tous les noms que vous possédez, modifiez les enregistrements sur place, frappez ou renouvelez depuis un seul endroit. La même auto-garde qu'aujourd'hui : le portail ne touche jamais vos clés.",
"Sirius Studio": "Sirius Studio",
"planned": "prévu",
"An in-browser site editor for names you already own — the WordPress / Tilda / Wix pattern, but the whole site persists to Sia and the name's": "Un éditeur de site dans le navigateur pour les noms que vous possédez déjà — le schéma WordPress / Tilda / Wix, mais tout le site est conservé sur Sia et l'enregistrement",
"record updates on save. Sites live where the name says they live.": "du nom se met à jour à l'enregistrement. Les sites vivent là où le nom le dit.",
"Decentralized git remote": "Remote git décentralisé",
"MVP live": "MVP en ligne",
"The Silent Mode repo is served as a bare git tree over dumb-HTTP from the VPS. Clone it with any git client, no login. Forgejo + Sia sync for a proper decentralized backend is the next track.": "Le dépôt Silent Mode est servi comme arbre git bare en dumb-HTTP depuis le VPS. Clonez-le avec n'importe quel client git, sans compte. Forgejo + synchronisation Sia pour un vrai backend décentralisé est la prochaine étape.",
"One-shot snapshot as a downloadable git bundle (works when dumb-HTTP is blocked):": "Instantané unique sous forme de git bundle téléchargeable (fonctionne quand dumb-HTTP est bloqué) :",
"Verify this page against the chain": "Vérifiez cette page sur la chaîne",
"You do not have to trust that": "Vous n'avez pas à croire que",
"is served by anyone specific. The name's certificate is on the Bitcoin Cash chain; the records point to Sia; every path is independently checkable.": "est servi par quelqu'un en particulier. Le certificat du nom est sur la chaîne Bitcoin Cash ; les enregistrements pointent vers Sia ; chaque chemin est vérifiable indépendamment.",
"1. Confirm the certificate exists on chain": "1. Confirmez que le certificat existe sur la chaîne",
"2. Fetch the TLD-registry snapshot from Nostr": "2. Récupérez l'instantané du registre des TLD depuis Nostr",
"The operator-signed snapshot of the TLD list is published as a Nostr replaceable event. Any relay carries it; the event's content field carries the current snapshot root.": "L'instantané de la liste des TLD, signé par l'opérateur, est publié comme événement remplaçable Nostr. N'importe quel relais le porte ; le champ content de l'événement contient la racine de l'instantané courant.",
"Kind / d-tag": "Kind / d-tag",
"Pubkey (x-only, hex)": "Clé publique (x-only, hex)",
"Relays": "Relais",
"3. Reach this site via more than one route": "3. Atteignez ce site par plus d'un chemin",
"The same content should be served from at least two independent paths. If one mirror is unavailable, the others still work. If two mirrors disagree, the on-chain record is the tiebreaker.": "Le même contenu doit être servi par au moins deux chemins indépendants. Si un miroir est indisponible, les autres fonctionnent. Si deux miroirs divergent, l'enregistrement on-chain tranche.",
"Via any BCNR resolver:": "Via n'importe quel résolveur BCNR :",
"(requires the local root CA)": "(nécessite l'AC racine locale)",
"Via the public gateway:": "Via la passerelle publique :",
"Via silentmode.st mirror:": "Via le miroir silentmode.st :",
"Direct from Sia (content-addressed): the": "Directement depuis Sia (adressé par contenu) : l'enregistrement",
"record on": "sur",
"names the exact bucket key": "donne la clé exacte du bucket",
"Register a": "Enregistrez un",
"A TLD is a certificate on the Bitcoin Cash chain. You mint it, you own it — any second-level name registered under it lives in your TLD's registry. One BCH transaction, no ICANN. Renewals? Your TLD, your policy.": "Un TLD est un certificat sur la chaîne Bitcoin Cash. Vous le frappez, il est à vous : tout nom de second niveau enregistré en dessous vit dans le registre de votre TLD. Une transaction BCH, pas d'ICANN. Renouvellements ? Votre TLD, votre politique.",
"Search a TLD": "Chercher un TLD",
"Type a label (a–z, 0–9, hyphen; up to 16 chars). Available TLDs get a Register button that opens the shared wallet-choice modal — the same flow name registration uses. As TLD owner you earn": "Tapez un libellé (a–z, 0–9, tiret ; jusqu'à 16 caractères). Les TLD disponibles affichent un bouton Enregistrer qui ouvre la fenêtre commune de choix du portefeuille — le même parcours que l'enregistrement d'un nom. En tant que propriétaire du TLD, vous gagnez",
"of every name registered under your TLD. Renewals are your call — set them per TLD, or don't.": "de chaque nom enregistré sous votre TLD. Les renouvellements, c'est vous qui décidez : fixez-les par TLD, ou pas.",
"Register minting to your token address; you become the registry operator.": "L'enregistrement frappe vers votre adresse de jetons ; vous devenez l'opérateur du registre.",
"Registered TLDs": "TLD enregistrés",
"Fetched from the on-chain TLD registry via the public gateway. Refresh the page for the latest.": "Lu depuis le registre des TLD on-chain via la passerelle publique. Rechargez la page pour les dernières données.",
"Loading…": "Chargement…",
"Mint price": "Prix de frappe",
"Category": "Catégorie",
"Portal sections": "Sections du portail",
"Your": "Votre portail de",
"names": "noms",
"portal": "",
"Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see every BCNR name your wallet holds. Your keys never leave this browser tab.": "Connectez-vous avec votre phrase de récupération Bitcoin Cash ou connectez un portefeuille externe pour voir tous les noms BCNR qu'il détient. Vos clés ne quittent jamais cet onglet.",
"Sign in or create a wallet": "Connectez-vous ou créez un portefeuille",
"The same wallet that will hold your names does the signing. Pick a tab — everything happens on this page; keys never leave your browser.": "C'est le portefeuille qui détiendra vos noms qui signe. Choisissez un onglet : tout se passe sur cette page ; les clés ne quittent jamais votre navigateur.",
"Overview": "Aperçu",
"Names": "Noms",
"TLDs": "TLD",
"Wallet": "Portefeuille",
"Settings": "Réglages",
"A snapshot of what this wallet holds on chain.": "Un aperçu de ce que ce portefeuille détient sur la chaîne.",
"Names held": "Noms détenus",
"CashTokens NFT certificates": "Certificats NFT CashTokens",
"TLDs owned": "TLD possédés",
"Per-TLD registry NFTs": "NFT de registre par TLD",
"Wallet balance": "Solde du portefeuille",
"chipnet sats": "sats chipnet",
"Chain height": "Hauteur de chaîne",
"Last seen block": "Dernier bloc vu",
"+ Register a name": "+ Enregistrer un nom",
"+ Register a TLD": "+ Enregistrer un TLD",
"Names you hold": "Vos noms",
"Every BCNR name your wallet's addresses currently hold a CashTokens NFT for. Edit records inline to publish an on-chain UPD.": "Tous les noms BCNR pour lesquels les adresses de votre portefeuille détiennent actuellement un NFT CashTokens. Modifiez les enregistrements sur place pour publier un UPD on-chain.",
"Loading names from the chain…": "Chargement des noms depuis la chaîne…",
"TLDs you own": "Vos TLD",
"Every per-TLD registry NFT held by this wallet. Set the": "Tous les NFT de registre de TLD détenus par ce portefeuille. Fixez le",
"price": "prix",
"every name under your TLD sells for, switch the TLD": "de vente de chaque nom sous votre TLD, allumez ou éteignez le TLD",
"on or off": "dans le registre public",
"in the public registry (off = a": "(éteint = un",
"private TLD": "TLD privé",
": nobody else can buy names under it, you still can from here), and tune policy —": " : personne d'autre ne peut y acheter de noms, vous le pouvez toujours depuis ici) et réglez la politique —",
"fee": "frais",
"min length": "longueur minimale",
"reserved labels": "libellés réservés",
"renewal period": "période de renouvellement",
". Every change is one signed TUPD on chain; you receive 90% of each sale.": ". Chaque changement est un TUPD signé sur la chaîne ; vous recevez 90 % de chaque vente.",
"Loading TLDs from the chain…": "Chargement des TLD depuis la chaîne…",
"Register a new TLD": "Enregistrer un nouveau TLD",
"TLDs are per-registry NFTs on the chipnet TLD beacon. Public mints go through a service-fee output to fund the registry. Chipnet uses a placeholder rate; mainnet will price by label length via a real oracle.": "Les TLD sont des NFT de registre sur le beacon TLD de chipnet. Les frappes publiques passent par des frais de service qui financent le registre. Chipnet utilise un taux provisoire ; sur mainnet un vrai oracle fixera le prix selon la longueur du libellé.",
"Label": "Libellé",
"1–16 chars, [a-z0-9-]": "1–16 caractères, [a-z0-9-]",
"Service fee (USD)": "Frais de service (USD)",
"chipnet test rate": "taux de test chipnet",
"sats · rate": "sats · taux",
"sats/USD": "sats/USD",
"Check availability": "Vérifier la disponibilité",
"Register (~0 sats)": "Enregistrer (~0 sats)",
"Your addresses and current balance. Keys stay in this browser.": "Vos adresses et votre solde actuel. Les clés restent dans ce navigateur.",
"Receive address": "Adresse de réception",
"Token address": "Adresse de jetons",
"holds your name certificates": "détient vos certificats de noms",
"Faucet →": "Robinet →",
"Reader preferences live per-browser; wallet changes require a signature.": "Les préférences de lecture sont propres au navigateur ; les changements de portefeuille exigent une signature.",
"Reading font": "Police de lecture",
"Fraunces (Silent Mode family) or Ubuntu (Bitcoin Cash brand font). The pill lives in the top nav.": "Fraunces (famille Silent Mode) ou Ubuntu (police de marque Bitcoin Cash). Le sélecteur est dans la barre du haut.",
"Session PIN": "PIN de session",
"PIN unlocks the wallet without re-typing your password. Wipes after 3 wrong attempts.": "Le PIN déverrouille le portefeuille sans retaper votre mot de passe. Effacé après 3 tentatives erronées.",
"Sign out": "Déconnexion",
"Clears the signed-in state in this browser. Your on-chain names are unaffected.": "Efface l'état de connexion dans ce navigateur. Vos noms on-chain ne sont pas touchés.",
"Edit records. Only your key can sign this UPD; the transaction fee is a few cents in chain fees plus the beacon dust. Leave a field blank to omit that record.": "Modifiez les enregistrements. Seule votre clé peut signer cet UPD ; la transaction coûte quelques centimes de frais de chaîne plus la poussière du beacon. Laissez un champ vide pour omettre cet enregistrement.",
"inline HTML — served as-is at the site root": "HTML inline — servi tel quel à la racine du site",
"Sia bucket key, trailing slash for directories": "clé du bucket Sia, barre oblique finale pour les répertoires",
"IPv4 that serves this name over Host header": "IPv4 qui sert ce nom via l'en-tête Host",
"SHA-256 of your leaf cert — chain-pinned TLS trust": "SHA-256 de votre certificat feuille — confiance TLS épinglée sur la chaîne",
"redirect target": "cible de redirection",
"payload:": "charge utile :",
"bytes": "octets",
"Cancel": "Annuler",
"Save records →": "Enregistrer les enregistrements →",
"DNS records for": "Enregistrements DNS de",
"DNS-style records live in a signed manifest on Sia — not on chain.": "Les enregistrements de type DNS vivent dans un manifeste signé sur Sia, pas sur la chaîne.",
"Free per edit": "Gratuit à chaque modification",
", no size cap. The signature proves you own the name; the gateway rejects anything not signed by the current NFT holder. See": ", sans limite de taille. La signature prouve que le nom est à vous ; la passerelle rejette tout ce qui n'est pas signé par le détenteur actuel du NFT. Voir",
"docs": "la documentation",
"IPv4 addresses, one per line": "adresses IPv4, une par ligne",
"IPv6 addresses, one per line": "adresses IPv6, une par ligne",
"one string per line (SPF, DKIM, verification tokens…)": "une chaîne par ligne (SPF, DKIM, jetons de vérification…)",
"one target host, or blank": "un hôte cible, ou vide",
"nameservers, one per line": "serveurs de noms, un par ligne",
"Sign & publish →": "Signer et publier →",
"Policy for": "Politique de",
"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).": "Fixez la politique des noms enregistrés sous ce TLD. Seule votre clé peut signer ce TUPD ; la transaction coûte quelques centimes de poussière de chaîne. Laissez un champ vide pour omettre cette règle (par défaut : politique ouverte, tarifs par paliers).",
"USD per name — flat, shown to every buyer; blank = length tiers. You receive 90% of each sale.": "USD par nom — forfaitaire, affiché à chaque acheteur ; vide = paliers par longueur. Vous recevez 90 % de chaque vente.",
"listing": "affichage",
"off hides the TLD from search and blocks new registrations until you switch it back on": "éteint masque le TLD de la recherche et bloque les nouveaux enregistrements jusqu'à ce que vous le rallumiez",
"On — listed, names for sale": "Allumé — listé, noms en vente",
"Off — hidden, not for sale": "Éteint — masqué, pas en vente",
"reject names shorter than N chars": "refuser les noms de moins de N caractères",
"service fee owner takes, in basis points (500 = 5%)": "part des frais revenant au propriétaire, en points de base (500 = 5 %)",
"open · frozen · reserved-only": "open · frozen · reserved-only",
"space-separated labels only owner can mint": "libellés séparés par des espaces que seul le propriétaire peut frapper",
"days between renewals, 0 = never expire": "jours entre renouvellements, 0 = n'expire jamais",
"renewal price in sats, 0 = free": "prix de renouvellement en sats, 0 = gratuit",
"where the TLD's own landing lives": "où vit la page propre du TLD",
"Save policy →": "Enregistrer la politique →",
"Signed in": "Connecté",
"You are signed in as": "Vous êtes connecté en tant que",
"Done": "Terminé",
"Close": "Fermer",
"Unlock my browser wallet": "Déverrouiller le portefeuille de mon navigateur",
"You already created one on this device.": "Vous en avez déjà créé un sur cet appareil.",
"Create a new wallet": "Créer un nouveau portefeuille",
"easiest": "le plus simple",
"Made here in your browser. You get a recovery phrase to write down — it is the only key.": "Créé ici, dans votre navigateur. Vous recevez une phrase de récupération à noter : c'est la seule clé.",
"Import a recovery phrase": "Importer une phrase de récupération",
"Restore a wallet you already have, from its 12-word phrase.": "Restaurez un portefeuille que vous avez déjà, à partir de sa phrase de 12 mots.",
"Connect a wallet — WizardConnect": "Connecter un portefeuille — WizardConnect",
"most private": "le plus privé",
"Cashonize 0.9+ or Paytaca. Encrypted end-to-end over Nostr; the relay sees only ciphertext. Your keys never leave your wallet.": "Cashonize 0.9+ ou Paytaca. Chiffré de bout en bout via Nostr ; le relais ne voit que du texte chiffré. Vos clés ne quittent jamais votre portefeuille.",
"Everything below runs on": "Tout ce qui suit tourne sur",
", Bitcoin Cash's test network. The coins are free and worth nothing — this is an alpha, and it is the honest place to try it before real money is involved.": ", le réseau de test de Bitcoin Cash. Les pièces sont gratuites et ne valent rien : c'est une alpha, et c'est l'endroit honnête pour essayer avant de mettre du vrai argent.",
"Starting the connection…": "Démarrage de la connexion…",
"Back": "Retour",
"Open your wallet": "Ouvrez votre portefeuille",
"Copy": "Copier",
"Waiting for your wallet… The link stays valid until you close this page.": "En attente de votre portefeuille… Le lien reste valide jusqu'à la fermeture de cette page.",
"Connected": "Connecté",
"Reading your wallet and building the registration…": "Lecture de votre portefeuille et préparation de l'enregistrement…",
"That wallet is empty": "Ce portefeuille est vide",
"Two approvals needed.": "Deux approbations nécessaires.",
"Register — approve in your wallet": "Enregistrer — approuvez dans votre portefeuille",
"Approve in your wallet": "Approuvez dans votre portefeuille",
"Create your wallet": "Créez votre portefeuille",
"Generated in this browser. The phrase is never sent anywhere — not to us, not to anyone.": "Généré dans ce navigateur. La phrase n'est jamais envoyée nulle part : ni à nous, ni à personne.",
"Password (encrypts the wallet on this device)": "Mot de passe (chiffre le portefeuille sur cet appareil)",
"Repeat password": "Répétez le mot de passe",
"There is no reset.": "Il n'y a pas de réinitialisation.",
"Generate phrase →": "Générer la phrase →",
"Write this down. Now.": "Notez ceci. Maintenant.",
"These 12 words are your wallet. Anyone who has them owns your names; if you lose them, nobody — including us — can recover anything.": "Ces 12 mots sont votre portefeuille. Quiconque les détient possède vos noms ; si vous les perdez, personne — nous compris — ne pourra rien récupérer.",
"Copy phrase": "Copier la phrase",
"I have written the phrase down somewhere safe and offline. I understand it cannot be reset.": "J'ai noté la phrase dans un endroit sûr et hors ligne. Je comprends qu'elle ne peut pas être réinitialisée.",
"Continue →": "Continuer →",
"12 words, separated by spaces. It stays in this browser.": "12 mots séparés par des espaces. Elle reste dans ce navigateur.",
"Recovery phrase": "Phrase de récupération",
"Password to encrypt it on this device": "Mot de passe pour la chiffrer sur cet appareil",
"Import →": "Importer →",
"No wallet on this device": "Aucun portefeuille sur cet appareil",
"📥 Import a wallet →": "📥 Importer un portefeuille →",
"🆕 Create a wallet →": "🆕 Créer un portefeuille →",
"Enter your PIN": "Saisissez votre PIN",
"Use password instead": "Utiliser le mot de passe",
"Unlock →": "Déverrouiller →",
"PIN reset": "PIN réinitialisé",
"3 wrong attempts — the PIN has been cleared. Enter your password to unlock and set a new PIN if you like.": "3 tentatives erronées : le PIN a été effacé. Saisissez votre mot de passe pour déverrouiller et définissez un nouveau PIN si vous le souhaitez.",
"Continue with password →": "Continuer avec le mot de passe →",
"Unlock your wallet": "Déverrouillez votre portefeuille",
"Decrypts the wallet stored in this browser. After unlocking you can set a PIN so future sessions ask for 4–6 digits instead of the full password.": "Déchiffre le portefeuille stocké dans ce navigateur. Après déverrouillage, vous pouvez définir un PIN pour que les prochaines sessions demandent 4–6 chiffres au lieu du mot de passe complet.",
"Password": "Mot de passe",
"Set a PIN": "Définir un PIN",
"optional": "facultatif",
"Repeat PIN": "Répétez le PIN",
"Not now": "Pas maintenant",
"Save PIN →": "Enregistrer le PIN →",
"Fund your wallet": "Approvisionnez votre portefeuille",
"Send test coins to this address. It is yours — derived from your phrase.": "Envoyez des pièces de test à cette adresse. Elle est à vous : dérivée de votre phrase.",
"checking balance…": "vérification du solde…",
"Preparing…": "Préparation…",
"Building your registration transaction.": "Construction de votre transaction d'enregistrement.",
"One transaction. It mints the certificate to": "Une transaction. Elle frappe le certificat vers",
"your": "votre",
"address and pays the fees.": "adresse et paie les frais.",
"The certificate will be minted to": "Le certificat sera frappé vers",
"— your key, your name. You can set where it points immediately afterwards.": "— votre clé, votre nom. Juste après, vous pouvez définir où il pointe.",
"Register — sign & broadcast": "Enregistrer — signer et diffuser",
"Could not prepare": "Préparation impossible",
"Confirm": "Confirmer",
"Beacon dust + chain fee": "Poussière de beacon + frais de chaîne",
"(covered by wallet)": "(couvert par le portefeuille)",
"Minted to": "Frappé vers",
"Service fee waived on chipnet": "Frais de service offerts sur chipnet",
"Approve payment": "Approuver le paiement",
"Approve →": "Approuver →",
"Signing in your browser and broadcasting to the chain. Do not close this tab.": "Signature dans votre navigateur et diffusion sur la chaîne. Ne fermez pas cet onglet.",
"Transaction": "Transaction",
"Certificate ID": "ID du certificat",
"Operator": "Opérateur",
"The certificate is on the chain, held by your key. Nobody can take it back.": "Le certificat est sur la chaîne, détenu par votre clé. Personne ne peut le reprendre.",
"Owner": "Propriétaire",
"Point it somewhere": "Faites-le pointer quelque part",
"Optional, and changeable any time — only your key can.": "Facultatif et modifiable à tout moment — seule votre clé le peut.",
"Record type": "Type d'enregistrement",
"A tiny site stored on the chain itself (h)": "Un tout petit site stocké sur la chaîne elle-même (h)",
"Redirect to a web address (u)": "Rediriger vers une adresse web (u)",
"Your own server's IPv4 address (ip)": "L'adresse IPv4 de votre propre serveur (ip)",
"TLS certificate fingerprint (tls)": "Empreinte du certificat TLS (tls)",
"Done for now": "C'est tout pour l'instant",
"Publish record": "Publier l'enregistrement",
"Publishing record": "Publication de l'enregistrement",
"Update transaction": "Transaction de mise à jour",
"Finish": "Terminer",
"My names": "Mes noms",
"records & holdings": "enregistrements et avoirs",
"Admin panel": "Panneau d'administration",
"operator tools": "outils opérateur",
"clear this browser": "effacer ce navigateur",
"Unlock my wallet": "Déverrouiller mon portefeuille",
"one you already created on this device": "celui que vous avez déjà créé sur cet appareil",
"Locked wallet on this device": "Portefeuille verrouillé sur cet appareil",
"Unlock or pick another action": "Déverrouillez ou choisissez une autre action",
"No wallet yet": "Pas encore de portefeuille",
"Pick how to sign in": "Choisissez comment vous connecter",
"Create a wallet": "Créer un portefeuille",
"generate a fresh 12-word phrase (sign up)": "générer une nouvelle phrase de 12 mots (inscription)",
"Import a wallet": "Importer un portefeuille",
"seed phrase you already have (sign in)": "une phrase de récupération que vous avez déjà (connexion)",
"Cashonize / Paytaca via QR": "Cashonize / Paytaca par QR",
"The home for names on Bitcoin Cash. Register a TLD, register a name, verify anything against the chain.": "La maison des noms sur Bitcoin Cash. Enregistrez un TLD, enregistrez un nom, vérifiez tout sur la chaîne.",
"Product": "Produit",
"✏️ Register a name": "✏️ Enregistrer un nom",
"🌐 Register a TLD": "🌐 Enregistrer un TLD",
"🔑 My names portal": "🔑 Mon portail de noms",
"🧭 Theseus browser": "🧭 Navigateur Theseus",
"Learn": "Apprendre",
"📚 Docs": "📚 Documentation",
"🗺 Roadmap": "🗺 Feuille de route",
"🏛 The Pantheon": "🏛 Le Panthéon",
"🎨 Brand kit": "🎨 Kit de marque",
"Alpha": "Alpha",
"Chipnet only. You hold your own keys; verify everything against the chain.": "Chipnet uniquement. Vous détenez vos propres clés ; vérifiez tout sur la chaîne.",
"brand assets": "ressources de marque",
"available": "disponible",
"taken": "pris",
"checking…": "vérification…",
"Register →": "Enregistrer →",
"loading…": "chargement…",
"(no records set)": "(aucun enregistrement)",
"on chain": "sur la chaîne",
"Edit": "Modifier",
"tier pricing": "tarif par paliers",
"(default policy — open, tier pricing)": "(politique par défaut — ouverte, tarifs par paliers)",
"Price & policy": "Prix et politique",
"Register a name under": "Enregistrer un nom sous",
"Preparing your addresses…": "Préparation de vos adresses…",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.": "Aucun nom BCNR trouvé pour ce portefeuille. Si vous venez d'enregistrer, attendez une minute la confirmation puis rechargez.",
"Off-chain DNS records — free per edit": "Enregistrements DNS hors chaîne — gratuit à chaque modification",
"Signing…": "Signature…",
"Saved ✓": "Enregistré ✓",
"Registered ✓": "Enregistré ✓",
"Switch on": "Allumer",
"Switch off": "Éteindre",
"Switch on: list the TLD and sell names again": "Allumer : lister le TLD et vendre à nouveau des noms",
"Switch off: hide the TLD, stop new registrations": "Éteindre : masquer le TLD, stopper les nouveaux enregistrements",
"no owner price set — buyers pay the length tier": "aucun prix fixé par le propriétaire — les acheteurs paient le palier par longueur",
"hidden from the public registry; no new names until you switch it on": "masqué du registre public ; aucun nouveau nom tant que vous ne l'allumez pas",
"listed in the public registry": "listé dans le registre public",
"label": "libellé",
"🔓 Unlock": "🔓 Déverrouiller",
"🆕 Create": "🆕 Créer",
"📥 Import": "📥 Importer",
"Dashboard — your names on Sirius.X": "Tableau de bord — vos noms sur Sirius.X",
"dashboard": "",
"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.": "Connectez-vous une fois avec votre phrase de récupération Bitcoin Cash ou un portefeuille externe. Cet appareil reste connecté jusqu'à la déconnexion — pas de mot de passe à chaque visite. Vos clés ne quittent jamais ce navigateur.",
"Manage": "Gérer",
"Domain names": "Noms de domaine",
"My TLD list": "Mes TLD",
"Get more": "Plus",
"Docs": "Documentation",
"What this wallet holds on chain, and where to go next.": "Ce que ce portefeuille détient sur la chaîne, et la suite.",
"↻ Refresh": "↻ Actualiser",
"Recent names": "Noms récents",
"The last few certificates that landed in this wallet.": "Les derniers certificats arrivés dans ce portefeuille.",
"Attention": "Attention",
"Names that point nowhere yet, or have no DNS.": "Noms qui ne pointent encore nulle part, ou sans DNS.",
"Every BCNR name this wallet holds. Open one to manage DNS, content, redirects or transfer it.": "Tous les noms BCNR de ce portefeuille. Ouvrez-en un pour gérer DNS, contenu, redirections ou le transférer.",
"Filter names…": "Filtrer les noms…",
"Sort: name": "Tri : nom",
"Sort: TLD": "Tri : TLD",
"Sort: newest": "Tri : plus récents",
"All TLDs": "Tous les TLD",
"no DNS": "pas de DNS",
"DNS …": "DNS …",
"DNS needs s3": "DNS requiert s3",
"Open site →": "Ouvrir le site →",
"Summary": "Résumé",
"DNS records": "Enregistrements DNS",
"Content & hosting": "Contenu et hébergement",
"Redirect": "Redirection",
"Transfer": "Transfert",
"Export": "Exporter",
"Certificate": "Certificat",
"Where it points": "Où il pointe",
"On-chain records decide what a resolver serves. Change them under Content & hosting.": "Les enregistrements on-chain décident de ce que sert un résolveur. Modifiez-les sous Contenu et hébergement.",
"DNS at a glance": "DNS en un coup d'œil",
"Signed off-chain records for mail, verification and classic DNS interop.": "Enregistrements signés hors chaîne pour le mail, la vérification et le DNS classique.",
"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.": "Enregistrements standard, signés par votre clé et stockés dans un manifeste sur Sia. Modification gratuite, sans transaction. Résolveurs et passerelle vérifient la signature auprès du détenteur actuel du NFT.",
"Type": "Type",
"Value": "Valeur",
"Priority / extra": "Priorité / extra",
"No DNS records yet. Add the first one below.": "Aucun enregistrement DNS pour l'instant. Ajoutez le premier ci-dessous.",
"Priority": "Priorité",
"Weight": "Poids",
"Port": "Port",
"Tag": "Tag",
"+ Add": "+ Ajouter",
"Discard changes": "Annuler les modifications",
"Nameservers": "Serveurs de noms",
"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.": "Les noms BCNR n'ont pas besoin de serveurs de noms — les résolveurs lisent la chaîne et ce manifeste directement. Ajoutez des NS seulement si vous déléguez aussi ce nom en DNS classique.",
"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.": "Enregistrements on-chain, publiés en une transaction UPD signée (quelques centimes de poussière). Un champ vide supprime l'enregistrement. Priorité pour les résolveurs : h, puis s3, puis p, puis ip.",
"inline HTML — served as-is at the site root (~150 bytes)": "HTML inline — servi tel quel à la racine (~150 octets)",
"Sia bucket key, trailing slash for directories — also where DNS manifests live": "clé du bucket Sia, barre finale pour les répertoires — les manifestes DNS y vivent aussi",
"reverse proxy: full upstream URL the gateway mirrors": "reverse proxy : URL complète de l'origine que la passerelle reflète",
"Reset": "Réinitialiser",
"Forward this name to any web address. Stored on chain as the": "Renvoyez ce nom vers n'importe quelle adresse web. Stocké sur la chaîne comme enregistrement",
"record; resolvers and the gateway issue the redirect. Clear it to stop forwarding.": "; résolveurs et passerelle effectuent la redirection. Videz-le pour l'arrêter.",
"Destination URL": "URL de destination",
"Remove redirect": "Supprimer la redirection",
"Save redirect →": "Enregistrer la redirection →",
"Transfer ownership": "Transférer la propriété",
"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.": "Déplace le certificat du nom vers une autre adresse Bitcoin Cash en une transaction. Les enregistrements restent. Le nouveau détenteur contrôle le nom dès cet instant — irréversible d'ici.",
"Recipient address": "Adresse du destinataire",
"I understand this hands the name to that address permanently.": "Je comprends que cela remet définitivement le nom à cette adresse.",
"Transfer name →": "Transférer le nom →",
"Download this name's DNS as a BIND-style zone file, or its full record set as JSON, for backups or importing elsewhere.": "Téléchargez le DNS de ce nom en fichier de zone type BIND, ou tous ses enregistrements en JSON, pour sauvegarde ou import ailleurs.",
"⬇ Zone file (.txt)": "⬇ Fichier de zone (.txt)",
"⬇ Records (.json)": "⬇ Enregistrements (.json)",
"Copy DNS manifest": "Copier le manifeste DNS",
"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.": "Tous les NFT de registre de TLD de ce portefeuille. Fixez le prix de chaque nom sous un TLD, allumez ou éteignez-le (éteint = privé : vous seul pouvez y enregistrer) et réglez la politique. Chaque changement est un TUPD signé sur la chaîne ; vous recevez 90 % de chaque vente.",
"Registry": "Registre",
"Register a name under this TLD": "Enregistrer un nom sous ce TLD",
"Works whether the TLD is on or off. As the owner you pay only the platform's 10% share.": "Fonctionne que le TLD soit allumé ou éteint. En tant que propriétaire, vous ne payez que la part de 10 % de la plateforme.",
"Names registered under this TLD": "Noms enregistrés sous ce TLD",
"Everyone's registrations, from the public registry.": "Les enregistrements de tous, depuis le registre public.",
"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.": "Les TLD sont des NFT de registre sur le beacon TLD de chipnet. Les frappes publiques paient des frais qui financent le registre. Chipnet utilise un taux provisoire ; sur mainnet un vrai oracle fixe le prix selon la longueur.",
"Faucet 2 →": "Robinet 2 →",
"Balance": "Solde",
"Spendable": "Disponible",
"UTXOs": "UTXOs",
"Watched addresses": "Adresses surveillées",
"Session and security choices for this browser. Nothing here changes what is on chain.": "Choix de session et de sécurité pour ce navigateur. Rien ici ne change ce qui est sur la chaîne.",
"Session": "Session",
"Stay signed in on this device": "Rester connecté sur cet appareil",
"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.": "Votre phrase de récupération reste chiffrée sous une clé que ce navigateur détient sans pouvoir l'exporter. Les prochaines visites ouvrent le tableau de bord directement. Désactivez pour être invité à saisir mot de passe ou PIN à chaque fois.",
"Ask for PIN before payments": "Demander le PIN avant les paiements",
"Adds a PIN prompt when registering a name or TLD. Off by default so signed-in sessions run uninterrupted.": "Ajoute une demande de PIN lors de l'enregistrement d'un nom ou d'un TLD. Désactivé par défaut pour des sessions sans interruption.",
"Set / change PIN": "Définir / changer le PIN",
"Remove PIN": "Supprimer le PIN",
"Reading & language": "Lecture et langue",
"Font pill and language picker live in the top bar; both are remembered per browser.": "Le sélecteur de police et celui de langue sont dans la barre du haut ; les deux sont mémorisés par navigateur.",
"This device": "Cet appareil",
"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.": "La déconnexion garde le portefeuille chiffré sur cet appareil pour le déverrouiller plus tard. Oublier le supprime entièrement — il faudra votre phrase de récupération.",
"Forget wallet on this device": "Oublier le portefeuille sur cet appareil",
"4–6 digits. Encrypts your recovery phrase under this PIN on this device. Three wrong PINs clear it and fall back to your password.": "4–6 chiffres. Chiffre votre phrase de récupération sous ce PIN sur cet appareil. Trois PIN erronés l'effacent et le mot de passe reprend.",
"No names yet.": "Pas encore de noms.",
"Register your first one →": "Enregistrez le premier →",
"Everything points somewhere and has DNS. Nice.": "Tout pointe quelque part et a un DNS. Parfait.",
"Nothing matches that filter.": "Rien ne correspond à ce filtre.",
"Status": "Statut",
"point it somewhere →": "faites-le pointer quelque part →",
"Add some →": "Ajoutez-en →",
"Register one →": "Enregistrez-en un →",
"yours": "à vous",
"Copied": "Copié",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and refresh.": "Aucun nom BCNR trouvé pour ce portefeuille. Si vous venez d'enregistrer, attendez une minute puis actualisez.",
"Remove": "Supprimer",
"Transferring…": "Transfert…",
"Transferred ✓": "Transféré ✓",
"off · private": "éteint · privé",
"on · public": "allumé · public",
"Signing you in…": "Connexion…",
"Restoring your session on this device.": "Restauration de votre session sur cet appareil.",
"Dashboard": "Tableau de bord",
"names, TLDs, DNS, settings": "noms, TLD, DNS, réglages",
"site on chain": "site sur la chaîne",
"site on Sia": "site sur Sia",
"reverse proxy": "reverse proxy",
"own server": "serveur propre",
"redirect": "redirection",
"not pointed": "non pointé",
"points nowhere yet": "ne pointe encore nulle part",
"no DNS records": "pas d'enregistrements DNS",
"DNS needs an s3 pointer": "DNS requiert un enregistrement s3",
"block": "bloc",
"Web-Builder": "Web-Builder",
"My TLDs": "Mes TLD",
"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.": "Sirius Studio construit un site pour chaque nom que vous détenez : glissez des blocs, modifiez le texte, publiez. Les pages vivent dans le dossier du nom sur Sia et le nom pointe dessus — sans hébergeur, sans renouvellement.",
"Session, security and wallet details for this browser. Nothing here changes what is on chain.": "Session, sécurité et détails du portefeuille pour ce navigateur. Rien ici ne change ce qui est sur la chaîne.",
"Reading, language & help": "Lecture, langue et aide",
"Font pill and language picker live in the top bar; both are remembered per browser. The technical documentation is at": "Le sélecteur de police et celui de langue sont dans la barre du haut ; les deux sont mémorisés par navigateur. La documentation technique est sur",
"Start from a template": "Partir d'un modèle",
"Preview the exported page in a new tab": "Aperçu de la page exportée dans un nouvel onglet",
"Sirius Studio — build the site for your name": "Sirius Studio — construisez le site de votre nom",
"Templates…": "Modèles…",
"Landing page": "Page d'accueil",
"Profile / link hub": "Profil / liens",
"Business one-pager": "Entreprise en une page",
"Blank page": "Page vierge",
"Preview": "Aperçu",
"Save draft": "Enregistrer le brouillon",
"Publish to Sia →": "Publier sur Sia →",
"View site →": "Voir le site →",
"Sign in first": "Connectez-vous d'abord",
"Sirius Studio publishes with your wallet's key. Sign in on the dashboard, then come back to this name.": "Sirius Studio publie avec la clé de votre portefeuille. Connectez-vous sur le tableau de bord, puis revenez à ce nom.",
"Open the dashboard →": "Ouvrir le tableau de bord →",
"Build the site for": "Construisez le site de",
"Pick a starting point. Everything is editable — drag blocks in from the right, click any text to change it. Nothing leaves your browser until you press Publish; then the page is stored on Sia and the name points at it.": "Choisissez un point de départ. Tout est modifiable — glissez des blocs depuis la droite, cliquez sur un texte pour le changer. Rien ne quitte votre navigateur avant Publier ; la page est alors stockée sur Sia et le nom pointe dessus.",
"Hero, three features, call to action.": "En-tête, trois atouts, appel à l'action.",
"Avatar, bio and a stack of links.": "Avatar, bio et une pile de liens.",
"About, services, hours, contact.": "À propos, services, horaires, contact.",
"Start from nothing.": "Partir de zéro.",
"Back to dashboard": "Retour au tableau de bord",
"Publish": "Publier",
"The page and its assets are uploaded to the name's folder on Sia, signed with your key. If the name does not point at that folder yet, one on-chain update sets it (a few cents of chain dust).": "La page et ses fichiers sont envoyés dans le dossier du nom sur Sia, signés avec votre clé. Si le nom ne pointe pas encore dessus, une mise à jour on-chain le fait (quelques centimes de poussière).",
"Needs attention": "À traiter",
"View →": "Voir →",
"Edit in Studio": "Modifier dans Studio",
"Open in Studio": "Ouvrir dans Studio",
"built with Studio": "fait avec Studio",
"site on Sia (external)": "site sur Sia (externe)",
"inline HTML": "HTML inline",
"no site yet": "pas encore de site",
"Pick a name to build or edit its site.": "Choisissez un nom pour créer ou modifier son site.",
"You need a name first.": "Il vous faut d'abord un nom.",
"— then come back here to build its site.": "— puis revenez ici pour construire son site.",
"New site": "Nouveau site",
"Not signed in": "Non connecté",
"Loading name…": "Chargement du nom…",
"Published": "Publié",
"Publish failed": "Échec de la publication",
"Template loaded — edit, then Publish": "Modèle chargé — modifiez, puis publiez",
"Draft saved on Sia": "Brouillon enregistré sur Sia",
"Saving draft…": "Enregistrement du brouillon…",
"Copy address": "Copier l'adresse",
"receive coins or names here": "recevez coins ou noms ici",
"Copy token address": "Copier l'adresse de jetons",
"where name certificates are minted": "où sont frappés les certificats de noms",
"Get test coins": "Obtenir des pièces de test",
"chipnet faucet": "robinet chipnet",
"Wallet settings": "Réglages du portefeuille",
"session, PIN, forget device": "session, PIN, oublier l'appareil",
"Holdings": "Avoirs",
"open the dashboard to load": "ouvrez le tableau de bord pour charger",
"🛒 Market": "🛒 Marché",
"🛒 Names for sale": "🛒 Noms à vendre",
"Market — names for sale on Sirius.X": "Marché — noms à vendre sur Sirius.X",
"for sale": "à vendre",
"Every sale is a single Bitcoin Cash transaction. The seller signed an offer that pays them only when the certificate moves to you — you add your coins, sign, broadcast. No escrow, no middleman, no way for either side to cheat.": "Chaque vente est une seule transaction Bitcoin Cash. Le vendeur a signé une offre qui ne le paie que lorsque le certificat vous est transféré — vous ajoutez vos pièces, signez, diffusez. Pas de séquestre, pas d'intermédiaire, aucun moyen de tricher.",
"Sort: price": "Trier : prix",
"Loading listings…": "Chargement des annonces…",
"Selling a name?": "Vous vendez un nom ?",
"Open it in your": "Ouvrez-le dans votre",
", choose": ", choisissez",
"Sell": "Vendre",
", set a price. The listing is a signed offer stored by the gateway; cancelling it moves your certificate once so the old offer can never be used.": ", fixez un prix. L'annonce est une offre signée conservée par la passerelle ; l'annuler déplace votre certificat une fois afin que l'ancienne offre ne puisse plus jamais servir.",
"One transaction: your coins pay the seller, the certificate lands in your wallet, and the registry is told about the new owner. Records stay as they are — you can change them in the dashboard right after.": "Une transaction : vos pièces paient le vendeur, le certificat arrive dans votre portefeuille et le registre apprend le nouveau propriétaire. Les enregistrements restent tels quels — vous pouvez les modifier dans le tableau de bord juste après.",
"Sign in to buy →": "Se connecter pour acheter →",
"Buy — sign & broadcast": "Acheter — signer et diffuser",
"Buy →": "Acheter →",
"Nothing is for sale right now. Owners list names from their dashboard.": "Rien n'est à vendre pour l'instant. Les propriétaires mettent leurs noms en vente depuis leur tableau de bord.",
"Sell this name": "Vendre ce nom",
"You sign an offer once: \"whoever pays me this price gets the certificate\". The offer is stored by the gateway and shown on the": "Vous signez une offre une seule fois : « quiconque me paie ce prix obtient le certificat ». La passerelle conserve l'offre et l'affiche sur le",
"market": "marché",
". 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.": ". Un acheteur la complète en une transaction — vous êtes payé dans la même transaction qui transfère le nom, ou pas du tout. Pas de séquestre, rien à devoir croire.",
"Checking the market…": "Vérification du marché…",
"Price (USD)": "Prix (USD)",
"Price (sat)": "Prix (sat)",
"List for sale →": "Mettre en vente →",
"Cancel listing →": "Annuler l'annonce →",
"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.": "L'annulation retire l'offre du marché et déplace votre certificat une fois (une mise à jour vide, quelques centimes), afin que l'offre signée ne puisse jamais être complétée plus tard.",
"Not for sale. Set a price to list it.": "Pas à vendre. Fixez un prix pour le mettre en vente.",
"This name is listed on the market.": "Ce nom est en vente sur le marché.",
"Pending approvals": "Approbations en attente",
"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.": "Enregistrements sous ce TLD qui attendent votre cosignature. Approuver signe votre certificat de TLD dans la transaction de l'acheteur et la diffuse ; le certificat vous revient dans la même transaction. Rien ne peut être enregistré sous un TLD à cosignature ou privé sans cette étape.",
"No requests waiting.": "Aucune demande en attente.",
"awaiting you": "vous attend",
"Approve & broadcast": "Approuver et diffuser",
"Decline": "Refuser",
"Request approval — sign": "Demander l'approbation — signer",
"Withdraw request": "Retirer la demande",
"Request declined": "Demande refusée",
"Open dashboard →": "Ouvrir le tableau de bord →",
"incl.": "dont",
"sat unconfirmed · spendable now": "sat non confirmés · disponibles maintenant",
"Nothing is for sale right now": "Rien n'est à vendre pour l'instant",
"Names go on sale when their owners list them from the dashboard. Have one to sell, or want a fresh one instead?": "Les noms sont mis en vente lorsque leurs propriétaires les listent depuis le tableau de bord. Vous en avez un à vendre, ou vous en voulez un tout neuf ?",
"Sell a name from your dashboard →": "Vendre un nom depuis le tableau de bord →",
"Register a new name": "Enregistrer un nouveau nom",
"↓ Import live site": "↓ Importer le site en ligne",
"Import the live site": "Importer le site en ligne",
"✨ Assistant": "✨ Assistant",
"Runs on your own device. Nothing you write or build is sent to Sirius.X or to any AI vendor.": "Fonctionne sur votre propre appareil. Rien de ce que vous écrivez ou construisez n'est envoyé à Sirius.X ni à un fournisseur d'IA.",
"Runs on": "S'exécute sur",
"This browser — your GPU, private": "Ce navigateur — votre GPU, privé",
"Local endpoint — Ollama, LM Studio": "Point local — Ollama, LM Studio",
"Model": "Modèle",
"Downloads once, then stays in the browser cache. Needs WebGPU (current Chrome, Edge, Firefox, Safari).": "Téléchargé une fois, puis conservé dans le cache du navigateur. Nécessite WebGPU (Chrome, Edge, Firefox, Safari récents).",
"Load model": "Charger le modèle",
"Endpoint": "Point d'accès",
"Connect": "Connecter",
"What do you want?": "Que voulez-vous ?",
"Make a section": "Créer une section",
"Rewrite selected text": "Réécrire le texte sélectionné",
"Restyle selection": "Restyler la sélection",
"Nothing selected": "Rien de sélectionné",
"Undo last change": "Annuler la dernière modification",
"Stop": "Arrêter"
}

612
i18n/pt.json Normal file
View file

@ -0,0 +1,612 @@
{
"Sirius.X — the home for names on Bitcoin Cash": "Sirius.X — a casa dos nomes no Bitcoin Cash",
"Portal — your names on Sirius.X": "Portal — os seus nomes no Sirius.X",
"Register a TLD — Sirius.X": "Registar um TLD — Sirius.X",
"Try it": "Experimentar",
"✏️ Register": "✏️ Registar",
"🌐 TLD": "🌐 TLD",
"🔑 Sign in": "🔑 Entrar",
"type a name — e.g. hello": "escreva um nome — p. ex. ola",
"Search a name across every BCNR TLD": "Procurar um nome em todos os TLD BCNR",
"Names on the": "Nomes na",
"chain": "cadeia",
"Sirius.X is the entry point for BCNR — Bitcoin Cash Name Registry. Register a top-level domain, register a name under one, look up records, verify anything against the chain.": "O Sirius.X é a porta de entrada do BCNR — o registo de nomes do Bitcoin Cash. Registe um domínio de topo, registe um nome sob ele, consulte registos e verifique tudo contra a cadeia.",
"One search checks the label across every TLD in the registry. Available names appear first.": "Uma única pesquisa verifica a etiqueta em todos os TLD do registo. Os nomes disponíveis aparecem primeiro.",
"Or browse what you can do →": "Ou veja o que pode fazer →",
"Read the docs": "Ler a documentação",
"Three things you can do right now. The registrar and TLD-registry UIs live at silentmode.st today; Sirius.X is the canonical home and will consolidate them here.": "Três coisas que pode fazer agora mesmo. O registrador e o registo de TLD vivem hoje em silentmode.st; o Sirius.X é a sua casa canónica e vai consolidá-los aqui.",
"Register a name": "Registar um nome",
"Pick a label, search across every TLD in the registry at once, mint the name certificate straight into your own wallet. No yearly renewal.": "Escolha uma etiqueta, pesquise em todos os TLD do registo de uma vez e cunhe o certificado do nome diretamente na sua própria carteira. Sem renovação anual.",
"≈ 10,000 sat service fee · 1,300 sat chain dust · < 1 ¢": "≈ 10 000 sat de taxa de serviço · 1 300 sat de poeira da cadeia · < 1 ¢",
"Chipnet placeholder. 90 % of the service fee flows to the TLD owner, 10 % to the platform.": "Valor provisório da chipnet. 90 % da taxa vai para o dono do TLD, 10 % para a plataforma.",
"Search a name →": "Procurar um nome →",
"Register a TLD": "Registar um TLD",
"A TLD is itself a certificate on the chain. Anyone can mint one — you become the registry operator for every second-level name under it, and earn 90 % of the fee on every name registered under it. Renewals are per-TLD policy set by the owner.": "Um TLD é, ele próprio, um certificado na cadeia. Qualquer pessoa pode cunhar um: torna-se operador do registo de cada nome de segundo nível sob ele e ganha 90 % da taxa de cada nome registado. As renovações são uma política por TLD definida pelo dono.",
"≈ 1,250,000 sat service fee (≈ $5) · 1,300 sat chain dust": "≈ 1 250 000 sat de taxa de serviço (≈ 5 $) · 1 300 sat de poeira da cadeia",
"Chipnet placeholder rate — mainnet will price by label length via an on-chain oracle.": "Taxa provisória da chipnet — na mainnet o preço dependerá do comprimento da etiqueta através de um oráculo on-chain.",
"Search a TLD →": "Procurar um TLD →",
"Operator admin →": "Administração do operador →",
"Look up & verify": "Consultar e verificar",
"Resolve any BCNR name, compare records across mirrors, and check the TLD registry snapshot against the chain. Everything is publicly verifiable.": "Resolva qualquer nome BCNR, compare registos entre espelhos e confira o snapshot do registo de TLD contra a cadeia. Tudo é verificável publicamente.",
"How to verify →": "Como verificar →",
"🔑 Sign in — your names portal": "🔑 Entrar — o seu portal de nomes",
"Import your seed phrase or connect a wallet (Cashonize / Paytaca via WizardConnect) to see every name you own, review records, and update them. Your keys never leave your browser.": "Importe a sua frase-semente ou ligue uma carteira (Cashonize / Paytaca via WizardConnect) para ver todos os nomes que possui, rever registos e atualizá-los. As suas chaves nunca saem do seu navegador.",
"Open the portal →": "Abrir o portal →",
"🧭 Theseus Navigator": "🧭 Theseus Navigator",
"The browser that speaks BCNR natively. Open": "O navegador que fala BCNR nativamente. Abra",
"in the address bar — it just resolves. TLS verified against on-chain fingerprints, no OS trust-store install.": "na barra de endereço e simplesmente resolve. TLS verificado contra impressões digitais on-chain, sem instalar nada no repositório de confiança do sistema.",
"Download →": "Transferir →",
"Documentation": "Documentação",
"The full docs — TLD registry model, record types, resolver & gateway paths, mainnet pricing, verification, and the operator runbook pointer — live on their own page so they can grow without cluttering the landing.": "A documentação completa — modelo do registo de TLD, tipos de registo, caminhos de resolvedor e gateway, preços na mainnet, verificação e a ligação ao runbook do operador — vive na sua própria página para crescer sem sobrecarregar a página inicial.",
"📚 Open the docs →": "📚 Abrir a documentação →",
"Current TLD list": "Lista atual de TLD",
"Propose a new TLD": "Propor um novo TLD",
"The per-TLD registry means minting a TLD is a real, paid action — not a namespace land-grab. During the alpha, all TLD mints are operator-signed. To propose a TLD, get in touch via the channels below. The design (mainnet) adds an on-chain covenant with countersignature + tiered USD price floors: 1-char $100k, 2-char $50k, 3-char $15k, 4-char $5k, 5–8-char $1k, 9+-char $250; one-time payment (not annual). See the design doc for the full model.": "O registo por TLD significa que cunhar um TLD é uma ação real e paga, não uma apropriação do espaço de nomes. Durante a alfa, todas as cunhagens de TLD são assinadas pelo operador. Para propor um TLD, contacte-nos pelos canais abaixo. O desenho (mainnet) acrescenta um covenant on-chain com contra-assinatura e preços mínimos escalonados em USD: 1 carácter 100 k$, 2 caracteres 50 k$, 3 caracteres 15 k$, 4 caracteres 5 k$, 5–8 caracteres 1 k$, 9+ caracteres 250 $; pagamento único (não anual). Veja o documento de desenho para o modelo completo.",
"ICANN-adjacent TLDs are not open for public mint.": "Os TLD que coincidem com a ICANN não estão abertos a cunhagem pública.",
"A TLD registry is only useful if it does not immediately collapse into an ICANN-shadow — the mainnet covenant enforces this; on chipnet the operator's countersignature is the gate.": "Um registo de TLD só é útil se não colapsar de imediato numa sombra da ICANN — na mainnet o covenant impõe isso; na chipnet a contra-assinatura do operador é a barreira.",
"The pantheon": "O panteão",
"Sirius.x is one of seven sibling": "O Sirius.x é um dos sete nomes irmãos",
"names — the Silent Mode pantheon. Each project is its own on-chain certificate; each site is reachable through any BCNR resolver, plus the silentmode.st gateway for browsers without one.": "— o panteão Silent Mode. Cada projeto é o seu próprio certificado on-chain; cada site é acessível através de qualquer resolvedor BCNR, além do gateway silentmode.st para navegadores sem um.",
"⛓️ Silentmode.X": "⛓️ Silentmode.X",
"The project umbrella. Redirects to": "O guarda-chuva do projeto. Redireciona para",
"where every pillar has its own landing page + download hub.": "onde cada pilar tem a sua própria página e as suas transferências.",
"Open →": "Abrir →",
"⭐ Sirius.X": "⭐ Sirius.X",
"you're here": "está aqui",
"Names on Bitcoin Cash — register, resolve, verify, manage. This site.": "Nomes no Bitcoin Cash — registar, resolver, verificar, gerir. Este site.",
"Home →": "Início →",
"🧭 Theseus.X": "🧭 Theseus.X",
"The browser that speaks BCNR natively — Chromium build with the resolver baked in, no OS-level daemon or root-store install.": "O navegador que fala BCNR nativamente — uma build do Chromium com o resolvedor integrado, sem daemon do sistema nem certificado raiz.",
"Learn more →": "Saber mais →",
"🔥 Hephaestus.X": "🔥 Hephaestus.X",
"The forge. Forgejo instance for the ecosystem's git repos, backed by BCH wallet auth. Sirius's own source lives here.": "A forja. Instância Forgejo para os repositórios git do ecossistema, com autenticação por carteira BCH. O código-fonte do Sirius vive aqui.",
"🔮 Prometheus.X": "🔮 Prometheus.X",
"Fire from the chain. The project's foresight / experimentation layer. Redirects to": "Fogo da cadeia. A camada de previsão e experimentação do projeto. Redireciona para",
"today.": "(hoje).",
"☀️ Helios.X": "☀️ Helios.X",
"The public gaze. Analytics, dashboards, transparency reports. Redirects to": "O olhar público. Análises, painéis, relatórios de transparência. Redireciona para",
"✉️ Hermes.X": "✉️ Hermes.X",
"Messenger. Nostr-based messaging bound to a BCNR name via the": "Mensageiro. Mensagens sobre Nostr ligadas a um nome BCNR através dos registos",
"records. Redirects to": ". Redireciona para",
"What's coming": "O que aí vem",
"Sirius.X consolidates docs and registration today; three larger pieces are on the roadmap.": "Hoje o Sirius.X consolida documentação e registo; três peças maiores estão no roteiro.",
"Wallet & name portal": "Portal de carteira e nomes",
"next": "a seguir",
"Sign in with your Bitcoin Cash wallet, see every name you own, edit records inline, mint or renew from one place. Same self-custody as today — the portal never handles your keys.": "Entre com a sua carteira Bitcoin Cash, veja todos os nomes que possui, edite registos no local, cunhe ou renove a partir de um único sítio. A mesma autocustódia de hoje: o portal nunca toca nas suas chaves.",
"Sirius Studio": "Sirius Studio",
"planned": "planeado",
"An in-browser site editor for names you already own — the WordPress / Tilda / Wix pattern, but the whole site persists to Sia and the name's": "Um editor de sites no navegador para nomes que já possui — o padrão WordPress / Tilda / Wix, mas todo o site fica guardado no Sia e o registo",
"record updates on save. Sites live where the name says they live.": "do nome é atualizado ao guardar. Os sites vivem onde o nome diz que vivem.",
"Decentralized git remote": "Remote git descentralizado",
"MVP live": "MVP no ar",
"The Silent Mode repo is served as a bare git tree over dumb-HTTP from the VPS. Clone it with any git client, no login. Forgejo + Sia sync for a proper decentralized backend is the next track.": "O repositório Silent Mode é servido como árvore git bare por dumb-HTTP a partir do VPS. Clone-o com qualquer cliente git, sem conta. O próximo passo é Forgejo + sincronização Sia como backend verdadeiramente descentralizado.",
"One-shot snapshot as a downloadable git bundle (works when dumb-HTTP is blocked):": "Snapshot único como git bundle transferível (funciona quando o dumb-HTTP está bloqueado):",
"Verify this page against the chain": "Verifique esta página contra a cadeia",
"You do not have to trust that": "Não tem de confiar que",
"is served by anyone specific. The name's certificate is on the Bitcoin Cash chain; the records point to Sia; every path is independently checkable.": "é servido por alguém em particular. O certificado do nome está na cadeia Bitcoin Cash; os registos apontam para o Sia; cada caminho é verificável de forma independente.",
"1. Confirm the certificate exists on chain": "1. Confirme que o certificado existe na cadeia",
"2. Fetch the TLD-registry snapshot from Nostr": "2. Obtenha o snapshot do registo de TLD a partir do Nostr",
"The operator-signed snapshot of the TLD list is published as a Nostr replaceable event. Any relay carries it; the event's content field carries the current snapshot root.": "O snapshot da lista de TLD, assinado pelo operador, é publicado como evento substituível do Nostr. Qualquer relay o transporta; o campo content do evento contém a raiz do snapshot atual.",
"Kind / d-tag": "Kind / d-tag",
"Pubkey (x-only, hex)": "Chave pública (x-only, hex)",
"Relays": "Relays",
"3. Reach this site via more than one route": "3. Chegue a este site por mais de um caminho",
"The same content should be served from at least two independent paths. If one mirror is unavailable, the others still work. If two mirrors disagree, the on-chain record is the tiebreaker.": "O mesmo conteúdo deve ser servido por pelo menos dois caminhos independentes. Se um espelho estiver indisponível, os outros continuam a funcionar. Se dois espelhos discordarem, o registo on-chain desempata.",
"Via any BCNR resolver:": "Através de qualquer resolvedor BCNR:",
"(requires the local root CA)": "(requer a CA raiz local)",
"Via the public gateway:": "Através do gateway público:",
"Via silentmode.st mirror:": "Através do espelho silentmode.st:",
"Direct from Sia (content-addressed): the": "Diretamente do Sia (endereçado por conteúdo): o registo",
"record on": "em",
"names the exact bucket key": "indica a chave exata do bucket",
"Register a": "Registe um",
"A TLD is a certificate on the Bitcoin Cash chain. You mint it, you own it — any second-level name registered under it lives in your TLD's registry. One BCH transaction, no ICANN. Renewals? Your TLD, your policy.": "Um TLD é um certificado na cadeia Bitcoin Cash. Cunha-o, é seu: qualquer nome de segundo nível registado sob ele vive no registo do seu TLD. Uma transação BCH, sem ICANN. Renovações? O seu TLD, a sua política.",
"Search a TLD": "Procurar um TLD",
"Type a label (a–z, 0–9, hyphen; up to 16 chars). Available TLDs get a Register button that opens the shared wallet-choice modal — the same flow name registration uses. As TLD owner you earn": "Escreva uma etiqueta (a–z, 0–9, hífen; até 16 caracteres). Os TLD disponíveis mostram um botão Registar que abre a janela partilhada de escolha da carteira — o mesmo fluxo do registo de nomes. Como dono do TLD, ganha",
"of every name registered under your TLD. Renewals are your call — set them per TLD, or don't.": "de cada nome registado sob o seu TLD. As renovações são decisão sua: defina-as por TLD, ou não.",
"Register minting to your token address; you become the registry operator.": "O registo cunha para o seu endereço de tokens; torna-se operador do registo.",
"Registered TLDs": "TLD registados",
"Fetched from the on-chain TLD registry via the public gateway. Refresh the page for the latest.": "Obtido do registo de TLD on-chain através do gateway público. Recarregue a página para os dados mais recentes.",
"Loading…": "A carregar…",
"Mint price": "Preço de cunhagem",
"Category": "Categoria",
"Portal sections": "Secções do portal",
"Your": "O seu portal de",
"names": "nomes",
"portal": "",
"Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see every BCNR name your wallet holds. Your keys never leave this browser tab.": "Entre com a sua frase-semente Bitcoin Cash ou ligue uma carteira externa para ver todos os nomes BCNR que ela possui. As suas chaves nunca saem deste separador.",
"Sign in or create a wallet": "Entre ou crie uma carteira",
"The same wallet that will hold your names does the signing. Pick a tab — everything happens on this page; keys never leave your browser.": "A mesma carteira que vai guardar os seus nomes é a que assina. Escolha um separador: tudo acontece nesta página; as chaves nunca saem do seu navegador.",
"Overview": "Resumo",
"Names": "Nomes",
"TLDs": "TLD",
"Wallet": "Carteira",
"Settings": "Definições",
"A snapshot of what this wallet holds on chain.": "Uma vista do que esta carteira possui na cadeia.",
"Names held": "Nomes detidos",
"CashTokens NFT certificates": "Certificados NFT CashTokens",
"TLDs owned": "TLD possuídos",
"Per-TLD registry NFTs": "NFT de registo por TLD",
"Wallet balance": "Saldo da carteira",
"chipnet sats": "sats chipnet",
"Chain height": "Altura da cadeia",
"Last seen block": "Último bloco visto",
"+ Register a name": "+ Registar um nome",
"+ Register a TLD": "+ Registar um TLD",
"Names you hold": "Os seus nomes",
"Every BCNR name your wallet's addresses currently hold a CashTokens NFT for. Edit records inline to publish an on-chain UPD.": "Todos os nomes BCNR para os quais os endereços da sua carteira detêm atualmente um NFT CashTokens. Edite os registos no local para publicar um UPD on-chain.",
"Loading names from the chain…": "A carregar nomes da cadeia…",
"TLDs you own": "Os seus TLD",
"Every per-TLD registry NFT held by this wallet. Set the": "Todos os NFT de registo de TLD desta carteira. Defina o",
"price": "preço",
"every name under your TLD sells for, switch the TLD": "a que cada nome sob o seu TLD é vendido, ligue ou desligue o TLD",
"on or off": "no registo público",
"in the public registry (off = a": "(desligado = um",
"private TLD": "TLD privado",
": nobody else can buy names under it, you still can from here), and tune policy —": ": mais ninguém pode comprar nomes sob ele, você continua a poder a partir daqui) e afine a política —",
"fee": "taxa",
"min length": "comprimento mínimo",
"reserved labels": "etiquetas reservadas",
"renewal period": "período de renovação",
". Every change is one signed TUPD on chain; you receive 90% of each sale.": ". Cada alteração é um TUPD assinado na cadeia; recebe 90 % de cada venda.",
"Loading TLDs from the chain…": "A carregar TLD da cadeia…",
"Register a new TLD": "Registar um novo TLD",
"TLDs are per-registry NFTs on the chipnet TLD beacon. Public mints go through a service-fee output to fund the registry. Chipnet uses a placeholder rate; mainnet will price by label length via a real oracle.": "Os TLD são NFT de registo no beacon de TLD da chipnet. As cunhagens públicas pagam uma taxa de serviço que financia o registo. A chipnet usa uma taxa provisória; na mainnet um oráculo real definirá o preço pelo comprimento da etiqueta.",
"Label": "Etiqueta",
"1–16 chars, [a-z0-9-]": "1–16 caracteres, [a-z0-9-]",
"Service fee (USD)": "Taxa de serviço (USD)",
"chipnet test rate": "taxa de teste chipnet",
"sats · rate": "sats · taxa",
"sats/USD": "sats/USD",
"Check availability": "Verificar disponibilidade",
"Register (~0 sats)": "Registar (~0 sats)",
"Your addresses and current balance. Keys stay in this browser.": "Os seus endereços e saldo atual. As chaves ficam neste navegador.",
"Receive address": "Endereço de receção",
"Token address": "Endereço de tokens",
"holds your name certificates": "guarda os certificados dos seus nomes",
"Faucet →": "Torneira →",
"Reader preferences live per-browser; wallet changes require a signature.": "As preferências de leitura são por navegador; as alterações à carteira exigem assinatura.",
"Reading font": "Tipo de letra de leitura",
"Fraunces (Silent Mode family) or Ubuntu (Bitcoin Cash brand font). The pill lives in the top nav.": "Fraunces (família Silent Mode) ou Ubuntu (tipo de letra da marca Bitcoin Cash). O seletor está na navegação superior.",
"Session PIN": "PIN de sessão",
"PIN unlocks the wallet without re-typing your password. Wipes after 3 wrong attempts.": "O PIN desbloqueia a carteira sem voltar a escrever a palavra-passe. Apaga-se após 3 tentativas erradas.",
"Sign out": "Sair",
"Clears the signed-in state in this browser. Your on-chain names are unaffected.": "Limpa o estado de sessão neste navegador. Os seus nomes on-chain não são afetados.",
"Edit records. Only your key can sign this UPD; the transaction fee is a few cents in chain fees plus the beacon dust. Leave a field blank to omit that record.": "Edite registos. Só a sua chave pode assinar este UPD; a transação custa alguns cêntimos em taxas de cadeia mais a poeira do beacon. Deixe um campo vazio para omitir esse registo.",
"inline HTML — served as-is at the site root": "HTML inline — servido tal como está na raiz do site",
"Sia bucket key, trailing slash for directories": "chave do bucket Sia, barra final para diretórios",
"IPv4 that serves this name over Host header": "IPv4 que serve este nome através do cabeçalho Host",
"SHA-256 of your leaf cert — chain-pinned TLS trust": "SHA-256 do seu certificado folha — confiança TLS fixada na cadeia",
"redirect target": "destino do redirecionamento",
"payload:": "carga:",
"bytes": "bytes",
"Cancel": "Cancelar",
"Save records →": "Guardar registos →",
"DNS records for": "Registos DNS de",
"DNS-style records live in a signed manifest on Sia — not on chain.": "Os registos tipo DNS vivem num manifesto assinado no Sia, não na cadeia.",
"Free per edit": "Grátis por edição",
", no size cap. The signature proves you own the name; the gateway rejects anything not signed by the current NFT holder. See": ", sem limite de tamanho. A assinatura prova que o nome é seu; o gateway rejeita tudo o que não for assinado pelo detentor atual do NFT. Ver",
"docs": "documentação",
"IPv4 addresses, one per line": "endereços IPv4, um por linha",
"IPv6 addresses, one per line": "endereços IPv6, um por linha",
"one string per line (SPF, DKIM, verification tokens…)": "uma cadeia por linha (SPF, DKIM, tokens de verificação…)",
"one target host, or blank": "um host de destino, ou vazio",
"nameservers, one per line": "servidores de nomes, um por linha",
"Sign & publish →": "Assinar e publicar →",
"Policy for": "Política de",
"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).": "Defina a política dos nomes registados sob este TLD. Só a sua chave pode assinar este TUPD; a transação custa alguns cêntimos de poeira da cadeia. Deixe um campo vazio para omitir essa regra (por omissão: política aberta, preços por escalões).",
"USD per name — flat, shown to every buyer; blank = length tiers. You receive 90% of each sale.": "USD por nome — fixo, mostrado a cada comprador; vazio = escalões por comprimento. Recebe 90 % de cada venda.",
"listing": "listagem",
"off hides the TLD from search and blocks new registrations until you switch it back on": "desligado esconde o TLD da pesquisa e bloqueia novos registos até o voltar a ligar",
"On — listed, names for sale": "Ligado — listado, nomes à venda",
"Off — hidden, not for sale": "Desligado — escondido, não está à venda",
"reject names shorter than N chars": "rejeitar nomes com menos de N caracteres",
"service fee owner takes, in basis points (500 = 5%)": "parte da taxa que fica para o dono, em pontos base (500 = 5 %)",
"open · frozen · reserved-only": "open · frozen · reserved-only",
"space-separated labels only owner can mint": "etiquetas separadas por espaços que só o dono pode cunhar",
"days between renewals, 0 = never expire": "dias entre renovações, 0 = nunca expira",
"renewal price in sats, 0 = free": "preço de renovação em sats, 0 = grátis",
"where the TLD's own landing lives": "onde vive a página própria do TLD",
"Save policy →": "Guardar política →",
"Signed in": "Sessão iniciada",
"You are signed in as": "Tem sessão iniciada como",
"Done": "Concluído",
"Close": "Fechar",
"Unlock my browser wallet": "Desbloquear a carteira do meu navegador",
"You already created one on this device.": "Já criou uma neste dispositivo.",
"Create a new wallet": "Criar uma carteira nova",
"easiest": "o mais fácil",
"Made here in your browser. You get a recovery phrase to write down — it is the only key.": "Criada aqui, no seu navegador. Recebe uma frase de recuperação para anotar: é a única chave.",
"Import a recovery phrase": "Importar uma frase de recuperação",
"Restore a wallet you already have, from its 12-word phrase.": "Restaure uma carteira que já tem, a partir da sua frase de 12 palavras.",
"Connect a wallet — WizardConnect": "Ligar uma carteira — WizardConnect",
"most private": "o mais privado",
"Cashonize 0.9+ or Paytaca. Encrypted end-to-end over Nostr; the relay sees only ciphertext. Your keys never leave your wallet.": "Cashonize 0.9+ ou Paytaca. Cifrado de ponta a ponta sobre Nostr; o relay só vê texto cifrado. As suas chaves nunca saem da sua carteira.",
"Everything below runs on": "Tudo o que está abaixo corre na",
", Bitcoin Cash's test network. The coins are free and worth nothing — this is an alpha, and it is the honest place to try it before real money is involved.": ", a rede de testes do Bitcoin Cash. As moedas são grátis e não valem nada: isto é uma alfa e é o sítio honesto para experimentar antes de haver dinheiro a sério.",
"Starting the connection…": "A iniciar a ligação…",
"Back": "Voltar",
"Open your wallet": "Abra a sua carteira",
"Copy": "Copiar",
"Waiting for your wallet… The link stays valid until you close this page.": "À espera da sua carteira… A ligação mantém-se válida até fechar esta página.",
"Connected": "Ligado",
"Reading your wallet and building the registration…": "A ler a sua carteira e a preparar o registo…",
"That wallet is empty": "Essa carteira está vazia",
"Two approvals needed.": "São necessárias duas aprovações.",
"Register — approve in your wallet": "Registar — aprove na sua carteira",
"Approve in your wallet": "Aprove na sua carteira",
"Create your wallet": "Crie a sua carteira",
"Generated in this browser. The phrase is never sent anywhere — not to us, not to anyone.": "Gerada neste navegador. A frase nunca é enviada para lado nenhum: nem para nós, nem para ninguém.",
"Password (encrypts the wallet on this device)": "Palavra-passe (cifra a carteira neste dispositivo)",
"Repeat password": "Repita a palavra-passe",
"There is no reset.": "Não há reposição.",
"Generate phrase →": "Gerar frase →",
"Write this down. Now.": "Anote isto. Agora.",
"These 12 words are your wallet. Anyone who has them owns your names; if you lose them, nobody — including us — can recover anything.": "Estas 12 palavras são a sua carteira. Quem as tiver possui os seus nomes; se as perder, ninguém — nem nós — consegue recuperar nada.",
"Copy phrase": "Copiar frase",
"I have written the phrase down somewhere safe and offline. I understand it cannot be reset.": "Anotei a frase num sítio seguro e offline. Compreendo que não pode ser reposta.",
"Continue →": "Continuar →",
"12 words, separated by spaces. It stays in this browser.": "12 palavras separadas por espaços. Fica neste navegador.",
"Recovery phrase": "Frase de recuperação",
"Password to encrypt it on this device": "Palavra-passe para a cifrar neste dispositivo",
"Import →": "Importar →",
"No wallet on this device": "Nenhuma carteira neste dispositivo",
"📥 Import a wallet →": "📥 Importar uma carteira →",
"🆕 Create a wallet →": "🆕 Criar uma carteira →",
"Enter your PIN": "Introduza o seu PIN",
"Use password instead": "Usar a palavra-passe",
"Unlock →": "Desbloquear →",
"PIN reset": "PIN reposto",
"3 wrong attempts — the PIN has been cleared. Enter your password to unlock and set a new PIN if you like.": "3 tentativas erradas: o PIN foi apagado. Introduza a palavra-passe para desbloquear e defina um novo PIN se quiser.",
"Continue with password →": "Continuar com palavra-passe →",
"Unlock your wallet": "Desbloqueie a sua carteira",
"Decrypts the wallet stored in this browser. After unlocking you can set a PIN so future sessions ask for 4–6 digits instead of the full password.": "Decifra a carteira guardada neste navegador. Depois de desbloquear pode definir um PIN para que as próximas sessões peçam 4–6 dígitos em vez da palavra-passe completa.",
"Password": "Palavra-passe",
"Set a PIN": "Definir um PIN",
"optional": "opcional",
"Repeat PIN": "Repita o PIN",
"Not now": "Agora não",
"Save PIN →": "Guardar PIN →",
"Fund your wallet": "Carregue a sua carteira",
"Send test coins to this address. It is yours — derived from your phrase.": "Envie moedas de teste para este endereço. É seu: derivado da sua frase.",
"checking balance…": "a verificar o saldo…",
"Preparing…": "A preparar…",
"Building your registration transaction.": "A construir a sua transação de registo.",
"One transaction. It mints the certificate to": "Uma transação. Cunha o certificado para",
"your": "o seu",
"address and pays the fees.": "endereço e paga as taxas.",
"The certificate will be minted to": "O certificado será cunhado para",
"— your key, your name. You can set where it points immediately afterwards.": "— a sua chave, o seu nome. Logo a seguir pode definir para onde aponta.",
"Register — sign & broadcast": "Registar — assinar e difundir",
"Could not prepare": "Não foi possível preparar",
"Confirm": "Confirmar",
"Beacon dust + chain fee": "Poeira do beacon + taxa de cadeia",
"(covered by wallet)": "(coberto pela carteira)",
"Minted to": "Cunhado para",
"Service fee waived on chipnet": "Taxa de serviço dispensada na chipnet",
"Approve payment": "Aprovar pagamento",
"Approve →": "Aprovar →",
"Signing in your browser and broadcasting to the chain. Do not close this tab.": "A assinar no seu navegador e a difundir para a cadeia. Não feche este separador.",
"Transaction": "Transação",
"Certificate ID": "ID do certificado",
"Operator": "Operador",
"The certificate is on the chain, held by your key. Nobody can take it back.": "O certificado está na cadeia, detido pela sua chave. Ninguém o pode tirar.",
"Owner": "Proprietário",
"Point it somewhere": "Aponte-o para algum sítio",
"Optional, and changeable any time — only your key can.": "Opcional e alterável a qualquer momento — só com a sua chave.",
"Record type": "Tipo de registo",
"A tiny site stored on the chain itself (h)": "Um site minúsculo guardado na própria cadeia (h)",
"Redirect to a web address (u)": "Redirecionar para um endereço web (u)",
"Your own server's IPv4 address (ip)": "O endereço IPv4 do seu próprio servidor (ip)",
"TLS certificate fingerprint (tls)": "Impressão digital do certificado TLS (tls)",
"Done for now": "Por agora está feito",
"Publish record": "Publicar registo",
"Publishing record": "A publicar registo",
"Update transaction": "Transação de atualização",
"Finish": "Terminar",
"My names": "Os meus nomes",
"records & holdings": "registos e posses",
"Admin panel": "Painel de administração",
"operator tools": "ferramentas do operador",
"clear this browser": "limpar este navegador",
"Unlock my wallet": "Desbloquear a minha carteira",
"one you already created on this device": "uma que já criou neste dispositivo",
"Locked wallet on this device": "Carteira bloqueada neste dispositivo",
"Unlock or pick another action": "Desbloqueie ou escolha outra ação",
"No wallet yet": "Ainda sem carteira",
"Pick how to sign in": "Escolha como entrar",
"Create a wallet": "Criar uma carteira",
"generate a fresh 12-word phrase (sign up)": "gerar uma frase nova de 12 palavras (registar-se)",
"Import a wallet": "Importar uma carteira",
"seed phrase you already have (sign in)": "uma frase-semente que já tem (entrar)",
"Cashonize / Paytaca via QR": "Cashonize / Paytaca por QR",
"The home for names on Bitcoin Cash. Register a TLD, register a name, verify anything against the chain.": "A casa dos nomes no Bitcoin Cash. Registe um TLD, registe um nome, verifique tudo contra a cadeia.",
"Product": "Produto",
"✏️ Register a name": "✏️ Registar um nome",
"🌐 Register a TLD": "🌐 Registar um TLD",
"🔑 My names portal": "🔑 O meu portal de nomes",
"🧭 Theseus browser": "🧭 Navegador Theseus",
"Learn": "Aprender",
"📚 Docs": "📚 Documentação",
"🗺 Roadmap": "🗺 Roteiro",
"🏛 The Pantheon": "🏛 O Panteão",
"🎨 Brand kit": "🎨 Kit de marca",
"Alpha": "Alfa",
"Chipnet only. You hold your own keys; verify everything against the chain.": "Só chipnet. As chaves são suas; verifique tudo contra a cadeia.",
"brand assets": "recursos de marca",
"available": "disponível",
"taken": "ocupado",
"checking…": "a verificar…",
"Register →": "Registar →",
"loading…": "a carregar…",
"(no records set)": "(sem registos)",
"on chain": "na cadeia",
"Edit": "Editar",
"tier pricing": "preço por escalões",
"(default policy — open, tier pricing)": "(política por omissão — aberta, preços por escalões)",
"Price & policy": "Preço e política",
"Register a name under": "Registar um nome sob",
"Preparing your addresses…": "A preparar os seus endereços…",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.": "Nenhum nome BCNR encontrado para esta carteira. Se acabou de registar, aguarde um minuto pela confirmação e recarregue.",
"Off-chain DNS records — free per edit": "Registos DNS fora da cadeia — grátis por edição",
"Signing…": "A assinar…",
"Saved ✓": "Guardado ✓",
"Registered ✓": "Registado ✓",
"Switch on": "Ligar",
"Switch off": "Desligar",
"Switch on: list the TLD and sell names again": "Ligar: listar o TLD e voltar a vender nomes",
"Switch off: hide the TLD, stop new registrations": "Desligar: esconder o TLD, parar novos registos",
"no owner price set — buyers pay the length tier": "sem preço do dono — os compradores pagam o escalão por comprimento",
"hidden from the public registry; no new names until you switch it on": "escondido do registo público; sem nomes novos até o ligar",
"listed in the public registry": "listado no registo público",
"label": "etiqueta",
"🔓 Unlock": "🔓 Desbloquear",
"🆕 Create": "🆕 Criar",
"📥 Import": "📥 Importar",
"Dashboard — your names on Sirius.X": "Painel — os seus nomes no Sirius.X",
"dashboard": "",
"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.": "Entre uma vez com a sua frase-semente Bitcoin Cash ou ligue uma carteira externa. Este dispositivo mantém a sessão até sair — sem palavras-passe a cada visita. As suas chaves nunca saem deste navegador.",
"Manage": "Gerir",
"Domain names": "Nomes de domínio",
"My TLD list": "Os meus TLD",
"Get more": "Mais",
"Docs": "Documentação",
"What this wallet holds on chain, and where to go next.": "O que esta carteira possui na cadeia e o que fazer a seguir.",
"↻ Refresh": "↻ Atualizar",
"Recent names": "Nomes recentes",
"The last few certificates that landed in this wallet.": "Os últimos certificados que chegaram a esta carteira.",
"Attention": "Atenção",
"Names that point nowhere yet, or have no DNS.": "Nomes que ainda não apontam para lado nenhum ou sem DNS.",
"Every BCNR name this wallet holds. Open one to manage DNS, content, redirects or transfer it.": "Todos os nomes BCNR desta carteira. Abra um para gerir DNS, conteúdo, redirecionamentos ou transferi-lo.",
"Filter names…": "Filtrar nomes…",
"Sort: name": "Ordenar: nome",
"Sort: TLD": "Ordenar: TLD",
"Sort: newest": "Ordenar: mais recentes",
"All TLDs": "Todos os TLD",
"no DNS": "sem DNS",
"DNS …": "DNS …",
"DNS needs s3": "DNS precisa de s3",
"Open site →": "Abrir site →",
"Summary": "Resumo",
"DNS records": "Registos DNS",
"Content & hosting": "Conteúdo e alojamento",
"Redirect": "Redirecionamento",
"Transfer": "Transferir",
"Export": "Exportar",
"Certificate": "Certificado",
"Where it points": "Para onde aponta",
"On-chain records decide what a resolver serves. Change them under Content & hosting.": "Os registos on-chain decidem o que um resolvedor serve. Altere-os em Conteúdo e alojamento.",
"DNS at a glance": "DNS num relance",
"Signed off-chain records for mail, verification and classic DNS interop.": "Registos assinados fora da cadeia para correio, verificação e DNS clássico.",
"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.": "Registos padrão, assinados pela sua chave e guardados num manifesto no Sia. Editar é grátis, sem transação. Resolvedores e gateway verificam a assinatura contra o detentor atual do NFT.",
"Type": "Tipo",
"Value": "Valor",
"Priority / extra": "Prioridade / extra",
"No DNS records yet. Add the first one below.": "Ainda sem registos DNS. Adicione o primeiro abaixo.",
"Priority": "Prioridade",
"Weight": "Peso",
"Port": "Porta",
"Tag": "Tag",
"+ Add": "+ Adicionar",
"Discard changes": "Descartar alterações",
"Nameservers": "Servidores de nomes",
"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.": "Os nomes BCNR não precisam de servidores de nomes — os resolvedores leem a cadeia e este manifesto diretamente. Adicione NS só se também delegar o nome em DNS clássico.",
"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.": "Registos on-chain, publicados numa transação UPD assinada (alguns cêntimos de poeira). Um campo vazio remove esse registo. Precedência para resolvedores: h, depois s3, depois p, depois ip.",
"inline HTML — served as-is at the site root (~150 bytes)": "HTML inline — servido tal como está na raiz (~150 bytes)",
"Sia bucket key, trailing slash for directories — also where DNS manifests live": "chave do bucket Sia, barra final para diretórios — também onde vivem os manifestos DNS",
"reverse proxy: full upstream URL the gateway mirrors": "proxy inverso: URL completo de origem que o gateway espelha",
"Reset": "Repor",
"Forward this name to any web address. Stored on chain as the": "Encaminhe este nome para qualquer endereço web. Guardado na cadeia como o registo",
"record; resolvers and the gateway issue the redirect. Clear it to stop forwarding.": "; resolvedores e gateway fazem o redirecionamento. Limpe para parar.",
"Destination URL": "URL de destino",
"Remove redirect": "Remover redirecionamento",
"Save redirect →": "Guardar redirecionamento →",
"Transfer ownership": "Transferir a propriedade",
"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.": "Move o certificado do nome para outro endereço Bitcoin Cash numa transação. Os registos mantêm-se. O novo detentor controla o nome a partir desse momento — não é reversível daqui.",
"Recipient address": "Endereço do destinatário",
"I understand this hands the name to that address permanently.": "Compreendo que isto entrega o nome a esse endereço permanentemente.",
"Transfer name →": "Transferir nome →",
"Download this name's DNS as a BIND-style zone file, or its full record set as JSON, for backups or importing elsewhere.": "Transfira o DNS deste nome como ficheiro de zona tipo BIND, ou todos os registos como JSON, para cópias ou importação noutro sítio.",
"⬇ Zone file (.txt)": "⬇ Ficheiro de zona (.txt)",
"⬇ Records (.json)": "⬇ Registos (.json)",
"Copy DNS manifest": "Copiar manifesto DNS",
"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.": "Todos os NFT de registo de TLD desta carteira. Defina o preço de cada nome sob um TLD, ligue-o ou desligue-o (desligado = privado: só você regista) e afine a política. Cada alteração é um TUPD assinado na cadeia; recebe 90 % de cada venda.",
"Registry": "Registo",
"Register a name under this TLD": "Registar um nome sob este TLD",
"Works whether the TLD is on or off. As the owner you pay only the platform's 10% share.": "Funciona com o TLD ligado ou desligado. Como dono paga apenas a parte de 10 % da plataforma.",
"Names registered under this TLD": "Nomes registados sob este TLD",
"Everyone's registrations, from the public registry.": "Os registos de todos, do registo público.",
"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.": "Os TLD são NFT de registo no beacon de TLD da chipnet. As cunhagens públicas pagam uma taxa que financia o registo. A chipnet usa uma taxa provisória; na mainnet um oráculo real define o preço pelo comprimento.",
"Faucet 2 →": "Torneira 2 →",
"Balance": "Saldo",
"Spendable": "Disponível",
"UTXOs": "UTXOs",
"Watched addresses": "Endereços monitorizados",
"Session and security choices for this browser. Nothing here changes what is on chain.": "Opções de sessão e segurança para este navegador. Nada aqui altera o que está na cadeia.",
"Session": "Sessão",
"Stay signed in on this device": "Manter sessão neste dispositivo",
"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.": "A sua frase de recuperação fica cifrada com uma chave que este navegador guarda e não consegue exportar. As próximas visitas abrem o painel de imediato. Desligue para pedir palavra-passe ou PIN de cada vez.",
"Ask for PIN before payments": "Pedir PIN antes de pagamentos",
"Adds a PIN prompt when registering a name or TLD. Off by default so signed-in sessions run uninterrupted.": "Adiciona um pedido de PIN ao registar um nome ou TLD. Desligado por omissão para que as sessões corram sem interrupções.",
"Set / change PIN": "Definir / alterar PIN",
"Remove PIN": "Remover PIN",
"Reading & language": "Leitura e idioma",
"Font pill and language picker live in the top bar; both are remembered per browser.": "O seletor de tipo de letra e o de idioma estão na barra superior; ambos são lembrados por navegador.",
"This device": "Este dispositivo",
"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.": "Sair mantém a carteira cifrada neste dispositivo para a desbloquear mais tarde. Esquecer remove-a por completo — precisará da sua frase de recuperação.",
"Forget wallet on this device": "Esquecer a carteira neste dispositivo",
"4–6 digits. Encrypts your recovery phrase under this PIN on this device. Three wrong PINs clear it and fall back to your password.": "4–6 dígitos. Cifra a sua frase de recuperação com este PIN neste dispositivo. Três PIN errados apagam-no e volta à palavra-passe.",
"No names yet.": "Ainda sem nomes.",
"Register your first one →": "Registe o primeiro →",
"Everything points somewhere and has DNS. Nice.": "Tudo aponta para algum lado e tem DNS. Ótimo.",
"Nothing matches that filter.": "Nada corresponde a esse filtro.",
"Status": "Estado",
"point it somewhere →": "aponte-o para algum lado →",
"Add some →": "Adicione alguns →",
"Register one →": "Registe um →",
"yours": "seu",
"Copied": "Copiado",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and refresh.": "Nenhum nome BCNR encontrado para esta carteira. Se acabou de registar, aguarde um minuto e atualize.",
"Remove": "Remover",
"Transferring…": "A transferir…",
"Transferred ✓": "Transferido ✓",
"off · private": "desligado · privado",
"on · public": "ligado · público",
"Signing you in…": "A iniciar sessão…",
"Restoring your session on this device.": "A restaurar a sua sessão neste dispositivo.",
"Dashboard": "Painel",
"names, TLDs, DNS, settings": "nomes, TLD, DNS, definições",
"site on chain": "site na cadeia",
"site on Sia": "site no Sia",
"reverse proxy": "proxy inverso",
"own server": "servidor próprio",
"redirect": "redirecionamento",
"not pointed": "não aponta",
"points nowhere yet": "ainda não aponta para lado nenhum",
"no DNS records": "sem registos DNS",
"DNS needs an s3 pointer": "DNS precisa de um registo s3",
"block": "bloco",
"Web-Builder": "Web-Builder",
"My TLDs": "Os meus TLD",
"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.": "O Sirius Studio constrói um site para qualquer nome que tenha: arraste blocos, edite texto, publique. As páginas vivem na pasta do nome no Sia e o nome aponta para elas — sem alojamento, sem renovação.",
"Session, security and wallet details for this browser. Nothing here changes what is on chain.": "Sessão, segurança e dados da carteira para este navegador. Nada aqui altera o que está na cadeia.",
"Reading, language & help": "Leitura, idioma e ajuda",
"Font pill and language picker live in the top bar; both are remembered per browser. The technical documentation is at": "O seletor de tipo de letra e o de idioma estão na barra superior; ambos são lembrados por navegador. A documentação técnica está em",
"Start from a template": "Começar de um modelo",
"Preview the exported page in a new tab": "Pré-visualizar a página exportada num novo separador",
"Sirius Studio — build the site for your name": "Sirius Studio — construa o site do seu nome",
"Templates…": "Modelos…",
"Landing page": "Página de destino",
"Profile / link hub": "Perfil / ligações",
"Business one-pager": "Negócio numa página",
"Blank page": "Página em branco",
"Preview": "Pré-visualizar",
"Save draft": "Guardar rascunho",
"Publish to Sia →": "Publicar no Sia →",
"View site →": "Ver site →",
"Sign in first": "Entre primeiro",
"Sirius Studio publishes with your wallet's key. Sign in on the dashboard, then come back to this name.": "O Sirius Studio publica com a chave da sua carteira. Entre no painel e volte a este nome.",
"Open the dashboard →": "Abrir o painel →",
"Build the site for": "Construa o site de",
"Pick a starting point. Everything is editable — drag blocks in from the right, click any text to change it. Nothing leaves your browser until you press Publish; then the page is stored on Sia and the name points at it.": "Escolha um ponto de partida. Tudo é editável — arraste blocos da direita, clique em qualquer texto para o mudar. Nada sai do seu navegador até carregar em Publicar; depois a página fica no Sia e o nome aponta para ela.",
"Hero, three features, call to action.": "Cabeçalho, três vantagens, apelo à ação.",
"Avatar, bio and a stack of links.": "Avatar, biografia e uma lista de ligações.",
"About, services, hours, contact.": "Sobre, serviços, horário, contacto.",
"Start from nothing.": "Começar do zero.",
"Back to dashboard": "Voltar ao painel",
"Publish": "Publicar",
"The page and its assets are uploaded to the name's folder on Sia, signed with your key. If the name does not point at that folder yet, one on-chain update sets it (a few cents of chain dust).": "A página e os seus ficheiros são enviados para a pasta do nome no Sia, assinados com a sua chave. Se o nome ainda não apontar para lá, uma atualização on-chain trata disso (alguns cêntimos de poeira).",
"Needs attention": "Precisa de atenção",
"View →": "Ver →",
"Edit in Studio": "Editar no Studio",
"Open in Studio": "Abrir no Studio",
"built with Studio": "feito com Studio",
"site on Sia (external)": "site no Sia (externo)",
"inline HTML": "HTML inline",
"no site yet": "ainda sem site",
"Pick a name to build or edit its site.": "Escolha um nome para criar ou editar o seu site.",
"You need a name first.": "Precisa primeiro de um nome.",
"— then come back here to build its site.": "— depois volte aqui para construir o seu site.",
"New site": "Novo site",
"Not signed in": "Sem sessão",
"Loading name…": "A carregar nome…",
"Published": "Publicado",
"Publish failed": "Falha ao publicar",
"Template loaded — edit, then Publish": "Modelo carregado — edite e depois publique",
"Draft saved on Sia": "Rascunho guardado no Sia",
"Saving draft…": "A guardar rascunho…",
"Copy address": "Copiar endereço",
"receive coins or names here": "receba moedas ou nomes aqui",
"Copy token address": "Copiar endereço de tokens",
"where name certificates are minted": "onde os certificados de nomes são cunhados",
"Get test coins": "Obter moedas de teste",
"chipnet faucet": "torneira chipnet",
"Wallet settings": "Definições da carteira",
"session, PIN, forget device": "sessão, PIN, esquecer dispositivo",
"Holdings": "Posses",
"open the dashboard to load": "abra o painel para carregar",
"🛒 Market": "🛒 Mercado",
"🛒 Names for sale": "🛒 Nomes à venda",
"Market — names for sale on Sirius.X": "Mercado — nomes à venda no Sirius.X",
"for sale": "à venda",
"Every sale is a single Bitcoin Cash transaction. The seller signed an offer that pays them only when the certificate moves to you — you add your coins, sign, broadcast. No escrow, no middleman, no way for either side to cheat.": "Cada venda é uma única transação Bitcoin Cash. O vendedor assinou uma oferta que só lhe paga quando o certificado passa para si — adiciona as suas moedas, assina, transmite. Sem custódia, sem intermediários, sem forma de alguém fazer batota.",
"Sort: price": "Ordenar: preço",
"Loading listings…": "A carregar anúncios…",
"Selling a name?": "Vai vender um nome?",
"Open it in your": "Abra-o no seu",
", choose": ", escolha",
"Sell": "Vender",
", set a price. The listing is a signed offer stored by the gateway; cancelling it moves your certificate once so the old offer can never be used.": ", defina um preço. O anúncio é uma oferta assinada guardada pelo gateway; cancelá-lo move o seu certificado uma vez para que a oferta antiga nunca possa ser usada.",
"One transaction: your coins pay the seller, the certificate lands in your wallet, and the registry is told about the new owner. Records stay as they are — you can change them in the dashboard right after.": "Uma transação: as suas moedas pagam ao vendedor, o certificado chega à sua carteira e o registo fica a saber do novo dono. Os registos ficam como estão — pode alterá-los no painel logo a seguir.",
"Sign in to buy →": "Iniciar sessão para comprar →",
"Buy — sign & broadcast": "Comprar — assinar e transmitir",
"Buy →": "Comprar →",
"Nothing is for sale right now. Owners list names from their dashboard.": "De momento não há nada à venda. Os donos anunciam nomes a partir do seu painel.",
"Sell this name": "Vender este nome",
"You sign an offer once: \"whoever pays me this price gets the certificate\". The offer is stored by the gateway and shown on the": "Assina uma oferta uma vez: «quem me pagar este preço fica com o certificado». O gateway guarda a oferta e mostra-a no",
"market": "mercado",
". 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.": ". Um comprador completa-a numa transação — recebe na mesma transação que move o nome, ou não recebe de todo. Sem custódia, nada em que confiar.",
"Checking the market…": "A verificar o mercado…",
"Price (USD)": "Preço (USD)",
"Price (sat)": "Preço (sat)",
"List for sale →": "Pôr à venda →",
"Cancel listing →": "Cancelar anúncio →",
"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.": "Cancelar retira a oferta do mercado e move o seu certificado uma vez (uma atualização vazia, alguns cêntimos), para que a oferta assinada nunca possa ser concluída mais tarde.",
"Not for sale. Set a price to list it.": "Não está à venda. Defina um preço para o anunciar.",
"This name is listed on the market.": "Este nome está anunciado no mercado.",
"Pending approvals": "Aprovações pendentes",
"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.": "Registos sob este TLD que aguardam a sua coassinatura. Aprovar assina o seu certificado de TLD na transação do comprador e transmite-a; o certificado volta para si na mesma transação. Nada pode ser registado sob um TLD de coassinatura ou privado sem este passo.",
"No requests waiting.": "Sem pedidos em espera.",
"awaiting you": "à sua espera",
"Approve & broadcast": "Aprovar e transmitir",
"Decline": "Recusar",
"Request approval — sign": "Pedir aprovação — assinar",
"Withdraw request": "Retirar pedido",
"Request declined": "Pedido recusado",
"Open dashboard →": "Abrir painel →",
"incl.": "incl.",
"sat unconfirmed · spendable now": "sat por confirmar · disponíveis já",
"Nothing is for sale right now": "De momento não há nada à venda",
"Names go on sale when their owners list them from the dashboard. Have one to sell, or want a fresh one instead?": "Os nomes são postos à venda quando os donos os anunciam a partir do painel. Tem um para vender, ou prefere um novo?",
"Sell a name from your dashboard →": "Vender um nome a partir do painel →",
"Register a new name": "Registar um nome novo",
"↓ Import live site": "↓ Importar o site em produção",
"Import the live site": "Importar o site em produção",
"✨ Assistant": "✨ Assistente",
"Runs on your own device. Nothing you write or build is sent to Sirius.X or to any AI vendor.": "Corre no seu próprio dispositivo. Nada do que escreve ou constrói é enviado para o Sirius.X ou para qualquer fornecedor de IA.",
"Runs on": "Corre em",
"This browser — your GPU, private": "Este navegador — a sua GPU, privado",
"Local endpoint — Ollama, LM Studio": "Servidor local — Ollama, LM Studio",
"Model": "Modelo",
"Downloads once, then stays in the browser cache. Needs WebGPU (current Chrome, Edge, Firefox, Safari).": "Descarrega uma vez e fica na cache do navegador. Precisa de WebGPU (Chrome, Edge, Firefox, Safari atuais).",
"Load model": "Carregar modelo",
"Endpoint": "Endpoint",
"Connect": "Ligar",
"What do you want?": "O que pretende?",
"Make a section": "Criar uma secção",
"Rewrite selected text": "Reescrever o texto selecionado",
"Restyle selection": "Restilizar a seleção",
"Nothing selected": "Nada selecionado",
"Undo last change": "Anular a última alteração",
"Stop": "Parar"
}

612
i18n/ru.json Normal file
View file

@ -0,0 +1,612 @@
{
"Sirius.X — the home for names on Bitcoin Cash": "Sirius.X — дом для имён на Bitcoin Cash",
"Portal — your names on Sirius.X": "Портал — ваши имена на Sirius.X",
"Register a TLD — Sirius.X": "Регистрация TLD — Sirius.X",
"Try it": "Попробовать",
"✏️ Register": "✏️ Регистрация",
"🌐 TLD": "🌐 TLD",
"🔑 Sign in": "🔑 Войти",
"type a name — e.g. hello": "введите имя — например, hello",
"Search a name across every BCNR TLD": "Поиск имени во всех TLD BCNR",
"Names on the": "Доменные имена в",
"chain": "блокчейне",
"Sirius.X is the entry point for BCNR — Bitcoin Cash Name Registry. Register a top-level domain, register a name under one, look up records, verify anything against the chain.": "Sirius.X — точка входа в BCNR, реестр имён Bitcoin Cash. Зарегистрируйте домен верхнего уровня, зарегистрируйте имя под ним, смотрите записи и проверяйте всё по блокчейну.",
"One search checks the label across every TLD in the registry. Available names appear first.": "Один поиск проверяет метку во всех TLD реестра. Свободные имена показываются первыми.",
"Or browse what you can do →": "Или посмотрите, что можно сделать →",
"Read the docs": "Читать документацию",
"Three things you can do right now. The registrar and TLD-registry UIs live at silentmode.st today; Sirius.X is the canonical home and will consolidate them here.": "Три вещи, которые можно сделать прямо сейчас. Регистратор и реестр TLD сегодня живут на silentmode.st; Sirius.X — их основной дом, и они переедут сюда.",
"Register a name": "Зарегистрировать имя",
"Pick a label, search across every TLD in the registry at once, mint the name certificate straight into your own wallet. No yearly renewal.": "Выберите метку, найдите её сразу во всех TLD реестра и выпустите сертификат имени прямо в свой кошелёк. Без ежегодного продления.",
"≈ 10,000 sat service fee · 1,300 sat chain dust · < 1 ¢": "≈ 10 000 сат сервисный сбор · 1 300 сат «пыль» блокчейна · < 1 ¢",
"Chipnet placeholder. 90 % of the service fee flows to the TLD owner, 10 % to the platform.": "Заглушка для chipnet. 90 % сервисного сбора идёт владельцу TLD, 10 % — платформе.",
"Search a name →": "Найти имя →",
"Register a TLD": "Зарегистрировать TLD",
"A TLD is itself a certificate on the chain. Anyone can mint one — you become the registry operator for every second-level name under it, and earn 90 % of the fee on every name registered under it. Renewals are per-TLD policy set by the owner.": "TLD — это тоже сертификат в блокчейне. Выпустить его может любой: вы становитесь оператором реестра для всех имён второго уровня под ним и получаете 90 % сбора с каждого зарегистрированного имени. Продление — политика каждого TLD, которую задаёт владелец.",
"≈ 1,250,000 sat service fee (≈ $5) · 1,300 sat chain dust": "≈ 1 250 000 сат сервисный сбор (≈ $5) · 1 300 сат «пыль» блокчейна",
"Chipnet placeholder rate — mainnet will price by label length via an on-chain oracle.": "Курс-заглушка для chipnet — в mainnet цена будет зависеть от длины метки через ончейн-оракул.",
"Search a TLD →": "Найти TLD →",
"Operator admin →": "Панель оператора →",
"Look up & verify": "Найти и проверить",
"Resolve any BCNR name, compare records across mirrors, and check the TLD registry snapshot against the chain. Everything is publicly verifiable.": "Разрешите любое имя BCNR, сравните записи на зеркалах и сверьте снимок реестра TLD с блокчейном. Всё проверяется публично.",
"How to verify →": "Как проверить →",
"🔑 Sign in — your names portal": "🔑 Войти — портал ваших имён",
"Import your seed phrase or connect a wallet (Cashonize / Paytaca via WizardConnect) to see every name you own, review records, and update them. Your keys never leave your browser.": "Импортируйте seed-фразу или подключите кошелёк (Cashonize / Paytaca через WizardConnect), чтобы увидеть все свои имена, просмотреть и обновить записи. Ключи никогда не покидают ваш браузер.",
"Open the portal →": "Открыть портал →",
"🧭 Theseus Navigator": "🧭 Theseus Navigator",
"The browser that speaks BCNR natively. Open": "Браузер, который понимает BCNR нативно. Откройте",
"in the address bar — it just resolves. TLS verified against on-chain fingerprints, no OS trust-store install.": "в адресной строке — и оно просто разрешается. TLS сверяется с отпечатками в блокчейне, ничего не нужно ставить в хранилище сертификатов ОС.",
"Download →": "Скачать →",
"Documentation": "Документация",
"The full docs — TLD registry model, record types, resolver & gateway paths, mainnet pricing, verification, and the operator runbook pointer — live on their own page so they can grow without cluttering the landing.": "Полная документация — модель реестра TLD, типы записей, пути резолвера и шлюза, цены в mainnet, проверка и ссылка на runbook оператора — живёт на отдельной странице, чтобы расти, не загромождая главную.",
"📚 Open the docs →": "📚 Открыть документацию →",
"Current TLD list": "Текущий список TLD",
"Propose a new TLD": "Предложить новый TLD",
"The per-TLD registry means minting a TLD is a real, paid action — not a namespace land-grab. During the alpha, all TLD mints are operator-signed. To propose a TLD, get in touch via the channels below. The design (mainnet) adds an on-chain covenant with countersignature + tiered USD price floors: 1-char $100k, 2-char $50k, 3-char $15k, 4-char $5k, 5–8-char $1k, 9+-char $250; one-time payment (not annual). See the design doc for the full model.": "Реестр по каждому TLD означает, что выпуск TLD — реальное платное действие, а не захват пространства имён. Во время альфы все выпуски TLD подписывает оператор. Чтобы предложить TLD, свяжитесь через каналы ниже. Дизайн (mainnet) добавляет ончейн-ковенант с контрподписью и ступенчатые минимальные цены в USD: 1 символ — $100k, 2 — $50k, 3 — $15k, 4 — $5k, 5–8 — $1k, 9+ — $250; разовый платёж (не ежегодный). Полная модель — в дизайн-документе.",
"ICANN-adjacent TLDs are not open for public mint.": "TLD, совпадающие с ICANN, не открыты для публичного выпуска.",
"A TLD registry is only useful if it does not immediately collapse into an ICANN-shadow — the mainnet covenant enforces this; on chipnet the operator's countersignature is the gate.": "Реестр TLD полезен, только если не превращается сразу в тень ICANN — в mainnet это обеспечивает ковенант; в chipnet барьером служит контрподпись оператора.",
"The pantheon": "Пантеон",
"Sirius.x is one of seven sibling": "Sirius.x — одно из семи родственных имён",
"names — the Silent Mode pantheon. Each project is its own on-chain certificate; each site is reachable through any BCNR resolver, plus the silentmode.st gateway for browsers without one.": "— пантеон Silent Mode. Каждый проект — отдельный ончейн-сертификат; каждый сайт доступен через любой резолвер BCNR, а также через шлюз silentmode.st для браузеров без резолвера.",
"⛓️ Silentmode.X": "⛓️ Silentmode.X",
"The project umbrella. Redirects to": "Зонтик проекта. Перенаправляет на",
"where every pillar has its own landing page + download hub.": "где у каждого направления своя страница и загрузки.",
"Open →": "Открыть →",
"⭐ Sirius.X": "⭐ Sirius.X",
"you're here": "вы здесь",
"Names on Bitcoin Cash — register, resolve, verify, manage. This site.": "Имена на Bitcoin Cash — регистрация, разрешение, проверка, управление. Этот сайт.",
"Home →": "Главная →",
"🧭 Theseus.X": "🧭 Theseus.X",
"The browser that speaks BCNR natively — Chromium build with the resolver baked in, no OS-level daemon or root-store install.": "Браузер, нативно понимающий BCNR — сборка Chromium со встроенным резолвером, без системного демона и корневого сертификата.",
"Learn more →": "Подробнее →",
"🔥 Hephaestus.X": "🔥 Hephaestus.X",
"The forge. Forgejo instance for the ecosystem's git repos, backed by BCH wallet auth. Sirius's own source lives here.": "Кузница. Экземпляр Forgejo для git-репозиториев экосистемы со входом через BCH-кошелёк. Здесь живёт исходный код Sirius.",
"🔮 Prometheus.X": "🔮 Prometheus.X",
"Fire from the chain. The project's foresight / experimentation layer. Redirects to": "Огонь из блокчейна. Слой предвидения и экспериментов проекта. Перенаправляет на",
"today.": "(сегодня).",
"☀️ Helios.X": "☀️ Helios.X",
"The public gaze. Analytics, dashboards, transparency reports. Redirects to": "Публичный взгляд. Аналитика, дашборды, отчёты о прозрачности. Перенаправляет на",
"✉️ Hermes.X": "✉️ Hermes.X",
"Messenger. Nostr-based messaging bound to a BCNR name via the": "Мессенджер. Обмен сообщениями на Nostr, привязанный к имени BCNR через записи",
"records. Redirects to": ". Перенаправляет на",
"What's coming": "Что дальше",
"Sirius.X consolidates docs and registration today; three larger pieces are on the roadmap.": "Сегодня Sirius.X объединяет документацию и регистрацию; в планах три крупных блока.",
"Wallet & name portal": "Портал кошелька и имён",
"next": "следующее",
"Sign in with your Bitcoin Cash wallet, see every name you own, edit records inline, mint or renew from one place. Same self-custody as today — the portal never handles your keys.": "Войдите с кошельком Bitcoin Cash, увидьте все свои имена, редактируйте записи на месте, выпускайте и продлевайте из одного места. То же самостоятельное хранение, что и сейчас — портал никогда не касается ваших ключей.",
"Sirius Studio": "Sirius Studio",
"planned": "в планах",
"An in-browser site editor for names you already own — the WordPress / Tilda / Wix pattern, but the whole site persists to Sia and the name's": "Редактор сайтов в браузере для имён, которыми вы уже владеете — по образцу WordPress / Tilda / Wix, но весь сайт хранится в Sia, а запись",
"record updates on save. Sites live where the name says they live.": "имени обновляется при сохранении. Сайты живут там, куда указывает имя.",
"Decentralized git remote": "Децентрализованный git-remote",
"MVP live": "MVP работает",
"The Silent Mode repo is served as a bare git tree over dumb-HTTP from the VPS. Clone it with any git client, no login. Forgejo + Sia sync for a proper decentralized backend is the next track.": "Репозиторий Silent Mode отдаётся как bare git-дерево по dumb-HTTP с VPS. Клонируйте любым git-клиентом, без входа. Следующий шаг — Forgejo + синхронизация с Sia как полноценный децентрализованный бэкенд.",
"One-shot snapshot as a downloadable git bundle (works when dumb-HTTP is blocked):": "Разовый снимок в виде загружаемого git-bundle (работает, когда dumb-HTTP заблокирован):",
"Verify this page against the chain": "Проверьте эту страницу по блокчейну",
"You do not have to trust that": "Вам не нужно верить, что",
"is served by anyone specific. The name's certificate is on the Bitcoin Cash chain; the records point to Sia; every path is independently checkable.": "отдаёт кто-то конкретный. Сертификат имени лежит в блокчейне Bitcoin Cash; записи указывают на Sia; каждый путь проверяется независимо.",
"1. Confirm the certificate exists on chain": "1. Убедитесь, что сертификат есть в блокчейне",
"2. Fetch the TLD-registry snapshot from Nostr": "2. Получите снимок реестра TLD из Nostr",
"The operator-signed snapshot of the TLD list is published as a Nostr replaceable event. Any relay carries it; the event's content field carries the current snapshot root.": "Подписанный оператором снимок списка TLD публикуется как заменяемое событие Nostr. Его несёт любой релей; поле content события содержит текущий корень снимка.",
"Kind / d-tag": "Kind / d-тег",
"Pubkey (x-only, hex)": "Публичный ключ (x-only, hex)",
"Relays": "Релеи",
"3. Reach this site via more than one route": "3. Откройте этот сайт более чем одним путём",
"The same content should be served from at least two independent paths. If one mirror is unavailable, the others still work. If two mirrors disagree, the on-chain record is the tiebreaker.": "Одно и то же содержимое должно отдаваться минимум по двум независимым путям. Если одно зеркало недоступно, работают остальные. Если два зеркала расходятся, решает ончейн-запись.",
"Via any BCNR resolver:": "Через любой резолвер BCNR:",
"(requires the local root CA)": "(нужен локальный корневой CA)",
"Via the public gateway:": "Через публичный шлюз:",
"Via silentmode.st mirror:": "Через зеркало silentmode.st:",
"Direct from Sia (content-addressed): the": "Напрямую из Sia (адресация по содержимому): запись",
"record on": "на",
"names the exact bucket key": "называет точный ключ бакета",
"Register a": "Зарегистрируйте",
"A TLD is a certificate on the Bitcoin Cash chain. You mint it, you own it — any second-level name registered under it lives in your TLD's registry. One BCH transaction, no ICANN. Renewals? Your TLD, your policy.": "TLD — это сертификат в блокчейне Bitcoin Cash. Вы выпускаете его, вы им владеете — любое имя второго уровня под ним живёт в реестре вашего TLD. Одна транзакция BCH, никакого ICANN. Продление? Ваш TLD — ваши правила.",
"Search a TLD": "Найти TLD",
"Type a label (a–z, 0–9, hyphen; up to 16 chars). Available TLDs get a Register button that opens the shared wallet-choice modal — the same flow name registration uses. As TLD owner you earn": "Введите метку (a–z, 0–9, дефис; до 16 символов). У свободных TLD появляется кнопка регистрации, открывающая общее окно выбора кошелька — тот же процесс, что и при регистрации имени. Как владелец TLD вы получаете",
"of every name registered under your TLD. Renewals are your call — set them per TLD, or don't.": "с каждого имени, зарегистрированного под вашим TLD. Продление — ваше решение: задайте его для TLD или не задавайте.",
"Register minting to your token address; you become the registry operator.": "Регистрация выпускает сертификат на ваш токен-адрес; вы становитесь оператором реестра.",
"Registered TLDs": "Зарегистрированные TLD",
"Fetched from the on-chain TLD registry via the public gateway. Refresh the page for the latest.": "Получено из ончейн-реестра TLD через публичный шлюз. Обновите страницу для актуальных данных.",
"Loading…": "Загрузка…",
"Mint price": "Цена выпуска",
"Category": "Категория",
"Portal sections": "Разделы портала",
"Your": "Ваш",
"names": "портал",
"portal": "имён",
"Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see every BCNR name your wallet holds. Your keys never leave this browser tab.": "Войдите с seed-фразой Bitcoin Cash или подключите внешний кошелёк, чтобы увидеть все имена BCNR, которые он держит. Ключи никогда не покидают эту вкладку браузера.",
"Sign in or create a wallet": "Войти или создать кошелёк",
"The same wallet that will hold your names does the signing. Pick a tab — everything happens on this page; keys never leave your browser.": "Подписывает тот же кошелёк, который будет держать ваши имена. Выберите вкладку — всё происходит на этой странице; ключи не покидают браузер.",
"Overview": "Обзор",
"Names": "Имена",
"TLDs": "TLD",
"Wallet": "Кошелёк",
"Settings": "Настройки",
"A snapshot of what this wallet holds on chain.": "Снимок того, что этот кошелёк держит в блокчейне.",
"Names held": "Имён во владении",
"CashTokens NFT certificates": "NFT-сертификаты CashTokens",
"TLDs owned": "TLD во владении",
"Per-TLD registry NFTs": "NFT реестра по каждому TLD",
"Wallet balance": "Баланс кошелька",
"chipnet sats": "сат chipnet",
"Chain height": "Высота блокчейна",
"Last seen block": "Последний блок",
"+ Register a name": "+ Зарегистрировать имя",
"+ Register a TLD": "+ Зарегистрировать TLD",
"Names you hold": "Ваши имена",
"Every BCNR name your wallet's addresses currently hold a CashTokens NFT for. Edit records inline to publish an on-chain UPD.": "Все имена BCNR, для которых адреса вашего кошелька сейчас держат NFT CashTokens. Редактируйте записи на месте, чтобы опубликовать ончейн-UPD.",
"Loading names from the chain…": "Загружаем имена из блокчейна…",
"TLDs you own": "Ваши TLD",
"Every per-TLD registry NFT held by this wallet. Set the": "Все NFT реестра TLD в этом кошельке. Задайте",
"price": "цену",
"every name under your TLD sells for, switch the TLD": "каждого имени под вашим TLD, включайте и выключайте TLD",
"on or off": "в публичном реестре",
"in the public registry (off = a": "(выключен =",
"private TLD": "приватный TLD",
": nobody else can buy names under it, you still can from here), and tune policy —": ": никто другой не может купить под ним имя, а вы можете отсюда) и настраивайте политику —",
"fee": "сбор",
"min length": "минимальная длина",
"reserved labels": "зарезервированные метки",
"renewal period": "период продления",
". Every change is one signed TUPD on chain; you receive 90% of each sale.": ". Каждое изменение — один подписанный TUPD в блокчейне; вы получаете 90 % с каждой продажи.",
"Loading TLDs from the chain…": "Загружаем TLD из блокчейна…",
"Register a new TLD": "Зарегистрировать новый TLD",
"TLDs are per-registry NFTs on the chipnet TLD beacon. Public mints go through a service-fee output to fund the registry. Chipnet uses a placeholder rate; mainnet will price by label length via a real oracle.": "TLD — это NFT реестра на TLD-маяке chipnet. Публичные выпуски платят сервисный сбор, финансирующий реестр. В chipnet курс-заглушка; в mainnet цену по длине метки задаст настоящий оракул.",
"Label": "Метка",
"1–16 chars, [a-z0-9-]": "1–16 символов, [a-z0-9-]",
"Service fee (USD)": "Сервисный сбор (USD)",
"chipnet test rate": "тестовый курс chipnet",
"sats · rate": "сат · курс",
"sats/USD": "сат/USD",
"Check availability": "Проверить доступность",
"Register (~0 sats)": "Зарегистрировать (~0 сат)",
"Your addresses and current balance. Keys stay in this browser.": "Ваши адреса и текущий баланс. Ключи остаются в этом браузере.",
"Receive address": "Адрес для получения",
"Token address": "Токен-адрес",
"holds your name certificates": "держит сертификаты ваших имён",
"Faucet →": "Кран →",
"Reader preferences live per-browser; wallet changes require a signature.": "Настройки чтения хранятся в браузере; изменения кошелька требуют подписи.",
"Reading font": "Шрифт для чтения",
"Fraunces (Silent Mode family) or Ubuntu (Bitcoin Cash brand font). The pill lives in the top nav.": "Fraunces (семейство Silent Mode) или Ubuntu (фирменный шрифт Bitcoin Cash). Переключатель — в верхней навигации.",
"Session PIN": "PIN сессии",
"PIN unlocks the wallet without re-typing your password. Wipes after 3 wrong attempts.": "PIN разблокирует кошелёк без повторного ввода пароля. Стирается после 3 неверных попыток.",
"Sign out": "Выйти",
"Clears the signed-in state in this browser. Your on-chain names are unaffected.": "Сбрасывает состояние входа в этом браузере. Ваши имена в блокчейне не затрагиваются.",
"Edit records. Only your key can sign this UPD; the transaction fee is a few cents in chain fees plus the beacon dust. Leave a field blank to omit that record.": "Редактирование записей. Подписать этот UPD может только ваш ключ; комиссия — несколько центов за транзакцию плюс «пыль» маяка. Оставьте поле пустым, чтобы не задавать запись.",
"inline HTML — served as-is at the site root": "встроенный HTML — отдаётся как есть в корне сайта",
"Sia bucket key, trailing slash for directories": "ключ бакета Sia, слеш в конце для каталогов",
"IPv4 that serves this name over Host header": "IPv4, который отдаёт это имя по заголовку Host",
"SHA-256 of your leaf cert — chain-pinned TLS trust": "SHA-256 вашего конечного сертификата — TLS-доверие, закреплённое в блокчейне",
"redirect target": "цель перенаправления",
"payload:": "полезная нагрузка:",
"bytes": "байт",
"Cancel": "Отмена",
"Save records →": "Сохранить записи →",
"DNS records for": "DNS-записи для",
"DNS-style records live in a signed manifest on Sia — not on chain.": "DNS-записи живут в подписанном манифесте на Sia — не в блокчейне.",
"Free per edit": "Бесплатно за каждое изменение",
", no size cap. The signature proves you own the name; the gateway rejects anything not signed by the current NFT holder. See": ", без ограничения размера. Подпись доказывает, что имя ваше; шлюз отклоняет всё, что не подписано текущим держателем NFT. См.",
"docs": "документацию",
"IPv4 addresses, one per line": "адреса IPv4, по одному в строке",
"IPv6 addresses, one per line": "адреса IPv6, по одному в строке",
"one string per line (SPF, DKIM, verification tokens…)": "по одной строке (SPF, DKIM, токены подтверждения…)",
"one target host, or blank": "один целевой хост или пусто",
"nameservers, one per line": "серверы имён, по одному в строке",
"Sign & publish →": "Подписать и опубликовать →",
"Policy for": "Политика для",
"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).": "Задайте политику для имён под этим TLD. Подписать этот TUPD может только ваш ключ; комиссия — несколько центов «пыли». Оставьте поле пустым, чтобы не задавать правило (по умолчанию — открытая политика, ступенчатые цены).",
"USD per name — flat, shown to every buyer; blank = length tiers. You receive 90% of each sale.": "USD за имя — фиксированно, видно каждому покупателю; пусто = ступени по длине. Вы получаете 90 % с каждой продажи.",
"listing": "листинг",
"off hides the TLD from search and blocks new registrations until you switch it back on": "«выкл» скрывает TLD из поиска и блокирует новые регистрации, пока вы снова его не включите",
"On — listed, names for sale": "Вкл — в списке, имена продаются",
"Off — hidden, not for sale": "Выкл — скрыт, не продаётся",
"reject names shorter than N chars": "отклонять имена короче N символов",
"service fee owner takes, in basis points (500 = 5%)": "доля владельца в сервисном сборе, в базисных пунктах (500 = 5 %)",
"open · frozen · reserved-only": "open · frozen · reserved-only",
"space-separated labels only owner can mint": "метки через пробел, которые может выпустить только владелец",
"days between renewals, 0 = never expire": "дней между продлениями, 0 = никогда не истекает",
"renewal price in sats, 0 = free": "цена продления в сатоши, 0 = бесплатно",
"where the TLD's own landing lives": "где живёт собственная страница TLD",
"Save policy →": "Сохранить политику →",
"Signed in": "Вы вошли",
"You are signed in as": "Вы вошли как",
"Done": "Готово",
"Close": "Закрыть",
"Unlock my browser wallet": "Разблокировать кошелёк браузера",
"You already created one on this device.": "Вы уже создали его на этом устройстве.",
"Create a new wallet": "Создать новый кошелёк",
"easiest": "проще всего",
"Made here in your browser. You get a recovery phrase to write down — it is the only key.": "Создаётся прямо в браузере. Вы получите фразу восстановления, которую нужно записать — это единственный ключ.",
"Import a recovery phrase": "Импортировать фразу восстановления",
"Restore a wallet you already have, from its 12-word phrase.": "Восстановите уже существующий кошелёк по его фразе из 12 слов.",
"Connect a wallet — WizardConnect": "Подключить кошелёк — WizardConnect",
"most private": "самый приватный",
"Cashonize 0.9+ or Paytaca. Encrypted end-to-end over Nostr; the relay sees only ciphertext. Your keys never leave your wallet.": "Cashonize 0.9+ или Paytaca. Сквозное шифрование через Nostr; релей видит только шифртекст. Ключи никогда не покидают ваш кошелёк.",
"Everything below runs on": "Всё ниже работает в",
", Bitcoin Cash's test network. The coins are free and worth nothing — this is an alpha, and it is the honest place to try it before real money is involved.": ", тестовой сети Bitcoin Cash. Монеты бесплатны и ничего не стоят — это альфа, и это честное место, чтобы попробовать до того, как появятся настоящие деньги.",
"Starting the connection…": "Устанавливаем соединение…",
"Back": "Назад",
"Open your wallet": "Откройте кошелёк",
"Copy": "Копировать",
"Waiting for your wallet… The link stays valid until you close this page.": "Ждём ваш кошелёк… Ссылка действует, пока вы не закроете эту страницу.",
"Connected": "Подключено",
"Reading your wallet and building the registration…": "Читаем кошелёк и собираем регистрацию…",
"That wallet is empty": "Этот кошелёк пуст",
"Two approvals needed.": "Нужны два подтверждения.",
"Register — approve in your wallet": "Регистрация — подтвердите в кошельке",
"Approve in your wallet": "Подтвердите в кошельке",
"Create your wallet": "Создайте кошелёк",
"Generated in this browser. The phrase is never sent anywhere — not to us, not to anyone.": "Создано в этом браузере. Фраза никуда не отправляется — ни нам, ни кому-либо ещё.",
"Password (encrypts the wallet on this device)": "Пароль (шифрует кошелёк на этом устройстве)",
"Repeat password": "Повторите пароль",
"There is no reset.": "Сброса нет.",
"Generate phrase →": "Создать фразу →",
"Write this down. Now.": "Запишите это. Сейчас.",
"These 12 words are your wallet. Anyone who has them owns your names; if you lose them, nobody — including us — can recover anything.": "Эти 12 слов — ваш кошелёк. Кто их знает, тот владеет вашими именами; если вы их потеряете, никто — включая нас — ничего не восстановит.",
"Copy phrase": "Копировать фразу",
"I have written the phrase down somewhere safe and offline. I understand it cannot be reset.": "Я записал(а) фразу в надёжном месте офлайн. Я понимаю, что её нельзя сбросить.",
"Continue →": "Продолжить →",
"12 words, separated by spaces. It stays in this browser.": "12 слов через пробел. Они остаются в этом браузере.",
"Recovery phrase": "Фраза восстановления",
"Password to encrypt it on this device": "Пароль для шифрования на этом устройстве",
"Import →": "Импортировать →",
"No wallet on this device": "На этом устройстве нет кошелька",
"📥 Import a wallet →": "📥 Импортировать кошелёк →",
"🆕 Create a wallet →": "🆕 Создать кошелёк →",
"Enter your PIN": "Введите PIN",
"Use password instead": "Использовать пароль",
"Unlock →": "Разблокировать →",
"PIN reset": "PIN сброшен",
"3 wrong attempts — the PIN has been cleared. Enter your password to unlock and set a new PIN if you like.": "3 неверные попытки — PIN стёрт. Введите пароль, чтобы разблокировать, и при желании задайте новый PIN.",
"Continue with password →": "Продолжить с паролем →",
"Unlock your wallet": "Разблокируйте кошелёк",
"Decrypts the wallet stored in this browser. After unlocking you can set a PIN so future sessions ask for 4–6 digits instead of the full password.": "Расшифровывает кошелёк, сохранённый в этом браузере. После разблокировки можно задать PIN, чтобы в следующих сессиях вводить 4–6 цифр вместо полного пароля.",
"Password": "Пароль",
"Set a PIN": "Задать PIN",
"optional": "необязательно",
"Repeat PIN": "Повторите PIN",
"Not now": "Не сейчас",
"Save PIN →": "Сохранить PIN →",
"Fund your wallet": "Пополните кошелёк",
"Send test coins to this address. It is yours — derived from your phrase.": "Отправьте тестовые монеты на этот адрес. Он ваш — получен из вашей фразы.",
"checking balance…": "проверяем баланс…",
"Preparing…": "Подготовка…",
"Building your registration transaction.": "Собираем транзакцию регистрации.",
"One transaction. It mints the certificate to": "Одна транзакция. Она выпускает сертификат на",
"your": "ваш",
"address and pays the fees.": "адрес и оплачивает комиссии.",
"The certificate will be minted to": "Сертификат будет выпущен на",
"— your key, your name. You can set where it points immediately afterwards.": "— ваш ключ, ваше имя. Сразу после этого можно указать, куда оно ведёт.",
"Register — sign & broadcast": "Зарегистрировать — подписать и отправить",
"Could not prepare": "Не удалось подготовить",
"Confirm": "Подтвердить",
"Beacon dust + chain fee": "«Пыль» маяка + комиссия блокчейна",
"(covered by wallet)": "(оплачивает кошелёк)",
"Minted to": "Выпущено на",
"Service fee waived on chipnet": "Сервисный сбор в chipnet не взимается",
"Approve payment": "Подтвердите платёж",
"Approve →": "Подтвердить →",
"Signing in your browser and broadcasting to the chain. Do not close this tab.": "Подписываем в браузере и отправляем в блокчейн. Не закрывайте эту вкладку.",
"Transaction": "Транзакция",
"Certificate ID": "ID сертификата",
"Operator": "Оператор",
"The certificate is on the chain, held by your key. Nobody can take it back.": "Сертификат в блокчейне, им владеет ваш ключ. Никто не сможет его забрать.",
"Owner": "Владелец",
"Point it somewhere": "Укажите, куда оно ведёт",
"Optional, and changeable any time — only your key can.": "Необязательно и можно изменить в любой момент — только вашим ключом.",
"Record type": "Тип записи",
"A tiny site stored on the chain itself (h)": "Крошечный сайт прямо в блокчейне (h)",
"Redirect to a web address (u)": "Перенаправление на веб-адрес (u)",
"Your own server's IPv4 address (ip)": "IPv4-адрес вашего сервера (ip)",
"TLS certificate fingerprint (tls)": "Отпечаток TLS-сертификата (tls)",
"Done for now": "Пока достаточно",
"Publish record": "Опубликовать запись",
"Publishing record": "Публикуем запись",
"Update transaction": "Транзакция обновления",
"Finish": "Завершить",
"My names": "Мои имена",
"records & holdings": "записи и владения",
"Admin panel": "Панель администратора",
"operator tools": "инструменты оператора",
"clear this browser": "очистить этот браузер",
"Unlock my wallet": "Разблокировать кошелёк",
"one you already created on this device": "тот, что вы уже создали на этом устройстве",
"Locked wallet on this device": "Заблокированный кошелёк на этом устройстве",
"Unlock or pick another action": "Разблокируйте или выберите другое действие",
"No wallet yet": "Кошелька пока нет",
"Pick how to sign in": "Выберите способ входа",
"Create a wallet": "Создать кошелёк",
"generate a fresh 12-word phrase (sign up)": "создать новую фразу из 12 слов (регистрация)",
"Import a wallet": "Импортировать кошелёк",
"seed phrase you already have (sign in)": "seed-фраза, которая у вас уже есть (вход)",
"Cashonize / Paytaca via QR": "Cashonize / Paytaca по QR",
"The home for names on Bitcoin Cash. Register a TLD, register a name, verify anything against the chain.": "Дом для имён на Bitcoin Cash. Зарегистрируйте TLD, зарегистрируйте имя, проверяйте всё по блокчейну.",
"Product": "Продукт",
"✏️ Register a name": "✏️ Зарегистрировать имя",
"🌐 Register a TLD": "🌐 Зарегистрировать TLD",
"🔑 My names portal": "🔑 Портал моих имён",
"🧭 Theseus browser": "🧭 Браузер Theseus",
"Learn": "Узнать",
"📚 Docs": "📚 Документация",
"🗺 Roadmap": "🗺 Дорожная карта",
"🏛 The Pantheon": "🏛 Пантеон",
"🎨 Brand kit": "🎨 Бренд-кит",
"Alpha": "Альфа",
"Chipnet only. You hold your own keys; verify everything against the chain.": "Только chipnet. Ключи у вас; проверяйте всё по блокчейну.",
"brand assets": "фирменные материалы",
"available": "свободно",
"taken": "занято",
"checking…": "проверяем…",
"Register →": "Зарегистрировать →",
"loading…": "загрузка…",
"(no records set)": "(записи не заданы)",
"on chain": "в блокчейне",
"Edit": "Изменить",
"tier pricing": "ступенчатая цена",
"(default policy — open, tier pricing)": "(политика по умолчанию — открытая, ступенчатые цены)",
"Price & policy": "Цена и политика",
"Register a name under": "Зарегистрировать имя под",
"Preparing your addresses…": "Подготавливаем ваши адреса…",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.": "Для этого кошелька имена BCNR не найдены. Если вы только что зарегистрировались, подождите минуту подтверждения и обновите страницу.",
"Off-chain DNS records — free per edit": "DNS-записи вне блокчейна — бесплатно за каждое изменение",
"Signing…": "Подписываем…",
"Saved ✓": "Сохранено ✓",
"Registered ✓": "Зарегистрировано ✓",
"Switch on": "Включить",
"Switch off": "Выключить",
"Switch on: list the TLD and sell names again": "Включить: снова показать TLD и продавать имена",
"Switch off: hide the TLD, stop new registrations": "Выключить: скрыть TLD, остановить новые регистрации",
"no owner price set — buyers pay the length tier": "цена владельца не задана — покупатели платят по ступени длины",
"hidden from the public registry; no new names until you switch it on": "скрыт из публичного реестра; новых имён не будет, пока вы его не включите",
"listed in the public registry": "в публичном реестре",
"label": "метка",
"🔓 Unlock": "🔓 Разблокировать",
"🆕 Create": "🆕 Создать",
"📥 Import": "📥 Импорт",
"Dashboard — your names on Sirius.X": "Панель управления — ваши имена на Sirius.X",
"dashboard": "",
"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.": "Войдите один раз с seed-фразой Bitcoin Cash или подключите внешний кошелёк. Устройство остаётся в системе, пока вы не выйдете — никаких паролей при каждом визите. Ключи никогда не покидают этот браузер.",
"Manage": "Управление",
"Domain names": "Доменные имена",
"My TLD list": "Мои TLD",
"Get more": "Ещё",
"Docs": "Документация",
"What this wallet holds on chain, and where to go next.": "Что этот кошелёк держит в блокчейне и что делать дальше.",
"↻ Refresh": "↻ Обновить",
"Recent names": "Недавние имена",
"The last few certificates that landed in this wallet.": "Последние сертификаты, поступившие в этот кошелёк.",
"Attention": "Внимание",
"Names that point nowhere yet, or have no DNS.": "Имена, которые пока никуда не ведут или без DNS.",
"Every BCNR name this wallet holds. Open one to manage DNS, content, redirects or transfer it.": "Все имена BCNR в этом кошельке. Откройте имя, чтобы управлять DNS, контентом, перенаправлениями или передать его.",
"Filter names…": "Фильтр имён…",
"Sort: name": "Сортировка: имя",
"Sort: TLD": "Сортировка: TLD",
"Sort: newest": "Сортировка: новые",
"All TLDs": "Все TLD",
"no DNS": "нет DNS",
"DNS …": "DNS …",
"DNS needs s3": "DNS нужен s3",
"Open site →": "Открыть сайт →",
"Summary": "Сводка",
"DNS records": "DNS-записи",
"Content & hosting": "Контент и хостинг",
"Redirect": "Перенаправление",
"Transfer": "Передача",
"Export": "Экспорт",
"Certificate": "Сертификат",
"Where it points": "Куда ведёт",
"On-chain records decide what a resolver serves. Change them under Content & hosting.": "Ончейн-записи определяют, что отдаёт резолвер. Меняйте их в разделе «Контент и хостинг».",
"DNS at a glance": "DNS вкратце",
"Signed off-chain records for mail, verification and classic DNS interop.": "Подписанные записи вне блокчейна для почты, подтверждений и совместимости с обычным DNS.",
"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.": "Стандартные записи, подписанные вашим ключом и хранящиеся в манифесте на Sia. Правки бесплатны, без транзакций. Резолверы и шлюз сверяют подпись с текущим держателем NFT.",
"Type": "Тип",
"Value": "Значение",
"Priority / extra": "Приоритет / доп.",
"No DNS records yet. Add the first one below.": "DNS-записей пока нет. Добавьте первую ниже.",
"Priority": "Приоритет",
"Weight": "Вес",
"Port": "Порт",
"Tag": "Тег",
"+ Add": "+ Добавить",
"Discard changes": "Отменить изменения",
"Nameservers": "Серверы имён",
"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.": "Именам BCNR не нужны серверы имён — резолверы читают блокчейн и этот манифест напрямую. Добавляйте NS-записи, только если делегируете имя и в обычном DNS.",
"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.": "Ончейн-записи публикуются одной подписанной транзакцией UPD (несколько центов «пыли»). Пустое поле удаляет запись. Приоритет для резолверов: h, затем s3, затем p, затем ip.",
"inline HTML — served as-is at the site root (~150 bytes)": "встроенный HTML — отдаётся как есть в корне сайта (~150 байт)",
"Sia bucket key, trailing slash for directories — also where DNS manifests live": "ключ бакета Sia, слеш в конце для каталогов — там же хранятся манифесты DNS",
"reverse proxy: full upstream URL the gateway mirrors": "обратный прокси: полный URL источника, который зеркалирует шлюз",
"Reset": "Сбросить",
"Forward this name to any web address. Stored on chain as the": "Перенаправляйте это имя на любой веб-адрес. Хранится в блокчейне как запись",
"record; resolvers and the gateway issue the redirect. Clear it to stop forwarding.": "; резолверы и шлюз выполняют перенаправление. Очистите, чтобы остановить.",
"Destination URL": "URL назначения",
"Remove redirect": "Убрать перенаправление",
"Save redirect →": "Сохранить перенаправление →",
"Transfer ownership": "Передать владение",
"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.": "Переносит сертификат имени на другой адрес Bitcoin Cash одной транзакцией. Записи сохраняются. С этого момента именем управляет новый владелец — отсюда это не отменить.",
"Recipient address": "Адрес получателя",
"I understand this hands the name to that address permanently.": "Я понимаю, что имя навсегда переходит на этот адрес.",
"Transfer name →": "Передать имя →",
"Download this name's DNS as a BIND-style zone file, or its full record set as JSON, for backups or importing elsewhere.": "Скачайте DNS этого имени как зонный файл в формате BIND или все записи как JSON — для резервной копии или импорта в другом месте.",
"⬇ Zone file (.txt)": "⬇ Файл зоны (.txt)",
"⬇ Records (.json)": "⬇ Записи (.json)",
"Copy DNS manifest": "Копировать манифест DNS",
"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.": "Все NFT реестра TLD в этом кошельке. Задайте цену каждого имени под TLD, включайте и выключайте его (выключен = приватный: регистрировать можете только вы) и настраивайте политику. Каждое изменение — один подписанный TUPD в блокчейне; вы получаете 90 % с каждой продажи.",
"Registry": "Реестр",
"Register a name under this TLD": "Зарегистрировать имя под этим TLD",
"Works whether the TLD is on or off. As the owner you pay only the platform's 10% share.": "Работает и когда TLD включён, и когда выключен. Как владелец вы платите только 10 % платформы.",
"Names registered under this TLD": "Имена, зарегистрированные под этим TLD",
"Everyone's registrations, from the public registry.": "Регистрации всех пользователей из публичного реестра.",
"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.": "TLD — это NFT реестра на TLD-маяке chipnet. Публичные выпуски платят сервисный сбор, финансирующий реестр. В chipnet курс-заглушка; в mainnet цену по длине метки задаёт настоящий оракул.",
"Faucet 2 →": "Кран 2 →",
"Balance": "Баланс",
"Spendable": "Доступно",
"UTXOs": "UTXO",
"Watched addresses": "Отслеживаемые адреса",
"Session and security choices for this browser. Nothing here changes what is on chain.": "Настройки сессии и безопасности для этого браузера. Ничто здесь не меняет данные в блокчейне.",
"Session": "Сессия",
"Stay signed in on this device": "Оставаться в системе на этом устройстве",
"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.": "Фраза восстановления хранится зашифрованной ключом, который держит браузер и не может экспортировать. Следующие визиты открывают панель сразу. Выключите, чтобы каждый раз запрашивался пароль или PIN.",
"Ask for PIN before payments": "Запрашивать PIN перед платежами",
"Adds a PIN prompt when registering a name or TLD. Off by default so signed-in sessions run uninterrupted.": "Добавляет запрос PIN при регистрации имени или TLD. По умолчанию выключено, чтобы сессия шла без прерываний.",
"Set / change PIN": "Задать / изменить PIN",
"Remove PIN": "Удалить PIN",
"Reading & language": "Чтение и язык",
"Font pill and language picker live in the top bar; both are remembered per browser.": "Переключатель шрифта и выбор языка — в верхней панели; оба запоминаются в браузере.",
"This device": "Это устройство",
"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.": "Выход оставляет зашифрованный кошелёк на устройстве, чтобы разблокировать его позже. Забыть удаляет его полностью — понадобится фраза восстановления.",
"Forget wallet on this device": "Забыть кошелёк на этом устройстве",
"4–6 digits. Encrypts your recovery phrase under this PIN on this device. Three wrong PINs clear it and fall back to your password.": "4–6 цифр. Шифрует фразу восстановления этим PIN на устройстве. Три неверных PIN стирают его, и действует пароль.",
"No names yet.": "Имён пока нет.",
"Register your first one →": "Зарегистрируйте первое →",
"Everything points somewhere and has DNS. Nice.": "Всё куда-то ведёт и имеет DNS. Отлично.",
"Nothing matches that filter.": "Ничего не подходит под этот фильтр.",
"Status": "Статус",
"point it somewhere →": "укажите, куда ведёт →",
"Add some →": "Добавить →",
"Register one →": "Зарегистрировать →",
"yours": "ваше",
"Copied": "Скопировано",
"No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and refresh.": "Для этого кошелька имена BCNR не найдены. Если вы только что зарегистрировались, подождите минуту и обновите.",
"Remove": "Удалить",
"Transferring…": "Передаём…",
"Transferred ✓": "Передано ✓",
"off · private": "выкл · приватный",
"on · public": "вкл · публичный",
"Signing you in…": "Выполняем вход…",
"Restoring your session on this device.": "Восстанавливаем вашу сессию на этом устройстве.",
"Dashboard": "Панель управления",
"names, TLDs, DNS, settings": "имена, TLD, DNS, настройки",
"site on chain": "сайт в блокчейне",
"site on Sia": "сайт на Sia",
"reverse proxy": "обратный прокси",
"own server": "свой сервер",
"redirect": "перенаправление",
"not pointed": "не указано",
"points nowhere yet": "пока никуда не ведёт",
"no DNS records": "нет DNS-записей",
"DNS needs an s3 pointer": "DNS нужна запись s3",
"block": "блок",
"Web-Builder": "Веб-конструктор",
"My TLDs": "Мои TLD",
"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.": "Sirius Studio создаёт сайт для любого вашего имени: перетаскивайте блоки, правьте текст, публикуйте. Страницы живут в папке имени на Sia, и имя указывает на них — без хостинга и продления.",
"Session, security and wallet details for this browser. Nothing here changes what is on chain.": "Сессия, безопасность и данные кошелька для этого браузера. Ничто здесь не меняет данные в блокчейне.",
"Reading, language & help": "Чтение, язык и справка",
"Font pill and language picker live in the top bar; both are remembered per browser. The technical documentation is at": "Переключатель шрифта и выбор языка — в верхней панели; оба запоминаются в браузере. Техническая документация:",
"Start from a template": "Начать с шаблона",
"Preview the exported page in a new tab": "Предпросмотр экспортированной страницы в новой вкладке",
"Sirius Studio — build the site for your name": "Sirius Studio — создайте сайт для своего имени",
"Templates…": "Шаблоны…",
"Landing page": "Лендинг",
"Profile / link hub": "Профиль / ссылки",
"Business one-pager": "Бизнес на одной странице",
"Blank page": "Пустая страница",
"Preview": "Предпросмотр",
"Save draft": "Сохранить черновик",
"Publish to Sia →": "Опубликовать на Sia →",
"View site →": "Открыть сайт →",
"Sign in first": "Сначала войдите",
"Sirius Studio publishes with your wallet's key. Sign in on the dashboard, then come back to this name.": "Sirius Studio публикует ключом вашего кошелька. Войдите в панели и вернитесь к этому имени.",
"Open the dashboard →": "Открыть панель →",
"Build the site for": "Создайте сайт для",
"Pick a starting point. Everything is editable — drag blocks in from the right, click any text to change it. Nothing leaves your browser until you press Publish; then the page is stored on Sia and the name points at it.": "Выберите отправную точку. Всё редактируется — перетаскивайте блоки справа, нажимайте на текст, чтобы изменить. Ничего не покидает браузер, пока вы не нажмёте «Опубликовать»; затем страница сохраняется на Sia, и имя указывает на неё.",
"Hero, three features, call to action.": "Заголовок, три преимущества, призыв к действию.",
"Avatar, bio and a stack of links.": "Аватар, описание и список ссылок.",
"About, services, hours, contact.": "О нас, услуги, часы работы, контакты.",
"Start from nothing.": "Начать с нуля.",
"Back to dashboard": "Назад в панель",
"Publish": "Публикация",
"The page and its assets are uploaded to the name's folder on Sia, signed with your key. If the name does not point at that folder yet, one on-chain update sets it (a few cents of chain dust).": "Страница и её файлы загружаются в папку имени на Sia с подписью вашим ключом. Если имя ещё не указывает на эту папку, одно ончейн-обновление это исправит (несколько центов «пыли»).",
"Needs attention": "Требует внимания",
"View →": "Открыть →",
"Edit in Studio": "Редактировать в Studio",
"Open in Studio": "Открыть в Studio",
"built with Studio": "создано в Studio",
"site on Sia (external)": "сайт на Sia (внешний)",
"inline HTML": "встроенный HTML",
"no site yet": "сайта пока нет",
"Pick a name to build or edit its site.": "Выберите имя, чтобы создать или изменить его сайт.",
"You need a name first.": "Сначала нужно имя.",
"— then come back here to build its site.": "— затем вернитесь сюда, чтобы создать его сайт.",
"New site": "Новый сайт",
"Not signed in": "Вход не выполнен",
"Loading name…": "Загрузка имени…",
"Published": "Опубликовано",
"Publish failed": "Публикация не удалась",
"Template loaded — edit, then Publish": "Шаблон загружен — отредактируйте и опубликуйте",
"Draft saved on Sia": "Черновик сохранён на Sia",
"Saving draft…": "Сохраняем черновик…",
"Copy address": "Копировать адрес",
"receive coins or names here": "получайте сюда монеты и имена",
"Copy token address": "Копировать токен-адрес",
"where name certificates are minted": "сюда выпускаются сертификаты имён",
"Get test coins": "Получить тестовые монеты",
"chipnet faucet": "кран chipnet",
"Wallet settings": "Настройки кошелька",
"session, PIN, forget device": "сессия, PIN, забыть устройство",
"Holdings": "Владения",
"open the dashboard to load": "откройте панель для загрузки",
"🛒 Market": "🛒 Маркет",
"🛒 Names for sale": "🛒 Имена на продажу",
"Market — names for sale on Sirius.X": "Маркет — имена на продажу на Sirius.X",
"for sale": "на продажу",
"Every sale is a single Bitcoin Cash transaction. The seller signed an offer that pays them only when the certificate moves to you — you add your coins, sign, broadcast. No escrow, no middleman, no way for either side to cheat.": "Каждая продажа — одна транзакция Bitcoin Cash. Продавец подписал оферту, по которой он получает деньги только когда сертификат переходит к вам — вы добавляете свои монеты, подписываете, отправляете. Без эскроу, без посредников, без возможности обмана с любой стороны.",
"Sort: price": "Сортировка: цена",
"Loading listings…": "Загрузка объявлений…",
"Selling a name?": "Продаёте имя?",
"Open it in your": "Откройте его в своей",
", choose": ", выберите",
"Sell": "Продать",
", set a price. The listing is a signed offer stored by the gateway; cancelling it moves your certificate once so the old offer can never be used.": ", укажите цену. Объявление — это подписанная оферта, которую хранит шлюз; при отмене ваш сертификат перемещается один раз, чтобы старую оферту нельзя было использовать.",
"One transaction: your coins pay the seller, the certificate lands in your wallet, and the registry is told about the new owner. Records stay as they are — you can change them in the dashboard right after.": "Одна транзакция: ваши монеты оплачивают продавца, сертификат попадает в ваш кошелёк, а реестр узнаёт о новом владельце. Записи остаются прежними — вы можете изменить их в панели сразу после.",
"Sign in to buy →": "Войти, чтобы купить →",
"Buy — sign & broadcast": "Купить — подписать и отправить",
"Buy →": "Купить →",
"Nothing is for sale right now. Owners list names from their dashboard.": "Сейчас ничего не продаётся. Владельцы выставляют имена из своей панели.",
"Sell this name": "Продать это имя",
"You sign an offer once: \"whoever pays me this price gets the certificate\". The offer is stored by the gateway and shown on the": "Вы один раз подписываете оферту: «кто заплатит мне эту цену, получит сертификат». Шлюз хранит оферту и показывает её на",
"market": "маркете",
". 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.": ". Покупатель завершает её одной транзакцией — вы получаете оплату в той же транзакции, которая передаёт имя, либо не получаете вовсе. Без эскроу, доверять никому не нужно.",
"Checking the market…": "Проверяем маркет…",
"Price (USD)": "Цена (USD)",
"Price (sat)": "Цена (сат)",
"List for sale →": "Выставить на продажу →",
"Cancel listing →": "Снять с продажи →",
"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.": "Отмена убирает оферту с маркета и один раз перемещает ваш сертификат (пустое обновление, несколько центов), чтобы подписанную оферту нельзя было исполнить позже.",
"Not for sale. Set a price to list it.": "Не продаётся. Укажите цену, чтобы выставить.",
"This name is listed on the market.": "Это имя выставлено на маркете.",
"Pending approvals": "Ожидают одобрения",
"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.": "Регистрации под этим TLD, ожидающие вашей подписи. Одобрение подписывает ваш сертификат TLD в транзакции покупателя и отправляет её; сертификат возвращается к вам в той же транзакции. Без этого шага под TLD с со-подписью или приватным TLD ничего зарегистрировать нельзя.",
"No requests waiting.": "Запросов нет.",
"awaiting you": "ждёт вас",
"Approve & broadcast": "Одобрить и отправить",
"Decline": "Отклонить",
"Request approval — sign": "Запросить одобрение — подписать",
"Withdraw request": "Отозвать запрос",
"Request declined": "Запрос отклонён",
"Open dashboard →": "Открыть панель →",
"incl.": "вкл.",
"sat unconfirmed · spendable now": "сат не подтверждено · доступно сейчас",
"Nothing is for sale right now": "Сейчас ничего не продаётся",
"Names go on sale when their owners list them from the dashboard. Have one to sell, or want a fresh one instead?": "Имена появляются в продаже, когда владельцы выставляют их из панели. Есть что продать — или лучше зарегистрировать новое?",
"Sell a name from your dashboard →": "Продать имя из панели →",
"Register a new name": "Зарегистрировать новое имя",
"↓ Import live site": "↓ Импортировать текущий сайт",
"Import the live site": "Импортировать текущий сайт",
"✨ Assistant": "✨ Ассистент",
"Runs on your own device. Nothing you write or build is sent to Sirius.X or to any AI vendor.": "Работает на вашем устройстве. Ничего из того, что вы пишете или строите, не отправляется в Sirius.X или поставщику ИИ.",
"Runs on": "Работает на",
"This browser — your GPU, private": "Этот браузер — ваша GPU, приватно",
"Local endpoint — Ollama, LM Studio": "Локальный сервер — Ollama, LM Studio",
"Model": "Модель",
"Downloads once, then stays in the browser cache. Needs WebGPU (current Chrome, Edge, Firefox, Safari).": "Скачивается один раз и остаётся в кэше браузера. Нужен WebGPU (актуальные Chrome, Edge, Firefox, Safari).",
"Load model": "Загрузить модель",
"Endpoint": "Адрес сервера",
"Connect": "Подключить",
"What do you want?": "Что нужно сделать?",
"Make a section": "Создать секцию",
"Rewrite selected text": "Переписать выбранный текст",
"Restyle selection": "Изменить стиль выбранного",
"Nothing selected": "Ничего не выбрано",
"Undo last change": "Отменить последнее изменение",
"Stop": "Стоп"
}

View file

@ -3,38 +3,80 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>sirius.x — the home for names on Bitcoin Cash</title>
<meta name="description" content="sirius.x is the operator-run entry point for BCNR: register a top-level domain, register a name under one, look up records, verify anything against the chain. Backed by Sia storage, mirrored on the operator's VPS, name published on the chain.">
<title>Sirius.X — the home for names on Bitcoin Cash</title>
<meta name="description" content="Sirius.X is the operator-run entry point for BCNR: register a top-level domain, register a name under one, look up records, verify anything against the chain. Backed by Sia storage, mirrored on the operator's VPS, name published on the chain.">
<!-- sirius.x branding: SVG favicon at 16/32/any size (the star + dark rounded
square scales cleanly); OpenGraph + Twitter Card so shared links preview
with the right title, description, and mark. -->
<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 — the home for names on Bitcoin Cash">
<meta property="og:site_name" content="Sirius.X">
<meta property="og:title" content="Sirius.X — the home for names on Bitcoin Cash">
<meta property="og:description" content="Register a top-level domain, register a name under one, look up records, verify anything against the chain. Backed by Sia + VPS + on-chain.">
<meta property="og:url" content="https://silentmode.st/sirius-x/">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="sirius.x — the home for names on Bitcoin Cash">
<meta name="twitter:title" content="Sirius.X — the home for names on Bitcoin Cash">
<meta name="twitter:description" content="Register a TLD or a name, look up records, verify against the chain. Your keys, your names.">
<!-- Silent Mode family fonts (Fraunces editorial + DM Sans body + JetBrains
Mono for code/hashes) plus Ubuntu as the Bitcoin Cash brand alt. Toggle
between Fraunces and Ubuntu lives in the top nav (see js/theme.js). -->
<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:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
/* Deviant "signal" sky palette — shared with silentmode.st/deviant/. */
--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;
/* #0AC18E = Bitcoin Cash brand green — used for chain-native badges */
--chain-native:#0AC18E;
--chain:#d6ff3d; --sia:#b39ddb; --srv:#4fd1a5; --ok:#4fd1a5; --taken:#f6768a;
--warn:#ffc75f;
--serif:'Fraunces',Georgia,serif;
--sans:'DM Sans','Inter',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
--mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
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:16px/1.6 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)}
/* Ubuntu reader-alt — swap when <html data-font-cmp="ubuntu"> */
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 pill (lives inside .topnav) */
.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}
.font-picker-float{position:fixed;bottom:20px;right:20px;z-index:99;
backdrop-filter:blur(10px);box-shadow:0 6px 20px rgba(0,0,0,.35)}
a{color:var(--acid)}
.wrap{max-width:980px;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)}
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}
@ -87,52 +129,211 @@
.verify dd{margin:2px 0 0;font-family:ui-monospace,monospace;font-size:12.5px;word-break:break-all;color:var(--ink)}
footer{border-top:1px solid var(--line);padding:2.4rem 0 3.5rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
</style>
<script src="./js/i18n.js?v=20260920d"></script>
</head>
<body>
<nav class="topnav">
<a class="brand" href="./">⭐ <span class="g">sirius.x</span></a>
<a class="brand" href="./">⭐ <span class="g">Sirius.X</span></a>
<a href="#try">Try it</a>
<a href="./docs/">📚 Docs</a>
<a href="./theseus/">🧭 Theseus</a>
<a href="#roadmap">Roadmap</a>
<a href="./brand/">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</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">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">⭐</div>
<h1>Names on the <span class="g">chain</span>.</h1>
<p class="tag">sirius.x is the entry point for BCNR — Bitcoin Cash Name Registry.
<p class="tag">Sirius.X is the entry point for BCNR — Bitcoin Cash Name Registry.
Register a top-level domain, register a name under one, look up records,
verify anything against the chain. Backed by Sia storage, mirrored on the
operator's VPS, name published on chain — this page survives if any single
mirror goes down.</p>
<div class="cta">
<a class="btn acid" href="#try">Get started</a>
<a class="btn ghost" href="#docs">Read the docs</a>
verify anything against the chain.</p>
<div style="margin:1.6rem auto 0;max-width:640px;padding:0 1rem">
<input id="search-input" type="search"
placeholder="type a name — e.g. hello"
spellcheck="false" autocomplete="off"
style="width:100%;padding:14px 18px;border-radius:12px;border:1px solid #ffffff22;background:#141a24;color:var(--ink);font-size:17px;outline:none;font-family:inherit"
aria-label="Search a name across every BCNR TLD">
<div id="search-hint" style="margin-top:8px;font-size:12.5px;color:var(--mut);text-align:center">
One search checks the label across every TLD in the registry. Available names appear first.
</div>
<div id="search-results" style="margin-top:14px;display:grid;gap:8px;text-align:left"></div>
</div>
<div class="cta" style="margin-top:1.4rem">
<a class="btn ghost" href="#try">Or browse what you can do →</a>
<a class="btn ghost" href="./docs/">Read the docs</a>
</div>
</header>
<style>
/* Inline search card styling: mirrors register.html's .card look. */
#search-results .row-card{display:grid;grid-template-columns:1fr auto auto auto;gap:12px;align-items:center;
background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:11px 16px;min-height:48px}
#search-results .row-card.checking{opacity:.55}
#search-results .row-card .n{font-family:ui-monospace,monospace;font-size:15px;overflow-wrap:anywhere}
#search-results .row-card .btn{padding:6px 12px;font-size:12.5px}
#search-results .row-card .price{
color:var(--acid);font-family:ui-monospace,monospace;font-size:14px;font-weight:600;
padding:2px 8px;border-radius:6px;background:rgba(214,255,61,.10);white-space:nowrap
}
#search-results .badge{font-size:11px;padding:2px 10px;border-radius:999px;font-weight:600;white-space:nowrap}
#search-results .b-ok{background:rgba(79,209,165,.15);color:var(--ok)}
#search-results .b-taken{background:rgba(246,118,138,.15);color:var(--taken)}
#search-results .b-check{background:rgba(139,152,169,.14);color:var(--mut)}
@media (max-width:520px){
#search-results .row-card{grid-template-columns:1fr auto;gap:8px}
#search-results .row-card .btn{justify-self:start}
}
</style>
<script>
// Inline name search — same UX as register.html but no wallet dependencies.
// Hits POST-friendly /api/labels/<label> (one call, returns every taken
// match across every TLD from the gateway's cached index) and cross-checks
// against the client-side TLDS list. Register buttons hand the label off
// to register.html?q= for the full mint flow.
(function () {
// Fallback list, used until /api/tlds answers (js/pricing.js loads it).
// The live list drops TLDs their owners switched off and carries the
// owner-set prices, so it wins whenever it is available.
let TLDS = [
"bch","p2p","bit","nav","test","x","asm","neo","gt","sc",
"sia","dex","cex","nt","dea","hub","os","vpn",
];
// .com is held off the public registry (2026-08-29) regardless of what
// the API says — the operator holds it; nobody buys names under it yet.
const NEVER_SELL = new Set(["com"]);
async function liveTlds() {
const sp = window.siriusPricing;
if (!sp) return TLDS;
await sp.tldReady();
const live = sp.visibleTlds();
if (live && live.length) TLDS = live.filter((t) => !NEVER_SELL.has(t) && sp.tldSellable(t).ok);
return TLDS;
}
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s).replace(/[&<>"']/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[c]));
const clean = (v) => v.toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 32);
let lastReq = 0, timer = null;
function row(full, state) {
const badge = state === "ok" ? '<span class="badge b-ok">available</span>'
: state === "taken" ? '<span class="badge b-taken">taken</span>'
: '<span class="badge b-check">checking…</span>';
// Label price (rendered only for available names). Tier logic lives in
// pricing.js so landing / tld.html / the mint modal all agree.
let price = "";
if (state === "ok" && window.siriusPricing) {
const [label, tld] = full.split(".");
const p = window.siriusPricing.priceForName(label, tld);
const why = p.ownerSet ? `price set by the .${tld} owner` : p.tier;
price = `<span class="price" title="${esc(why)}">${esc(window.siriusPricing.formatUsd(p.usd))}</span>`;
}
const btn = state === "ok"
? `<button class="btn acid" data-register="${esc(full)}">Register →</button>`
: state === "taken"
? `<a class="btn ghost" href="https://navigate.st/bns/${encodeURIComponent(full)}" target="_blank" rel="noopener">view →</a>`
: "<span></span>";
return `<div class="row-card ${state === "checking" ? "checking" : ""}"><span class="n">${esc(full)}</span>${badge}${price}${btn}</div>`;
}
async function search(label) {
const my = ++lastReq;
const out = $("search-results");
// Immediate feedback: paint one 'checking' row per TLD so the user
// sees something is happening in the ~300ms before results land.
out.innerHTML = TLDS.map((t) => row(`${label}.${t}`, "checking")).join("");
let taken = new Set();
try {
const [r] = await Promise.all([
fetch(`https://silentmode.st/api/labels/${encodeURIComponent(label)}`),
liveTlds(), // owner prices + on/off state, same round-trip
]);
if (r.ok) {
const j = await r.json();
for (const m of (j.matches || [])) taken.add(m.name);
}
} catch { /* fall through: everything shows as "checking" then flips to error-free available; a gateway blip shouldn't block the user */ }
if (my !== lastReq) return; // superseded by newer keystroke
const rows = TLDS
.map((t) => ({ full: `${label}.${t}`, state: taken.has(`${label}.${t}`) ? "taken" : "ok" }))
.sort((a, b) => (a.state === "ok" ? 0 : 1) - (b.state === "ok" ? 0 : 1));
out.innerHTML = rows.map((x) => row(x.full, x.state)).join("");
// Wire Register buttons — hand the chosen name off to the shared mint
// flow (js/register-flow.js exposes window.siriusRegisterName).
out.querySelectorAll("[data-register]").forEach((b) => {
b.onclick = () => {
const name = b.getAttribute("data-register");
if (typeof window.siriusRegisterName === "function") {
window.siriusRegisterName(name);
} else {
// Module still loading — retry once it settles.
b.textContent = "loading…"; b.disabled = true;
const t = setInterval(() => {
if (typeof window.siriusRegisterName === "function") {
clearInterval(t); b.disabled = false; b.textContent = "Register →";
window.siriusRegisterName(name);
}
}, 100);
}
};
});
}
$("search-input").addEventListener("input", () => {
clearTimeout(timer);
const v = clean($("search-input").value);
$("search-input").value = v;
if (!v) { $("search-results").innerHTML = ""; return; }
timer = setTimeout(() => search(v), 200);
});
$("search-input").addEventListener("keydown", (e) => {
if (e.key === "Enter") {
clearTimeout(timer);
const v = clean($("search-input").value);
if (v) search(v);
}
});
})();
</script>
<div class="wrap">
<section id="try">
<h2>Try it</h2>
<p class="lede">Three things you can do right now. The registrar and TLD-registry UIs live at
silentmode.st today; sirius.x is the canonical home and will consolidate them here.</p>
silentmode.st today; Sirius.X is the canonical home and will consolidate them here.</p>
<div class="grid">
<div class="card">
<h3><span class="dot d-chain"></span> Register a name</h3>
<p>Pick a label, search across every TLD in the registry at once, mint the name
certificate straight into your own wallet. A few cents in chain fees, no yearly renewal.</p>
<div class="cta"><a class="btn acid" href="https://silentmode.st/sirius/register.html">Search a name →</a></div>
certificate straight into your own wallet. No yearly renewal.</p>
<p class="price" style="color:var(--acid);font-family:ui-monospace,monospace;font-size:13px;margin:.6rem 0 0">
≈ 10,000 sat service fee · 1,300 sat chain dust · &lt; 1 ¢
</p>
<p style="color:var(--dim);font-size:11.5px;margin:.3rem 0 0">
Chipnet placeholder. 90 % of the service fee flows to the TLD owner, 10 % to the platform.
</p>
<div class="cta"><a class="btn acid" href="#search-input">Search a name →</a></div>
</div>
<div class="card">
<h3><span class="dot d-chain"></span> Register a TLD</h3>
<p>Under the per-TLD registry, a TLD is itself a certificate on the chain. Public mints
are operator-gated today; propose one below.</p>
<div class="cta"><a class="btn ghost" href="#request-tld">Propose a TLD →</a></div>
<p>A TLD is itself a certificate on the chain. Anyone can mint one — you become the registry
operator for every second-level name under it, and earn 90 % of the fee on every name
registered under it. Renewals are per-TLD policy set by the owner.</p>
<p class="price" style="color:var(--acid);font-family:ui-monospace,monospace;font-size:13px;margin:.6rem 0 0">
≈ 1,250,000 sat service fee (≈ $5) · 1,300 sat chain dust
</p>
<p style="color:var(--dim);font-size:11.5px;margin:.3rem 0 0">
Chipnet placeholder rate — mainnet will price by label length via an on-chain oracle.
</p>
<div class="cta">
<a class="btn acid" href="./tld.html">Search a TLD →</a>
<a class="btn ghost" href="./admin/">Operator admin →</a>
</div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> Look up &amp; verify</h3>
@ -178,13 +379,63 @@
enforces this; on chipnet the operator's countersignature is the gate.</div>
</section>
<section id="pantheon">
<h2>The pantheon</h2>
<p class="lede">Sirius.x is one of seven sibling <b>.x</b> names — the Silent Mode pantheon.
Each project is its own on-chain certificate; each site is reachable through any BCNR
resolver, plus the silentmode.st gateway for browsers without one.</p>
<div class="grid">
<div class="card">
<h3><span class="dot d-chain"></span> ⛓️ Silentmode.X</h3>
<p>The project umbrella. Redirects to <code>silentmode.st</code> where every pillar
has its own landing page + download hub.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/silentmode.x/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-chain"></span> ⭐ Sirius.X <span class="pill">you're here</span></h3>
<p>Names on Bitcoin Cash — register, resolve, verify, manage. This site.</p>
<div class="cta"><a class="btn ghost" href="./">Home →</a></div>
</div>
<div class="card">
<h3><span class="dot d-chain"></span> 🧭 Theseus.X</h3>
<p>The browser that speaks BCNR natively — Chromium build with the resolver baked in,
no OS-level daemon or root-store install.</p>
<div class="cta"><a class="btn ghost" href="./theseus/">Learn more →</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> 🔥 Hephaestus.X</h3>
<p>The forge. Forgejo instance for the ecosystem's git repos, backed by BCH wallet
auth. Sirius's own source lives here.</p>
<div class="cta"><a class="btn ghost" href="https://code.silentmode.st/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> 🔮 Prometheus.X</h3>
<p>Fire from the chain. The project's foresight / experimentation layer.
Redirects to <code>silentmode.st/prometheus/</code> today.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/prometheus.x/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> ☀️ Helios.X</h3>
<p>The public gaze. Analytics, dashboards, transparency reports.
Redirects to <code>silentmode.st/helios/</code> today.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/helios.x/" rel="noopener">Open →</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> ✉️ Hermes.X</h3>
<p>Messenger. Nostr-based messaging bound to a BCNR name via the <code>np</code>
+ <code>nr</code> records. Redirects to <code>silentmode.st/hermes/</code>.</p>
<div class="cta"><a class="btn ghost" href="https://silentmode.st/bns/hermes.x/" rel="noopener">Open →</a></div>
</div>
</div>
</section>
<section id="roadmap">
<h2>What's coming</h2>
<p class="lede">sirius.x consolidates docs and registration today; three larger pieces are on the roadmap.</p>
<p class="lede">Sirius.X consolidates docs and registration today; three larger pieces are on the roadmap.</p>
<div class="grid">
<div class="card">
<h3>Wallet &amp; name portal <span class="pill soon">next</span></h3>
<p>Sign in with your BCNR wallet, see every name you own, edit records inline, mint or renew
<p>Sign in with your Bitcoin Cash wallet, see every name you own, edit records inline, mint or renew
from one place. Same self-custody as today — the portal never handles your keys.</p>
</div>
<div class="card">
@ -248,13 +499,21 @@ process.exit(0);"</pre>
</div>
<footer>
sirius.x — the Silent Mode name registry entry point ·
<a href="https://silentmode.st/">silentmode.st</a> ·
<a href="https://silentmode.st/tlds/">TLD registry</a> ·
<a href="https://silentmode.st/sirius/register.html">register a name</a><br>
Alpha on a test network (chipnet). You hold your own keys; verify everything against the chain.
</footer>
<footer id="site-footer"></footer>
<!-- Shared mint flow — modal + wallet steps used to live in register.html.
The module injects its own modal into <body> and exposes
window.siriusRegisterName(fullName) for the search-result buttons. -->
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
<script type="module" src="./js/register-flow.js?v=20260917bal"></script>
<script src="./js/pricing.js?v=20260917market"></script>
<script src="./js/session.js?v=20260917dash"></script>
<script src="./js/pin-escrow.js?v=20260909pin"></script>
<script defer src="./js/theme.js?v=20260910font"></script>
<script defer src="./js/site-footer.js?v=20260917market"></script>
<script defer src="./js/profile-menu.js?v=20260920m"></script>
</body>
</html>

7
js/ai-worker.js Normal file
View file

@ -0,0 +1,7 @@
// Web Worker for the in-browser assistant: runs the WebLLM engine off the UI
// thread. Weights and the model library are fetched by WebLLM itself and
// cached by the browser; nothing is sent anywhere.
import { WebWorkerMLCEngineHandler } from "../vendor/web-llm/index.js?v=0.2.85";
const handler = new WebWorkerMLCEngineHandler();
self.onmessage = (msg) => handler.onmessage(msg);

1029
js/dashboard.js Normal file

File diff suppressed because it is too large Load diff

357
js/i18n.js Normal file
View file

@ -0,0 +1,357 @@
// Sirius.X runtime translation.
//
// The pages are written in English. This script picks the reader's language
// (saved choice → ?lang= → browser languages → English), fetches
// i18n/<lang>.json — a flat map of English text → translation — and swaps
// every matching text node, placeholder, title and aria-label. A
// MutationObserver keeps script-built content (search rows, the register
// modal, portal rows, footer, profile menu) translated as it appears, so
// page scripts never need to know about languages.
//
// Rules of the road:
// • Keys are the exact English text of a node (whitespace collapsed).
// • <code>, <pre>, <kbd>, <textarea>, .mono and anything under
// [translate="no"] / [data-i18n-skip] is left alone — names, hashes,
// record keys and addresses must never change.
// • English is the source of truth: every node remembers its English
// text, so switching languages (or back to English) is lossless.
// • Adding a language = one JSON file in i18n/ + one line in LANGS.
//
// Exposed as window.siriusI18n = { lang, langs, t(text), setLang(code) }.
(function () {
var STORE = "sirius-lang";
var CACHE = "sirius-i18n:";
var VERSION = "20260920d"; // bump when dictionaries change
var LANGS = {
en: "English",
de: "Deutsch",
el: "Ελληνικά",
ru: "Русский",
es: "Español",
fr: "Français",
pt: "Português",
};
var SKIP_TAGS = { SCRIPT: 1, STYLE: 1, CODE: 1, PRE: 1, KBD: 1, TEXTAREA: 1, NOSCRIPT: 1, SVG: 1 };
var ATTRS = ["placeholder", "title", "aria-label"];
var base = (function () {
try { return new URL("../i18n/", document.currentScript.src).href; }
catch (e) { return "./i18n/"; }
})();
var dict = null; // English -> translation for the active language
var lang = "en";
var applying = false;
// ---------- language choice ----------
function normalise(code) {
if (!code) return null;
var primary = String(code).toLowerCase().split(/[-_]/)[0];
return LANGS[primary] ? primary : null;
}
function detect() {
var fromQuery = null;
try { fromQuery = normalise(new URLSearchParams(location.search).get("lang")); } catch (e) {}
if (fromQuery) { save(fromQuery); return fromQuery; }
var saved = null;
try { saved = normalise(localStorage.getItem(STORE)); } catch (e) {}
if (saved) return saved;
var list = navigator.languages && navigator.languages.length ? navigator.languages : [navigator.language];
for (var i = 0; i < list.length; i++) { var n = normalise(list[i]); if (n) return n; }
return "en";
}
function save(code) { try { localStorage.setItem(STORE, code); } catch (e) {} }
// ---------- dictionary loading (cache first, network second) ----------
function readCache(code) {
try {
var raw = localStorage.getItem(CACHE + code);
if (!raw) return null;
var obj = JSON.parse(raw);
return obj && obj.v === VERSION ? obj.d : null;
} catch (e) { return null; }
}
function writeCache(code, d) {
try { localStorage.setItem(CACHE + code, JSON.stringify({ v: VERSION, d: d })); } catch (e) {}
}
function load(code) {
if (code === "en") return Promise.resolve({});
var cached = readCache(code);
var net = fetch(base + code + ".json?v=" + VERSION, { cache: "no-cache" })
.then(function (r) { if (!r.ok) throw new Error("i18n " + r.status); return r.json(); })
.then(function (d) { writeCache(code, d); return d; });
if (cached) { net.then(function (d) { if (lang === code) { dict = d; applyAll(); } }).catch(function () {}); return Promise.resolve(cached); }
return net;
}
// ---------- translation ----------
function t(text) {
if (!dict) return text;
var key = String(text).replace(/\s+/g, " ").trim();
// An empty string is a valid translation (the word is dropped in that
// language) — only a missing key falls back to English.
var out = Object.prototype.hasOwnProperty.call(dict, key) ? dict[key] : undefined;
return typeof out === "string" ? out : text;
}
function skip(el) {
for (var e = el; e && e.nodeType === 1; e = e.parentNode) {
if (SKIP_TAGS[e.tagName]) return true;
if (e.getAttribute) {
if (e.getAttribute("translate") === "no" || e.hasAttribute("data-i18n-skip")) return true;
var cls = e.getAttribute("class") || "";
if (/(^|\s)mono(\s|$)/.test(cls)) return true;
}
}
return false;
}
function translateText(node) {
var cur = node.nodeValue;
if (!cur || !/\S/.test(cur)) return;
// A page script changed the text since we last touched it → new source.
if (node.__i18nOut !== cur) { node.__i18nSrc = cur; node.__i18nOut = null; }
var src = node.__i18nSrc != null ? node.__i18nSrc : cur;
var key = src.replace(/\s+/g, " ").trim();
var has = dict && key && Object.prototype.hasOwnProperty.call(dict, key) && typeof dict[key] === "string";
// Keep the node's leading/trailing whitespace (it separates inline
// siblings) but drop the source's internal line breaks — a multi-line
// paragraph in the HTML is one text node and must match its collapsed key.
var next = has
? src.match(/^\s*/)[0] + dict[key] + src.match(/\s*$/)[0]
: src;
if (next !== cur) node.nodeValue = next;
node.__i18nSrc = src;
node.__i18nOut = next;
}
function translateAttrs(el) {
for (var i = 0; i < ATTRS.length; i++) {
var a = ATTRS[i];
if (!el.hasAttribute(a)) continue;
var cur = el.getAttribute(a);
var orig = el.getAttribute("data-i18n-orig-" + a);
if (orig == null || el.getAttribute("data-i18n-out-" + a) !== cur) { orig = cur; el.setAttribute("data-i18n-orig-" + a, orig); }
var next = t(orig);
if (next !== cur) el.setAttribute(a, next);
el.setAttribute("data-i18n-out-" + a, next);
}
}
function walk(root) {
if (!root) return;
if (root.nodeType === 3) { if (!skip(root.parentNode)) translateText(root); return; }
if (root.nodeType !== 1 && root.nodeType !== 11) return;
if (root.nodeType === 1) {
if (skip(root)) return;
translateAttrs(root);
}
var tw = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null);
var n;
while ((n = tw.nextNode())) {
if (n.nodeType === 1) { if (!skip(n)) translateAttrs(n); }
else if (!skip(n.parentNode)) translateText(n);
}
}
function applyAll() {
applying = true;
try {
walk(document.body);
if (document.title) {
if (!document.__i18nTitle) document.__i18nTitle = document.title;
document.title = t(document.__i18nTitle);
}
document.documentElement.setAttribute("lang", lang);
} finally { applying = false; }
}
// Keep script-built content translated. Mutations we cause ourselves are
// ignored (applying flag); everything else is walked as it lands.
var observer = null;
function observe() {
if (observer || !window.MutationObserver) return;
observer = new MutationObserver(function (records) {
if (applying || !dict) return;
applying = true;
try {
for (var i = 0; i < records.length; i++) {
var r = records[i];
if (r.type === "characterData") { if (!skip(r.target.parentNode)) translateText(r.target); }
else if (r.type === "attributes") { if (r.target.nodeType === 1 && !skip(r.target)) translateAttrs(r.target); }
else for (var j = 0; j < r.addedNodes.length; j++) walk(r.addedNodes[j]);
}
} finally { applying = false; }
});
observer.observe(document.documentElement, {
childList: true, subtree: true, characterData: true,
attributes: true, attributeFilter: ATTRS,
});
}
// ---------- switching ----------
function setLang(code) {
code = normalise(code) || "en";
lang = code;
save(code);
return load(code).then(function (d) {
if (lang !== code) return;
dict = code === "en" ? null : d;
applyAll();
if (!dict) { document.documentElement.setAttribute("lang", "en"); }
refreshPicker();
}).catch(function () {
// Dictionary unreachable → stay on English rather than half-translate.
dict = null; lang = "en"; applyAll(); refreshPicker();
});
}
// ---------- the dropdown ----------
// A custom menu rather than a <select>: a native select cannot show
// flags, and emoji flags render as bare letters on Windows. Flags are
// tiny inline SVGs (3:2, simplified) so no third-party image request
// ever leaves the visitor's browser. Sits on the right of the top nav,
// just before the wallet button.
var FLAGS = {
en: '<rect width="60" height="40" fill="#012169"/><path d="M0 0L60 40M60 0L0 40" stroke="#fff" stroke-width="8"/><path d="M0 0L60 40M60 0L0 40" stroke="#C8102E" stroke-width="3"/><path d="M30 0V40M0 20H60" stroke="#fff" stroke-width="10"/><path d="M30 0V40M0 20H60" stroke="#C8102E" stroke-width="6"/>',
de: '<rect width="60" height="40" fill="#000"/><rect y="13.33" width="60" height="13.34" fill="#D00"/><rect y="26.67" width="60" height="13.33" fill="#FFCE00"/>',
el: '<rect width="60" height="40" fill="#0D5EAF"/><rect y="4.44" width="60" height="4.45" fill="#fff"/><rect y="13.33" width="60" height="4.45" fill="#fff"/><rect y="22.22" width="60" height="4.45" fill="#fff"/><rect y="31.11" width="60" height="4.45" fill="#fff"/><rect width="22.22" height="22.22" fill="#0D5EAF"/><rect x="8.89" width="4.44" height="22.22" fill="#fff"/><rect y="8.89" width="22.22" height="4.44" fill="#fff"/>',
ru: '<rect width="60" height="40" fill="#fff"/><rect y="13.33" width="60" height="13.34" fill="#0039A6"/><rect y="26.67" width="60" height="13.33" fill="#D52B1E"/>',
es: '<rect width="60" height="40" fill="#AA151B"/><rect y="10" width="60" height="20" fill="#F1BF00"/>',
fr: '<rect width="20" height="40" fill="#0055A4"/><rect x="20" width="20" height="40" fill="#fff"/><rect x="40" width="20" height="40" fill="#EF4135"/>',
pt: '<rect width="60" height="40" fill="#F00"/><rect width="24" height="40" fill="#060"/><circle cx="24" cy="20" r="7" fill="#FFE000"/><circle cx="24" cy="20" r="3.5" fill="#F00"/>',
};
var GLOBE = '<svg class="lp-globe" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3.5 3 14.5 0 18M12 3c-3 3.5-3 14.5 0 18"/></svg>';
var CARET = '<svg class="lp-caret" viewBox="0 0 10 6" aria-hidden="true"><path d="M1 1l4 4 4-4" fill="none" stroke="currentColor" stroke-width="1.6"/></svg>';
function flagSvg(code) {
return '<svg class="lp-flag" viewBox="0 0 60 40" aria-hidden="true">' + (FLAGS[code] || "") + "</svg>";
}
var picker = null, pickerBtn = null, pickerMenu = null;
function closePicker() {
if (!picker) return;
picker.classList.remove("open");
pickerBtn.setAttribute("aria-expanded", "false");
}
function openPicker() {
if (!picker) return;
picker.classList.add("open");
pickerBtn.setAttribute("aria-expanded", "true");
var active = pickerMenu.querySelector('[aria-selected="true"]');
if (active) active.focus();
}
function paintPicker() {
if (picker) return;
var css = document.createElement("style");
css.textContent =
".lang-picker{position:relative;margin-left:auto;font-family:var(--sans,inherit)}" +
".topnav .lang-picker + .profile-wrap,.topnav .lang-picker + a.portal{margin-left:8px}" +
".lp-btn{display:inline-flex;align-items:center;gap:7px;padding:5px 10px 5px 9px;border-radius:999px;" +
"background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);color:var(--mut,#b8c2d4);" +
"font:inherit;font-size:12.5px;line-height:1;cursor:pointer;transition:border-color .12s,color .12s,background .12s}" +
".lp-btn:hover,.lang-picker.open .lp-btn{color:var(--ink,#f1f4fa);border-color:rgba(214,255,61,.35);background:rgba(214,255,61,.08)}" +
".lp-globe{width:15px;height:15px;opacity:.85;flex:none}" +
".lp-flag{width:20px;height:14px;border-radius:2px;box-shadow:0 0 0 1px rgba(255,255,255,.14);flex:none}" +
".lp-caret{width:9px;height:9px;opacity:.7;transition:transform .15s;flex:none}" +
".lang-picker.open .lp-caret{transform:rotate(180deg)}" +
".lp-menu{position:absolute;right:0;top:calc(100% + 8px);min-width:200px;padding:6px;border-radius:12px;" +
"background:var(--panel,#141a24);border:1px solid rgba(255,255,255,.1);box-shadow:0 12px 32px rgba(0,0,0,.45);z-index:200;display:none}" +
".lang-picker.open .lp-menu{display:block}" +
".lp-opt{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:0;border-radius:8px;" +
"background:transparent;color:var(--mut,#b8c2d4);font:inherit;font-size:13.5px;text-align:left;cursor:pointer}" +
".lp-opt:hover,.lp-opt:focus-visible{background:rgba(255,255,255,.06);color:var(--ink,#f1f4fa);outline:none}" +
'.lp-opt[aria-selected="true"]{color:var(--acid,#d6ff3d);background:rgba(214,255,61,.08)}' +
".lp-opt .lp-code{margin-left:auto;font-family:var(--mono,monospace);font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;opacity:.55}" +
".lang-picker-float{position:fixed;bottom:20px;right:20px;z-index:99}" +
".lang-picker-inline{margin-left:0}" +
"@media (max-width:560px){.lp-name{display:none}}";
document.head.appendChild(css);
picker = document.createElement("div");
picker.className = "lang-picker";
picker.setAttribute("translate", "no");
pickerBtn = document.createElement("button");
pickerBtn.type = "button";
pickerBtn.className = "lp-btn";
pickerBtn.setAttribute("aria-haspopup", "listbox");
pickerBtn.setAttribute("aria-expanded", "false");
pickerBtn.setAttribute("aria-label", "Language");
pickerBtn.title = "Language";
pickerMenu = document.createElement("div");
pickerMenu.className = "lp-menu";
pickerMenu.setAttribute("role", "listbox");
pickerMenu.setAttribute("aria-label", "Language");
var html = "";
for (var code in LANGS) {
html += '<button type="button" class="lp-opt" role="option" data-lang="' + code + '" aria-selected="false" tabindex="-1">' +
flagSvg(code) + "<span>" + LANGS[code] + '</span><span class="lp-code">' + code + "</span></button>";
}
pickerMenu.innerHTML = html;
picker.appendChild(pickerBtn);
picker.appendChild(pickerMenu);
pickerBtn.addEventListener("click", function (e) {
e.stopPropagation();
if (picker.classList.contains("open")) closePicker(); else openPicker();
});
pickerMenu.addEventListener("click", function (e) {
var opt = e.target.closest ? e.target.closest("[data-lang]") : null;
if (!opt) return;
e.stopPropagation();
closePicker();
pickerBtn.focus();
setLang(opt.getAttribute("data-lang"));
});
picker.addEventListener("keydown", function (e) {
var opts = pickerMenu.querySelectorAll("[data-lang]");
var i = Array.prototype.indexOf.call(opts, document.activeElement);
if (e.key === "Escape") { closePicker(); pickerBtn.focus(); }
else if (e.key === "ArrowDown") { e.preventDefault(); if (!picker.classList.contains("open")) openPicker(); else opts[Math.min(i + 1, opts.length - 1)].focus(); }
else if (e.key === "ArrowUp") { e.preventDefault(); if (i > 0) opts[i - 1].focus(); }
});
document.addEventListener("click", closePicker);
var slot = document.querySelector("[data-lang-slot]");
var nav = document.querySelector(".topnav");
if (slot) { slot.replaceWith(picker); picker.classList.add("lang-picker-inline"); } else
if (nav) {
// Right side: directly before the wallet button (profile-wrap once
// profile-menu.js has wrapped the portal link, the bare link before
// that), after everything else.
// Order on the right: language · Dashboard (when signed in) · wallet.
var wallet = nav.querySelector(".dash-link") || nav.querySelector(".profile-wrap") || nav.querySelector("a.portal");
if (wallet) nav.insertBefore(picker, wallet); else nav.appendChild(picker);
} else {
picker.classList.add("lang-picker-float");
document.body.appendChild(picker);
}
refreshPicker();
}
function refreshPicker() {
if (!picker) return;
pickerBtn.innerHTML = GLOBE + flagSvg(lang) + '<span class="lp-name">' + (LANGS[lang] || lang) + "</span>" + CARET;
var opts = pickerMenu.querySelectorAll("[data-lang]");
for (var i = 0; i < opts.length; i++) {
opts[i].setAttribute("aria-selected", opts[i].getAttribute("data-lang") === lang ? "true" : "false");
}
}
// ---------- boot ----------
lang = detect();
var ready = lang === "en" ? Promise.resolve(null) : load(lang).then(function (d) { dict = d; return d; }).catch(function () { lang = "en"; return null; });
function boot() {
observe();
ready.then(function () { applyAll(); });
}
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", boot);
else boot();
// The picker is painted on `load`, after the deferred nav scripts
// (theme.js font pill, profile-menu.js wallet button) have laid out the
// top nav, so it lands in a stable spot on the right.
if (document.readyState === "complete") paintPicker();
else window.addEventListener("load", paintPicker);
window.siriusI18n = {
get lang() { return lang; },
langs: LANGS,
t: t,
setLang: setLang,
apply: function (root) { if (dict) { applying = true; try { walk(root || document.body); } finally { applying = false; } } },
};
})();

133
js/market.js Normal file
View file

@ -0,0 +1,133 @@
// Marketplace page: list the gateway's active offers and complete a purchase.
//
// A listing is the seller's partially signed transaction (see
// Argus/src/lib/market-tx.js). Buying = verify it locally, append our own
// funding inputs and the outputs that give us the certificate and update
// the registry, sign our inputs, broadcast. The seller's signature only
// stays valid while their certificate UTXO is unspent, so the gateway prunes
// stale offers and the buyer's broadcast is the final arbiter.
import * as BNS from "https://silentmode.st/js/bns-register.js?v=20260917market";
const API = "https://silentmode.st";
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
const fmtInt = (n) => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
const usd = (sats) => { const r = window.siriusPricing?.CHIPNET_SATS_PER_USD || 250000; const v = Number(sats) / r; return (window.siriusPricing?.formatUsd || ((n) => "$" + n.toFixed(2)))(Math.round(v * 100) / 100); };
const shortAddr = (a) => (a ? a.replace(/^[^:]+:/, "").slice(0, 8) + "…" + a.slice(-5) : "—");
let listings = [];
let wallet = null;
let selected = null;
async function restoreWallet() {
if (window.siriusWallet) return window.siriusWallet;
const S = window.siriusSession;
if (!S?.restore) return null;
try {
const s = await S.restore();
if (!s?.mnemonic) return null;
const w = await BNS.BuiltInWallet.fromMnemonic(s.mnemonic, BNS.CHIPNET_PREFIX, s.accountPath || undefined);
window.siriusWallet = w;
return w;
} catch { return null; }
}
async function load() {
const status = $("status");
try {
const r = await fetch(`${API}/api/market`, { cache: "no-store" });
if (!r.ok) throw new Error("API " + r.status);
const j = await r.json();
listings = (j.listings || []).map((l) => ({ ...l, label: l.name.split(".")[0], tld: l.tld || l.name.split(".").pop() }));
render();
} catch (e) { status.className = "status err"; status.textContent = "Could not load listings: " + (e.message || e); }
}
function render() {
const q = ($("q").value || "").toLowerCase().trim();
const sort = $("sort").value;
const tldSel = $("tld");
const tlds = [...new Set(listings.map((l) => l.tld))].sort();
const keep = tldSel.value;
tldSel.innerHTML = `<option value="">All TLDs</option>` + tlds.map((t) => `<option value="${esc(t)}"${t === keep ? " selected" : ""}>.${esc(t)}</option>`).join("");
let rows = listings.filter((l) => (!q || l.name.includes(q)) && (!tldSel.value || l.tld === tldSel.value));
rows.sort((a, b) => sort === "name" ? a.name.localeCompare(b.name) : sort === "new" ? Date.parse(b.created_at) - Date.parse(a.created_at) : Number(a.price_sats) - Number(b.price_sats));
$("count").textContent = `${rows.length} of ${listings.length}`;
const status = $("status");
document.querySelector(".toolbar").hidden = !listings.length;
if (!listings.length) {
status.hidden = true;
$("list").innerHTML = `<div class="empty big">
<div class="ico">🛒</div>
<h3>Nothing is for sale right now</h3>
<p>Names go on sale when their owners list them from the dashboard. Have one to sell, or want a fresh one instead?</p>
<div class="cta"><a class="btn acid" href="./portal.html#domains">Sell a name from your dashboard →</a><a class="btn ghost" href="./#search-input">Register a new name</a></div>
</div>`;
return;
}
status.hidden = false;
status.className = "status"; status.textContent = `${listings.length} name${listings.length === 1 ? "" : "s"} for sale. Prices are set by the sellers; you pay the price plus about 1,300 sat of chain dust and fee.`;
$("list").innerHTML = rows.length ? rows.map((l) => `
<div class="row">
<div class="n">${esc(l.label)}.<span class="tld">${esc(l.tld)}</span> ${wallet && l.seller === wallet.address ? '<span class="badge">yours</span>' : ""}</div>
<div class="price"><b>${fmtInt(l.price_sats)} sat</b><span>≈ ${esc(usd(l.price_sats))}</span></div>
<div><button class="btn acid small" data-buy="${esc(l.name)}" ${wallet && l.seller === wallet.address ? "disabled" : ""}>Buy →</button></div>
<div class="meta"><span>seller ${esc(shortAddr(l.seller))}</span><span>·</span><span>listed ${esc(new Date(l.created_at).toLocaleDateString())}</span><span>·</span><a href="${API}/bns/${encodeURIComponent(l.name)}/" target="_blank" rel="noopener">view site →</a></div>
</div>`).join("") : `<div class="empty">Nothing matches that filter.</div>`;
}
["q", "sort", "tld"].forEach((id) => $(id).addEventListener("input", render));
document.addEventListener("click", (e) => { const b = e.target.closest("[data-buy]"); if (b) openBuy(b.dataset.buy); });
// ---------- buy ----------
function setMsg(t, cls = "") { $("buy-msg").textContent = t; $("buy-msg").className = "msg " + cls; }
function push(t) { const log = $("buy-steps"); log.className = "steps on"; const d = document.createElement("div"); d.textContent = t; log.appendChild(d); log.scrollTop = 1e6; }
function openBuy(name) {
selected = listings.find((l) => l.name === name); if (!selected) return;
$("buy-name").textContent = name;
const price = BigInt(selected.price_sats);
const check = BNS.verifyListing(selected, { category: selected.category });
$("buy-kv").innerHTML = [
["Price", `${fmtInt(price)} sat (≈ ${esc(usd(price))})`],
["Seller", esc(selected.seller)],
["You receive", "the name's certificate, to your token address"],
["Offer check", check.ok ? "seller signature valid" : "INVALID: " + esc(check.error)],
["Extra", "≈ 1,600 sat dust + fee"],
].map(([k, v]) => `<div class="k">${k}</div><div class="v">${v}</div>`).join("");
$("buy-steps").className = "steps"; $("buy-steps").innerHTML = ""; setMsg("");
const canBuy = !!wallet && check.ok && wallet.address !== selected.seller;
$("buy-go").disabled = !canBuy; $("buy-go").textContent = "Buy — sign & broadcast";
$("buy-signin").hidden = !!wallet;
if (!wallet) setMsg("Sign in on the dashboard first — the purchase is signed with your wallet in this browser.");
$("buy").classList.add("open");
}
const closeBuy = () => $("buy").classList.remove("open");
$("buy-close").addEventListener("click", closeBuy); $("buy-cancel").addEventListener("click", closeBuy);
$("buy").addEventListener("click", (e) => { if (e.target === $("buy")) closeBuy(); });
$("buy-go").addEventListener("click", async () => {
if (!selected || !wallet) return;
const btn = $("buy-go"); btn.disabled = true; btn.textContent = "Buying…"; setMsg("");
let el = null;
try {
el = await BNS.connect(); push("connected to chipnet");
const utxos = await BNS.getUtxosForAddresses(el, wallet.watchedAddresses);
push(`wallet has ${utxos.filter((u) => !u.token).length} spendable coin(s)`);
const built = BNS.completeSale({ listing: selected, buyerAddress: wallet.address, buyerTokenAddress: wallet.tokenAddress, utxos, records: selected.records || {}, addressToLockingBytecode: BNS.addressToLockingBytecode });
push(`built sale · price ${fmtInt(built.costs.priceSats)} sat · fee ${built.costs.chainFeeSats} sat`);
const signed = BNS.signInputs(built.transaction, built.sourceOutputs, (h) => wallet.keyFor(h), { skip: [built.sellerInputIndex] });
push("signed your inputs (the seller's signature is already in place)");
const txid = await BNS.broadcast(el, signed.hex);
push("broadcast: " + txid);
setMsg(`Done. ${selected.name} is yours — it appears in your dashboard within a minute.`, "ok");
btn.textContent = "Bought ✓";
setTimeout(load, 3000);
} catch (e) {
const raw = String(e.message || e);
setMsg(/not enough funds/i.test(raw) ? `Not enough coins: ${raw}. Fund ${wallet.address} first.` : "Failed: " + raw, "err");
push("error: " + raw); btn.disabled = false; btn.textContent = "Buy — sign & broadcast";
} finally { try { el?.close?.(); } catch {} }
});
(async function boot() {
wallet = await restoreWallet();
await load();
})();

118
js/pin-escrow.js Normal file
View file

@ -0,0 +1,118 @@
// PIN-escrow for the Sirius.X built-in wallet.
//
// After a user signs in with their full password, they may set a 4–6 digit
// PIN. The wallet's mnemonic is encrypted with the PIN via PBKDF2 → AES-GCM
// and stored under localStorage."siriusPinBlob" (survives browser close, so
// next visit shows the PIN pad instead of the password field).
//
// Wrong PIN increments localStorage."siriusPinAttempts". After 3 wrong tries
// the PIN blob is destroyed and the user falls back to their full password —
// same UX pattern the Digibyte.x/web mobile wallet uses.
//
// Iteration counts are lower than the BuiltInWallet's 250k because a numeric
// PIN's key space is tiny anyway. The point of PIN encryption is "not
// plaintext in localStorage", not resistance to serious brute-force. Users
// keep the real password as their durable secret.
(() => {
const PIN_BLOB_KEY = "siriusPinBlob";
const PIN_ATTEMPTS_KEY = "siriusPinAttempts";
const MAX_ATTEMPTS = 3;
const PBKDF2_ITERATIONS = 50_000;
const enc = new TextEncoder();
const dec = new TextDecoder();
const b64 = (bytes) => btoa(String.fromCharCode(...new Uint8Array(bytes)));
const unb64 = (str) => Uint8Array.from(atob(str), (c) => c.charCodeAt(0));
async function deriveKey(pin, salt) {
const material = await crypto.subtle.importKey("raw", enc.encode(pin), "PBKDF2", false, ["deriveKey"]);
return crypto.subtle.deriveKey(
{ name: "PBKDF2", salt, iterations: PBKDF2_ITERATIONS, hash: "SHA-256" },
material,
{ name: "AES-GCM", length: 256 },
false,
["encrypt", "decrypt"],
);
}
function validPin(pin) {
return typeof pin === "string" && /^\d{4,6}$/.test(pin);
}
// Encrypt the mnemonic (or any string secret) with the PIN and stash it.
// Called right after a successful password unlock, when the user opts in
// to the PIN shortcut.
async function savePinBlob(secret, pin) {
if (!validPin(pin)) throw new Error("PIN must be 4-6 digits");
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12));
const key = await deriveKey(pin, salt);
const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, enc.encode(secret));
const blob = {
v: 1,
it: PBKDF2_ITERATIONS,
s: b64(salt),
iv: b64(iv),
ct: b64(ct),
};
localStorage.setItem(PIN_BLOB_KEY, JSON.stringify(blob));
localStorage.setItem(PIN_ATTEMPTS_KEY, "0");
}
// Try decrypting with the supplied PIN. On success returns the mnemonic
// and resets the attempt counter. On failure increments attempts and
// wipes the blob when the ceiling is hit (forcing password fallback).
async function tryUnlock(pin) {
const raw = localStorage.getItem(PIN_BLOB_KEY);
if (!raw) throw new Error("no PIN set on this device");
if (!validPin(pin)) throw new Error("PIN must be 4-6 digits");
const blob = JSON.parse(raw);
try {
const key = await deriveKey(pin, unb64(blob.s));
const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv: unb64(blob.iv) }, key, unb64(blob.ct));
const secret = dec.decode(pt);
localStorage.setItem(PIN_ATTEMPTS_KEY, "0");
return secret;
} catch {
const now = (parseInt(localStorage.getItem(PIN_ATTEMPTS_KEY) || "0", 10) || 0) + 1;
if (now >= MAX_ATTEMPTS) {
localStorage.removeItem(PIN_BLOB_KEY);
localStorage.removeItem(PIN_ATTEMPTS_KEY);
const err = new Error("PIN locked — enter your full password to continue");
err.locked = true;
throw err;
}
localStorage.setItem(PIN_ATTEMPTS_KEY, String(now));
const err = new Error(`Wrong PIN — ${MAX_ATTEMPTS - now} attempt${MAX_ATTEMPTS - now === 1 ? "" : "s"} left`);
err.attemptsRemaining = MAX_ATTEMPTS - now;
throw err;
}
}
function hasPin() {
try { return !!localStorage.getItem(PIN_BLOB_KEY); } catch { return false; }
}
function attemptsUsed() {
try { return parseInt(localStorage.getItem(PIN_ATTEMPTS_KEY) || "0", 10) || 0; } catch { return 0; }
}
function attemptsRemaining() {
return Math.max(0, MAX_ATTEMPTS - attemptsUsed());
}
function clear() {
try { localStorage.removeItem(PIN_BLOB_KEY); localStorage.removeItem(PIN_ATTEMPTS_KEY); } catch {}
}
window.siriusPin = {
savePinBlob,
tryUnlock,
hasPin,
attemptsUsed,
attemptsRemaining,
clear,
MAX_ATTEMPTS,
};
})();

230
js/pricing.js Normal file
View file

@ -0,0 +1,230 @@
// Sirius.X pricing model — deterministic per-label cost so users can predict
// what a name or TLD will cost before they click Register. Public tiers only;
// operator-level discounts and coupon overrides land in a future revision
// (the plan is oracle-fed rates + coupon-code redemption at mint time).
//
// Two layers decide what a NAME costs:
// 1. The TLD owner's on-chain policy (`price`, `hidden`, `policy`) — read
// from the gateway's /api/tlds snapshot of the TLD beacon. A TLD owner
// who sets `price: 7` sells every name under that TLD for $7, flat.
// 2. Otherwise the length tiers below.
//
// Exposed as window.siriusPricing so both the register-flow modal and the
// inline search widgets on landing/tld.html use one source of truth.
(() => {
// Chipnet placeholder rate: mainnet swaps this for a real BCH/USD oracle.
// The numbers keep the demo transactions in the "few chipnet coins" range
// so a single faucet visit covers a name or a TLD.
const CHIPNET_SATS_PER_USD = 250_000;
const usdToSats = (usd) => BigInt(Math.max(0, Math.round(Number(usd) * CHIPNET_SATS_PER_USD)));
const cleanLabel = (s) => String(s || "").toLowerCase().replace(/[^a-z0-9-]/g, "");
// ---------- TLD owner policies ----------
// tld -> { price, hidden, frozen, policy, owner, records }
// Filled from /api/tlds (see loadTldPolicies). Unknown TLDs fall through
// to tier pricing and are treated as sellable, so a gateway blip never
// blocks a purchase; the chain is the authority at mint time anyway.
// include_hidden=1 so the policy map knows about switched-off (private)
// TLDs too — their owners register names under them from the portal, and
// the register flow must be able to price and gate them. The public
// listing (visibleTlds) still drops anything hidden.
const TLD_API = "https://navigate.st/api/tlds?include_hidden=1";
const TLD_POLICIES = new Map();
let tldList = null; // raw /api/tlds rows, once loaded (hidden ones excluded)
let tldLoad = null; // memoised in-flight fetch
function normalisePolicy(row) {
const rec = row && row.records && typeof row.records === "object" ? row.records : {};
const priceRaw = row && row.price_usd != null ? row.price_usd : rec.price;
const price = typeof priceRaw === "number" && Number.isFinite(priceRaw) && priceRaw >= 0 ? priceRaw : null;
const hidden = !!(row && row.hidden) || rec.hidden === 1 || rec.hidden === true;
const policy = typeof rec.policy === "string" ? rec.policy : "open";
return {
tld: row.tld,
price,
hidden,
hiddenBy: row && row.hidden_by ? row.hidden_by : (hidden ? "owner" : null),
frozen: policy === "frozen",
// cosign: anyone may register, but the TLD owner must co-sign the
// registration (indexers reject a REG under a cosign/hidden TLD that
// does not carry the TLD certificate). hidden implies the same rule
// on chain; in the UI hidden is owner-only, cosign is request-based.
cosign: policy === "cosign",
policy,
category: row && row.category ? row.category : null,
owner: row && row.owner ? row.owner : null,
records: rec,
};
}
function setTldPolicies(rows) {
TLD_POLICIES.clear();
for (const r of rows || []) {
const row = typeof r === "string" ? { tld: r } : r;
const tld = cleanLabel(row && row.tld);
if (!tld) continue;
TLD_POLICIES.set(tld, normalisePolicy({ ...row, tld }));
}
}
// Fetch the TLD list once per page. Resolves to the array of visible TLD
// rows (or null on failure) — never rejects, callers just fall back.
function loadTldPolicies({ url = TLD_API, force = false } = {}) {
if (tldLoad && !force) return tldLoad;
tldLoad = (async () => {
try {
const r = await fetch(url, { cache: "no-store" });
if (!r.ok) throw new Error("api " + r.status);
const j = await r.json();
const rows = Array.isArray(j.tlds) ? j.tlds : [];
setTldPolicies(rows);
// Only a beacon-sourced list is a sellable list. A gateway still
// serving the legacy `tlds.bch`-derived union includes every suffix
// that ever appeared on a name (".de", ".silentmode", …), which is
// not what the registry sells — keep the page's own fallback then.
tldList = j.source === "TLD_BEACON" ? rows.filter((t) => !t.hidden) : null;
return tldList;
} catch {
return null;
}
})();
return tldLoad;
}
// Resolves once the list is loaded, or after `ms` — search UIs await this
// so the first paint already shows owner prices without ever hanging.
function tldReady(ms = 2500) {
return Promise.race([
loadTldPolicies(),
new Promise((res) => setTimeout(() => res(null), ms)),
]);
}
function tldPolicy(tld) {
return TLD_POLICIES.get(cleanLabel(tld)) || null;
}
// Does one of `addresses` (the signed-in wallet's) hold this TLD's NFT?
// `owner` comes from the gateway's beacon snapshot (mint output, updated
// on every TUPD carrier), so a wallet that owns the TLD matches here.
function isTldOwner(tld, addresses) {
const p = tldPolicy(tld);
if (!p || !p.owner || !addresses) return false;
const list = Array.isArray(addresses) ? addresses : [addresses];
return list.some((a) => typeof a === "string" && a === p.owner);
}
// Can names be sold under this TLD right now?
// hidden → owner switched the TLD off: private TLD. The public cannot
// buy, but the OWNER still can — pass their wallet addresses
// and a hidden TLD they hold answers ok with owner: true.
// frozen → owner set policy "frozen" (no new registrations, owner included)
function tldSellable(tld, addresses) {
const p = tldPolicy(tld);
if (!p) return { ok: true, reason: null, owner: false };
const owner = isTldOwner(tld, addresses);
if (p.frozen) return { ok: false, reason: "frozen", policy: p, owner };
if (p.hidden && !owner) return { ok: false, reason: "hidden", policy: p, owner };
// Sellable, but the registration needs the owner's co-signature: the
// flow builds the request and parks it in the gateway's approval queue.
if (p.cosign && !owner) return { ok: true, reason: "cosign", policy: p, owner };
return { ok: true, reason: null, policy: p, owner };
}
// Visible TLD labels in listing order, or null if no beacon-sourced list
// is available (callers keep their own fallback list then).
function visibleTlds() {
return tldList ? tldList.map((t) => t.tld) : null;
}
// ---------- name pricing ----------
// Owner-set flat price first; else LENGTH-first tiers, then downshift for
// "less brandable" shapes (all-digits, hyphenated). Kept as multiplicative
// modifiers so tiers remain the primary story and mods just soften an
// edge case.
function priceForName(label, tld) {
const s = cleanLabel(label);
if (!s) return { usd: 0, tier: "invalid" };
const p = tld ? tldPolicy(tld) : null;
if (p && p.price != null) {
return { usd: p.price, tier: "tld-set", sats: usdToSats(p.price), tld: p.tld, ownerSet: true };
}
let usd, tier;
if (s.length === 1) { usd = 5.00; tier = "premium-1"; }
else if (s.length === 2) { usd = 3.00; tier = "short-2"; }
else if (s.length === 3) { usd = 2.00; tier = "short-3"; }
else if (s.length <= 5) { usd = 1.00; tier = "standard"; }
else if (s.length <= 7) { usd = 0.50; tier = "long"; }
else if (s.length <= 16) { usd = 0.25; tier = "extended"; }
else { usd = 0.10; tier = "very-long"; }
// Modifiers.
if (/^\d+$/.test(s)) { usd = round2(usd * 0.5); tier += "+digits"; }
if (s.includes("-")) { usd = round2(usd * 0.7); tier += "+hyphen"; }
return { usd, tier, sats: usdToSats(usd) };
}
// Per-label overrides — TLDs the operator wants priced outside the tiers.
// Cheap namespaces (`.test`, `.dev`, `.local`) exist for experimentation,
// school assignments and demo throwaways: length-tier pricing prices them
// like premium TLDs, which isn't the point. Add labels here to opt them
// out of the tier and (optionally) mark them renewal-free.
//
// Shape: label -> { usd, tier, noRenewal? }
const SPECIAL_TLDS = {
"test": { usd: 0.01, tier: "sandbox", noRenewal: true },
};
function priceForTld(label) {
const s = cleanLabel(label);
if (!s) return { usd: 0, tier: "invalid" };
if (Object.prototype.hasOwnProperty.call(SPECIAL_TLDS, s)) {
const o = SPECIAL_TLDS[s];
return { usd: o.usd, tier: o.tier, sats: usdToSats(o.usd), noRenewal: !!o.noRenewal };
}
let usd, tier;
if (s.length === 1) { usd = 500.00; tier = "premium-1"; }
else if (s.length === 2) { usd = 250.00; tier = "short-2"; }
else if (s.length === 3) { usd = 150.00; tier = "short-3"; }
else if (s.length <= 6) { usd = 100.00; tier = "standard"; }
else if (s.length <= 10) { usd = 50.00; tier = "long"; }
else { usd = 25.00; tier = "extended"; }
return { usd, tier, sats: usdToSats(usd) };
}
// Rounded USD → display string. Under $1 shows cents ($0.25); $1 and up
// shows whole dollars ($5) unless there's a fractional part.
function formatUsd(usd) {
const n = Number(usd || 0);
if (n >= 1 && n === Math.floor(n)) return `$${n}`;
return `$${n.toFixed(2)}`;
}
function formatSats(sats) {
return `${BigInt(sats || 0n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} sat`;
}
function round2(n) { return Math.round(Number(n) * 100) / 100; }
window.siriusPricing = {
priceForName,
priceForTld,
formatUsd,
formatSats,
usdToSats,
CHIPNET_SATS_PER_USD,
// TLD owner policy layer
loadTldPolicies,
setTldPolicies,
tldReady,
tldPolicy,
tldSellable,
isTldOwner,
visibleTlds,
TLD_API,
};
// Warm the policy cache as soon as the script lands; every consumer
// awaits tldReady() before it paints a price.
loadTldPolicies();
})();

343
js/profile-menu.js Normal file
View file

@ -0,0 +1,343 @@
// Transforms the "🔑 Sign in" nav pill on every Sirius.X page into a wallet
// dropdown. Reads siriusProfile from localStorage; when null shows the three
// onboarding actions (New wallet / Import a phrase / WizardConnect), when
// present shows the signed-in menu (address, My names, Admin, Sign out).
//
// Each onboarding action deep-links portal.html?mode=new|import|wc; portal.html
// picks that up and immediately runs the matching flow — no extra click on
// arrival. Signed-in state changes flip the button label without a reload:
// the storage event covers cross-tab, a custom 'siriusProfileChanged' event
// covers same-tab (portal.html and tld.html both dispatch it on write/clear).
(() => {
const anchor = document.querySelector(".topnav a.portal");
if (!anchor) return;
// Base URL for local links — the nav's brand link is already set with the
// right relative path per page (./ at root, ../ in subdirs). Reuse it so
// absolute /sirius-x/... paths (which break under the BCNR route) never
// slip in.
const PORTAL_URL = anchor.getAttribute("href") || "./portal.html";
const BASE = PORTAL_URL.replace(/portal\.html.*$/, "");
const ADMIN_URL = BASE + "admin/";
const readProfile = () => {
try { return JSON.parse(localStorage.getItem("siriusProfile") || "null"); } catch { return null; }
};
// Build wrapper + button + (empty) menu around the existing pill.
const wrap = document.createElement("div");
wrap.className = "profile-wrap";
const btn = document.createElement("button");
btn.type = "button";
btn.className = anchor.className; // reuse .portal (and .here if present)
btn.setAttribute("aria-haspopup", "menu");
btn.setAttribute("aria-expanded", "false");
const menu = document.createElement("div");
menu.className = "profile-menu";
menu.setAttribute("role", "menu");
menu.hidden = true;
// Header "Dashboard" button — sits left of the wallet pill and is the one
// way into names, TLDs, the web-builder and (for the operator) the admin
// panel. Always visible: signed out it lands on the portal's sign-in.
const dash = document.createElement("a");
dash.className = "dash-link" + (/\/portal\.html(?:$|[?#])/.test(location.pathname) ? " here" : "");
dash.href = PORTAL_URL;
dash.innerHTML = `<span aria-hidden="true">▦</span> Dashboard`;
const readWalletInfo = () => {
try { return JSON.parse(localStorage.getItem("siriusWalletInfo") || "null"); } catch { return null; }
};
const fmtInt = (n) => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// ---------- render ----------
// Re-renders the button label AND the menu innerHTML from the current
// profile in localStorage. Called at load, on every open(), and whenever
// another tab or this tab updates the storage key.
function render() {
const p = readProfile();
if (p) {
const dot = `<span class="wallet-dot ok" aria-hidden="true"></span>`;
const label = shortAddr(p.address);
const sourceBadge = p.source === "wc"
? `<span class="wallet-src">WC</span>`
: `<span class="wallet-src">seed</span>`;
btn.innerHTML = `${dot}<span class="wallet-label">${escapeAttr(label)}</span>${sourceBadge}<span class="wallet-caret" aria-hidden="true">▾</span>`;
btn.setAttribute("aria-label", `Wallet ${label}, signed in via ${p.source || "seed"}`);
// Wallet-only menu: identity, balance, receive, settings, sign out.
// Names/TLDs/admin live behind the Dashboard button next to this one.
const info = readWalletInfo();
const bal = info?.sats != null ? `${fmtInt(info.sats)} sat` : "—";
const held = info ? `${info.names ?? 0} name${info.names === 1 ? "" : "s"} · ${info.tlds ?? 0} TLD${info.tlds === 1 ? "" : "s"}` : "open the dashboard to load";
menu.innerHTML = `
<div class="profile-header">
<span class="profile-hint">Signed in via ${escapeAttr(p.source === "wc" ? "WizardConnect" : "seed phrase")} · chipnet</span>
<code>${escapeAttr(p.address)}</code>
</div>
<div class="wallet-stats">
<div><span class="ws-k">Balance</span><span class="ws-v">${escapeAttr(bal)}</span></div>
<div><span class="ws-k">Holdings</span><span class="ws-v">${escapeAttr(held)}</span></div>
</div>
<a href="#" role="menuitem" data-action="copy" data-copy="${escapeAttr(p.address)}">
<span class="mi-ic">⧉</span>
<span class="mi-body"><b>Copy address</b><span class="mi-hint">receive coins or names here</span></span>
</a>
${p.tokenAddress ? `<a href="#" role="menuitem" data-action="copy" data-copy="${escapeAttr(p.tokenAddress)}">
<span class="mi-ic">🎟</span>
<span class="mi-body"><b>Copy token address</b><span class="mi-hint">where name certificates are minted</span></span>
</a>` : ""}
<a href="https://tbch.googol.cash/" target="_blank" rel="noopener" role="menuitem">
<span class="mi-ic">🚰</span>
<span class="mi-body"><b>Get test coins</b><span class="mi-hint">chipnet faucet</span></span>
</a>
<a href="${PORTAL_URL}#settings" role="menuitem">
<span class="mi-ic">⚙</span>
<span class="mi-body"><b>Wallet settings</b><span class="mi-hint">session, PIN, forget device</span></span>
</a>
<hr>
<a href="#" role="menuitem" data-action="signout">
<span class="mi-ic">🚪</span>
<span class="mi-body"><b>Sign out</b><span class="mi-hint">clear this browser</span></span>
</a>
`;
} else {
const dot = `<span class="wallet-dot" aria-hidden="true"></span>`;
btn.innerHTML = `${dot}<span class="wallet-label">Wallet</span><span class="wallet-caret" aria-hidden="true">▾</span>`;
btn.setAttribute("aria-label", "Wallet — not signed in");
// If a saved encrypted wallet already exists in this browser (created
// in a previous session), surface an Unlock option as the first item so
// users can sign back into the same wallet the mint flow would use —
// instead of hunting for it inside the Register modal's wallet-choice.
const hasSaved = (() => {
try { return !!localStorage.getItem("bns.wallet.v1"); } catch { return false; }
})();
const unlockItem = hasSaved ? `
<a href="#" role="menuitem" data-action="unlock">
<span class="mi-ic">🔓</span>
<span class="mi-body"><b>Unlock my wallet</b><span class="mi-hint">one you already created on this device</span></span>
</a>
<hr>
` : "";
const headerHint = hasSaved
? `<span class="profile-hint">Locked wallet on this device</span><span class="profile-sub">Unlock or pick another action</span>`
: `<span class="profile-hint">No wallet yet</span><span class="profile-sub">Pick how to sign in</span>`;
// Four direct actions — each opens the shared modal at the matching
// step (Unlock/Create/Import/WizardConnect) with tabs across the top
// of the modal so the user can switch between them without going back
// to a landing screen.
menu.innerHTML = `
<div class="profile-header">${headerHint}</div>
${unlockItem}
<a href="#" role="menuitem" data-action="new">
<span class="mi-ic">🆕</span>
<span class="mi-body"><b>Create a wallet</b><span class="mi-hint">generate a fresh 12-word phrase (sign up)</span></span>
</a>
<a href="#" role="menuitem" data-action="import">
<span class="mi-ic">📥</span>
<span class="mi-body"><b>Import a wallet</b><span class="mi-hint">seed phrase you already have (sign in)</span></span>
</a>
<a href="#" role="menuitem" data-action="wc">
<span class="mi-ic">🔗</span>
<span class="mi-body"><b>WizardConnect</b><span class="mi-hint">Cashonize / Paytaca via QR</span></span>
</a>
`;
}
}
render();
// ---------- open/close ----------
// Opening the menu asks the dashboard (when it is the current page) for a
// fresh electrum balance; the numbers repaint when it arrives. Other pages
// show the last figure the dashboard or a sign-in wrote, with its age.
const open = () => {
render(); menu.hidden = false; btn.setAttribute("aria-expanded", "true");
if (typeof window.siriusRefreshBalance === "function") { try { window.siriusRefreshBalance(); } catch {} }
};
window.addEventListener("sirius:balance", () => { if (!menu.hidden) render(); });
const close = () => { menu.hidden = true; btn.setAttribute("aria-expanded", "false"); };
btn.addEventListener("click", (e) => { e.stopPropagation(); menu.hidden ? open() : close(); });
document.addEventListener("click", (e) => { if (!wrap.contains(e.target)) close(); });
document.addEventListener("keydown", (e) => { if (e.key === "Escape") close(); });
// Cross-tab (storage event fires only in other tabs) + same-tab (portal.html
// dispatches this after writing/clearing) — either wakes render().
window.addEventListener("storage", (e) => { if (e.key === "siriusProfile") render(); });
window.addEventListener("siriusProfileChanged", render);
// ---------- menu actions ----------
// Sign-out clears siriusProfile; the wallet-onboarding items (new/import/wc)
// open the shared mint modal inline (register-flow.js). If the page did not
// ship register-flow.js in its own <script>, load it on demand.
const FLOW_URL = "js/register-flow.js?v=20260907signin";
async function ensureFlow() {
if (typeof window.siriusSignInWallet === "function") return true;
try {
// Same base as the nav portal anchor — works from root pages and
// subdirs equally (../ vs ./ handled by BASE).
await import(BASE + FLOW_URL);
// Its top-level code exposes the global synchronously after the
// module graph resolves; still, wait a tick for definiteness.
for (let i = 0; i < 50 && typeof window.siriusSignInWallet !== "function"; i++) {
await new Promise((r) => setTimeout(r, 30));
}
return typeof window.siriusSignInWallet === "function";
} catch { return false; }
}
menu.addEventListener("click", async (e) => {
const t = e.target.closest("[data-action]");
if (!t) return;
e.preventDefault();
const action = t.dataset.action;
if (action === "copy") {
try { await navigator.clipboard?.writeText(t.dataset.copy || ""); } catch {}
const b = t.querySelector("b"); const orig = b?.textContent;
if (b) { b.textContent = "Copied"; setTimeout(() => { b.textContent = orig; }, 1200); }
return;
}
if (action === "signout") {
try { localStorage.removeItem("siriusProfile"); } catch {}
// Also wipe the PIN blob so a signed-out device can't be quick-
// unlocked with a stale PIN. The password-encrypted BuiltInWallet
// blob (bns.wallet.v1) stays — the user's device, the user's data;
// they'd remove it explicitly via 'forget wallet' in a future
// settings screen.
try { window.siriusPin?.clear(); } catch {}
try { delete window.siriusWallet; } catch { window.siriusWallet = null; }
// End the persistent device session too (js/session.js) — otherwise
// the next visit would sign straight back in.
try { await window.siriusSession?.forget?.(); } catch {}
window.dispatchEvent(new Event("siriusProfileChanged"));
// Reload so any signed-in section on the current page (portal, tld) resets.
location.reload();
return;
}
if (["new", "import", "wc", "unlock"].includes(action)) {
close();
// Always route to the portal — it renders the tabbed sign-in INLINE
// as page content (?mode=X picks the starting tab). Prevents the
// "modal opens on top of the page" symptom the launcher used to have.
// Only stay on-page if we're already on portal.html.
const onPortal = /\/portal\.html(?:$|[?#])/.test(location.pathname + location.search);
if (onPortal && typeof window.siriusRenderSignInInline === "function") {
const hasSaved = (() => { try { return !!localStorage.getItem("bns.wallet.v1"); } catch { return false; } })();
const mode = (action === "unlock" && !hasSaved) ? "import" : action;
const mount = document.getElementById("signin-inline");
if (mount) {
window.siriusRenderSignInInline(mount, mode);
document.getElementById("signin")?.scrollIntoView({ behavior: "smooth", block: "start" });
return;
}
}
// Not on portal (or the inline mount is missing) — take the user
// there. portal.html?mode=X renders the tabbed sign-in as its main
// content, no modal.
location.href = PORTAL_URL + "?mode=" + action;
}
});
wrap.appendChild(btn);
wrap.appendChild(menu);
anchor.replaceWith(wrap);
wrap.parentNode.insertBefore(dash, wrap);
render(); // dash visibility depends on the profile
// ---------- inline CSS ----------
if (!document.getElementById("profile-menu-css")) {
const s = document.createElement("style");
s.id = "profile-menu-css";
s.textContent = `
.topnav .profile-wrap{position:relative;margin-left:auto}
/* Phones: the bar was wrapping into four rows. Drop the font-comparison
pill, tighten link padding, and shrink the two buttons. */
@media (max-width:640px){
.topnav{padding:8px 10px;gap:0}
.topnav .font-picker{display:none !important}
.topnav > a{padding:5px 8px;font-size:13px}
.topnav .brand{margin-right:6px}
.topnav .dash-link{padding:5px 9px;font-size:12.5px}
.topnav .profile-wrap button.portal{padding:5px 9px;font-size:12.5px}
.topnav .profile-wrap .wallet-label{max-width:88px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
.topnav .dash-link{margin-left:auto;display:inline-flex;align-items:center;gap:6px;
padding:6px 12px;border-radius:999px;font-size:13.5px;font-weight:500;text-decoration:none;
color:var(--ink,#f1f4fa);background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12)}
.topnav .dash-link:hover{background:rgba(255,255,255,.1)}
.topnav .dash-link.here{color:var(--acid,#d6ff3d);border-color:rgba(214,255,61,.35);background:rgba(214,255,61,.08)}
.topnav .dash-link[hidden]{display:none}
.topnav .dash-link + .profile-wrap{margin-left:8px}
.topnav .lang-picker + .dash-link{margin-left:8px}
.topnav .profile-menu .wallet-stats{display:grid;grid-template-columns:1fr 1fr;gap:6px;padding:6px 4px 10px;border-bottom:1px solid rgba(255,255,255,.08);margin-bottom:4px}
.topnav .profile-menu .wallet-stats > div{background:rgba(255,255,255,.04);border-radius:9px;padding:8px 10px;display:flex;flex-direction:column;gap:2px}
.topnav .profile-menu .ws-k{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:#8b98a9;font-weight:600}
.topnav .profile-menu .ws-v{font-size:12.5px;color:#e7eaf1;font-family:ui-monospace,monospace}
.topnav .profile-wrap button.portal{
display:inline-flex;align-items:center;gap:8px;
cursor:pointer;font-family:inherit;font-size:13.5px;font-weight:500;
padding:6px 12px 6px 10px;border-radius:999px;
background:rgba(214,255,61,.10);color:var(--acid);
border:1px solid rgba(214,255,61,.22);transition:background .1s,border-color .1s
}
.topnav .profile-wrap button.portal:hover{background:rgba(214,255,61,.16);border-color:rgba(214,255,61,.35)}
.topnav .profile-wrap button.portal[aria-expanded="true"]{background:rgba(214,255,61,.20)}
.topnav .profile-wrap .wallet-dot{
width:7px;height:7px;border-radius:50%;background:rgba(139,152,169,.45);
box-shadow:0 0 0 2px rgba(139,152,169,.10)
}
.topnav .profile-wrap .wallet-dot.ok{
background:#4fd1a5;box-shadow:0 0 0 2px rgba(79,209,165,.20)
}
.topnav .profile-wrap .wallet-label{font-family:ui-monospace,monospace;font-size:12.5px;letter-spacing:.2px}
.topnav .profile-wrap .wallet-src{
font-size:9.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
padding:2px 6px;border-radius:4px;background:rgba(214,255,61,.15);color:var(--acid);
margin-left:2px
}
.topnav .profile-wrap .wallet-caret{opacity:.6;font-size:11px;margin-left:2px}
.topnav .profile-menu{
position:absolute;right:0;top:calc(100% + 8px);
min-width:280px;z-index:30;
background:rgba(18,24,34,.98);backdrop-filter:blur(12px);
border:1px solid rgba(255,255,255,.12);border-radius:14px;
padding:8px;display:flex;flex-direction:column;gap:2px;
box-shadow:0 12px 40px rgba(0,0,0,.55),0 0 0 1px rgba(0,0,0,.4)
}
.topnav .profile-menu[hidden]{display:none}
.topnav .profile-menu > a{
display:grid;grid-template-columns:24px 1fr;gap:12px;align-items:center;
padding:9px 11px;border-radius:9px;
color:#e7eaf1;text-decoration:none;transition:background .08s
}
.topnav .profile-menu > a:hover{background:rgba(214,255,61,.10)}
.topnav .profile-menu > a:hover .mi-ic{filter:brightness(1.2)}
.topnav .profile-menu .mi-ic{font-size:17px;line-height:1;text-align:center}
.topnav .profile-menu .mi-body{display:flex;flex-direction:column;gap:1px;font-size:13.5px;font-weight:600;color:#e7eaf1}
.topnav .profile-menu .mi-hint{font-weight:400;font-size:11.5px;color:#8b98a9;letter-spacing:.1px}
.topnav .profile-menu hr{border:0;border-top:1px solid rgba(255,255,255,.08);margin:4px 2px}
.topnav .profile-menu .profile-header{
padding:8px 11px 12px;display:flex;flex-direction:column;gap:4px;
border-bottom:1px solid rgba(255,255,255,.08);margin-bottom:4px
}
.topnav .profile-menu .profile-hint{
color:#8b98a9;font-size:11px;text-transform:uppercase;letter-spacing:.4px;font-weight:600
}
.topnav .profile-menu .profile-sub{color:#5e6678;font-size:12px}
.topnav .profile-menu code{
font-family:ui-monospace,monospace;font-size:11.5px;
color:#e7eaf1;word-break:break-all;background:transparent;padding:0;border:0
}
`;
document.head.appendChild(s);
}
// ---------- helpers ----------
function shortAddr(a) {
if (!a) return "wallet";
const i = a.indexOf(":");
const body = i > 0 ? a.slice(i + 1) : a;
return body.slice(0, 6) + "…" + body.slice(-4);
}
function escapeAttr(s) {
return String(s).replace(/[&<>"']/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;","\"":"&quot;","'":"&#39;"}[c]));
}
})();

1336
js/register-flow.js Normal file

File diff suppressed because it is too large Load diff

141
js/session.js Normal file
View file

@ -0,0 +1,141 @@
// Sirius.X persistent sign-in ("stay signed in on this device").
//
// Problem: every visit asked for the seed phrase, the password or the PIN
// again. A dashboard people come back to daily cannot work like that.
//
// Model: after one successful sign-in the wallet's recovery phrase is
// encrypted with a random AES-GCM key that lives ONLY inside IndexedDB as a
// non-extractable CryptoKey (the browser can use it, scripts cannot read
// its bytes). The ciphertext sits in localStorage. On the next visit the
// dashboard decrypts silently and the user is in — no prompt. Signing out,
// or turning "stay signed in" off in Settings, destroys both halves.
//
// Trust boundary, stated honestly: this is a device session, like a
// "remember me" cookie. Anyone who can run scripts in this browser profile
// can use the wallet while the session exists. The password-encrypted
// wallet blob (bns.wallet.v1) and the optional PIN escrow are unchanged and
// still the durable secrets. Users who want a prompt before every payment
// can keep that in Settings ("Ask for PIN before payments").
//
// window.siriusSession = { isEnabled, setEnabled, remember, restore, forget,
// requirePinForPayments, setRequirePinForPayments }
(() => {
const DB = "sirius-session";
const STORE = "keys";
const KEY_ID = "device";
const BLOB = "siriusSessionBlob";
const ENABLED = "siriusStaySignedIn"; // "0" = off; anything else = on (default on)
const REQUIRE_PIN = "siriusRequirePin"; // "1" = ask PIN before payments (default off)
const enc = new TextEncoder();
const dec = new TextDecoder();
const b64 = (bytes) => btoa(String.fromCharCode(...new Uint8Array(bytes)));
const unb64 = (str) => Uint8Array.from(atob(str), (c) => c.charCodeAt(0));
function openDb() {
return new Promise((resolve, reject) => {
if (!("indexedDB" in window)) return reject(new Error("IndexedDB unavailable"));
const req = indexedDB.open(DB, 1);
req.onupgradeneeded = () => { req.result.createObjectStore(STORE); };
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error || new Error("IndexedDB open failed"));
});
}
function idbGet(db, key) {
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE, "readonly");
const req = tx.objectStore(STORE).get(key);
req.onsuccess = () => resolve(req.result || null);
req.onerror = () => reject(req.error);
});
}
function idbPut(db, key, value) {
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE, "readwrite");
tx.objectStore(STORE).put(value, key);
tx.oncomplete = () => resolve();
tx.onerror = () => reject(tx.error);
});
}
function idbDel(db, key) {
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE, "readwrite");
tx.objectStore(STORE).delete(key);
tx.oncomplete = () => resolve();
tx.onerror = () => reject(tx.error);
});
}
async function deviceKey(create) {
const db = await openDb();
try {
let key = await idbGet(db, KEY_ID);
if (!key && create) {
key = await crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
await idbPut(db, KEY_ID, key);
}
return key;
} finally { db.close(); }
}
function isEnabled() {
try { return localStorage.getItem(ENABLED) !== "0"; } catch { return true; }
}
function setEnabled(on) {
try { localStorage.setItem(ENABLED, on ? "1" : "0"); } catch {}
if (!on) forget();
}
function requirePinForPayments() {
try { return localStorage.getItem(REQUIRE_PIN) === "1"; } catch { return false; }
}
function setRequirePinForPayments(on) {
try { localStorage.setItem(REQUIRE_PIN, on ? "1" : "0"); } catch {}
}
function hasSession() {
try { return !!localStorage.getItem(BLOB); } catch { return false; }
}
// Encrypt and store the recovery phrase for silent restore. `meta` may
// carry { accountPath } for wallets derived on a non-default path.
async function remember(mnemonic, meta = {}) {
if (!isEnabled() || !mnemonic) return false;
try {
const key = await deviceKey(true);
const iv = crypto.getRandomValues(new Uint8Array(12));
const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, enc.encode(mnemonic));
localStorage.setItem(BLOB, JSON.stringify({ v: 1, iv: b64(iv), ct: b64(ct), at: Date.now(), path: meta.accountPath || null }));
return true;
} catch { return false; }
}
// Silent restore. Resolves { mnemonic, accountPath } or null. Never throws.
async function restore() {
if (!isEnabled()) return null;
let raw = null;
try { raw = localStorage.getItem(BLOB); } catch {}
if (!raw) return null;
try {
const blob = JSON.parse(raw);
const key = await deviceKey(false);
if (!key) { forget(); return null; }
const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv: unb64(blob.iv) }, key, unb64(blob.ct));
return { mnemonic: dec.decode(pt), accountPath: blob.path || null };
} catch {
// Key rotated / storage cleared / tampered — drop the stale blob.
forget();
return null;
}
}
async function forget() {
try { localStorage.removeItem(BLOB); } catch {}
try { const db = await openDb(); try { await idbDel(db, KEY_ID); } finally { db.close(); } } catch {}
}
window.siriusSession = {
isEnabled, setEnabled, hasSession,
remember, restore, forget,
requirePinForPayments, setRequirePinForPayments,
};
})();

100
js/site-footer.js Normal file
View file

@ -0,0 +1,100 @@
// Injects the Sirius.X site footer into the current page. Every page in
// site-sirius-x/ ships an empty <footer id="site-footer"></footer> and a
// `<script defer src=".../js/site-footer.js">` include — this file paints
// the four-column layout, meta row, and CSS once, so nav changes stay
// single-source.
//
// Base URL detection: the nav's brand link is already set with the right
// relative path per page (./ at root, ../ in subdirs). Reuse it as the base
// for every same-site href, so root pages and subdir pages both link to the
// right destinations without the script needing to know its own depth.
(() => {
const mount = document.getElementById("site-footer");
if (!mount) return;
const brand = document.querySelector(".topnav .brand");
const base = (brand?.getAttribute("href") || "./").replace(/index\.html$/, "");
// Same-site link builder — prefixes the current-page base so ./docs/ becomes
// ./docs/ from root and ../docs/ from a subdir.
const s = (path) => base + path;
mount.className = "site-footer";
mount.innerHTML = `
<div class="cols">
<div class="brand-col">
<div class="mark">⭐</div>
<h4>Sirius<span class="g">.X</span></h4>
<p>The home for names on Bitcoin Cash. Register a TLD, register a name, verify anything against the chain.</p>
</div>
<div>
<h5>Product</h5>
<ul>
<li><a href="${s("#search-input")}">✏️ Register a name</a></li>
<li><a href="${s("tld.html")}">🌐 Register a TLD</a></li>
<li><a href="${s("market.html")}">🛒 Names for sale</a></li>
<li><a href="${s("portal.html")}">🔑 My names portal</a></li>
<li><a href="${s("theseus/")}">🧭 Theseus browser</a></li>
</ul>
</div>
<div>
<h5>Learn</h5>
<ul>
<li><a href="${s("docs/")}">📚 Docs</a></li>
<li><a href="${s("#roadmap")}">🗺 Roadmap</a></li>
<li><a href="${s("#pantheon")}">🏛 The Pantheon</a></li>
<li><a href="${s("brand/")}">🎨 Brand kit</a></li>
</ul>
</div>
<div>
<h5>Silent Mode</h5>
<ul>
<li><a href="https://silentmode.st/" rel="noopener">silentmode.st <span class="ext">↗</span></a></li>
<li><a href="https://silentmode.st/tlds/" rel="noopener">TLD registry <span class="ext">↗</span></a></li>
<li><a href="https://silentmode.st/bns/theseus.x/" rel="noopener">theseus.x downloads <span class="ext">↗</span></a></li>
<li><a href="https://silentmode.st/bns/hephaestus.x/" rel="noopener">hephaestus.x forge <span class="ext">↗</span></a></li>
</ul>
</div>
</div>
<div class="meta">
<span><span class="footer-badge">Alpha</span>Chipnet only. You hold your own keys; verify everything against the chain.</span>
<span>© 2026 · MIT-licensed content · <a href="${s("brand/")}">brand assets</a></span>
</div>
`;
// Inline CSS — kept out of every page's <style> block so the footer stays
// single-source and consistent. Uses the CSS variables every page already
// sets on :root (so any page's palette applies automatically).
if (!document.getElementById("site-footer-css")) {
const css = document.createElement("style");
css.id = "site-footer-css";
css.textContent = `
footer.site-footer{background:linear-gradient(180deg,transparent,rgba(255,255,255,.015));
border-top:1px solid var(--line);padding:3.2rem 1.2rem 2rem;margin-top:3rem;color:var(--mut)}
footer.site-footer .cols{max-width:980px;margin:0 auto;display:grid;
grid-template-columns:1.4fr repeat(3,1fr);gap:2.2rem}
@media (max-width:760px){ footer.site-footer .cols{grid-template-columns:1fr 1fr;gap:1.6rem} }
@media (max-width:440px){ footer.site-footer .cols{grid-template-columns:1fr} }
footer.site-footer .brand-col .mark{font-size:26px;line-height:1;margin-bottom:.4rem}
footer.site-footer .brand-col h4{color:var(--ink);font-size:15px;font-weight:600;margin:0 0 .35rem;letter-spacing:.2px}
footer.site-footer .brand-col h4 .g{color:var(--acid)}
footer.site-footer .brand-col p{font-size:12.5px;color:var(--dim);max-width:260px;margin:0}
footer.site-footer h5{color:var(--ink);font-size:11.5px;font-weight:600;text-transform:uppercase;
letter-spacing:.6px;margin:0 0 .8rem}
footer.site-footer ul{list-style:none;padding:0;margin:0;display:grid;gap:.55rem}
footer.site-footer ul a{color:var(--mut);text-decoration:none;font-size:13.5px;transition:color .1s}
footer.site-footer ul a:hover{color:var(--acid)}
footer.site-footer ul a .ext{color:var(--dim);font-size:11px;margin-left:2px}
footer.site-footer .meta{max-width:980px;margin:2.4rem auto 0;padding-top:1.4rem;
border-top:1px solid var(--line);display:flex;flex-wrap:wrap;gap:.6rem 1.2rem;
font-size:12px;color:var(--dim);justify-content:space-between;align-items:center}
footer.site-footer .meta a{color:var(--mut);text-decoration:none}
footer.site-footer .meta a:hover{color:var(--acid)}
footer.site-footer .footer-badge{display:inline-block;padding:2px 8px;border-radius:999px;
background:rgba(255,199,95,.13);color:var(--warn);font-size:10.5px;font-weight:600;
text-transform:uppercase;letter-spacing:.4px;margin-right:.5rem}
`;
document.head.appendChild(css);
}
})();

223
js/studio-ai.js Normal file
View file

@ -0,0 +1,223 @@
// Sirius Studio — Assistant panel.
//
// Two providers, both on the user's own hardware, no key and no spend:
// webllm — the model runs inside this tab on the GPU through WebGPU
// (vendor/web-llm, Apache-2.0). Weights download once from the
// MLC mirror and stay in the browser cache.
// local — any OpenAI-compatible endpoint on the user's machine (Ollama,
// LM Studio, llama.cpp). The page talks to localhost directly; the
// runtime has to allow this origin (OLLAMA_ORIGINS=https://silentmode.st).
//
// The model returns data (HTML + CSS or text as JSON); Studio inserts it
// through the editor API. Model output is never executed as code.
const LS_KEY = "siriusAi";
// Base ids; the quantisation suffix is chosen at load time: q4f16 when the
// GPU exposes the shader-f16 feature (half the memory), q4f32 otherwise.
const WEBLLM_MODELS = [
{ id: "Qwen2.5-Coder-1.5B-Instruct", label: "Qwen2.5 Coder 1.5B · best HTML/CSS (≈1 GB download)" },
{ id: "Qwen2.5-1.5B-Instruct", label: "Qwen2.5 1.5B · balanced copy + layout (≈1 GB)" },
{ id: "Qwen2.5-Coder-0.5B-Instruct", label: "Qwen2.5 Coder 0.5B · light, still builds sections (≈400 MB, 1 GB GPU)" },
{ id: "SmolLM2-360M-Instruct", label: "SmolLM2 360M · weakest machines; rewrites text, rarely builds sections (≈250 MB)" },
{ id: "Qwen2.5-Coder-3B-Instruct", label: "Qwen2.5 Coder 3B · strongest here (≈2 GB, needs 4 GB GPU)" },
{ id: "Llama-3.2-3B-Instruct", label: "Llama 3.2 3B · better prose (≈2 GB, needs 4 GB GPU)" },
];
let gpuF16 = null;
async function gpuSupportsF16() {
if (gpuF16 != null) return gpuF16;
try { const a = await navigator.gpu.requestAdapter(); gpuF16 = !!a?.features?.has("shader-f16"); } catch { gpuF16 = false; }
return gpuF16;
}
const fullModelId = async (base) => `${base}-q4${(await gpuSupportsF16()) ? "f16" : "f32"}_1-MLC`;
export function initAssistant(editor, { esc, name }) {
const $ = (id) => document.getElementById(id);
const panel = $("ai"); if (!panel) return;
const settings = Object.assign({ provider: "webllm", model: WEBLLM_MODELS[0].id, url: "http://localhost:11434/v1", lmodel: "" }, load());
let engine = null, engineModel = null, worker = null, webllm = null, busy = false, abort = null, lastApplied = false;
// ---------- ui ----------
$("ai-model").innerHTML = WEBLLM_MODELS.map((m) => `<option value="${m.id}">${esc(m.label)}</option>`).join("");
$("ai-model").value = settings.model;
if (!$("ai-model").value) { $("ai-model").value = WEBLLM_MODELS[0].id; settings.model = WEBLLM_MODELS[0].id; }
$("ai-provider").value = settings.provider;
$("ai-url").value = settings.url;
$("ai-lmodel").value = settings.lmodel;
const showProvider = () => { const w = $("ai-provider").value === "webllm"; $("ai-webllm").hidden = !w; $("ai-local").hidden = w; };
showProvider();
const st = (text, cls = "") => { const el = $("ai-status"); el.textContent = text; el.className = "ai-status " + cls; };
const out = (text) => { const el = $("ai-out"); el.textContent = text; el.scrollTop = 1e6; };
const persist = () => { settings.provider = $("ai-provider").value; settings.model = $("ai-model").value; settings.url = $("ai-url").value.trim().replace(/\/+$/, ""); settings.lmodel = $("ai-lmodel").value.trim(); save(settings); };
$("btn-ai").addEventListener("click", () => { panel.hidden = !panel.hidden; $("btn-ai").classList.toggle("on", !panel.hidden); setTimeout(() => editor.refresh(), 60); if (!panel.hidden) paintTarget(); });
$("ai-close").addEventListener("click", () => { panel.hidden = true; $("btn-ai").classList.remove("on"); setTimeout(() => editor.refresh(), 60); });
$("ai-provider").addEventListener("change", () => { showProvider(); persist(); st(readyText(), ""); });
$("ai-model").addEventListener("change", persist);
$("ai-url").addEventListener("change", persist);
$("ai-lmodel").addEventListener("change", persist);
$("ai-load").addEventListener("click", () => ensureWebLLM().catch((e) => st(e.message || String(e), "err")));
$("ai-connect").addEventListener("click", () => probeLocal().catch((e) => st(e.message || String(e), "err")));
$("ai-undo").addEventListener("click", () => { if (lastApplied) { editor.UndoManager.undo(); lastApplied = false; $("ai-undo").hidden = true; } });
$("ai-stop").addEventListener("click", () => { try { abort?.abort(); engine?.interruptGenerate?.(); } catch {} });
panel.querySelectorAll("[data-verb]").forEach((b) => b.addEventListener("click", () => run(b.dataset.verb).catch((e) => { st(friendly(e), "err"); })));
function friendly(e) {
const m = e?.message || String(e);
if (/disposed|out of memory|OutOfMemory|device lost|DeviceLost/i.test(m)) {
try { worker?.terminate(); } catch {} engine = null; engineModel = null;
return "Your GPU ran out of memory for this model. Pick a smaller one (Qwen2.5 Coder 0.5B or SmolLM2) and press Load model again.";
}
return m;
}
editor.on("component:selected component:deselected component:toggled", paintTarget);
if (!("gpu" in navigator)) { const o = $("ai-provider").querySelector('option[value="webllm"]'); if (o) o.textContent += " — no WebGPU here"; if (settings.provider === "webllm") st("This browser has no WebGPU. Use a local endpoint, or a browser with WebGPU.", "warn"); else st(readyText()); }
else st(readyText());
function readyText() { return $("ai-provider").value === "webllm" ? (engine && engineModel === $("ai-model").value ? "Model loaded — ask away" : "Model not loaded yet — press Load model (once)") : "Press Connect to check the local endpoint"; }
function selected() { return editor.getSelected(); }
function isText(c) { return !!c && (c.get("type") === "text" || c.is?.("text")); }
function paintTarget() {
const c = selected();
const t = $("ai-target");
if (!c) { t.textContent = "Nothing selected — “Make a section” adds at the end of the page."; return; }
const tag = c.get("tagName") || "element", cls = (c.getClasses?.() || []).slice(0, 2).join("."), text = (c.getEl?.()?.innerText || "").trim().slice(0, 60);
t.textContent = `Selected: <${tag}${cls ? "." + cls : ""}>${text ? " “" + text + (text.length >= 60 ? "…" : "") + "”" : ""}`;
}
// ---------- providers ----------
async function ensureWebLLM() {
if (!("gpu" in navigator)) throw new Error("WebGPU is not available in this browser.");
const base = $("ai-model").value;
if (engine && engineModel === base) return engine;
const modelId = await fullModelId(base);
if (!webllm) { st("Loading the engine…", "busy"); webllm = await import("../vendor/web-llm/index.js?v=0.2.85"); }
$("ai-load").disabled = true;
try {
const progress = (r) => st((r.text || "Loading…").replace(/\[.*?\]\s*/g, "").slice(0, 140), "busy");
// Switching models: a fresh worker every time. Reloading inside the same
// engine left the runtime with disposed objects ("Object has already
// been disposed" on the next generation).
if (engine) { try { await engine.unload?.(); } catch {} try { worker?.terminate(); } catch {} engine = null; engineModel = null; }
worker = new Worker(new URL("./ai-worker.js?v=20260920ai", import.meta.url), { type: "module" });
engine = await webllm.CreateWebWorkerMLCEngine(worker, modelId, { initProgressCallback: progress });
engineModel = base;
st(`Model loaded (${(await gpuSupportsF16()) ? "f16" : "f32 — this GPU has no f16 shaders, so the slightly larger build"}) — runs on this device, nothing leaves it`, "ok");
return engine;
} finally { $("ai-load").disabled = false; }
}
async function probeLocal() {
persist();
st("Checking " + settings.url + "…", "busy");
const r = await fetch(settings.url + "/models", { signal: AbortSignal.timeout(6000) }).catch((e) => { throw new Error(`Cannot reach ${settings.url}: ${e.message}. Is the runtime running and is this origin allowed (e.g. OLLAMA_ORIGINS=${location.origin})?`); });
if (!r.ok) throw new Error(`Endpoint answered ${r.status}`);
const j = await r.json().catch(() => ({}));
const ids = (j.data || []).map((m) => m.id).filter(Boolean);
$("ai-lmodels").innerHTML = ids.map((id) => `<option value="${esc(id)}">`).join("");
if (!settings.lmodel && ids.length) { $("ai-lmodel").value = ids[0]; persist(); }
st(`Connected — ${ids.length} model${ids.length === 1 ? "" : "s"} available${settings.lmodel ? ", using " + settings.lmodel : ""}`, "ok");
}
async function complete(messages, onToken) {
const provider = $("ai-provider").value;
let text = "";
if (provider === "webllm") {
const eng = await ensureWebLLM();
st("Thinking on your GPU…", "busy");
const stream = await eng.chat.completions.create({ messages, stream: true, temperature: 0.5, max_tokens: 1400 });
for await (const chunk of stream) { const d = chunk.choices?.[0]?.delta?.content || ""; if (d) { text += d; onToken(text); } }
return text;
}
persist();
if (!settings.lmodel) throw new Error("Pick a model name for the local endpoint first (press Connect to list them).");
abort = new AbortController();
st(`Asking ${settings.lmodel} at ${settings.url}…`, "busy");
const r = await fetch(settings.url + "/chat/completions", { method: "POST", headers: { "content-type": "application/json" }, signal: abort.signal, body: JSON.stringify({ model: settings.lmodel, messages, stream: true, temperature: 0.5 }) });
if (!r.ok) throw new Error(`Endpoint answered ${r.status}: ${(await r.text().catch(() => "")).slice(0, 200)}`);
const reader = r.body.getReader(); const dec = new TextDecoder(); let buf = "";
for (;;) {
const { value, done } = await reader.read(); if (done) break;
buf += dec.decode(value, { stream: true });
let nl; while ((nl = buf.indexOf("\n")) >= 0) {
const line = buf.slice(0, nl).trim(); buf = buf.slice(nl + 1);
if (!line.startsWith("data:")) continue;
const data = line.slice(5).trim(); if (data === "[DONE]") continue;
try { const d = JSON.parse(data).choices?.[0]?.delta?.content || ""; if (d) { text += d; onToken(text); } } catch {}
}
}
return text;
}
// ---------- prompts + apply ----------
const SYSTEM = `You are a web designer working inside a visual site builder. Reply with a single JSON object and nothing else: no prose, no markdown fences, no explanations. Never emit <script>, <iframe>, <link>, <style> tags, event handlers or external URLs other than images already given. Write clean semantic HTML and plain CSS. Every CSS class you create starts with the given prefix and every rule targets those classes. Keep copy short and honest; keep the language of the page.`;
function palette() {
try {
const d = document.querySelector("#gjs iframe").contentDocument; const cs = getComputedStyle(d.body);
return `page background ${cs.backgroundColor}, text ${cs.color}, font ${cs.fontFamily.split(",")[0]}`;
} catch { return "unknown"; }
}
const strip = (raw) => String(raw).replace(/<think>[\s\S]*?<\/think>/g, "").replace(/```(?:json|html|css)?/gi, "").trim();
function parseJson(raw) {
let s = strip(raw);
const a = s.indexOf("{"), b = s.lastIndexOf("}");
if (a >= 0 && b > a) s = s.slice(a, b + 1);
try { const j = JSON.parse(s); return j && typeof j === "object" ? j : null; } catch { return null; }
}
// Small models often answer with bare HTML or CSS instead of the JSON we
// asked for. Accept that too: tags → html (+ any <style> as css); a block
// of rules without tags → css.
function parseLoose(raw) {
const s = strip(raw);
if (/<[a-z][^>]*>/i.test(s)) {
const css = (s.match(/<style[^>]*>[\s\S]*?<\/style>/gi) || []).map((m) => m.replace(/<\/?style[^>]*>/gi, "")).join("\n");
const html = s.replace(/<style[\s\S]*?<\/style>/gi, "").replace(/^[\s\S]*?(?=<)/, "").trim();
return html ? { html, css } : null;
}
if (/\{[\s\S]*\}/.test(s) && /[:;]/.test(s)) return { css: s.slice(s.indexOf(".") >= 0 ? 0 : 0) };
return null;
}
const sanitize = (html) => String(html || "").replace(/<\s*(script|iframe|object|embed|link|meta|style)[^>]*>[\s\S]*?<\s*\/\s*\1\s*>/gi, "").replace(/<\s*(script|iframe|object|embed|link|meta)[^>]*\/?>/gi, "").replace(/\son\w+\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, "").replace(/javascript:/gi, "");
const sanitizeCss = (css) => String(css || "").replace(/@import[^;]*;/gi, "").replace(/expression\s*\(/gi, "").replace(/url\(\s*['"]?\s*(?!data:image|https?:)[^)]*\)/gi, "none");
async function run(verb) {
if (busy) return;
const ask = $("ai-prompt").value.trim();
const sel = selected();
if (verb !== "section" && !sel) { st("Select something on the page first.", "warn"); return; }
if (verb === "text" && !isText(sel)) { st("Select a text block (heading, paragraph, button label) to rewrite.", "warn"); return; }
if (!ask && verb !== "text") { st("Describe what you want first.", "warn"); return; }
busy = true; $("ai-stop").hidden = false; $("ai-undo").hidden = true; out("");
const prefix = "ai" + Math.random().toString(36).slice(2, 6);
try {
let messages, raw, data;
if (verb === "section") {
messages = [{ role: "system", content: SYSTEM }, { role: "user", content: `Create one <section> for the site "${name}". Request: ${ask}. Match this palette unless told otherwise: ${palette()}. Class prefix: "${prefix}-". Answer with a JSON object with two string keys, html (the complete section markup) and css (the rules for its classes).` }];
raw = await complete(messages, out); data = parseJson(raw); if (!/<[a-z][^>]*>/i.test(data?.html || "")) data = parseLoose(raw);
if (!/<[a-z][^>]*>/i.test(data?.html || "")) throw new Error("The model did not return a usable section. Try again, rephrase, or pick a larger model (Qwen2.5 Coder).");
const html = sanitize(data.html), css = sanitizeCss(data.css);
const parent = sel?.parent?.(); const at = sel ? sel.index() + 1 : undefined;
const added = parent ? parent.components().add(html, { at }) : editor.addComponents(html);
if (css) editor.Css.addRules(css);
const first = Array.isArray(added) ? added[0] : added; if (first) { editor.select(first); first.getEl?.()?.scrollIntoView?.({ behavior: "smooth", block: "center" }); }
lastApplied = true; st("Section added — edit it like any other block", "ok");
} else if (verb === "text") {
const current = (sel.getEl()?.innerText || sel.toHTML().replace(/<[^>]+>/g, " ")).trim();
messages = [{ role: "system", content: SYSTEM }, { role: "user", content: `Rewrite this text${ask ? " — instruction: " + ask : " to be clearer and shorter"}. Keep its language and meaning, no quotes around it. Text: """${current.slice(0, 1500)}""" Answer with a JSON object with one string key, text, holding the rewritten text.` }];
raw = await complete(messages, out); data = parseJson(raw);
const text = (data?.text ?? "").trim() || String(raw).replace(/<think>[\s\S]*?<\/think>/g, "").trim();
if (!text) throw new Error("Empty answer.");
sel.components(esc(text));
lastApplied = true; st("Text replaced", "ok");
} else if (verb === "style") {
sel.addClass(prefix);
const snippet = sel.toHTML().slice(0, 1500);
messages = [{ role: "system", content: SYSTEM }, { role: "user", content: `Restyle this element. Request: ${ask}. Page palette: ${palette()}. The element already has the class "${prefix}"; write CSS rules for ".${prefix}" and its descendants only. Element: ${snippet} Answer with a JSON object with one string key, css, holding the rules.` }];
raw = await complete(messages, out); data = parseJson(raw); if (!/\{[\s\S]*:[\s\S]*\}/.test(data?.css || "")) data = parseLoose(raw);
if (!/\{[\s\S]*:[\s\S]*\}/.test(data?.css || "")) { sel.removeClass(prefix); throw new Error("The model did not return usable CSS. Try again, rephrase, or pick a larger model."); }
editor.Css.addRules(sanitizeCss(data.css));
lastApplied = true; st("Styles applied to the selection", "ok");
}
$("ai-undo").hidden = false;
} finally { busy = false; $("ai-stop").hidden = true; abort = null; }
}
function load() { try { return JSON.parse(localStorage.getItem(LS_KEY) || "{}"); } catch { return {}; } }
function save(s) { try { localStorage.setItem(LS_KEY, JSON.stringify(s)); } catch {} }
}

533
js/studio.js Normal file
View file

@ -0,0 +1,533 @@
// Sirius Studio — a site builder for BCNR names.
//
// GrapesJS (BSD-3, vendored under ./vendor/grapesjs/) edits the page. On
// Publish the exported HTML+CSS becomes index.html in the name's own folder
// on Sia — bns/<name>/ — uploaded through the gateway's /api/site route,
// every request signed with the wallet key that holds the name's NFT. The
// editor's project data is saved next to it (_studio.json) so the site can
// be reopened and edited later. If the name's on-chain s3 record does not
// point at that folder yet, Publish also sends one UPD that sets it.
//
// The gateway never holds a key: it verifies each upload's signature
// against the current NFT owner and refuses writes outside bns/<name>/.
import * as BNS from "https://silentmode.st/js/bns-register.js?v=20260917market";
import { initAssistant } from "./studio-ai.js?v=20260920ai";
const API = "https://silentmode.st";
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
const name = (new URLSearchParams(location.search).get("name") || "").toLowerCase().trim();
const folder = name ? `bns/${name}/` : null;
const readUrl = (path) => `${API}/api/site/${encodeURIComponent(name)}/${path}`;
const siteUrl = () => `${API}/bns/${encodeURIComponent(name)}/`;
let wallet = null;
let entry = null; // { records, category, ... } from /api/name
let editor = null;
let dirty = false;
function status(text, cls = "") { const el = $("status"); el.textContent = text; el.className = "st " + cls; }
// ---------- session ----------
async function restoreWallet() {
if (window.siriusWallet) return window.siriusWallet;
const S = window.siriusSession;
if (!S?.restore) return null;
try {
const s = await S.restore();
if (!s?.mnemonic) return null;
return await BNS.BuiltInWallet.fromMnemonic(s.mnemonic, BNS.CHIPNET_PREFIX, s.accountPath || undefined);
} catch { return null; }
}
// ---------- signed uploads ----------
const hex = (buf) => [...new Uint8Array(buf)].map((b) => b.toString(16).padStart(2, "0")).join("");
async function signedHeaders(path, bodyBytes) {
const ts = String(Date.now());
const bodyHash = hex(await crypto.subtle.digest("SHA-256", bodyBytes));
const msg = `BNS-SITE1\n${name}\n${path}\n${bodyHash}\n${ts}`;
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(msg)));
const sig = wallet.signMessage(digest);
return { "x-bns-ts": ts, "x-bns-sig": btoa(String.fromCharCode(...sig)) };
}
async function putFile(path, body, contentType) {
const bytes = body instanceof Uint8Array ? body : new Uint8Array(await new Blob([body]).arrayBuffer());
const headers = { "content-type": contentType, ...(await signedHeaders(path, bytes)) };
const r = await fetch(readUrl(path), { method: "PUT", headers, body: bytes });
const j = await r.json().catch(() => ({}));
if (!r.ok) throw new Error(`${path}: ${j.error || r.status}`);
return j;
}
async function listFiles(live = false) {
const r = await fetch(`${API}/api/site/${encodeURIComponent(name)}${live ? "?src=live" : ""}`, { cache: "no-store" });
if (!r.ok) return { files: [], prefix: null, source: null };
const j = await r.json().catch(() => ({}));
return { files: j.files || [], prefix: j.prefix ?? null, source: j.source ?? null };
}
// ---------- import the page the name serves right now ----------
// Sites are hosted three ways: the Studio folder bns/<name>/, a CLI-published
// bucket the `s3` record points at (bns/<label>/ by convention), or inline
// HTML in the `h` record. The editor must start from whichever one is live,
// not from an empty Studio folder. Relative URLs are made absolute against
// the public site URL so the canvas shows the real images and links, and
// stylesheets are inlined so the imported page keeps its look.
let extraHeadLinks = []; // cross-origin stylesheets we could not inline (fonts CDNs)
// Rules the editor's CSS parser drops or cannot target — :root variables,
// html/body background and fonts, @import. Kept verbatim: injected into the
// canvas so the page looks like the live one, saved with the draft, and
// emitted ahead of the editor's CSS on export.
let importedCss = "";
// Attributes of the source page's <html> (lang, data-theme, class): themed
// sites key their variables on them, so they go on the canvas root and on
// the exported page.
let importedHtmlAttrs = {};
function splitRootCss(css) {
const root = [], rest = [];
// Whole selectors that only address the document root — including themed
// variants such as html[data-theme="dark"] or :root:not([data-theme="light"])
// — but never descendants (body .hero stays with the editor).
const isRootSel = (sel) => /^(:root|html|body)[^\s,>+~]*(\s*,\s*(:root|html|body)[^\s,>+~]*)*$/i.test(sel.trim());
let sheet;
try { sheet = new CSSStyleSheet(); sheet.replaceSync(css); } catch { return { root: css, rest: "" }; }
const walk = (rules, into) => {
for (const r of rules) {
if (r.type === CSSRule.STYLE_RULE) (isRootSel(r.selectorText) ? into.root : into.rest).push(r.cssText);
else if (r.type === CSSRule.MEDIA_RULE) {
const sub = { root: [], rest: [] }; walk(r.cssRules, sub);
if (sub.root.length) into.root.push(`@media ${r.conditionText}{${sub.root.join("\n")}}`);
if (sub.rest.length) into.rest.push(`@media ${r.conditionText}{${sub.rest.join("\n")}}`);
} else if (r.type === CSSRule.IMPORT_RULE) into.root.push(r.cssText);
else into.rest.push(r.cssText);
}
};
walk(sheet.cssRules, { root, rest });
return { root: root.join("\n"), rest: rest.join("\n") };
}
function injectImportedCss() {
try {
const doc = editor.Canvas.getDocument(); if (!doc) return;
let st = doc.getElementById("sirius-imported");
if (!st) { st = doc.createElement("style"); st.id = "sirius-imported"; }
// The editor's base sheet paints <body> white, which hides a page whose
// background lives on <html> (common in app bundles). Body stays
// transparent in the canvas; the export never had that rule anyway.
st.textContent = "html body{background-color:transparent}\n" + importedCss.replace(/(^|[,{}\s])body(?=[\s,{.:\[#>])/g, "$1html body");
doc.head.appendChild(st);
for (const [k, v] of Object.entries(importedHtmlAttrs)) doc.documentElement.setAttribute(k, v);
for (const href of extraHeadLinks) if (!doc.head.querySelector(`link[href="${href}"]`)) { const l = doc.createElement("link"); l.rel = "stylesheet"; l.href = href; doc.head.appendChild(l); }
} catch {}
}
function liveSource() {
const rec = entry?.records || {};
const s3 = typeof rec.s3 === "string" ? rec.s3.trim().replace(/\/?$/, "/") : "";
if (s3 && s3 !== folder) return { kind: "s3", label: s3 };
if (!s3 && typeof rec.h === "string" && rec.h) return { kind: "inline", label: "the inline h record" };
if (s3 === folder) return { kind: "studio", label: folder };
return null;
}
async function fetchLiveHtml() {
const src = liveSource();
if (!src) return null;
const url = src.kind === "studio" ? readUrl("index.html") : readUrl("index.html") + "?src=live";
const r = await fetch(url, { cache: "no-store" });
if (!r.ok) return null;
return { html: await r.text(), base: siteUrl(), src };
}
async function importHtml(html, base) {
const doc = new DOMParser().parseFromString(html, "text/html");
doc.querySelectorAll("script, base, noscript").forEach((n) => n.remove());
const isRel = (u) => !!u && !/^(https?:|data:|blob:|mailto:|tel:|#|\/\/|javascript:)/i.test(u.trim());
const abs = (u) => { try { return new URL(u.trim(), base).href; } catch { return u; } };
doc.querySelectorAll("[src]").forEach((el) => { const v = el.getAttribute("src"); if (isRel(v)) el.setAttribute("src", abs(v)); });
doc.querySelectorAll("[poster]").forEach((el) => { const v = el.getAttribute("poster"); if (isRel(v)) el.setAttribute("poster", abs(v)); });
doc.querySelectorAll("a[href]").forEach((el) => { const v = el.getAttribute("href"); if (isRel(v)) el.setAttribute("href", abs(v)); });
doc.querySelectorAll("[srcset]").forEach((el) => {
el.setAttribute("srcset", el.getAttribute("srcset").split(",").map((part) => { const [u, d] = part.trim().split(/\s+/); return (isRel(u) ? abs(u) : u) + (d ? " " + d : ""); }).join(", "));
});
let css = "";
extraHeadLinks = [];
for (const link of [...doc.querySelectorAll('link[rel~="stylesheet"][href]')]) {
const href = link.getAttribute("href");
const url = isRel(href) ? abs(href) : href;
try {
const r = await fetch(url, { cache: "no-store" });
if (!r.ok) throw new Error(String(r.status));
css += `\n/* ${url} */\n` + (await r.text()).replace(/url\(\s*(['"]?)([^'")]+)\1\s*\)/g, (m, q, u) => (isRel(u) ? `url(${q}${new URL(u.trim(), url).href}${q})` : m));
} catch { extraHeadLinks.push(url); }
link.remove();
}
doc.querySelectorAll("style").forEach((st) => { css += "\n" + st.textContent; st.remove(); });
css = css.replace(/url\(\s*(['"]?)([^'")]+)\1\s*\)/g, (m, q, u) => (isRel(u) ? `url(${q}${abs(u)}${q})` : m));
const parts = splitRootCss(css);
importedCss = parts.root;
importedHtmlAttrs = Object.fromEntries([...doc.documentElement.attributes].map((a) => [a.name, a.value]).filter(([k]) => k === "lang" || k === "class" || k.startsWith("data-")));
const bodyClass = doc.body.getAttribute("class");
if (bodyClass) editor.getWrapper().addClass(bodyClass.split(/\s+/).filter(Boolean));
editor.setComponents(doc.body.innerHTML);
editor.setStyle(parts.rest);
injectImportedCss();
setTimeout(injectImportedCss, 50);
editor.once("canvas:frame:load", injectImportedCss);
}
async function importLive({ confirmIfDirty = true } = {}) {
if (confirmIfDirty && dirty && !confirm("Replace your unsaved changes with the page the name serves right now?")) return false;
status("Importing the live site…", "busy");
try {
const live = await fetchLiveHtml();
if (!live) { status("The name serves no page yet", "err"); return false; }
await importHtml(live.html, live.base);
dirty = true; $("btn-draft").disabled = false;
$("notice").hidden = true;
status(`Imported the live site from ${live.src.label}`, "ok");
return true;
} catch (e) { status("Import failed: " + (e.message || e), "err"); return false; }
}
function notice(text) { $("notice-text").textContent = text; $("notice").hidden = false; }
// ---------- templates ----------
const TEMPLATES = {
blank: { html: `<section style="padding:60px 20px;text-align:center"><h1>${esc(name)}</h1><p>Start building.</p></section>`, css: `body{font-family:system-ui,sans-serif;margin:0;color:#111}` },
landing: {
html: `
<header class="hero">
<h1>Hello from ${esc(name)}</h1>
<p>A name on the Bitcoin Cash chain, a site on Sia. No host, no renewal, no permission.</p>
<a class="cta" href="#more">Learn more</a>
</header>
<section id="more" class="features">
<div class="f"><h3>Yours</h3><p>The certificate sits in your wallet. Nobody can take it back.</p></div>
<div class="f"><h3>Fast</h3><p>Served from Sia through any BCNR resolver or the public gateway.</p></div>
<div class="f"><h3>Simple</h3><p>Edit this page in Sirius Studio and publish in one click.</p></div>
</section>
<footer class="foot">© ${new Date().getFullYear()} ${esc(name)} · built with Sirius Studio</footer>`,
css: `
body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#12161f;background:#fff}
.hero{padding:96px 24px 72px;text-align:center;background:linear-gradient(180deg,#0b0e14,#141a24);color:#f1f4fa}
.hero h1{font-size:44px;margin:0 0 12px;letter-spacing:-.01em}
.hero p{font-size:18px;color:#b8c2d4;max-width:560px;margin:0 auto 26px}
.cta{display:inline-block;background:#d6ff3d;color:#0b0e14;font-weight:700;padding:12px 22px;border-radius:10px;text-decoration:none}
.features{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:20px;max-width:960px;margin:0 auto;padding:56px 24px}
.f{background:#f5f7fb;border-radius:14px;padding:22px}
.f h3{margin:0 0 8px}
.f p{margin:0;color:#4a5568}
.foot{text-align:center;padding:28px;color:#6a7488;font-size:13px;border-top:1px solid #e6e9f0}`,
},
profile: {
html: `
<main class="card">
<div class="avatar">★</div>
<h1>${esc(name)}</h1>
<p class="bio">One line about you. Edit me.</p>
<a class="link" href="https://">Website</a>
<a class="link" href="https://">Nostr</a>
<a class="link" href="https://">Bitcoin Cash tips</a>
<a class="link" href="mailto:">Email</a>
</main>`,
css: `
body{margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle at 50% 0,#1a2233,#050810);font-family:system-ui,sans-serif;color:#f1f4fa}
.card{width:min(420px,92vw);text-align:center;padding:36px 24px}
.avatar{width:88px;height:88px;border-radius:50%;background:#d6ff3d;color:#0b0e14;font-size:40px;line-height:88px;margin:0 auto 14px}
h1{margin:0 0 6px;font-size:26px}
.bio{color:#b8c2d4;margin:0 0 22px}
.link{display:block;background:#141a24;border:1px solid rgba(255,255,255,.1);color:#f1f4fa;text-decoration:none;padding:14px;border-radius:12px;margin:10px 0;font-weight:600}
.link:hover{border-color:#d6ff3d}`,
},
business: {
html: `
<nav class="nav"><b>${esc(name)}</b><span><a href="#about">About</a><a href="#services">Services</a><a href="#contact">Contact</a></span></nav>
<header class="top"><h1>We are open</h1><p>Say what you do in one sentence.</p></header>
<section id="about" class="sec"><h2>About</h2><p>Two or three sentences about the business, the people and the place.</p></section>
<section id="services" class="sec alt"><h2>Services</h2>
<ul class="grid"><li><b>Service one</b><span>Short description.</span></li><li><b>Service two</b><span>Short description.</span></li><li><b>Service three</b><span>Short description.</span></li></ul></section>
<section id="contact" class="sec"><h2>Contact</h2><p>Street 1, City · Mon–Fri 9–18 · <a href="mailto:">hello@example</a></p></section>
<footer class="foot">© ${new Date().getFullYear()} ${esc(name)}</footer>`,
css: `
body{margin:0;font-family:Georgia,serif;color:#2b1d12;background:#fff8f0}
.nav{display:flex;justify-content:space-between;align-items:center;padding:16px 28px;border-bottom:1px solid #eadfd0;font-family:system-ui,sans-serif}
.nav a{margin-left:18px;color:#7a3b00;text-decoration:none}
.top{text-align:center;padding:80px 24px;background:#7a3b00;color:#fff4e6}
.top h1{font-size:42px;margin:0 0 10px}
.sec{max-width:820px;margin:0 auto;padding:48px 24px}
.sec.alt{max-width:none;background:#fff1e0}
.sec.alt h2,.sec.alt ul{max-width:820px;margin-left:auto;margin-right:auto}
.grid{list-style:none;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px}
.grid li{background:#fff;border-radius:12px;padding:18px;box-shadow:0 2px 10px rgba(0,0,0,.05)}
.grid b{display:block;margin-bottom:6px}
.foot{text-align:center;padding:24px;color:#8a6d55;font-size:13px}`,
},
};
// ---------- editor ----------
function plugin(nameOrObj) {
const p = window[nameOrObj];
return p && (p.default || p);
}
function initEditor() {
const plugins = [];
const pluginsOpts = {};
const use = (global, opts = {}) => { const p = plugin(global); if (p) { plugins.push(p); pluginsOpts[p] = opts; } };
use("gjs-blocks-basic", { flexGrid: true, category: "Layout" }); // the bundle registers itself as gjs-blocks-basic
// useCustomTheme:false — the preset's mauve demo palette used to override
// ours and made the panels low-contrast; the theme lives in studio.html.
use("grapesjs-preset-webpage", { modalImportTitle: "Import HTML", blocks: [], useCustomTheme: false, showStylesOnChange: true });
use("grapesjs-plugin-forms", { category: "Forms" });
use("grapesjs-navbar");
use("grapesjs-tabs");
use("grapesjs-tooltip");
use("grapesjs-custom-code");
use("grapesjs-component-countdown");
use("grapesjs-style-bg");
use("grapesjs-touch");
// PostCSS parser: the browser CSSOM path drops shorthands that contain
// var() (background: var(--surface) came back empty), which stripped
// imported pages of their panels and borders.
use("grapesjs-parser-postcss");
editor = grapesjs.init({
container: "#gjs",
height: "100%",
fromElement: false,
storageManager: false,
plugins,
pluginsOpts,
canvas: { styles: [] },
assetManager: {
upload: false,
uploadFile: async (e) => {
const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
for (const f of files) await uploadAsset(f);
},
},
});
editor.on("update", () => { dirty = true; $("btn-draft").disabled = false; });
setupEditing();
try { initAssistant(editor, { esc, name }); } catch (e) { console.warn("assistant unavailable:", e); }
// Ctrl/Cmd+S saves a draft.
document.addEventListener("keydown", (e) => { if ((e.ctrlKey || e.metaKey) && e.key === "s") { e.preventDefault(); saveDraft(); } });
window.addEventListener("beforeunload", (e) => { if (dirty) { e.preventDefault(); e.returnValue = ""; } });
}
// ---------- Tilda-style editing: resize handles, richer text toolbar,
// ready-made sections, style panel on select ----------
function setupEditing() {
// 1. Every box can be dragged to size: right, bottom and corner handles set
// width/height on the element (images keep their own ratio-aware resizer).
const rz = { tl: 0, tc: 0, tr: 0, cl: 0, cr: 1, bl: 0, bc: 1, br: 1, minDim: 16 };
for (const t of ["default", "text", "link", "video", "map", "table", "row", "cell", "svg", "iframe"]) {
if (editor.Components.getType(t)) editor.Components.addType(t, { model: { defaults: { resizable: rz } } });
}
// 2. Text toolbar: size, colour, highlight, alignment, headings.
const rte = editor.RichTextEditor;
const wrapSel = (r, style) => { const t = String(r.selection()); if (t) r.insertHTML(`<span style="${style}">${esc(t)}</span>`); };
rte.add("fontsize", {
icon: `<select title="Text size">${["", "12px", "14px", "16px", "18px", "20px", "24px", "28px", "32px", "40px", "48px", "64px"].map((v) => `<option value="${v}">${v || "Size"}</option>`).join("")}</select>`,
event: "change",
result: (r, action) => { const v = action.btn.querySelector("select").value; if (v) wrapSel(r, `font-size:${v}`); action.btn.querySelector("select").value = ""; },
});
rte.add("forecolor", { icon: `<input type="color" title="Text colour" value="#111111">`, event: "change", result: (r, action) => r.exec("foreColor", action.btn.querySelector("input").value) });
rte.add("hilite", { icon: `<input type="color" title="Highlight" value="#fff59d">`, event: "change", result: (r, action) => r.exec("hiliteColor", action.btn.querySelector("input").value) });
for (const [name, cmd, glyph, title] of [["alignL", "justifyLeft", "≡", "Align left"], ["alignC", "justifyCenter", "☰", "Centre"], ["alignR", "justifyRight", "≡", "Align right"]]) {
rte.add(name, { icon: `<b title="${title}" style="font-style:normal">${glyph}</b>`, result: (r) => r.exec(cmd) });
}
rte.add("heading", {
icon: `<select title="Paragraph style"><option value="">Style</option><option value="h1">Heading 1</option><option value="h2">Heading 2</option><option value="h3">Heading 3</option><option value="p">Paragraph</option><option value="blockquote">Quote</option></select>`,
event: "change",
result: (r, action) => { const v = action.btn.querySelector("select").value; if (v) r.exec("formatBlock", v); action.btn.querySelector("select").value = ""; },
});
// 3. Fonts the exported page can rely on without loading anything.
const ff = editor.StyleManager.getProperty("typography", "font-family");
if (ff) {
const extra = [
["'DM Sans', system-ui, sans-serif", "DM Sans"], ["Fraunces, Georgia, serif", "Fraunces"], ["Ubuntu, system-ui, sans-serif", "Ubuntu"],
["system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif", "System"], ["Georgia, 'Times New Roman', serif", "Georgia"],
["'JetBrains Mono', ui-monospace, Menlo, monospace", "Mono"],
].map(([id, label]) => ({ id, label }));
ff.set("options", [...extra, ...(ff.get("options") || [])]);
}
// 4. Ready-made sections, Tilda style: drop, then edit text and images in place.
const bm = editor.BlockManager;
const sec = (id, label, html, css) => bm.add(`sx-${id}`, { label, category: "Sections", media: SECTION_ICON, content: `<style>${css}</style>${html}` });
sec("hero", "Hero", `<section class="sx-hero"><div class="sx-wrap"><p class="sx-kicker">NEW</p><h1>A headline that earns the scroll</h1><p class="sx-lead">One sentence on what this is and who it is for. Keep it honest and short.</p><a class="sx-btn" href="#">Get started</a></div></section>`,
`.sx-hero{padding:96px 24px;background:#0b0e14;color:#f1f4fa;text-align:center}.sx-wrap{max-width:820px;margin:0 auto}.sx-kicker{letter-spacing:.2em;font-size:12px;color:#d6ff3d;margin:0 0 12px}.sx-hero h1{font-size:44px;line-height:1.1;margin:0 0 16px}.sx-lead{font-size:18px;color:#b8c2d4;margin:0 0 28px}.sx-btn{display:inline-block;background:#d6ff3d;color:#0b0e14;padding:12px 22px;border-radius:10px;text-decoration:none;font-weight:600}`);
sec("features", "Three features", `<section class="sx-feat"><div class="sx-grid3"><div><h3>Fast</h3><p>Say what it does in one line.</p></div><div><h3>Simple</h3><p>Say why it is easy.</p></div><div><h3>Yours</h3><p>Say what the visitor keeps.</p></div></div></section>`,
`.sx-feat{padding:64px 24px;background:#fff;color:#111}.sx-grid3{max-width:1000px;margin:0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:28px}.sx-feat h3{margin:0 0 8px;font-size:20px}.sx-feat p{margin:0;color:#555;line-height:1.6}`);
sec("split", "Image + text", `<section class="sx-split"><div class="sx-split-in"><img src="https://silentmode.st/sirius-x/brand/banner.svg" alt=""><div><h2>Show, then tell</h2><p>A picture on one side, the explanation on the other. Swap the image by clicking it.</p><a class="sx-btn2" href="#">Learn more →</a></div></div></section>`,
`.sx-split{padding:64px 24px;background:#f6f7f9;color:#111}.sx-split-in{max-width:1000px;margin:0 auto;display:grid;grid-template-columns:1fr 1fr;gap:40px;align-items:center}.sx-split img{width:100%;border-radius:14px}.sx-split h2{font-size:32px;margin:0 0 12px}.sx-split p{color:#555;line-height:1.6}.sx-btn2{color:#111;font-weight:600;text-decoration:none}@media(max-width:700px){.sx-split-in{grid-template-columns:1fr}}`);
sec("gallery", "Gallery", `<section class="sx-gal"><div class="sx-gal-grid">${Array.from({ length: 6 }, () => `<img src="https://silentmode.st/sirius-x/brand/avatar.svg" alt="">`).join("")}</div></section>`,
`.sx-gal{padding:48px 24px;background:#fff}.sx-gal-grid{max-width:1000px;margin:0 auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}.sx-gal img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:12px;background:#eee}`);
sec("quote", "Testimonial", `<section class="sx-quote"><blockquote>“Put the kindest true thing a customer said right here.”</blockquote><p class="sx-who">— A real person, their role</p></section>`,
`.sx-quote{padding:72px 24px;background:#0b0e14;color:#f1f4fa;text-align:center}.sx-quote blockquote{max-width:760px;margin:0 auto 14px;font-size:26px;line-height:1.35;font-style:italic}.sx-who{color:#b8c2d4;margin:0}`);
sec("pricing", "Pricing", `<section class="sx-price"><div class="sx-grid3"><div class="sx-plan"><h3>Basic</h3><p class="sx-amt">$0</p><ul><li>One page</li><li>Your name</li></ul><a class="sx-btn" href="#">Choose</a></div><div class="sx-plan sx-hot"><h3>Pro</h3><p class="sx-amt">$9</p><ul><li>Everything in Basic</li><li>Priority help</li></ul><a class="sx-btn" href="#">Choose</a></div><div class="sx-plan"><h3>Team</h3><p class="sx-amt">$29</p><ul><li>Everything in Pro</li><li>Five seats</li></ul><a class="sx-btn" href="#">Choose</a></div></div></section>`,
`.sx-price{padding:64px 24px;background:#f6f7f9;color:#111}.sx-price .sx-grid3{max-width:1000px;margin:0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px}.sx-plan{background:#fff;border:1px solid #e6e8ee;border-radius:16px;padding:28px 24px;text-align:center}.sx-hot{border-color:#111}.sx-amt{font-size:40px;font-weight:700;margin:8px 0 16px}.sx-plan ul{list-style:none;padding:0;margin:0 0 20px;color:#555;line-height:1.9}.sx-price .sx-btn{display:inline-block;background:#111;color:#fff;padding:10px 20px;border-radius:10px;text-decoration:none;font-weight:600}`);
sec("cta", "Call to action", `<section class="sx-cta"><h2>Ready when you are</h2><p>One line that removes the last doubt.</p><a class="sx-btn" href="#">Do the thing →</a></section>`,
`.sx-cta{padding:72px 24px;text-align:center;background:#d6ff3d;color:#0b0e14}.sx-cta h2{font-size:34px;margin:0 0 8px}.sx-cta p{margin:0 0 24px;font-size:17px}.sx-cta .sx-btn{display:inline-block;background:#0b0e14;color:#d6ff3d;padding:12px 22px;border-radius:10px;text-decoration:none;font-weight:600}`);
sec("contact", "Contact form", `<section class="sx-contact"><div class="sx-wrap"><h2>Get in touch</h2><form class="sx-form" method="post"><input type="text" name="name" placeholder="Your name"><input type="email" name="email" placeholder="Email"><textarea name="message" rows="4" placeholder="Message"></textarea><button type="submit" class="sx-btn">Send</button></form></div></section>`,
`.sx-contact{padding:64px 24px;background:#fff;color:#111}.sx-contact .sx-wrap{max-width:560px;margin:0 auto}.sx-contact h2{margin:0 0 16px}.sx-form{display:grid;gap:10px}.sx-form input,.sx-form textarea{width:100%;padding:12px;border:1px solid #d9dce3;border-radius:10px;font:inherit}.sx-contact .sx-btn{background:#111;color:#fff;border:0;padding:12px 20px;border-radius:10px;font-weight:600;cursor:pointer}`);
sec("footer", "Footer", `<footer class="sx-footer"><div class="sx-wrap sx-foot-in"><span>© <b>your name</b> · on Bitcoin Cash</span><nav><a href="#">About</a><a href="#">Contact</a><a href="#">Privacy</a></nav></div></footer>`,
`.sx-footer{padding:28px 24px;background:#0b0e14;color:#b8c2d4;font-size:14px}.sx-foot-in{max-width:1000px;margin:0 auto;display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap}.sx-footer a{color:#b8c2d4;text-decoration:none;margin-left:16px}.sx-footer b{color:#f1f4fa}`);
// Group the plugin blocks under readable categories.
const cat = { navbar: "Sections", tabs: "Widgets", tooltip: "Widgets", "custom-code": "Widgets", countdown: "Widgets" };
bm.getAll().forEach((b) => { const c = cat[b.getId()]; if (c) b.set("category", c); });
// 5. Selecting anything opens the style panel; the layer tree is one click away.
editor.on("component:selected", () => { const btn = editor.Panels.getButton("views", "open-sm"); if (btn && !btn.get("active")) btn.set("active", true); });
}
const SECTION_ICON = `<svg viewBox="0 0 24 24" width="36" height="36"><rect x="2" y="4" width="20" height="5" rx="1.5" fill="currentColor" opacity=".9"/><rect x="2" y="11" width="20" height="9" rx="1.5" fill="currentColor" opacity=".45"/></svg>`;
function loadTemplate(key) {
const t = TEMPLATES[key] || TEMPLATES.blank;
importedCss = ""; extraHeadLinks = []; importedHtmlAttrs = {}; injectImportedCss();
editor.setComponents(t.html);
editor.setStyle(t.css);
dirty = true; $("btn-draft").disabled = false;
}
async function uploadAsset(file) {
const safe = file.name.toLowerCase().replace(/[^a-z0-9._-]/g, "-").replace(/-+/g, "-");
const path = `assets/${Date.now().toString(36)}-${safe}`;
status(`Uploading ${file.name}…`, "busy");
try {
const bytes = new Uint8Array(await file.arrayBuffer());
await putFile(path, bytes, file.type || "application/octet-stream");
editor.AssetManager.add({ src: readUrl(path), name: file.name, type: "image" });
status(`Uploaded ${file.name}`, "ok");
} catch (e) { status("Upload failed: " + (e.message || e), "err"); }
}
// Exported page: inline CSS, asset URLs rewritten to be relative to the
// site folder so the page works from Sia, any resolver and the gateway.
function exportHtml() {
const html = editor.getHtml();
const css = editor.getCss();
const rel = (s) => s.split(readUrl("")).join("");
const links = extraHeadLinks.map((h) => `<link rel="stylesheet" href="${esc(h)}">`).join("\n");
const htmlAttrs = Object.entries({ lang: document.documentElement.lang || "en", ...importedHtmlAttrs }).map(([k, v]) => `${k}="${esc(v)}"`).join(" ");
return `<!doctype html>
<html ${htmlAttrs}>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>${esc(name)}</title>
<meta name="generator" content="Sirius Studio">
${links}
<style>
${rel(importedCss)}
${rel(css)}
</style>
</head>
${rel(html)}
</html>
`;
}
// ---------- draft / publish ----------
function pushStep(t) { const d = document.createElement("div"); d.textContent = t; $("pub-steps").appendChild(d); $("pub-steps").scrollTop = 1e6; }
async function saveDraft() {
if (!editor || !wallet) return;
status("Saving draft…", "busy");
try {
const data = JSON.stringify({ v: 1, name, saved_at: new Date().toISOString(), project: editor.getProjectData(), importedCss, extraHeadLinks, importedHtmlAttrs });
await putFile("_studio.json", data, "application/json");
dirty = false; $("btn-draft").disabled = true;
status("Draft saved on Sia", "ok");
} catch (e) { status("Draft not saved: " + (e.message || e), "err"); }
}
async function publish() {
if (!editor || !wallet) return;
$("pub-name").textContent = name; $("pub-steps").innerHTML = ""; $("pub-view").hidden = true; $("pub").hidden = false;
$("btn-publish").disabled = true;
try {
const html = exportHtml();
pushStep(`exported page · ${html.length.toLocaleString()} bytes`);
const res = await putFile("index.html", html, "text/html; charset=utf-8");
pushStep(`uploaded index.html → ${res.sia_key}`);
const data = JSON.stringify({ v: 1, name, saved_at: new Date().toISOString(), project: editor.getProjectData(), importedCss, extraHeadLinks, importedHtmlAttrs });
await putFile("_studio.json", data, "application/json");
pushStep("saved editor project (_studio.json)");
dirty = false; $("btn-draft").disabled = true;
// Point the name at the folder if it does not already.
const rec = entry?.records || {};
if (rec.s3 !== folder) {
pushStep(`name points at ${rec.s3 ? `"${rec.s3}"` : "nothing"} — setting s3 = ${folder} on chain`);
const next = { ...rec, s3: folder };
delete next.h; // inline HTML would shadow the Sia site
let el = null;
try {
el = await BNS.connect();
const r = await BNS.setRecordsWithBuiltInWallet(el, { wallet, name, records: next, onProgress: (s) => pushStep(String(s)) });
pushStep(`broadcast ${r.txid || r.txId || ""}`);
entry = { ...(entry || {}), records: next };
} finally { try { el?.close?.(); } catch {} }
pushStep("resolvers switch to the new site within a block");
} else {
pushStep("name already points at this folder — live now");
}
$("pub-view").href = siteUrl(); $("pub-view").hidden = false;
$("btn-view").href = siteUrl(); $("btn-view").hidden = false;
status("Published", "ok");
} catch (e) {
pushStep("error: " + (e.message || e));
status("Publish failed", "err");
} finally { $("btn-publish").disabled = false; }
}
// ---------- boot ----------
(async function boot() {
if (!name) { location.replace("./portal.html#studio"); return; }
$("site-name").innerHTML = `${esc(name.split(".")[0])}.<span class="tld">${esc(name.split(".").slice(1).join("."))}</span>`;
$("picker-name").textContent = name;
document.title = `${name} — Sirius Studio`;
wallet = await restoreWallet();
if (!wallet) { $("gate-link").href = `./portal.html?next=${encodeURIComponent(location.pathname + location.search)}`; $("gate").hidden = false; status("Not signed in", "err"); return; }
status("Loading name…");
try { const r = await fetch(`${API}/api/name/${encodeURIComponent(name)}`, { cache: "no-store" }); entry = r.ok ? await r.json() : null; } catch { entry = null; }
initEditor();
$("btn-publish").disabled = false;
const src = liveSource();
if (src) { $("btn-view").href = siteUrl(); $("btn-view").hidden = false; $("btn-import").hidden = false; }
// Start from the right thing: the saved Studio draft if there is one and
// it is what the name serves; otherwise the page the name serves right now
// (wherever it lives); otherwise the template picker.
const { files } = await listFiles();
const draft = files.find((f) => f.path === "_studio.json");
const studioIndex = files.find((f) => f.path === "index.html");
if (draft) {
try {
const j = await (await fetch(readUrl("_studio.json"), { cache: "no-store" })).json();
if (j?.project) {
editor.loadProjectData(j.project);
importedCss = typeof j.importedCss === "string" ? j.importedCss : ""; extraHeadLinks = Array.isArray(j.extraHeadLinks) ? j.extraHeadLinks : [];
importedHtmlAttrs = j.importedHtmlAttrs && typeof j.importedHtmlAttrs === "object" ? j.importedHtmlAttrs : {};
editor.once("canvas:frame:load", injectImportedCss); injectImportedCss();
dirty = false; status(`Loaded draft from ${j.saved_at ? new Date(j.saved_at).toLocaleString() : "Sia"}`, "ok");
}
if (src && src.kind !== "studio") notice(`This draft is not what visitors see: the name currently serves ${src.label}.`);
else if (studioIndex && j?.saved_at && studioIndex.modified && Date.parse(studioIndex.modified) > Date.parse(j.saved_at) + 60_000) notice("index.html on Sia is newer than this draft — it was published by another tool.");
} catch (e) { status("Could not load the saved project: " + (e.message || e), "err"); $("picker").hidden = false; }
} else if (src) {
const ok = await importLive({ confirmIfDirty: false });
if (ok) { dirty = false; $("btn-draft").disabled = true; if (src.kind !== "studio") notice(`Imported the page the name serves from ${src.label}. Publishing writes to ${folder} and repoints the name there.`); }
else { $("picker").hidden = false; }
} else {
$("picker").hidden = false; status("New site");
}
})();
$("btn-import").addEventListener("click", () => importLive());
$("notice-import").addEventListener("click", () => importLive());
$("notice-close").addEventListener("click", () => { $("notice").hidden = true; });
$("picker").addEventListener("click", (e) => {
const b = e.target.closest("[data-tpl]"); if (!b) return;
loadTemplate(b.dataset.tpl); $("picker").hidden = true; status("Template loaded — edit, then Publish");
});
$("tpl-select").addEventListener("change", (e) => {
const v = e.target.value; e.target.value = "";
if (!v) return;
if (!confirm("Replace the current page with this template?")) return;
loadTemplate(v);
});
$("btn-preview").addEventListener("click", () => {
const w = window.open("", "_blank"); if (!w) return;
w.document.open(); w.document.write(exportHtml()); w.document.close();
});
$("btn-draft").addEventListener("click", saveDraft);
$("btn-publish").addEventListener("click", publish);
$("pub-close").addEventListener("click", () => { $("pub").hidden = true; });

63
js/theme.js Normal file
View file

@ -0,0 +1,63 @@
// Sirius.X font picker — reader chooses between Fraunces (Silent Mode
// family — editorial serif, default) and Ubuntu (Bitcoin Cash brand
// font — humanist sans). Persisted in localStorage under 'sirius-font'.
//
// The runtime attribute goes on <html> — pages that want to opt out
// simply omit the include. The actual font-swap CSS is defined per
// page (in each page's <style> block) so it can override the page's
// own font-family declarations at high specificity; this script only
// toggles the attribute and paints the picker UI.
(function () {
var KEY = "sirius-font";
var saved = null;
try { saved = localStorage.getItem(KEY); } catch (e) { /* private mode */ }
var initial = saved === "ubuntu" ? "ubuntu" : "fraunces";
if (initial === "ubuntu") document.documentElement.setAttribute("data-font-cmp", "ubuntu");
// Inject the picker into the topnav's right side when one exists.
// Falls back to a fixed-position pill (bottom-right) for pages without
// a topnav, so the choice is always available.
function paintPicker() {
var nav = document.querySelector(".topnav");
var host = nav || document.body;
var mount = document.createElement("div");
mount.className = "font-picker";
mount.setAttribute("role", "group");
mount.setAttribute("aria-label", "Reading font");
mount.innerHTML =
'<button data-font="fraunces" title="Silent Mode family (Fraunces)">Fraunces</button>' +
'<button data-font="ubuntu" title="Bitcoin Cash brand font (Ubuntu)">Ubuntu</button>';
if (nav) {
// Put it just before the sign-in link if present, else append.
var portalLink = nav.querySelector("a.portal");
if (portalLink) nav.insertBefore(mount, portalLink);
else nav.appendChild(mount);
} else {
mount.classList.add("font-picker-float");
host.appendChild(mount);
}
var btns = mount.querySelectorAll("button");
function refresh(v) {
for (var i = 0; i < btns.length; i++) {
btns[i].classList.toggle("active", btns[i].dataset.font === v);
}
}
refresh(initial);
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function (e) {
var v = e.currentTarget.dataset.font;
if (v === "ubuntu") document.documentElement.setAttribute("data-font-cmp", "ubuntu");
else document.documentElement.removeAttribute("data-font-cmp");
try { localStorage.setItem(KEY, v); } catch (e2) { /* ignore */ }
refresh(v);
});
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", paintPicker);
} else {
paintPicker();
}
})();

138
market.html Normal file
View file

@ -0,0 +1,138 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Market — names for sale on Sirius.X</title>
<meta name="description" content="Buy and sell BCNR names. Every sale is one Bitcoin Cash transaction: the seller is paid in the same transaction that hands you the certificate, or not at all.">
<link rel="icon" href="./assets/favicon.svg" type="image/svg+xml">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,600&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;--ok:#4fd1a5;--taken:#f6768a;--warn:#ffc75f;
--serif:'Fraunces',Georgia,serif;--sans:'DM Sans',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%),var(--bg);background-attachment:fixed;color:var(--ink);font:15px/1.55 var(--sans);min-height:100vh}
h1,h2,h3{font-family:var(--serif)}
a{color:var(--acid)}
.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}
.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}
.wrap{max-width:900px;margin:0 auto;padding:0 1.2rem 3rem}
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}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);max-width:620px;margin:0 auto}
.toolbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:18px 0 8px}
input[type=text],select{padding:9px 12px;border-radius:10px;border:1px solid #ffffff22;background:#0e131b;color:var(--ink);font:inherit;font-size:14px;outline:none}
select{appearance:auto}
.status{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 14px;font-size:13px;color:var(--mut);margin-top:10px}
.status.err{border-left:3px solid var(--taken);color:var(--taken)}
.row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:10px 16px;align-items:center;padding:14px 16px;background:var(--panel2);border:1px solid var(--line);border-radius:12px;margin-top:8px}
.row .n{font-family:var(--mono);font-size:16px}
.row .n .tld{color:var(--acid)}
.row .price{font-family:var(--mono);text-align:right}
.row .price b{font-size:16px}
.row .price span{display:block;color:var(--dim);font-size:12px}
.row .meta{grid-column:1/-1;color:var(--dim);font-size:12px;display:flex;gap:10px;flex-wrap:wrap}
.btn{display:inline-flex;align-items:center;gap:6px;padding:9px 16px;border-radius:10px;background:#4b7bec;color:#fff;font:inherit;font-size:14px;border:none;cursor:pointer;text-decoration:none;line-height:1.2}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.small{padding:6px 11px;font-size:12.5px}
.btn:disabled{opacity:.45;cursor:not-allowed}
.badge{display:inline-block;font-size:11px;padding:2px 9px;border-radius:999px;font-weight:600;background:rgba(214,255,61,.14);color:var(--acid)}
.empty{padding:28px;text-align:center;color:var(--mut);border:1px dashed var(--line);border-radius:12px;margin-top:10px}
.empty.big{padding:40px 24px;border-style:solid;background:var(--panel2)}
.empty.big .ico{font-size:34px;line-height:1;opacity:.8}
.empty.big h3{margin:.6rem 0 .3rem;font-family:var(--serif);font-size:1.25rem;color:var(--ink)}
.empty.big p{margin:0 auto;max-width:460px;font-size:14px}
.empty.big .cta{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:18px}
.toolbar[hidden],.status[hidden]{display:none}
@media (max-width:560px){.row > div:nth-child(3){grid-column:1/-1}.row > div:nth-child(3) .btn{width:100%;justify-content:center}}
.note{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--acid);border-radius:10px;padding:14px 18px;color:var(--mut);font-size:14px;margin-top:1.6rem}
.note b{color:var(--ink)}
/* buy dialog */
.modal{position:fixed;inset:0;background:rgba(6,9,14,.85);backdrop-filter:blur(3px);display:none;align-items:flex-start;justify-content:center;padding:4vh 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:560px;width:100%;padding:24px 26px;position:relative}
.sheet h3{margin:0 0 .3rem;font-family:var(--mono);font-size:1.2rem}
.sheet .sub{color:var(--mut);font-size:13px;margin:0 0 1rem}
.sheet .x{position:absolute;top:14px;right:16px;background:none;border:none;color:var(--dim);font-size:22px;cursor:pointer}
.kv{display:grid;grid-template-columns:150px 1fr;gap:6px 12px;font-size:13.5px}
.kv .k{color:var(--dim)} .kv .v{font-family:var(--mono);word-break:break-all}
.steps{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:150px;overflow:auto;display:none}
.steps.on{display:block}
.steps div::before{content:"› ";color:var(--acid)}
.msg{font-size:13px;margin-top:12px} .msg.err{color:var(--taken)} .msg.ok{color:var(--ok)}
.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:560px){.row{grid-template-columns:1fr auto}.row .price{grid-column:1/-1;text-align:left}}
</style>
<script src="./js/i18n.js?v=20260920d"></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" class="here">🛒 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">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">🛒</div>
<h1>Names <span class="g">for sale</span></h1>
<p class="tag">Every sale is a single Bitcoin Cash transaction. The seller signed an offer that pays them only when the
certificate moves to you — you add your coins, sign, broadcast. No escrow, no middleman, no way for either side to cheat.</p>
</header>
<div class="wrap">
<div class="toolbar">
<input type="text" id="q" placeholder="Filter names…" autocomplete="off" style="max-width:300px">
<select id="sort"><option value="price">Sort: price</option><option value="name">Sort: name</option><option value="new">Sort: newest</option></select>
<select id="tld"><option value="">All TLDs</option></select>
<span id="count" style="color:var(--dim);font-size:12.5px"></span>
</div>
<div class="status" id="status">Loading listings…</div>
<div id="list"></div>
<div class="note"><b>Selling a name?</b> Open it in your <a href="./portal.html">dashboard</a>, choose <b>Sell</b>, set a price. The listing is a signed offer stored by the gateway; cancelling it moves your certificate once so the old offer can never be used.</div>
</div>
<div class="modal" id="buy">
<div class="sheet">
<button class="x" id="buy-close" title="close">×</button>
<h3 id="buy-name">—</h3>
<p class="sub">One transaction: your coins pay the seller, the certificate lands in your wallet, and the registry is told about the new owner. Records stay as they are — you can change them in the dashboard right after.</p>
<div class="kv" id="buy-kv"></div>
<div class="steps" id="buy-steps"></div>
<div class="msg" id="buy-msg"></div>
<div class="actions">
<button class="btn ghost" id="buy-cancel">Cancel</button>
<a class="btn ghost" id="buy-signin" href="./portal.html" hidden>Sign in to buy →</a>
<button class="btn acid" id="buy-go" disabled>Buy — sign &amp; broadcast</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/pricing.js?v=20260917market"></script>
<script type="module" src="./js/market.js?v=20260920m"></script>
<script defer src="./js/theme.js?v=20260910font"></script>
<script defer src="./js/site-footer.js?v=20260917market"></script>
<script defer src="./js/profile-menu.js?v=20260920m"></script>
</body>
</html>

View file

@ -3,30 +3,61 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Portal — your names on sirius.x</title>
<meta name="description" content="Sign in with your Bitcoin Cash seed phrase to see every BCNR name your wallet holds and manage records. Your keys never leave the browser.">
<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 portal — your BCNR names">
<meta property="og:description" content="Sign in with your seed phrase to see every name your wallet holds and manage records. Keys never leave the browser.">
<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:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--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(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
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)}
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}
@ -39,248 +70,618 @@
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.25rem;margin:0 0 .4rem}
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]{
width:100%;padding:11px 13px;border-radius:10px;border:1px solid #ffffff22;background:#0e131b;
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
}
textarea{min-height:74px;resize:vertical;font-family:ui-monospace,monospace;font-size:13px}
textarea:focus,input:focus{border-color:#4b7bec}
.btn{display:inline-block;text-decoration:none;padding:10px 18px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit}
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.small{padding:6px 12px;font-size:12.5px}
.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:16px;align-items:center}
.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:ui-monospace,monospace;font-size:13px;word-break:break-all}
.badge{display:inline-block;font-size:11px;padding:2px 10px;border-radius:999px;font-weight:600}
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}
.authbox{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.authbox .card{margin:0}
.authbox h3{margin:0 0 .3rem;font-size:1rem}
.authbox p{margin:0;color:var(--mut);font-size:13px}
.authbox .card > .cta{margin-top:14px}
.name-row{display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center;
padding:14px 16px;background:var(--panel2);border:1px solid var(--line);border-radius:12px;margin-top:8px}
.name-row .n{font-family:ui-monospace,monospace;font-size:15px}
.name-row .rec{color:var(--mut);font-family:ui-monospace,monospace;font-size:12px;grid-column:1/-1;margin-top:6px;word-break:break-all}
.name-row .rec .k{color:var(--dim)}
.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:520px){
.name-row{grid-template-columns:1fr auto}
@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=20260920d"></script>
</head>
<body>
<nav class="topnav">
<a class="brand" href="./">⭐ <span class="g">sirius.x</span></a>
<a class="brand" href="./">⭐ <span class="g">Sirius.X</span></a>
<a href="./#try">Try it</a>
<a href="./docs/">📚 Docs</a>
<a href="./theseus/">🧭 Theseus</a>
<a href="./#roadmap">Roadmap</a>
<a href="./brand/">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</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> portal</h1>
<p class="tag">Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see
every BCNR name your wallet holds. Your keys never leave this browser tab.</p>
<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</h2>
<p class="muted">Pick one. Nothing is transmitted — resolution is a read-only chain query,
and signing (for record edits) happens locally in the browser or in your external wallet.</p>
<div class="authbox" style="margin-top:14px">
<div class="card">
<h3>Import a seed phrase</h3>
<p>Paste your 12- or 24-word BIP-39 recovery phrase. It stays in memory only, wiped when you
close the tab or sign out.</p>
<label for="seed">Recovery phrase</label>
<textarea id="seed" placeholder="word1 word2 … word12" spellcheck="false" autocomplete="off"></textarea>
<div class="row">
<button class="btn acid" id="signin-btn">Sign in →</button>
<span class="dim">Chipnet only for now.</span>
</div>
<div id="signin-err" class="err hidden"></div>
</div>
<div class="card">
<h3>Connect an external wallet</h3>
<p>Use Cashonize 0.9+ or Paytaca via WizardConnect. The wallet signs record edits — the seed
never touches this page.</p>
<div class="row">
<button class="btn ghost" id="wc-btn" disabled>WizardConnect
<span class="badge b-warn" style="margin-left:6px">soon</span></button>
</div>
<p class="dim" style="margin-top:8px">Portal-side WizardConnect wiring is in progress; the
register.html flow already ships the WizardConnect adapter, and the portal will reuse it.</p>
</div>
</div>
<div class="status" style="margin-top:14px">
Don't have a wallet? Create one during
<a href="https://silentmode.st/sirius/register.html">name registration</a> — the recovery phrase
is generated in your browser and encrypted with your password.
</div>
<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>
<section id="me" class="hidden">
<h2>Signed in</h2>
<div class="card">
<label>Receive address</label>
<div><code id="me-addr">—</code></div>
<label style="margin-top:14px">Token address (holds your name certificates)</label>
<div><code id="me-taddr">—</code></div>
<div class="row">
<button class="btn ghost small" id="signout-btn">Sign out</button>
<span class="dim" id="me-info">—</span>
</div>
</div>
<h2 style="margin-top:2rem">Names you hold</h2>
<div class="status" id="names-status">Loading names from the chain…</div>
<div id="names-list"></div>
</section>
</div>
</div>
<footer>
Your keys, your names, your browser. ·
<a href="./">back to sirius.x</a> ·
<a href="https://silentmode.st/sirius/register.html">register a new name</a>
</footer>
<!-- ============ 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">1–16 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">4–6 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 type="module">
// The registrar bundle exports everything we need: BuiltInWallet for local
// wallet unlock, resolveName/buildIndex for chain queries, getUtxosForAddresses
// for holdings. This portal is a read-first surface; record edits (UPD) will
// come next and will piggyback on the same signing path the registrar uses.
// Cache-buster bumped whenever the bundle changes. Chrome's in-memory ES
// module map ignores Cache-Control on the .js URL for the lifetime of a tab,
// so a plain "/js/bns-register.js" import can return a stale instance days
// after deploy. A query string forces the module loader to treat this as a
// new URL and fetch fresh bytes.
import * as BNS from "https://silentmode.st/js/bns-register.js?v=20260831c";
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s).replace(/[&<>"']/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[c]));
let wallet = null;
// ---------- sign in ----------
$("signin-btn").addEventListener("click", async () => {
const btn = $("signin-btn");
const errBox = $("signin-err");
errBox.classList.add("hidden");
const raw = $("seed").value.trim();
if (!raw) { errBox.textContent = "Enter your seed phrase to sign in."; errBox.classList.remove("hidden"); return; }
btn.disabled = true; btn.textContent = "Unlocking…";
try {
wallet = await BNS.BuiltInWallet.fromMnemonic(raw);
} catch (e) {
errBox.textContent = "Could not unlock: " + (e.message || e);
errBox.classList.remove("hidden");
btn.disabled = false; btn.textContent = "Sign in →";
return;
}
// Wipe the textarea immediately — the seed is now in the wallet object only.
$("seed").value = "";
btn.disabled = false; btn.textContent = "Sign in →";
await enterPortal();
});
$("signout-btn").addEventListener("click", () => {
wallet = null;
$("me").classList.add("hidden");
$("signin").classList.remove("hidden");
$("names-list").innerHTML = "";
$("names-status").textContent = "Loading names from the chain…";
});
async function enterPortal() {
$("signin").classList.add("hidden");
$("me").classList.remove("hidden");
$("me-addr").textContent = wallet.address;
$("me-taddr").textContent = wallet.tokenAddress;
$("me-info").textContent = "watched addresses: " + wallet.watchedAddresses.length;
await loadNames();
}
// ---------- load names ----------
// Approach: derive the scripthash for each watched address locally (the
// wallet code already knows how), send them in one POST to
// /api/holdings, and render whatever the gateway returns. Doing the
// wallet-holdings query server-side is what makes this work on browsers
// stuck behind firewalls that block chipnet electrum ports (50004,
// 50011, 62002) — the API is same-origin HTTPS on port 443, and the
// gateway can reach the full electrums the browser can't.
async function loadNames() {
const status = $("names-status");
const list = $("names-list");
list.innerHTML = "";
status.className = "status";
status.textContent = "Preparing your addresses…";
try {
const addresses = wallet.watchedAddresses;
const scripthashes = addresses.map((a) => BNS.addressToScripthash(a));
status.textContent = `Asking the gateway about ${addresses.length} addresses…`;
const r = await fetch("https://silentmode.st/api/holdings", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ scripthashes }),
});
if (!r.ok) {
const detail = await r.text().catch(() => "");
throw new Error(`API ${r.status}: ${detail.slice(0, 200)}`);
}
const { count, names: mine } = await r.json();
if (!count) {
status.className = "status";
status.textContent = "No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.";
return;
}
status.className = "status ok";
status.textContent = `You own ${count} name${count === 1 ? "" : "s"}.`;
for (const e of mine) {
const div = document.createElement("div");
div.className = "name-row";
const records = e.records && Object.keys(e.records).length
? Object.entries(e.records).map(([k, v]) => `<span class="k">${esc(k)}=</span>${esc(String(v).slice(0, 80))}`).join(" &nbsp;·&nbsp; ")
: '<span class="k">(no records set)</span>';
div.innerHTML =
`<div class="n">${esc(e.name)}</div>` +
'<span class="badge b-x">on chain</span>' +
`<a class="btn small ghost" href="https://silentmode.st/bns/${encodeURIComponent(e.name)}/" target="_blank" rel="noopener">view →</a>` +
`<div class="rec">${records}</div>`;
list.appendChild(div);
}
} catch (e) {
status.className = "status err";
status.textContent = "Could not load names: " + (e.message || e);
}
}
</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>

40
register.html Normal file
View file

@ -0,0 +1,40 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Register a name — Sirius.X</title>
<meta name="description" content="Search a Bitcoin Cash name and mint the certificate to your own wallet. The name-registration flow lives on the Sirius.X landing.">
<link rel="icon" href="./assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="./assets/favicon.svg" color="#d6ff3d">
<meta name="robots" content="noindex">
<!-- register.html used to host a duplicate search-and-mint flow. The Sirius.X
landing now owns both the search UI and the shared mint modal
(js/register-flow.js), so this page redirects there with any `?q=` label
preserved. The meta-refresh is a fallback for JS-off; the script picks
up first when JS is on. -->
<meta http-equiv="refresh" content="0; url=./">
<script>
(function () {
// Preserve ?q= if the user (or an old link) still points here with a label.
const q = new URLSearchParams(location.search).get("q");
const target = q ? `./?q=${encodeURIComponent(q)}` : "./";
location.replace(target);
})();
</script>
<style>
body{margin:0;font:16px/1.55 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
background:#0b0e14;color:#8b98a9;min-height:100vh;
display:flex;align-items:center;justify-content:center;padding:2rem;text-align:center}
a{color:#d6ff3d}
.mark{font-size:40px;line-height:1;margin-bottom:.6rem}
</style>
</head>
<body>
<div>
<div class="mark">⭐</div>
<p>Redirecting to <a href="./">Sirius.X</a>…</p>
<p style="font-size:12.5px;color:#5e6678;margin-top:1rem">Name search moved to the home page.</p>
</div>
</body>
</html>

249
studio.html Normal file
View file

@ -0,0 +1,249 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sirius Studio — build the site for your name</title>
<meta name="description" content="Sirius Studio: a drag-and-drop site builder for BCNR names. Pages live on Sia, the name on the chain — your keys, your site.">
<link rel="icon" href="./assets/favicon.svg" type="image/svg+xml">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,600&family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="./vendor/grapesjs/grapes.min.css?v=0.23.6">
<style>
:root{
--bg:#050810; --panel:#141a24; --panel2:#0a0f1c; --line:rgba(255,255,255,.08);
--ink:#f1f4fa; --mut:#b8c2d4; --dim:#6a7488; --acid:#d6ff3d; --ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
--serif:'Fraunces',Georgia,serif; --sans:'DM Sans',system-ui,sans-serif; --mono:'JetBrains Mono',ui-monospace,monospace;
/* GrapesJS theme hooks */
--gjs-primary-color:#0e131b; --gjs-secondary-color:#b8c2d4; --gjs-tertiary-color:#d6ff3d; --gjs-quaternary-color:#d6ff3d;
--gjs-font-color:#f1f4fa; --gjs-main-dark-color:#0a0f1c; --gjs-main-light-color:#141a24;
}
*{box-sizing:border-box}
html,body{height:100%;margin:0}
body{background:var(--bg);color:var(--ink);font:14px/1.5 var(--sans);display:flex;flex-direction:column;overflow:hidden}
a{color:var(--acid)}
.bar{display:flex;align-items:center;gap:10px;padding:8px 14px;background:rgba(11,14,20,.95);border-bottom:1px solid var(--line);flex:none;flex-wrap:wrap}
.bar .brand{font-weight:600;color:var(--ink);text-decoration:none;font-size:15px;display:flex;align-items:center;gap:6px}
.bar .brand .g{color:var(--acid)}
.bar .name{font-family:var(--mono);font-size:14px;color:var(--ink);background:var(--panel);border:1px solid var(--line);padding:5px 10px;border-radius:8px}
.bar .name .tld{color:var(--acid)}
.bar .sp{flex:1}
.bar .st{font-size:12.5px;color:var(--dim);max-width:360px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bar .st.ok{color:var(--ok)} .bar .st.err{color:var(--taken)} .bar .st.busy{color:var(--warn)}
.notice{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 14px;font-size:13px;color:var(--ink);
background:rgba(255,199,95,.10);border-bottom:1px solid rgba(255,199,95,.35);flex:none}
.notice[hidden]{display:none}
.notice .x{margin-left:auto;background:none;border:0;color:var(--dim);font-size:18px;cursor:pointer;line-height:1}
.btn{display:inline-flex;align-items:center;gap:6px;padding:7px 13px;border-radius:9px;background:#4b7bec;color:#fff;font:inherit;font-size:13px;border:none;cursor:pointer;text-decoration:none;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.small{padding:5px 10px;font-size:12px}
.btn:disabled{opacity:.45;cursor:not-allowed}
select.sel{padding:6px 28px 6px 10px;border-radius:9px;background:var(--panel);color:var(--ink);border:1px solid var(--line);font:inherit;font-size:13px}
#editor{flex:1;min-height:0;display:flex;min-width:0}
#gjs{height:100%;flex:1;min-width:0}
/* assistant drawer */
.ai{width:340px;flex:none;display:flex;flex-direction:column;gap:8px;padding:12px 14px;background:#0e131b;border-left:1px solid var(--line);overflow:auto;font-size:13px}
.ai[hidden]{display:none}
.ai-head{display:flex;align-items:center;justify-content:space-between}
.ai-head b{font-size:14px}
.ai .x{background:none;border:0;color:var(--dim);font-size:20px;cursor:pointer;line-height:1}
.ai label{display:block;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);margin:6px 0 3px}
.ai select,.ai input,.ai textarea{width:100%;padding:8px 10px;border-radius:8px;border:1px solid rgba(255,255,255,.12);background:#070a12;color:var(--ink);font:inherit;font-size:13px}
.ai textarea{resize:vertical;min-height:72px}
.ai-hint{color:var(--dim);font-size:11.5px;line-height:1.4}
.ai-hint code{font-size:11px}
.ai-status{font-size:12px;color:var(--mut);padding:7px 10px;border-radius:8px;background:rgba(255,255,255,.04);border-left:3px solid rgba(255,255,255,.12);min-height:30px}
.ai-status.ok{border-left-color:var(--ok);color:var(--ok)} .ai-status.err{border-left-color:var(--taken);color:var(--taken)} .ai-status.busy{border-left-color:var(--warn)} .ai-status.warn{border-left-color:var(--warn);color:var(--warn)}
.ai-verbs{display:flex;flex-wrap:wrap;gap:6px}
.ai-target{font-size:11.5px;color:var(--dim);font-family:var(--mono);word-break:break-word}
.ai-out{flex:1;min-height:80px;max-height:40vh;margin:0;padding:8px 10px;background:#070a12;border:1px solid rgba(255,255,255,.08);border-radius:8px;font-family:var(--mono);font-size:11px;color:var(--mut);white-space:pre-wrap;word-break:break-word;overflow:auto}
.ai-actions{display:flex;gap:6px}
.bar .btn.on{background:rgba(214,255,61,.14);border-color:rgba(214,255,61,.4);color:var(--acid)}
@media (max-width:900px){.ai{position:fixed;right:0;top:0;bottom:0;width:min(340px,92vw);z-index:60;box-shadow:-12px 0 30px rgba(0,0,0,.5)}}
/* Editor theme: GrapesJS 0.23 is themed through CSS variables. Dark panels,
near-white text (>= 12:1), acid accents. The preset's own mauve palette is
switched off in studio.js (useCustomTheme:false). */
:root{
--gjs-primary-color:#0e131b; /* panel backgrounds */
--gjs-secondary-color:#e7ebf2; /* panel text */
--gjs-tertiary-color:#d6ff3d; /* active buttons */
--gjs-quaternary-color:#d6ff3d; /* highlights, selection badge */
--gjs-main-color:#0e131b;
--gjs-main-dark-color:rgba(0,0,0,.35); /* inputs */
--gjs-main-light-color:rgba(255,255,255,.07);
--gjs-secondary-light-color:rgba(255,255,255,.82);
--gjs-secondary-dark-color:rgba(0,0,0,.3);
--gjs-font-color:#e7ebf2;
--gjs-font-color-active:#ffffff;
--gjs-light-border:rgba(255,255,255,.09);
--gjs-arrow-color:rgba(255,255,255,.8);
--gjs-color-highlight:#d6ff3d;
--gjs-font-size:.8rem;
--gjs-main-font:'DM Sans',system-ui,sans-serif;
}
.gjs-three-bg,.gjs-pn-btn.gjs-pn-active{color:#0b0e14 !important}
.gjs-pn-btn.gjs-pn-active{background:var(--acid);border-radius:6px}
.gjs-pn-panel{border-color:var(--line)}
.gjs-pn-views-container{box-shadow:none;border-left:1px solid var(--line)}
.gjs-block{min-height:78px;border:1px solid rgba(255,255,255,.08);border-radius:10px;margin:6px;padding:10px 6px;transition:border-color .12s,background .12s}
.gjs-block:hover{border-color:rgba(214,255,61,.45);background:rgba(214,255,61,.06)}
.gjs-block-label{font-size:11.5px;line-height:1.25;margin-top:6px}
.gjs-block svg{fill:#e7ebf2}
.gjs-block-category .gjs-title,.gjs-sm-sector-title,.gjs-layer-title{font-weight:600;letter-spacing:.02em}
.gjs-sm-sector .gjs-sm-property .gjs-sm-label,.gjs-trt-trait .gjs-label,.gjs-layer-name{color:#e7ebf2}
.gjs-field{border:1px solid rgba(255,255,255,.1);border-radius:6px}
.gjs-field:focus-within{border-color:rgba(214,255,61,.6)}
.gjs-field input,.gjs-field select,.gjs-field textarea{color:#fff}
.gjs-radio-item-label,.gjs-sm-btn{color:#e7ebf2}
.gjs-sm-btn{background:rgba(255,255,255,.08);border-radius:6px}
.gjs-clm-tag{background:rgba(214,255,61,.14);color:#d6ff3d}
.gjs-selected{outline:2px solid #d6ff3d !important}
.gjs-badge{background:#d6ff3d;color:#0b0e14}
.gjs-toolbar{background:#0e131b;border:1px solid rgba(255,255,255,.12);border-radius:8px}
.gjs-toolbar-item{color:#fff}
.gjs-rte-toolbar{background:#0e131b;border:1px solid rgba(255,255,255,.12);border-radius:8px}
.gjs-rte-action{color:#fff;border-right-color:rgba(255,255,255,.08)}
.gjs-rte-action select,.gjs-rte-action input[type=color]{background:#0e131b;color:#fff;border:1px solid rgba(255,255,255,.15);border-radius:4px;font:inherit;font-size:12px;cursor:pointer}
.gjs-rte-action input[type=color]{width:24px;height:22px;padding:0}
.gjs-resizer-h{border-color:#d6ff3d;background:#0b0e14;width:10px;height:10px}
.gjs-mdl-dialog{background:#141a24;color:#e7ebf2;border:1px solid var(--line)}
.gjs-mdl-header{border-bottom-color:var(--line)}
.gjs-cv-canvas{background:#fff}
/* gate / picker overlays */
.overlay{position:fixed;inset:0;background:rgba(5,8,16,.92);backdrop-filter:blur(4px);z-index:100;display:flex;align-items:center;justify-content:center;padding:20px;overflow:auto}
.overlay[hidden]{display:none}
.sheet{background:var(--panel);border:1px solid var(--line);border-radius:16px;max-width:860px;width:100%;padding:26px 28px}
.sheet h2{font-family:var(--serif);margin:0 0 .3rem;font-size:1.5rem}
.sheet p{color:var(--mut);margin:.2rem 0 1rem}
.tpls{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-top:10px}
.tpl{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:0;overflow:hidden;cursor:pointer;text-align:left;color:inherit;font:inherit;transition:border-color .12s}
.tpl:hover{border-color:rgba(214,255,61,.4)}
.tpl .prev{height:110px;background:#fff;display:flex;align-items:center;justify-content:center;font-family:var(--serif);color:#111;font-size:22px}
.tpl .prev.dark{background:#0b0e14;color:#d6ff3d}
.tpl .prev.warm{background:#fff4e6;color:#7a3b00}
.tpl .prev.blue{background:#0f2a4a;color:#e6f0ff}
.tpl b{display:block;padding:10px 12px 2px;font-size:14px}
.tpl span{display:block;padding:0 12px 12px;color:var(--dim);font-size:12px}
.steps{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:160px;overflow:auto}
.steps div::before{content:"› ";color:var(--acid)}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-top:14px}
.row.end{justify-content:flex-end}
.muted{color:var(--mut);font-size:13px}
code{font-family:var(--mono);background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-size:12px}
</style>
<script src="./js/i18n.js?v=20260920d"></script>
</head>
<body>
<div class="bar">
<a class="brand" href="./portal.html#studio">⭐ <span class="g">Sirius</span> Studio</a>
<span class="name" id="site-name">—</span>
<select class="sel" id="tpl-select" title="Start from a template">
<option value="">Templates…</option>
<option value="landing">Landing page</option>
<option value="profile">Profile / link hub</option>
<option value="business">Business one-pager</option>
<option value="blank">Blank page</option>
</select>
<button class="btn ghost small" id="btn-preview" title="Preview the exported page in a new tab">Preview</button>
<button class="btn ghost small" id="btn-import" title="Replace the editor contents with the page the name serves right now" hidden>↓ Import live site</button>
<button class="btn ghost small" id="btn-ai" title="AI assistant — runs on your own device">✨ Assistant</button>
<span class="sp"></span>
<span class="st" id="status">Loading…</span>
<button class="btn ghost small" id="btn-draft" disabled>Save draft</button>
<button class="btn acid small" id="btn-publish" disabled>Publish to Sia →</button>
<a class="btn ghost small" id="btn-view" href="#" target="_blank" rel="noopener" hidden>View site →</a>
<span data-lang-slot></span>
</div>
<div class="notice" id="notice" hidden><span id="notice-text"></span> <button class="btn ghost small" id="notice-import">Import the live site</button> <button class="x" id="notice-close" title="dismiss">×</button></div>
<div id="editor"><div id="gjs"></div>
<aside class="ai" id="ai" hidden>
<div class="ai-head"><b>✨ Assistant</b><button class="x" id="ai-close" title="close">×</button></div>
<p class="ai-hint" style="margin:0">Runs on your own device. Nothing you write or build is sent to Sirius.X or to any AI vendor.</p>
<label>Runs on</label>
<select id="ai-provider">
<option value="webllm">This browser — your GPU, private</option>
<option value="local">Local endpoint — Ollama, LM Studio</option>
</select>
<div id="ai-webllm">
<label>Model</label>
<select id="ai-model"></select>
<div class="ai-hint">Downloads once, then stays in the browser cache. Needs WebGPU (current Chrome, Edge, Firefox, Safari).</div>
<div class="ai-actions" style="margin-top:6px"><button class="btn ghost small" id="ai-load">Load model</button></div>
</div>
<div id="ai-local" hidden>
<label>Endpoint</label>
<input type="text" id="ai-url" value="http://localhost:11434/v1" spellcheck="false">
<label>Model</label>
<input type="text" id="ai-lmodel" list="ai-lmodels" placeholder="qwen2.5-coder:7b" spellcheck="false"><datalist id="ai-lmodels"></datalist>
<div class="ai-hint">Allow this site in your runtime first, e.g. <code>OLLAMA_ORIGINS=https://silentmode.st ollama serve</code>. LM Studio: enable CORS in its server settings (port 1234).</div>
<div class="ai-actions" style="margin-top:6px"><button class="btn ghost small" id="ai-connect">Connect</button></div>
</div>
<div class="ai-status" id="ai-status">—</div>
<label>What do you want?</label>
<textarea id="ai-prompt" placeholder="A hero section for a bakery in Athens, warm colours, one button that says Order"></textarea>
<div class="ai-verbs">
<button class="btn acid small" data-verb="section">Make a section</button>
<button class="btn ghost small" data-verb="text">Rewrite selected text</button>
<button class="btn ghost small" data-verb="style">Restyle selection</button>
</div>
<div class="ai-target" id="ai-target">Nothing selected</div>
<pre class="ai-out" id="ai-out"></pre>
<div class="ai-actions"><button class="btn ghost small" id="ai-undo" hidden>Undo last change</button><button class="btn ghost small" id="ai-stop" hidden>Stop</button></div>
</aside></div>
<!-- sign-in gate -->
<div class="overlay" id="gate" hidden>
<div class="sheet" style="max-width:520px">
<h2>Sign in first</h2>
<p>Sirius Studio publishes with your wallet's key. Sign in on the dashboard, then come back to this name.</p>
<div class="row end"><a class="btn acid" id="gate-link" href="./portal.html">Open the dashboard →</a></div>
</div>
</div>
<!-- template picker for a fresh site -->
<div class="overlay" id="picker" hidden>
<div class="sheet">
<h2>Build the site for <span id="picker-name" style="font-family:var(--mono);color:var(--acid)">—</span></h2>
<p>Pick a starting point. Everything is editable — drag blocks in from the right, click any text to change it. Nothing leaves your browser until you press Publish; then the page is stored on Sia and the name points at it.</p>
<div class="tpls">
<button class="tpl" data-tpl="landing"><div class="prev">Hello, world</div><b>Landing page</b><span>Hero, three features, call to action.</span></button>
<button class="tpl" data-tpl="profile"><div class="prev dark">@you</div><b>Profile / link hub</b><span>Avatar, bio and a stack of links.</span></button>
<button class="tpl" data-tpl="business"><div class="prev warm">Open today</div><b>Business one-pager</b><span>About, services, hours, contact.</span></button>
<button class="tpl" data-tpl="blank"><div class="prev blue">—</div><b>Blank page</b><span>Start from nothing.</span></button>
</div>
<div class="row end"><a class="btn ghost" href="./portal.html#studio">Back to dashboard</a></div>
</div>
</div>
<!-- publish dialog -->
<div class="overlay" id="pub" hidden>
<div class="sheet" style="max-width:620px">
<h2>Publish <span id="pub-name" style="font-family:var(--mono);color:var(--acid)">—</span></h2>
<p id="pub-intro">The page and its assets are uploaded to the name's folder on Sia, signed with your key. If the name does not point at that folder yet, one on-chain update sets it (a few cents of chain dust).</p>
<div class="steps" id="pub-steps"></div>
<div class="row end">
<button class="btn ghost" id="pub-close">Close</button>
<a class="btn acid" id="pub-view" href="#" target="_blank" rel="noopener" hidden>View site →</a>
</div>
</div>
</div>
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
<script src="./js/session.js?v=20260917dash"></script>
<script src="./vendor/grapesjs/grapes.min.js?v=0.23.6"></script>
<script src="./vendor/grapesjs/blocks-basic.js?v=1.0.2b"></script>
<script src="./vendor/grapesjs/preset-webpage.js?v=1.0.3b"></script>
<script src="./vendor/grapesjs/plugin-forms.js?v=2.0.6"></script>
<script src="./vendor/grapesjs/navbar.js?v=1.0.2"></script>
<script src="./vendor/grapesjs/tabs.js?v=1.0.6"></script>
<script src="./vendor/grapesjs/tooltip.js?v=0.1.8"></script>
<script src="./vendor/grapesjs/custom-code.js?v=1.0.2"></script>
<script src="./vendor/grapesjs/countdown.js?v=1.0.2"></script>
<script src="./vendor/grapesjs/style-bg.js?v=2.0.2"></script>
<script src="./vendor/grapesjs/touch.js?v=0.1.1"></script>
<script src="./vendor/grapesjs/parser-postcss.js?v=1.0.3"></script>
<script type="module" src="./js/studio.js?v=20260920pc"></script>
</body>
</html>

View file

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<!-- theseus.x — Navigator compass mark. Rounded dark square (matches the
sirius.x sibling family). N (top) half red like every real compass
needle, S (bottom) half in Silent Mode acid green. E-W arm softened
so the N-S bearing reads clearly at 16x16 tab-icon size. -->
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
<!-- N half — red bearing indicator -->
<path d="M32 6 L38 32 L26 32 Z" fill="#e04e4e"/>
<!-- S half — acid -->
<path d="M38 32 L32 58 L26 32 Z" fill="#d6ff3d"/>
<!-- E-W arm — softened acid so the vertical bearing dominates -->
<path d="M6 32 L32 27 L58 32 L32 37 Z" fill="#d6ff3d" opacity="0.55"/>
<!-- Center hole -->
<circle cx="32" cy="32" r="3" fill="#0b0e14"/>
</svg>

After

Width:  |  Height:  |  Size: 809 B

16
theseus/assets/logo.svg Normal file
View file

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 96">
<!-- theseus.x wordmark for OpenGraph previews. Compass mark on the left,
wordmark on the right; kept single-color palette (dark + acid + red
bearing) so it survives dark and light preview cards. -->
<g>
<rect x="8" y="16" width="64" height="64" rx="12" fill="#0b0e14"/>
<path d="M40 22 L46 48 L34 48 Z" fill="#e04e4e"/>
<path d="M46 48 L40 74 L34 48 Z" fill="#d6ff3d"/>
<path d="M14 48 L40 43 L66 48 L40 53 Z" fill="#d6ff3d" opacity="0.55"/>
<circle cx="40" cy="48" r="3" fill="#0b0e14"/>
</g>
<text x="88" y="60" font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
font-size="30" font-weight="600" fill="#e7eaf1" letter-spacing=".5">
theseus<tspan fill="#d6ff3d">.x</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 826 B

View file

@ -3,31 +3,39 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Theseus Navigator — the browser that speaks Bitcoin Cash names — sirius.x</title>
<meta name="description" content="Theseus Navigator is a Chromium-based browser with native .bch / BCNR name resolution built in — no OS-level daemon, no DNS shim, no root-store install. Download for Windows.">
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="../assets/favicon.svg" color="#d6ff3d">
<title>Theseus Navigator — the browser that speaks Bitcoin Cash names — Sirius.X</title>
<meta name="description" content="Theseus Navigator is a Chromium-based browser with native Bitcoin Cash Domain Names resolution built in — no OS-level daemon, no DNS shim, no root-store install. Download for Windows.">
<!-- Theseus.X has its own compass-mark favicon and logo — reuse them here so
tabs on this subpage read as Theseus (compass), not Sirius (star), and
shared-link previews carry Theseus's own OG image. Copied from
silentmode.st/bns/theseus.x/assets/ to keep sirius.x self-contained. -->
<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:site_name" content="Theseus Navigator">
<meta property="og:title" content="Theseus Navigator — the browser that speaks Bitcoin Cash names">
<meta property="og:description" content="Native .bch and BCNR name resolution built into a Chromium browser. No OS-level daemon, no root-store install. Download for Windows.">
<meta property="og:url" content="https://silentmode.st/sirius-x/theseus/">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<meta property="og:image" content="https://silentmode.st/sirius-x/theseus/assets/logo.svg">
<meta name="theme-color" content="#0b0e14">
<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:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--bg:#050810; --panel:#141a24; --panel2:#0a0f1c; --line:rgba(255,255,255,.06);
--ink:#f1f4fa; --mut:#b8c2d4; --dim:#6a7488; --acid:#d6ff3d;
--chain:#d6ff3d; --sia:#b39ddb; --srv:#4fd1a5; --ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
body{margin:0;background:radial-gradient(ellipse 1200px 600px at 50% -5%,#131a2a 0%,transparent 60%),radial-gradient(ellipse 900px 500px at 100% 100%,#0a0f1c 0%,transparent 55%),radial-gradient(ellipse 900px 500px at 0% 100%,#0c1424 0%,transparent 55%),var(--bg);
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:980px;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)}
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}
@ -75,25 +83,37 @@
ol.steps b{color:var(--ink)} ol.steps span{color:var(--mut);font-size:14px}
.pill{display:inline-block;font-size:11px;padding:2px 8px;border-radius:999px;background:rgba(214,255,61,.13);color:var(--acid);margin-left:8px;vertical-align:middle;font-weight:500}
footer{border-top:1px solid var(--line);padding:2.4rem 0 3.5rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
/* Deviant-family fonts + Fraunces/Ubuntu reader toggle. */
h1,h2,h3{font-family:'Fraunces',Georgia,serif;font-feature-settings:"ss01","ss02"}
code,.mono{font-family:'JetBrains Mono',ui-monospace,monospace}
body{font-family:'DM Sans','Inter',system-ui,sans-serif !important;font-feature-settings:"ss01","ss02"}
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:'JetBrains Mono',ui-monospace,monospace !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:'JetBrains Mono',monospace;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}
.font-picker button:hover{color:var(--ink)}
.font-picker button.active{background:var(--acid);color:var(--bg);font-weight:600}
</style>
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
</head>
<body>
<nav class="topnav">
<a class="brand" href="../">⭐ <span class="g">sirius.x</span></a>
<a class="brand" href="../">⭐ <span class="g">Sirius.X</span></a>
<a href="../#try">Try it</a>
<a href="../docs/">📚 Docs</a>
<a href="./" class="here">🧭 Theseus</a>
<a href="../#roadmap">Roadmap</a>
<a href="../brand/">🎨 Brand</a>
<a href="https://silentmode.st/" rel="noopener">Silent Mode ↗</a>
<a href="../#search-input">✏️ Register</a>
<a href="../tld.html">🌐 TLD</a>
<a href="../market.html">🛒 Market</a>
<a href="./" class="here"><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">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">🧭</div>
<div class="mark"><img src="./assets/favicon.svg" alt="" width="72" height="72" style="vertical-align:middle;filter:drop-shadow(0 0 24px rgba(214,255,61,.15))"></div>
<h1>Theseus <span class="g">Navigator</span></h1>
<p class="tag">A Chromium-based browser with native <b>.bch / BCNR</b> name resolution built in.
<p class="tag">A Chromium-based browser with native <b>Bitcoin Cash Domain Names</b> resolution built in.
No OS-level daemon, no DNS shim, no root-store install. Type <code>hello.bch</code> in the
address bar and it just works.</p>
<div class="cta">
@ -105,34 +125,13 @@
<div class="wrap">
<section id="download">
<h2>Download <span class="pill">v0.0.4</span></h2>
<p class="lede">Windows builds for now. The installer wires shortcuts and file associations; the
portable build is a single .exe that runs from anywhere. Ariadne Resolver is the older,
lighter option for systems where you only need name resolution without the browser.</p>
<div class="grid">
<div class="card">
<h3><span class="dot d-chain"></span> Theseus Navigator — Setup</h3>
<p>Installs with shortcuts + Start menu entry. Recommended for most users.</p>
<div class="cta"><a class="btn acid" href="https://dl.silentmode.st/TheseusNavigator-Setup-0.0.4.exe">Download Setup .exe (~97 MB)</a></div>
<div class="sub">SmartScreen may warn on first run — the binary is unsigned. Verify the SHA-256 against the checksum published on this page (below) before running.</div>
</div>
<div class="card">
<h3><span class="dot d-sia"></span> Theseus Navigator — Portable</h3>
<p>Single .exe. Nothing installed, nothing modified in the registry. Run and go.</p>
<div class="cta"><a class="btn acid" href="https://dl.silentmode.st/TheseusNavigator-0.0.4-portable.exe">Download Portable .exe (~97 MB)</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> Ariadne Resolver — Setup</h3>
<p>The lighter option: a system-wide BCNR resolver (no browser). Works with any browser via
the local trust anchor. Windows installer.</p>
<div class="cta"><a class="btn ghost" href="https://dl.silentmode.st/AriadneResolver-Setup-0.1.0.exe">Download Ariadne (~25 MB)</a></div>
</div>
<div class="card">
<h3><span class="dot d-srv"></span> Ariadne Resolver — Android</h3>
<p>Android APK. Runs as a VPN service to intercept and resolve BCNR names on the device.</p>
<div class="cta"><a class="btn ghost" href="https://dl.silentmode.st/ariadne-v0.8.apk">Download APK</a></div>
</div>
<h2>Download</h2>
<p class="lede">Theseus ships from its own site — <a href="https://silentmode.st/bns/theseus.x/#download" rel="noopener"><b>theseus.x</b></a> — so the version and checksums you see are always the current build, not a snapshot cached here. Windows installer + portable, plus Ariadne Resolver (lighter, no-browser).</p>
<div class="cta" style="justify-content:flex-start;margin-top:1.2rem">
<a class="btn acid" href="https://silentmode.st/bns/theseus.x/#download" rel="noopener">Open theseus.x downloads →</a>
<a class="btn ghost" href="https://silentmode.st/bns/theseus.x/" rel="noopener">Full Theseus site</a>
</div>
<div class="note" style="margin-top:1.4rem"><b>Why not list versions here?</b> Theseus updates weekly; a hardcoded version on this page went stale within days last time. theseus.x is the single source of truth — its own operator ships the current build, and Sirius.X links there instead of duplicating.</div>
</section>
<section id="how">
@ -159,7 +158,7 @@
</ol>
<div class="note"><b>What Theseus is NOT.</b> Not a wallet — for that, use Deviant, Cashonize,
Paytaca, or the built-in browser wallet at
<a href="https://silentmode.st/sirius/register.html" rel="noopener">sirius/register.html</a>.
<a href="../#search-input">the name search</a>.
Not a hosting service — for that, register a name and point its records at any host (Sia, VPS,
your own server). Theseus just makes those names openable in a normal-feeling browser.</div>
</section>
@ -167,28 +166,27 @@
<section id="verify">
<h2>Verify a download</h2>
<p class="lede">The binaries are unsigned (Windows will show a SmartScreen warning). Before
running, verify the SHA-256 against what the operator publishes on-chain and in the release
notes:</p>
running, verify the SHA-256 against what the operator publishes on-chain — the current
hashes live on the theseus.x download page itself, alongside each release:</p>
<pre>PowerShell:
Get-FileHash TheseusNavigator-Setup-0.0.4.exe
Get-FileHash &lt;downloaded-file&gt;.exe
Bash:
sha256sum TheseusNavigator-Setup-0.0.4.exe</pre>
<p class="lede">Compare the digest to the release manifest at
<a href="https://silentmode.st/releases/" rel="noopener">silentmode.st/releases/</a>.
sha256sum &lt;downloaded-file&gt;.exe</pre>
<p class="lede">Compare the digest to the hash panel on
<a href="https://silentmode.st/bns/theseus.x/#verify" rel="noopener">theseus.x/#verify</a>.
For a stronger guarantee, sign in with the wallet and check that the release-signing key
matches the on-chain identity for <code>releases.silentmode.bch</code>.</p>
</section>
</div>
<footer>
Theseus Navigator on sirius.x ·
<a href="../">back to sirius.x</a> ·
<a href="https://silentmode.st/tools/">Silent Mode Tools</a> ·
<a href="https://silentmode.st/releases/">Release notes</a><br>
Alpha, Windows for now. macOS and Linux builds are on the roadmap.
</footer>
<footer id="site-footer"></footer>
<script src="../js/pin-escrow.js?v=20260909pin"></script>
<script src="../js/pricing.js?v=20260909tldhigh"></script>
<script defer src="../js/site-footer.js?v=20260907rel"></script>
<script defer src="../js/theme.js?v=20260910font"></script>
<script defer src="../js/profile-menu.js?v=20260908tabs"></script>
</body>
</html>

314
tld.html Normal file
View file

@ -0,0 +1,314 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Register a TLD — Sirius.X</title>
<meta name="description" content="Mint a top-level domain on Bitcoin Cash. Any wallet can register a TLD; second-level names can then be sold under it.">
<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="Register a TLD on Bitcoin Cash">
<meta property="og:description" content="Mint a TLD certificate. One BCH transaction, no registrar. Renewals are per-TLD policy.">
<meta property="og:url" content="https://silentmode.st/sirius-x/tld.html">
<meta property="og:image" content="https://silentmode.st/sirius-x/brand/banner.svg">
<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}
html{scroll-behavior:smooth}
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:16px/1.6 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)}
.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:3.4rem 1.2rem 1rem}
.mark{font-size:44px;line-height:1}
h1{font-size:clamp(1.7rem,4.5vw,2.3rem);margin:.3rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1rem;max-width:600px;margin:0 auto}
h2{font-size:1.25rem;margin:0 0 .4rem}
section{padding:2rem 0;border-top:1px solid var(--line);margin-top:2rem}
section:first-of-type{border-top:none;margin-top:1rem}
.btn{display:inline-block;text-decoration:none;padding:10px 18px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn:hover{filter:brightness(1.12)}
.btn:disabled{opacity:.45;cursor:not-allowed;filter:none}
.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:ui-monospace,monospace;font-size:13px;word-break:break-all}
.badge{display:inline-block;font-size:11px;padding:2px 10px;border-radius:999px;font-weight:600}
.b-ok{background:rgba(79,209,165,.15);color:var(--ok)}
.b-taken{background:rgba(246,118,138,.15);color:var(--taken)}
.b-check{background:rgba(139,152,169,.14);color:var(--mut)}
.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)}
.status.warn{border-left:3px solid var(--warn);color:var(--warn)}
/* TLD search cell */
.search{max-width:600px;margin:1.5rem auto 0}
.searchrow{display:flex;gap:8px}
.searchrow input{flex:1;padding:14px 18px;font-size:17px;border-radius:12px;border:1px solid #ffffff22;background:#141a24;color:var(--ink);font-family:inherit;outline:none}
.searchrow input:focus{border-color:#4b7bec}
.searchhint{font-size:12.5px;color:var(--mut);margin-top:8px;text-align:center}
.result-card{display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center;
background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 18px;margin-top:12px}
.result-card .lbl{font-family:ui-monospace,monospace;font-size:18px;color:var(--ink)}
.result-card .lbl .dot{color:var(--acid)}
/* Registered-TLDs table */
table.tlds{width:100%;border-collapse:collapse;margin-top:1rem;font-size:13px}
table.tlds th,table.tlds td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
table.tlds th{color:var(--mut);font-weight:500;font-size:11.5px;text-transform:uppercase;letter-spacing:.4px}
table.tlds .tld{font-family:ui-monospace,monospace;color:var(--acid);font-size:13.5px;font-weight:600}
table.tlds .cat{font-family:ui-monospace,monospace;color:var(--mut);font-size:11.5px;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.price, table.tlds .price{
color:var(--acid);font-family:ui-monospace,monospace;font-size:13px;font-weight:600;
padding:2px 8px;border-radius:6px;background:rgba(214,255,61,.10);white-space:nowrap;display:inline-block
}
.result-card{grid-template-columns:1fr auto auto auto !important}
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
</style>
<script type="importmap">
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
</script>
<script src="./js/i18n.js?v=20260920d"></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" class="here">🌐 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">🔑 Sign in</a>
</nav>
<header class="hero">
<div class="mark">🌐</div>
<h1>Register a <span class="g">TLD</span></h1>
<p class="tag">A TLD is a certificate on the Bitcoin Cash chain. You mint it, you own it — any
second-level name registered under it lives in your TLD's registry. One BCH transaction,
no ICANN. Renewals? Your TLD, your policy.</p>
</header>
<div class="wrap">
<section id="search-section">
<h2>Search a TLD</h2>
<p class="muted">Type a label (a–z, 0–9, hyphen; up to 16 chars). Available TLDs get a Register
button that opens the shared wallet-choice modal — the same flow name registration uses.
As TLD owner you earn <b style="color:var(--ok)">90 %</b> of every name registered under
your TLD. Renewals are your call — set them per TLD, or don't.</p>
<div class="search">
<div class="searchrow">
<input id="q" placeholder="your-tld" spellcheck="false" autocomplete="off" autofocus maxlength="16">
</div>
<div class="searchhint">Register minting to your token address; you become the registry operator.</div>
</div>
<div id="result"></div>
</section>
<section id="listing">
<h2>Registered TLDs</h2>
<p class="muted">Fetched from the on-chain TLD registry via the public gateway. Refresh the page for the latest.</p>
<div id="tlds-status" class="status">Loading…</div>
<table class="tlds" id="tlds-table" style="display:none">
<thead><tr><th>TLD</th><th>Mint price</th><th>Category</th></tr></thead>
<tbody></tbody>
</table>
</section>
</div>
<footer id="site-footer"></footer>
<script>
// Simple oracle stub: static chipnet rate for testing. Same number the
// portal uses. Mainnet swaps for a real price feed.
const CHIPNET_SATS_PER_USD = 250_000;
const DEFAULT_USD = 5;
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s).replace(/[&<>"']/g, (c) => ({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[c]));
const validLabel = (s) => /^[a-z0-9-]{1,16}$/.test(s);
const normLabel = (s) => String(s).toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 16);
// ---------- registered-TLD list ----------
let registeredTlds = null;
async function loadTldList() {
const status = $("tlds-status"), tbody = $("tlds-table").querySelector("tbody");
try {
const r = await fetch("https://navigate.st/api/tlds");
if (!r.ok) throw new Error("api " + r.status);
const j = await r.json();
const tlds = (j.tlds || []).map((t) => (typeof t === "string" ? { tld: t } : t));
tlds.sort((a, b) => a.tld.localeCompare(b.tld));
tbody.innerHTML = tlds.map((t) => {
const p = window.siriusPricing?.priceForTld(t.tld);
const priceCell = p ? `<span class="price" title="${esc(p.tier)}">${esc(window.siriusPricing.formatUsd(p.usd))}</span>` : "—";
return `<tr>
<td class="tld">.${esc(t.tld)}</td>
<td class="price-cell">${priceCell}</td>
<td class="cat">${esc(t.certificate || t.category || "")}</td>
</tr>`;
}).join("");
$("tlds-table").style.display = "";
status.className = "status ok";
status.textContent = `${tlds.length} TLDs registered on chipnet.`;
registeredTlds = tlds.map((t) => t.tld);
refreshSearch();
} catch (e) {
status.className = "status err";
status.textContent = "Could not load TLD list: " + (e.message || e);
}
}
loadTldList();
// ---------- search result renderer ----------
function renderResult(label, state) {
const res = $("result");
if (!label) { res.innerHTML = ""; return; }
if (state === "checking") {
res.innerHTML = `<div class="result-card">
<div class="lbl"><span class="dot">.</span>${esc(label)}</div>
<span class="badge b-check">checking…</span><span></span></div>`;
return;
}
if (state === "taken") {
res.innerHTML = `<div class="result-card">
<div class="lbl"><span class="dot">.</span>${esc(label)}</div>
<span class="badge b-taken">taken</span><span></span></div>
<p class="dim" style="margin-top:8px">Someone already minted <code>.${esc(label)}</code>. Try a
different label — TLDs are first-come, first-served.</p>`;
return;
}
const p = window.siriusPricing?.priceForTld(label);
const priceBadge = p
? `<span class="price" title="${esc(p.tier)}">${esc(window.siriusPricing.formatUsd(p.usd))}</span>`
: "";
res.innerHTML = `<div class="result-card">
<div class="lbl"><span class="dot">.</span>${esc(label)}</div>
<span class="badge b-ok">available</span>
${priceBadge}
<button class="btn acid" id="go-register">Register .${esc(label)} →</button>
</div>`;
$("go-register").onclick = () => beginRegister(label);
}
// ---------- search wiring ----------
let currentLabel = "";
function refreshSearch() {
const raw = normLabel($("q").value);
currentLabel = raw;
if (!raw) { renderResult("", null); return; }
if (!validLabel(raw)) { renderResult(raw, "invalid"); return; }
if (registeredTlds !== null) {
renderResult(raw, registeredTlds.includes(raw) ? "taken" : "ok");
return;
}
renderResult(raw, "checking");
}
$("q").addEventListener("input", () => {
$("q").value = normLabel($("q").value);
refreshSearch();
});
$("q").addEventListener("keydown", (e) => {
if (e.key === "Enter" && currentLabel && registeredTlds && !registeredTlds.includes(currentLabel)) {
beginRegister(currentLabel);
}
});
// ---------- mint delegation ----------
// Register button hands the label off to the shared modal (register-flow.js
// — window.siriusRegisterTld). That modal owns the wallet-choice, fund,
// confirm, and mint steps — same UX as name registration.
function beginRegister(label) {
// Label-based tier pricing lives in siriusPricing (js/pricing.js) so
// landing / tld / mint agree. Fall back to the flat DEFAULT_USD if the
// pricing module hasn't loaded for some reason.
const p = window.siriusPricing?.priceForTld(label);
const fee = p ? p.sats : BigInt(DEFAULT_USD * CHIPNET_SATS_PER_USD);
const call = () => window.siriusRegisterTld(label, { serviceFeeSats: fee });
if (typeof window.siriusRegisterTld === "function") { call(); return; }
// Module still loading — retry until it lands.
const btn = $("go-register");
const orig = btn?.textContent;
if (btn) { btn.disabled = true; btn.textContent = "loading…"; }
const t = setInterval(() => {
if (typeof window.siriusRegisterTld === "function") {
clearInterval(t);
if (btn) { btn.disabled = false; btn.textContent = orig; }
call();
}
}, 100);
}
// ---------- ?q= deep-link (from landing links etc.) ----------
(() => {
const q = normLabel(new URLSearchParams(location.search).get("q") || "");
if (!q) return;
$("q").value = q;
const wait = setInterval(() => {
if (registeredTlds === null) return;
clearInterval(wait);
refreshSearch();
setTimeout(() => $("q").scrollIntoView({ behavior: "smooth", block: "start" }), 100);
}, 150);
})();
</script>
<script type="module" src="./js/register-flow.js?v=20260917bal"></script>
<script src="./js/pricing.js?v=20260917market"></script>
<script src="./js/session.js?v=20260917dash"></script>
<script src="./js/pin-escrow.js?v=20260909pin"></script>
<script defer src="./js/theme.js?v=20260910font"></script>
<script defer src="./js/site-footer.js?v=20260917market"></script>
<script defer src="./js/profile-menu.js?v=20260920m"></script>
</body>
</html>

View file

@ -0,0 +1,25 @@
Copyright (c) 2017-current, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

25
vendor/grapesjs/LICENSE-countdown.txt vendored Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2017, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

25
vendor/grapesjs/LICENSE-custom-code.txt vendored Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2018-current, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

25
vendor/grapesjs/LICENSE-grapesjs.txt vendored Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2017-current, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

25
vendor/grapesjs/LICENSE-navbar.txt vendored Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2017-current, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,25 @@
Copyright (c) 2018-current, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,25 @@
Copyright (c) 2017, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,25 @@
Copyright (c) 2017, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

7
vendor/grapesjs/LICENSE-style-bg.txt vendored Normal file
View file

@ -0,0 +1,7 @@
MIT License Copyright (c) 2020-current Grapesjs Style Bg
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

25
vendor/grapesjs/LICENSE-tabs.txt vendored Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2018-current, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

25
vendor/grapesjs/LICENSE-tooltip.txt vendored Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2018-current, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

25
vendor/grapesjs/LICENSE-touch.txt vendored Normal file
View file

@ -0,0 +1,25 @@
Copyright (c) 2018-current, Artur Arseniev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "GrapesJS" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

14
vendor/grapesjs/VERSIONS.txt vendored Normal file
View file

@ -0,0 +1,14 @@
Vendored 2026-09-20 from npm (no CDN at runtime; see the LICENSE-*.txt files, all BSD-3 or MIT):
grapesjs 0.23.6 grapes.min.js / grapes.min.css
grapesjs-blocks-basic 1.0.2 blocks-basic.js
grapesjs-preset-webpage 1.0.3 preset-webpage.js
grapesjs-plugin-forms 2.0.6 plugin-forms.js
grapesjs-navbar 1.0.2 navbar.js
grapesjs-custom-code 1.0.2 custom-code.js
grapesjs-tabs 1.0.6 tabs.js
grapesjs-tooltip 0.1.8 tooltip.js
grapesjs-style-bg 2.0.2 style-bg.js
grapesjs-touch 0.1.1 touch.js
grapesjs-component-countdown 1.0.2 countdown.js
Update: npm pack <pkg> ; copy package/dist/*.js here ; bump ?v= in studio.html.
grapesjs-parser-postcss 1.0.3 parser-postcss.js (CSS parsed with PostCSS: keeps var() shorthands the browser parser drops)

3
vendor/grapesjs/blocks-basic.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/countdown.js vendored Normal file
View file

@ -0,0 +1,3 @@
/*! grapesjs-component-countdown - 1.0.2 */
!function(n,t){'object'==typeof exports&&'object'==typeof module?module.exports=t():'function'==typeof define&&define.amd?define([],t):'object'==typeof exports?exports["grapesjs-component-countdown"]=t():n["grapesjs-component-countdown"]=t()}('undefined'!=typeof globalThis?globalThis:'undefined'!=typeof window?window:this,(()=>(()=>{"use strict";var n={d:(t,e)=>{for(var o in e)n.o(e,o)&&!n.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},o:(n,t)=>Object.prototype.hasOwnProperty.call(n,t),r:n=>{'undefined'!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:'Module'}),Object.defineProperty(n,'__esModule',{value:!0})}},t={};n.r(t),n.d(t,{default:()=>o});var e=void 0&&(void 0).__assign||function(){return e=Object.assign||function(n){for(var t,e=1,o=arguments.length;e<o;e++)for(var a in t=arguments[e])Object.prototype.hasOwnProperty.call(t,a)&&(n[a]=t[a]);return n},e.apply(this,arguments)};const o=function(n,t){void 0===t&&(t={});var o=e({id:'countdown',label:'Countdown',block:{},props:{},style:'',styleAdditional:'',startTime:'',endText:'EXPIRED',dateInputType:'date',labelDays:'days',labelHours:'hours',labelMinutes:'minutes',labelSeconds:'seconds',classPrefix:'countdown'},t),a=o.block,c=o.props,d=o.style,s=o.id,l=o.label,i=o.classPrefix;a&&n.Blocks.add(s,e({media:"<svg viewBox=\"0 0 24 24\">\n <path fill=\"currentColor\" d=\"M12 20C16.4 20 20 16.4 20 12S16.4 4 12 4 4 7.6 4 12 7.6 20 12 20M12 2C17.5 2 22 6.5 22 12S17.5 22 12 22C6.5 22 2 17.5 2 12C2 6.5 6.5 2 12 2M17 11.5V13H11V7H12.5V11.5H17Z\" />\n </svg>",label:l,category:'Extra',select:!0,content:{type:s}},a));n.Components.addType(s,{model:{defaults:e({startfrom:o.startTime,classes:[i],endText:o.endText,droppable:!1,script:function(n){var t=n.startfrom,e=n.endText,o=this,a=new Date(t).getTime(),c=o.querySelector('[data-js=countdown]'),d=o.querySelector('[data-js=countdown-endtext]'),s=o.querySelector('[data-js=countdown-day]'),l=o.querySelector('[data-js=countdown-hour]'),i=o.querySelector('[data-js=countdown-minute]'),r=o.querySelector('[data-js=countdown-second]'),u=o.__gjsCountdownInterval;u&&clearInterval(u);var p=window.__gjsCountdownIntervals||[],v=[];p.forEach((function(n){n.isConnected||(clearInterval(n.__gjsCountdownInterval),v.push(n))})),p.indexOf(o)<0&&p.push(o),window.__gjsCountdownIntervals=p.filter((function(n){return v.indexOf(n)<0}));var y=function(n,t,e,o){s.innerHTML="".concat(n<10?'0'+n:n),l.innerHTML="".concat(t<10?'0'+t:t),i.innerHTML="".concat(e<10?'0'+e:e),r.innerHTML="".concat(o<10?'0'+o:o)},f=function(){var n=(new Date).getTime(),t=a-n,s=Math.floor(t/864e5),l=Math.floor(t%864e5/36e5),i=Math.floor(t%36e5/6e4),r=Math.floor(t%6e4/1e3);y(s,l,i,r),t<0&&(clearInterval(o.__gjsCountdownInterval),d.innerHTML=e,c.style.display='none',d.style.display='')};a?(o.__gjsCountdownInterval=setInterval(f,1e3),d.style.display='none',c.style.display='',f()):y(0,0,0,0)},'script-props':['startfrom','endText'],traits:[{label:'Start',name:'startfrom',changeProp:!0,type:o.dateInputType},{label:'End text',name:'endText',changeProp:!0}],components:"\n <span data-js=\"countdown\" class=\"".concat(i,"-cont\">\n <div class=\"").concat(i,"-block\">\n <div data-js=\"countdown-day\" class=\"").concat(i,"-digit\"></div>\n <div class=\"").concat(i,"-label\">").concat(o.labelDays,"</div>\n </div>\n <div class=\"").concat(i,"-block\">\n <div data-js=\"countdown-hour\" class=\"").concat(i,"-digit\"></div>\n <div class=\"").concat(i,"-label\">").concat(o.labelHours,"</div>\n </div>\n <div class=\"").concat(i,"-block\">\n <div data-js=\"countdown-minute\" class=\"").concat(i,"-digit\"></div>\n <div class=\"").concat(i,"-label\">").concat(o.labelMinutes,"</div>\n </div>\n <div class=\"").concat(i,"-block\">\n <div data-js=\"countdown-second\" class=\"").concat(i,"-digit\"></div>\n <div class=\"").concat(i,"-label\">").concat(o.labelSeconds,"</div>\n </div>\n </span>\n <span data-js=\"countdown-endtext\" class=\"").concat(i,"-endtext\"></span>\n "),styles:(d||"\n .".concat(i," {\n text-align: center;\n }\n\n .").concat(i,"-block {\n display: inline-block;\n margin: 0 10px;\n padding: 10px;\n }\n\n .").concat(i,"-digit {\n font-size: 5rem;\n }\n\n .").concat(i,"-endtext {\n font-size: 5rem;\n }\n\n .").concat(i,"-cont {\n display: inline-block;\n }\n "))+o.styleAdditional},c)}})};return t})()));
//# sourceMappingURL=index.js.map

3
vendor/grapesjs/custom-code.js vendored Normal file

File diff suppressed because one or more lines are too long

1
vendor/grapesjs/grapes.min.css vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/grapes.min.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/navbar.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/parser-postcss.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/plugin-forms.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/preset-webpage.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/style-bg.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/tabs.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/tooltip.js vendored Normal file

File diff suppressed because one or more lines are too long

3
vendor/grapesjs/touch.js vendored Normal file

File diff suppressed because one or more lines are too long

211
vendor/web-llm/LICENSE.txt vendored Normal file
View file

@ -0,0 +1,211 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
------------------------------------------------------------------------------------
This product bundles various third-party components under other open source licenses.
This section summarizes those components and their licenses. See licenses/
for text of these licenses.
Apache Software Foundation License 2.0
--------------------------------------
src/openai_api_protocols

93
vendor/web-llm/index.js vendored Normal file

File diff suppressed because one or more lines are too long