Whitepaper: rebuildable from its Markdown, with the workflow written down
The page was generated by a one-off script that no longer exists, so a text change meant rebuilding the tooling first. build/build.mjs turns whitepaper.md into index.html byte-for-byte as published; the page chrome and the two diagrams are checked in beside it (the folder needs an exception from the generic build/ ignore rule). README.md records the publishing steps for both mirrors and the editorial decisions the text follows.
This commit is contained in:
parent
78da8fbbde
commit
95f1ab55aa
5 changed files with 321 additions and 0 deletions
64
whitepaper/README.md
Normal file
64
whitepaper/README.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# Theseus Navigator whitepaper
|
||||
|
||||
Published at `theseus.x/whitepaper/` (Sia bucket `bns/theseus/whitepaper/`), mirrored at
|
||||
`https://silentmode.st/theseus-x/whitepaper/` and reachable through the gateway at
|
||||
`https://navigate.st/bns/theseus.x/whitepaper/`. Licence: CC BY 4.0 (see `LICENSES.md` at the repo root).
|
||||
|
||||
## Files
|
||||
|
||||
| File | Role |
|
||||
| --- | --- |
|
||||
| `whitepaper.md` | The text. Source of truth in the repo; one paragraph per line, `##` sections. |
|
||||
| `index.html` | Generated. Never edit by hand; rebuild it. |
|
||||
| `build/build.mjs` | Markdown → page. `node build/build.mjs` writes `index.html`; `--check` verifies it is current. |
|
||||
| `build/template.html` | Page chrome (nav, styles, footer, TOC script) with `{{title}}`, `{{byline}}`, `{{toc}}`, `{{article}}`. |
|
||||
| `build/figure-*.html` | The diagrams, hand-written SVG. Placed where the text has `[embedded content: <name> · …]`. |
|
||||
|
||||
The text may also be edited in a shared document outside the repo and exported as Markdown over
|
||||
`whitepaper.md`; the export keeps the `[embedded content: …]` markers the build needs. Either way,
|
||||
after a change:
|
||||
|
||||
```
|
||||
node WebsiteDev/site-theseus-x/whitepaper/build/build.mjs
|
||||
```
|
||||
|
||||
Open `index.html` locally to review, then publish both surfaces (the ICANN mirror does not sync
|
||||
from the Sia bucket):
|
||||
|
||||
```
|
||||
node Argus/src/lib/sia-upload.js WebsiteDev/site-theseus-x/whitepaper/index.html bns/theseus/whitepaper
|
||||
scp WebsiteDev/site-theseus-x/whitepaper/index.html silentmode:/opt/silent-mode/site/theseus-x/whitepaper/index.html
|
||||
```
|
||||
|
||||
Check `https://silentmode.st/theseus-x/whitepaper/` and `https://navigate.st/bns/theseus.x/whitepaper/`
|
||||
afterwards (compare the SHA-256 with the local file; the gateway may cache a folder for a minute or two).
|
||||
Commit `whitepaper.md`, `index.html` and any figure change together.
|
||||
|
||||
When the whole theseus.x site is republished anyway, `scripts/mirror-bcnr-site.sh` (usage in its header)
|
||||
carries the whitepaper folder along with everything else.
|
||||
|
||||
## Writing rules
|
||||
|
||||
These are decisions already taken for this paper; keep them.
|
||||
|
||||
- Names are "digital certificate records" on Bitcoin Cash. Do not describe them as NFTs or
|
||||
CashTokens; those words are fine for chats and forums, not for this paper.
|
||||
- A name is neither "owned" nor "rented" by definition. The point is that the record lives on the
|
||||
chain and the intermediaries between owner and record are gone. A TLD's certificate holder sets its
|
||||
terms (a yearly fee, a longer term, or none).
|
||||
- No list of current TLDs, no prices, no network status, no release version numbers or dates.
|
||||
The paper describes how the system works and its security model, not the state of the network.
|
||||
- No personal names, nicknames or contact details. The author is Silent Mode. No references to the
|
||||
tools the text was written with.
|
||||
- The licensing paragraph names MPL-2.0 for the clients, Apache-2.0 for Argus, CC BY 4.0 for the
|
||||
documents, and points at the brand pages for the trademark terms.
|
||||
- Every factual claim is checked against the source tree and the live surfaces; the closing
|
||||
paragraph states the date of that check. Update that date and the byline (line 3) when a
|
||||
revised text is published.
|
||||
|
||||
## Diagrams
|
||||
|
||||
Each figure is one `<figure class="diagram">…</figure>` fragment with an inline SVG sized to a
|
||||
760-unit-wide viewBox, using the page colours (`#e7eaf1` ink, `#8b98a9` muted, `#5e6678` dim,
|
||||
`#d6ff3d` accent) and a `<figcaption>`. To add one, write `build/figure-<name>.html` and put a line
|
||||
`[embedded content: <name>]` in `whitepaper.md` where it belongs.
|
||||
95
whitepaper/build/build.mjs
Normal file
95
whitepaper/build/build.mjs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env node
|
||||
// Builds ../index.html (the theseus.x whitepaper page) from ../whitepaper.md.
|
||||
//
|
||||
// node build/build.mjs # write ../index.html
|
||||
// node build/build.mjs --check # exit 1 if ../index.html is not what the build produces
|
||||
//
|
||||
// whitepaper.md is the Markdown export of the editable document (see ../README.md).
|
||||
// The page chrome lives in template.html; the two diagrams are the figure-*.html
|
||||
// fragments and are placed where the export left its "[embedded content: <name> · …]"
|
||||
// marker. Markdown handled: #/## headings, paragraphs, "- " and "1. " lists, pipe
|
||||
// tables, **bold**, `code`, [text](url), backslash escapes. Each paragraph is one line.
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const here = path.dirname(fileURLToPath(import.meta.url));
|
||||
const root = path.join(here, "..");
|
||||
const md = fs.readFileSync(path.join(root, "whitepaper.md"), "utf8").replace(/\r\n/g, "\n");
|
||||
const template = fs.readFileSync(path.join(here, "template.html"), "utf8");
|
||||
const figure = (name) => {
|
||||
const f = path.join(here, `figure-${name}.html`);
|
||||
if (!fs.existsSync(f)) throw new Error(`no figure fragment for "${name}" (expected ${f})`);
|
||||
return fs.readFileSync(f, "utf8").replace(/\n$/, "");
|
||||
};
|
||||
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const unescapeMd = (s) => s.replace(/\\([\\`*_{}\[\]()#+\-.!|>~"'])/g, "$1");
|
||||
|
||||
// Inline Markdown → HTML. Code spans are protected first so nothing inside them is touched.
|
||||
function inline(src) {
|
||||
const codes = [];
|
||||
let s = src.replace(/`([^`]+)`/g, (_, c) => { codes.push(`<code>${esc(c)}</code>`); return `\u0000${codes.length - 1}\u0000`; });
|
||||
s = esc(unescapeMd(s));
|
||||
s = s.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
|
||||
s = s.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, (_, t, u) => `<a href="${u}">${t}</a>`);
|
||||
return s.replace(/\u0000(\d+)\u0000/g, (_, i) => codes[+i]);
|
||||
}
|
||||
|
||||
const slug = (t) => t.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
||||
const cells = (row) => row.replace(/^\s*\|/, "").replace(/\|\s*$/, "").split(/(?<!\\)\|/).map((c) => c.trim());
|
||||
|
||||
const lines = md.split("\n");
|
||||
let title = "", byline = "";
|
||||
const toc = [], out = [];
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (!line.trim()) continue;
|
||||
if (line.startsWith("# ")) { title = line.slice(2).trim(); continue; }
|
||||
if (line.startsWith("## ")) {
|
||||
const text = line.slice(3).trim(), id = slug(text);
|
||||
toc.push(` <a href="#${id}">${inline(text)}</a>`);
|
||||
out.push(`<h2 id="${id}">${inline(text)}</h2>`);
|
||||
continue;
|
||||
}
|
||||
if (!toc.length && !byline) { byline = inline(line.trim()); continue; }
|
||||
const embed = line.match(/^(?:\[|[)embedded content:\s*([a-z0-9-]+)\s*(?:·.*)?(?:\]|\\\]|])\s*$/i);
|
||||
if (embed) { out.push(figure(embed[1])); continue; }
|
||||
if (/^[-*] /.test(line) || /^\d+\. /.test(line)) {
|
||||
const ordered = /^\d+\. /.test(line);
|
||||
const items = [];
|
||||
while (i < lines.length && (ordered ? /^\d+\. / : /^[-*] /).test(lines[i])) items.push(lines[i++].replace(/^(?:[-*]|\d+\.) /, ""));
|
||||
i--;
|
||||
out.push(`<${ordered ? "ol" : "ul"}>${items.map((t) => `<li>${inline(t)}</li>`).join("")}</${ordered ? "ol" : "ul"}>`);
|
||||
continue;
|
||||
}
|
||||
if (line.trimStart().startsWith("|")) {
|
||||
const rows = [];
|
||||
while (i < lines.length && lines[i].trimStart().startsWith("|")) rows.push(lines[i++]);
|
||||
i--;
|
||||
const head = cells(rows[0]), body = rows.slice(2).filter((r) => !/^\s*\|?\s*(:?-+:?\s*\|)+/.test(r) || true);
|
||||
const tr = (cs, tag) => `<tr>${cs.map((c) => `<${tag}>${inline(c)}</${tag}>`).join("")}</tr>`;
|
||||
out.push(`<table><thead>${tr(head, "th")}</thead><tbody>${rows.slice(2).map((r) => tr(cells(r), "td")).join("")}</tbody></table>`);
|
||||
continue;
|
||||
}
|
||||
out.push(`<p>${inline(line.trim())}</p>`);
|
||||
}
|
||||
if (!title || !byline) throw new Error("whitepaper.md needs a '# title' line and a byline paragraph before the first '## ' heading");
|
||||
|
||||
// "Theseus Navigator Whitepaper" → last word in the accent colour, like the other theseus.x pages.
|
||||
const titleHtml = esc(title).replace(/\s(\S+)$/, ' <span class="g">$1</span>');
|
||||
const html = template
|
||||
.replace("{{title}}", titleHtml)
|
||||
.replace("{{byline}}", byline)
|
||||
.replace("{{toc}}", toc.join("\n"))
|
||||
.replace("{{article}}", out.join("\n"));
|
||||
|
||||
const target = path.join(root, "index.html");
|
||||
if (process.argv.includes("--check")) {
|
||||
const cur = fs.existsSync(target) ? fs.readFileSync(target, "utf8") : "";
|
||||
if (cur !== html) { console.error("index.html differs from the build of whitepaper.md"); process.exit(1); }
|
||||
console.log("index.html is up to date");
|
||||
} else {
|
||||
fs.writeFileSync(target, html);
|
||||
console.log(`wrote ${path.relative(process.cwd(), target)} (${html.length} bytes, ${toc.length} sections)`);
|
||||
}
|
||||
9
whitepaper/build/figure-architecture.html
Normal file
9
whitepaper/build/figure-architecture.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<figure class="diagram"><svg viewBox="0 0 760 368" role="img" aria-label="Every client reads the chain itself; the gateway only serves bytes" font-family="system-ui,-apple-system,Segoe UI,Roboto,sans-serif" font-size="13"><defs><marker id="arch-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#5e6678"/></marker></defs>
|
||||
<text x="24" y="34" font-size="15" font-weight="600" fill="#e7eaf1">Every client reads the chain itself; the gateway only serves bytes</text>
|
||||
<g fill="none" stroke="#5e6678" stroke-width="1.25"><path d="M109 120L109 176" marker-end="url(#arch-arrow)"/><path d="M283 120L283 176" marker-end="url(#arch-arrow)"/><path d="M457 120L320 176" marker-end="url(#arch-arrow)"/><path d="M631 120L320 176" marker-end="url(#arch-arrow)"/><path d="M109 120L440 176" marker-end="url(#arch-arrow)"/><path d="M283 120L440 176" marker-end="url(#arch-arrow)"/><path d="M457 120L457 176" marker-end="url(#arch-arrow)"/><path d="M631 120L631 176" marker-end="url(#arch-arrow)"/><path d="M416 204H344" marker-end="url(#arch-arrow)"/><path d="M576 232V288" marker-end="url(#arch-arrow)"/></g>
|
||||
<text x="380" y="196" text-anchor="middle" font-size="11.5" fill="#8b98a9">same chain</text>
|
||||
<g><rect x="24" y="64" width="170" height="56" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="36" y="84" font-weight="600" fill="#e7eaf1">Theseus Navigator</text><text x="36" y="101" font-size="11.5" fill="#8b98a9">desktop browser</text></g><g><rect x="198" y="64" width="170" height="56" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="210" y="84" font-weight="600" fill="#e7eaf1">Ariadne's Thread</text><text x="210" y="101" font-size="11.5" fill="#8b98a9">Windows resolver</text></g><g><rect x="372" y="64" width="170" height="56" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="384" y="84" font-weight="600" fill="#e7eaf1">Ariadne for Android</text><text x="384" y="101" font-size="11.5" fill="#8b98a9">phone browser</text></g><g><rect x="546" y="64" width="170" height="56" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="558" y="84" font-weight="600" fill="#e7eaf1">Sirius</text><text x="558" y="101" font-size="11.5" fill="#8b98a9">registrar and studio</text></g>
|
||||
<g><rect x="24" y="176" width="320" height="56" rx="8" fill="#d6ff3d" fill-opacity=".12" stroke="#d6ff3d" stroke-width="2"/><text x="184" y="196" text-anchor="middle" font-weight="600" fill="#e7eaf1">Bitcoin Cash chain</text><text x="184" y="213" text-anchor="middle" font-size="11.5" fill="#8b98a9">read through Electrum servers, reduced locally</text></g>
|
||||
<g><rect x="416" y="176" width="320" height="56" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="576" y="196" text-anchor="middle" font-weight="600" fill="#e7eaf1">Gateway, navigate.st</text><text x="576" y="213" text-anchor="middle" font-size="11.5" fill="#8b98a9">serves Sia sites, verifies signed records</text></g>
|
||||
<g><rect x="416" y="288" width="320" height="56" rx="8" fill="rgba(255,255,255,.04)" stroke="#5e6678" stroke-width="1.25"/><text x="576" y="310" text-anchor="middle" font-weight="600" fill="#e7eaf1">Sia storage</text><text x="576" y="328" text-anchor="middle" font-size="11.5" fill="#8b98a9">sites, signed records, extensions</text></g>
|
||||
</svg><figcaption>Architecture: four clients, one chain, one gateway.</figcaption></figure>
|
||||
7
whitepaper/build/figure-resolution.html
Normal file
7
whitepaper/build/figure-resolution.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<figure class="diagram"><svg viewBox="0 0 760 328" role="img" aria-label="Four sources build one local index and the record picks the source" font-family="system-ui,-apple-system,Segoe UI,Roboto,sans-serif" font-size="13"><defs><marker id="res-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#5e6678"/></marker></defs>
|
||||
<text x="24" y="34" font-size="15" font-weight="600" fill="#e7eaf1">Four sources build one local index; the record picks the source</text>
|
||||
<g fill="none" stroke="#5e6678" stroke-width="1.25"><path d="M220 88L290 184" marker-end="url(#res-arrow)"/><path d="M220 152L290 184" marker-end="url(#res-arrow)"/><path d="M220 216L290 184" marker-end="url(#res-arrow)"/><path d="M220 280L290 184" marker-end="url(#res-arrow)"/><path d="M470 184L540 88" marker-end="url(#res-arrow)"/><path d="M470 184L540 152" marker-end="url(#res-arrow)"/><path d="M470 184L540 216" marker-end="url(#res-arrow)"/><path d="M470 184L540 280" marker-end="url(#res-arrow)"/></g>
|
||||
<g><rect x="24" y="64" width="196" height="48" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="36" y="84" font-weight="600" fill="#e7eaf1">Bundled snapshot</text><text x="36" y="101" font-size="11.5" fill="#8b98a9">ships in the build</text></g><g><rect x="24" y="128" width="196" height="48" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="36" y="148" font-weight="600" fill="#e7eaf1">Profile snapshot</text><text x="36" y="165" font-size="11.5" fill="#8b98a9">saved after every poll</text></g><g><rect x="24" y="192" width="196" height="48" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="36" y="212" font-weight="600" fill="#e7eaf1">Electrum delta poll</text><text x="36" y="229" font-size="11.5" fill="#8b98a9">beacon history, every 30 s</text></g><g><rect x="24" y="256" width="196" height="48" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="36" y="276" font-weight="600" fill="#e7eaf1">Sia name list</text><text x="36" y="293" font-size="11.5" fill="#8b98a9">a further floor, rarely needed</text></g>
|
||||
<g><rect x="290" y="140" width="180" height="88" rx="8" fill="#d6ff3d" fill-opacity=".12" stroke="#d6ff3d" stroke-width="2"/><text x="380" y="170" text-anchor="middle" font-weight="600" fill="#e7eaf1">Local name index</text><text x="380" y="192" text-anchor="middle" font-size="11.5" fill="#8b98a9">first valid REG wins</text><text x="380" y="210" text-anchor="middle" font-size="11.5" fill="#8b98a9">UPD only from the holder</text></g>
|
||||
<g><rect x="540" y="64" width="196" height="48" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="552" y="84" font-weight="600" fill="#e7eaf1">Sia site (s3)</text><text x="552" y="101" font-size="11.5" fill="#8b98a9">through the gateway mount</text></g><g><rect x="540" y="128" width="196" height="48" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="552" y="148" font-weight="600" fill="#e7eaf1">Owner's server (ip)</text><text x="552" y="165" font-size="11.5" fill="#8b98a9">TLS fingerprint pinned</text></g><g><rect x="540" y="192" width="196" height="48" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="552" y="212" font-weight="600" fill="#e7eaf1">Proxy and inline</text><text x="552" y="229" font-size="11.5" fill="#8b98a9">p and h records</text></g><g><rect x="540" y="256" width="196" height="48" rx="8" fill="none" stroke="#5e6678" stroke-width="1.25"/><text x="552" y="276" font-weight="600" fill="#e7eaf1">Redirect (u)</text><text x="552" y="293" font-size="11.5" fill="#8b98a9">to any URL</text></g>
|
||||
</svg><figcaption>Resolution: four sources, one index, four ways to serve.</figcaption></figure>
|
||||
146
whitepaper/build/template.html
Normal file
146
whitepaper/build/template.html
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Whitepaper — Theseus.X</title>
|
||||
<meta name="description" content="How Theseus Navigator resolves Bitcoin Cash names without a registrar or a resolver in the middle, how content and records are published and verified, the protections it ships on by default, the wallet and extension model, and the security model as it stands.">
|
||||
<link rel="icon" href="../brand/favicon.svg" type="image/svg+xml">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:site_name" content="Theseus.X">
|
||||
<meta property="og:title" content="Theseus Navigator Whitepaper">
|
||||
<meta property="og:description" content="A browser in which a site's name is a record on the Bitcoin Cash blockchain, not an entry in a registrar's database.">
|
||||
<meta property="og:url" content="https://theseus.x/whitepaper/">
|
||||
<style>
|
||||
:root{ --bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
|
||||
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d; }
|
||||
*{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.7 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh;padding-top:52px}
|
||||
a{color:var(--acid)}
|
||||
.topnav{position:fixed;top:0;left:0;right:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
|
||||
padding:10px 1.2rem;background:rgba(11,14,20,.88);backdrop-filter:blur(10px)}
|
||||
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px;display:flex;align-items:center;gap:8px}
|
||||
.topnav .brand .g{color:var(--acid)}
|
||||
.topnav .brand svg{width:20px;height:20px}
|
||||
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px;display:inline-flex;align-items:center;gap:6px}
|
||||
.topnav a:hover{color:var(--ink);background:var(--panel)}
|
||||
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
|
||||
.topnav a.get{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
|
||||
.topnav a.get:hover{background:rgba(214,255,61,.18)}
|
||||
.topnav a .g{color:var(--acid)}
|
||||
.topnav a svg.tabicon{width:15px;height:15px;flex:none}
|
||||
|
||||
/* Mobile hamburger — matches the home-page pattern. */
|
||||
.topnav .menu{display:none}
|
||||
@media (max-width:720px){
|
||||
.topnav{flex-wrap:nowrap;padding:10px 1rem}
|
||||
.topnav .brand{margin-right:0}
|
||||
.topnav > a:not(.brand){display:none}
|
||||
.topnav .menu{display:block;margin-left:auto;position:relative}
|
||||
.topnav .menu > summary{list-style:none;cursor:pointer;padding:8px 10px;
|
||||
border-radius:8px;color:var(--mut);display:inline-flex;align-items:center;gap:6px}
|
||||
.topnav .menu > summary::-webkit-details-marker{display:none}
|
||||
.topnav .menu > summary svg{width:22px;height:22px;display:block}
|
||||
.topnav .menu > summary:hover,
|
||||
.topnav .menu[open] > summary{color:var(--ink);background:var(--panel)}
|
||||
.topnav .menu .menu-panel{position:absolute;top:calc(100% + 6px);right:0;
|
||||
background:var(--bg);border:1px solid var(--line);border-radius:12px;
|
||||
padding:6px;min-width:220px;display:flex;flex-direction:column;gap:2px;
|
||||
box-shadow:0 10px 32px rgba(0,0,0,.55)}
|
||||
.topnav .menu .menu-panel a{padding:10px 14px;border-radius:8px;font-size:14.5px;
|
||||
color:var(--mut);text-decoration:none;display:flex;align-items:center;gap:8px}
|
||||
.topnav .menu .menu-panel a:hover{color:var(--ink);background:var(--panel)}
|
||||
}
|
||||
.wrap{max-width:1040px;margin:0 auto;padding:0 1.2rem}
|
||||
.layout{display:grid;grid-template-columns:220px minmax(0,760px);gap:48px;justify-content:center;align-items:start}
|
||||
header.hero{padding:3rem 0 1rem}
|
||||
h1{font-size:clamp(1.8rem,4.6vw,2.5rem);line-height:1.15;margin:0 0 .5rem}
|
||||
h1 .g{color:var(--acid)}
|
||||
.byline{color:var(--mut);font-size:.95rem;margin:0}
|
||||
.toc{position:sticky;top:72px;font-size:13.5px;padding-top:3.4rem}
|
||||
.toc a{display:block;color:var(--mut);text-decoration:none;padding:5px 10px;border-left:2px solid var(--line);line-height:1.35}
|
||||
.toc a:hover{color:var(--ink)}
|
||||
.toc a.active{color:var(--acid);border-left-color:var(--acid)}
|
||||
article h2{font-size:1.45rem;margin:2.6rem 0 .8rem;padding-top:1.4rem;border-top:1px solid var(--line);scroll-margin-top:70px}
|
||||
article h2:first-of-type{border-top:none;margin-top:1rem;padding-top:0}
|
||||
article p{margin:0 0 1rem;max-width:72ch}
|
||||
article b{color:var(--ink)}
|
||||
article ul,article ol{padding-left:1.4rem;margin:0 0 1rem;max-width:72ch}
|
||||
article li{margin:0 0 .45rem}
|
||||
article table{border-collapse:collapse;width:100%;margin:.4rem 0 1.4rem;font-size:14px;background:var(--panel);border:1px solid var(--line);border-radius:12px;overflow:hidden}
|
||||
article th,article td{padding:9px 12px;border-top:1px solid var(--line);text-align:left;vertical-align:top}
|
||||
article thead th{border-top:none;background:var(--panel2);color:var(--mut);font-weight:600;font-size:12.5px;letter-spacing:.04em;text-transform:uppercase}
|
||||
article td:first-child{white-space:nowrap;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-word}
|
||||
figure.diagram{margin:1.2rem 0 1.6rem;background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:10px 12px 6px}
|
||||
figure.diagram svg{width:100%;height:auto;display:block}
|
||||
figure.diagram figcaption{color:var(--dim);font-size:12.5px;padding:6px 6px 4px}
|
||||
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:3rem}
|
||||
@media (max-width:900px){ .layout{grid-template-columns:minmax(0,1fr)} .toc{position:static;padding-top:0;display:flex;flex-wrap:wrap;gap:4px} .toc a{border-left:none;border:1px solid var(--line);border-radius:8px;padding:4px 9px} article td:first-child{white-space:normal} }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="topnav">
|
||||
<a class="brand" href="../">
|
||||
<svg viewBox="0 0 64 64" 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>
|
||||
<span>Theseus<span class="g">.X</span></span>
|
||||
</a>
|
||||
<a href="../plug-ins/">Plug-ins</a>
|
||||
<a href="../extensions/">Extensions</a>
|
||||
<a href="../dev/">Developers</a>
|
||||
<a href="//sirius.x/" title="Register a BCNR name"><svg class="tabicon" viewBox="0 0 64 64" aria-hidden="true"><rect width="64" height="64" rx="12" fill="#0b0e14"/><path d="M32 4 L36.4 27.6 L60 32 L36.4 36.4 L32 60 L27.6 36.4 L4 32 L27.6 27.6 Z" fill="#d6ff3d"/></svg><span>Sirius<span class="g">.X</span></span></a>
|
||||
<a class="get" href="../#download">Get Theseus</a>
|
||||
<details class="menu">
|
||||
<summary aria-label="Open menu">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"/></svg>
|
||||
</summary>
|
||||
<div class="menu-panel">
|
||||
<a href="../plug-ins/">Plug-ins</a>
|
||||
<a href="../extensions/">Extensions</a>
|
||||
<a href="../dev/">Developers</a>
|
||||
<a href="//sirius.x/">Sirius.X</a>
|
||||
</div>
|
||||
</details>
|
||||
</nav>
|
||||
|
||||
<div class="wrap">
|
||||
<div class="layout">
|
||||
<aside class="toc" aria-label="Contents">
|
||||
{{toc}}
|
||||
</aside>
|
||||
<main>
|
||||
<header class="hero">
|
||||
<h1>{{title}}</h1>
|
||||
<p class="byline">{{byline}}</p>
|
||||
</header>
|
||||
<article>
|
||||
{{article}}
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>theseus.x is a BCNR name resolving to a Sia-hosted static site.
|
||||
Source and issues: <a href="https://silentmode.st/">silentmode.st</a>.
|
||||
Alpha software on a test network.</p>
|
||||
<p>This paper is published under <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.
|
||||
Theseus Navigator is free software under the <a href="https://code.silentmode.st/silentmode/theseus/src/branch/master/LICENSE">Mozilla Public License 2.0</a>;
|
||||
its <a href="https://code.silentmode.st/silentmode/theseus/src/branch/master/THIRD-PARTY-NOTICES.md">third-party notices</a> and
|
||||
<a href="https://code.silentmode.st/silentmode/theseus/src/branch/master/TRADEMARKS.md">trademark note</a> are in the source repository.</p>
|
||||
</footer>
|
||||
<script>
|
||||
const links = [...document.querySelectorAll('.toc a')], heads = links.map(a => document.getElementById(a.getAttribute('href').slice(1)));
|
||||
const mark = () => { let cur = 0; heads.forEach((h, i) => { if (h && h.getBoundingClientRect().top < 90) cur = i; }); links.forEach((a, i) => a.classList.toggle('active', i === cur)); };
|
||||
addEventListener('scroll', mark, { passive: true }); mark();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue