orgchain: Super Testnet restyled for lineage (lineage.yolopreneur.lol/orgchain/)
Skin and copy only: src/lineage.css over style.css with lineage's tokens, a rehearsal guide and lineage branding, relative paths (base './'), the theme follows the system under its own key, and Inscriboor downloads link to supertestnet.lol (the extension only connects there). Unit tests 32/32; checked in Chrome at 1280 and 390 wide, light and dark, through a full root → birth → recursive inscription run with no CSP or script errors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4upF5LVwmPDDqrhdUfnXh
This commit is contained in:
1 parent
96876db762
commit
6d48c5c8ff
14 files changed
+200
-20
No files matched your search
+13
@@ -0,0 +1,13 @@
|
|||||||
|
# Orgchain (branch `orgchain`)
|
||||||
|
|
||||||
|
Super Testnet restyled for lineage, served at https://lineage.yolopreneur.lol/orgchain/.
|
||||||
|
|
||||||
|
- Same lab and code as `main`. The differences are a skin and copy: `src/lineage.css` (loads after `style.css` and
|
||||||
|
points its tokens at lineage's), a rehearsal guide and lineage branding in `index.html`, the lineage favicon,
|
||||||
|
relative paths (`vite.config.js` `base: './'`, the recursive preview, license links), the theme following the system
|
||||||
|
setting under its own storage key, and Inscriboor downloads linking to supertestnet.lol (the extension only connects
|
||||||
|
there, so the local test wallet is the path here).
|
||||||
|
- Build: `npm ci && npm run build`, then copy `dist/` to `ventures/lineage/orgchain/` on `teahubxyz/time` `gh-pages`.
|
||||||
|
Headers (CSP and the rest, matching supertestnet.lol's) come from `ventures/lineage/_headers`, scoped to
|
||||||
|
`/orgchain/*`.
|
||||||
|
- Keep in step with `main`: rebase this branch onto `main`, rebuild, recopy.
|
||||||
+23
-13
@@ -2,28 +2,38 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<meta name="theme-color" content="#f7931a">
|
<meta name="theme-color" content="#141414">
|
||||||
<meta name="description" content="A private Bitcoin playground. Mine fake coins, inscribe a thought, and follow it into a block.">
|
<meta name="description" content="Super Testnet in lineage's clothes: rehearse an org's lineage (root, births, badges) as inscriptions on a private toy Bitcoin chain in your browser, with pretend money.">
|
||||||
<title>Super Testnet — your own little Bitcoin universe</title>
|
<title>Orgchain — rehearse an org on a small chain · Lineage</title>
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
<link rel="icon" type="image/svg+xml" href="favicon.svg">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header class="band">
|
||||||
<a class="brand" href="#"><span class="mark" aria-hidden="true"></span> SUPER TESTNET <span class="version">v0</span></a>
|
<div class="band-in">
|
||||||
<div class="header-actions"><span class="network"><i></i> PRIVATE LOCAL CHAIN</span><button id="theme-toggle" class="theme-toggle quiet" type="button" aria-label="Toggle color theme">☀ Light</button></div>
|
<div>
|
||||||
|
<h1 class="wordmark">Orgchain</h1>
|
||||||
|
<p class="lede"><b>Rehearse an org on a small chain.</b> Mint a root, give birth to children, award a badge, all as inscriptions on a private toy Bitcoin chain in this tab, with pretend money.</p>
|
||||||
|
</div>
|
||||||
|
<div class="flags">
|
||||||
|
<span class="flag hz">Test coins</span>
|
||||||
|
<span class="flag">Private chain</span>
|
||||||
|
<a class="flag" href="../">Lineage ↗</a>
|
||||||
|
<button id="theme-toggle" class="flag" type="button" aria-label="Toggle color theme">☾ Dark</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<section class="hero"><div><p class="eyebrow">BITCOIN, WITH ROOM TO EXPERIMENT</p><h1>Your own little<br>Bitcoin universe.</h1><p class="intro">Mine a block. Inscribe a thought. See it land in your wallet.<br>All in your browser, all with pretend money.</p></div><div class="orbit" aria-hidden="true"><div class="cube"><svg viewBox="0 0 100 100" width="82" height="82" fill="none" stroke="currentColor" stroke-width="5" aria-hidden="true"><path d="M35 17v12m12-12v12M35 76v12m12-12v12M24 29h25c22 0 22 23 0 23H24m0 0h28c22 0 22 24 0 24H24m7-47v47"/></svg></div><span>YOUR CHAIN. YOUR PACE.</span></div></section>
|
<section class="rehearse blk" aria-labelledby="t-rehearse"><h2 class="tab" id="t-rehearse">Rehearsal <span class="sub">a lineage in four moves</span></h2><div class="panel"><ol class="moves"><li><b>Root.</b> Fund a wallet, then inscribe the org with metaprotocol <code>lineage/v0</code> and metadata like <code>{"lineage":"root","name":"yolopreneur"}</code>.</li><li><b>Birth.</b> Inscribe a child with the root as its parent. Only the parent's holder can: the parent is spent to make the child, and the child carries the parent's ID on-chain (ord tag 3).</li><li><b>Generations.</b> Children can be parents too: <code>time</code> under the root, <code>docscope</code> under <code>time</code>, as deep as the tree goes.</li><li><b>Badge.</b> Inscribe a badge once, like <code>{"lineage":"badge","skill":"launch","belt":"green"}</code>, then mint each award as a child of it with the badge as delegate, so every award shows the same mark.</li></ol><p class="later"><b>Not in this lab yet:</b> handing an award to a seat, graduation (moving a venture's inscription to its own new root) and closing (burning a parent so no more children can be born). Those need transfers and burns, which this lab doesn't do.</p></div></section>
|
||||||
<aside class="notice"><strong>Test coins only.</strong> This is a private simulation, not Bitcoin testnet or mainnet. Local-wallet keys stay in this browser, unencrypted. Inscriboor keys stay in the extension. Never load real keys or send real funds here.</aside>
|
<aside class="notice"><strong>Test coins only.</strong> This is a private simulation, not Bitcoin testnet or mainnet. Local-wallet keys stay in this browser, unencrypted. Inscriboor keys stay in the extension. Never load real keys or send real funds here. Nothing on Orgchain is a real org, key or badge.</aside>
|
||||||
<div id="status" role="status" aria-live="polite">Choose Inscriboor or a local test wallet to start your first loop.</div>
|
<div id="status" role="status" aria-live="polite">Choose Inscriboor or a local test wallet to start your first loop.</div>
|
||||||
<section class="workspace">
|
<section class="workspace">
|
||||||
<article class="panel wallet"><div class="panel-title"><span class="step">01</span><h2>Your test wallet</h2><span id="wallet-state" class="tag">NOT CREATED</span></div>
|
<article class="panel wallet"><div class="panel-title"><span class="step">01</span><h2>Your test wallet</h2><span id="wallet-state" class="tag">NOT CREATED</span></div>
|
||||||
<div id="empty-wallet"><p>One wallet. A whole chain to play with.</p><button id="connect-inscriboor" class="primary">Get Inscriboor ↓</button> <button id="create-wallet" class="quiet">Use local test wallet</button><p id="inscriboor-status" class="muted">Looking for the extension…</p><details class="install-help"><summary>Install Inscriboor</summary><ol><li>Download and unzip Inscriboor.</li><li>Open <code>chrome://extensions</code> (or Brave extensions).</li><li>Turn on Developer mode.</li><li>Choose <strong>Load unpacked</strong> and select the unzipped <code>extension</code> folder.</li><li>Refresh this page. The button above will change from <strong>Get Inscriboor</strong> to <strong>Connect Inscriboor</strong>.</li></ol></details></div>
|
<div id="empty-wallet"><p>One wallet. A whole chain to play with.</p><button id="create-wallet" class="primary">Use local test wallet</button> <button id="connect-inscriboor" class="quiet">Get Inscriboor ↓</button><p id="inscriboor-status" class="muted">Looking for the extension…</p><details class="install-help"><summary>Install Inscriboor</summary><p class="muted">Inscriboor 0.2.4 connects on supertestnet.lol only. On Orgchain, use the local test wallet.</p><ol><li>Download and unzip Inscriboor.</li><li>Open <code>chrome://extensions</code> (or Brave extensions).</li><li>Turn on Developer mode.</li><li>Choose <strong>Load unpacked</strong> and select the unzipped <code>extension</code> folder.</li><li>Refresh this page. The button above will change from <strong>Get Inscriboor</strong> to <strong>Connect Inscriboor</strong>.</li></ol></details></div>
|
||||||
<div id="active-wallet" hidden><p class="label">FAKE BTC BALANCE</p><div class="balance"><span id="balance">0</span><small>BTC</small></div><p id="reserved" class="muted"></p><label for="address">Local regtest-format address</label><input id="address" readonly><button id="export-wallet" class="quiet">↓ Save test wallet</button></div>
|
<div id="active-wallet" hidden><p class="label">FAKE BTC BALANCE</p><div class="balance"><span id="balance">0</span><small>BTC</small></div><p id="reserved" class="muted"></p><label for="address">Local regtest-format address</label><input id="address" readonly><button id="export-wallet" class="quiet">↓ Save test wallet</button></div>
|
||||||
<div class="wallet-footer"><label class="file-button" for="load-wallet">↑ Load test wallet or lab backup</label><input id="load-wallet" type="file" accept=".json,application/json"><p class="muted">Saved on this device. Local-wallet backups contain their test key; Inscriboor backups contain only a public descriptor. A lab backup also preserves the chain.</p></div>
|
<div class="wallet-footer"><label class="file-button" for="load-wallet">↑ Load test wallet or lab backup</label><input id="load-wallet" type="file" accept=".json,application/json"><p class="muted">Saved on this device. Local-wallet backups contain their test key; Inscriboor backups contain only a public descriptor. A lab backup also preserves the chain.</p></div>
|
||||||
</article>
|
</article>
|
||||||
<article class="panel"><div class="panel-title"><span class="step">02</span><h2>Make some blocks</h2></div><p>Skip the faucet queue. Every block gives you <strong>50 fake BTC</strong>, ready to use immediately.</p><div class="chain-stats"><div><span class="label">BLOCK HEIGHT</span><strong id="height">0</strong></div><div><span class="label">PENDING TXS</span><strong id="pending">0</strong></div></div><button id="mine" class="primary" disabled>Mine now <span>+</span></button><label for="miner-interval">Auto miner</label><select id="miner-interval"><option value="0">OFF</option><option value="10">10s</option><option value="30">30s</option><option value="60">60s</option></select><p id="miner-status" aria-live="polite">Auto mining OFF</p><p class="muted">Keep a lab tab open; browser throttling may delay blocks. Mining also confirms your pending inscriptions.</p></article>
|
<article class="panel"><div class="panel-title"><span class="step">02</span><h2>Make some blocks</h2></div><p>Skip the faucet queue. Every block gives you <strong>50 fake BTC</strong>, ready to use immediately.</p><div class="chain-stats"><div><span class="label">BLOCK HEIGHT</span><strong id="height">0</strong></div><div><span class="label">PENDING TXS</span><strong id="pending">0</strong></div></div><button id="mine" class="primary" disabled>Mine now <span>+</span></button><label for="miner-interval">Auto miner</label><select id="miner-interval"><option value="0">OFF</option><option value="10">10s</option><option value="30">30s</option><option value="60">60s</option></select><p id="miner-status" aria-live="polite">Auto mining OFF</p><p class="muted">Keep a lab tab open; browser throttling may delay blocks. Mining also confirms your pending inscriptions.</p></article>
|
||||||
<article class="panel inscribe"><div class="panel-title"><span class="step">03</span><h2>Leave a little something</h2><span class="tag">INSCRIPTION LAB</span></div><label for="mime-type">Content type</label><select id="mime-type"></select><label for="body-file">Or upload a local file (16 KiB maximum)</label><input id="body-file" type="file"><label for="parent">Parent inscription (optional, immutable)</label><select id="parent"><option value="">No parent</option></select><label for="delegate">Delegate inscription ID (optional, future IDs allowed)</label><input id="delegate" placeholder="64 hex characters + i0"><label for="reinscribe">Reinscribe an owned sat (optional)</label><select id="reinscribe"><option value="">New sat</option></select><label for="pointer">Advanced pointer (zero-based output sat position)</label><input id="pointer" inputmode="numeric" placeholder="Default first sat"><button id="recursive-demo" class="quiet">Use recursive demo</button><p class="muted">Recursive HTML/SVG scripts use local fetch and ord.render(text) in an isolated worker; ord.id is the requested inscription. No DOM or network access.</p><label for="payload">What will you put on your chain?</label><textarea id="payload" placeholder="Hello, little Bitcoin universe…" rows="3" disabled></textarea><label for="metadata">JSON metadata (optional, independent of body)</label><textarea id="metadata" rows="3" placeholder='{"protocol":"my-experiment","note":"hello"}'></textarea><p id="metadata-count" class="muted">0 / 2048 CBOR bytes · ord tag 5 · JSON is authoring format only</p><label for="metaprotocol">Metaprotocol (optional, independent field)</label><input id="metaprotocol" placeholder="e.g. tea-v1 · ord tag 7"><p class="muted">Native ord metaprotocol identifier. Metadata and inscription data remain independent.</p><div class="compose-footer"><span id="byte-count" class="muted">0 / 16384 bytes</span><button id="review" disabled>Review inscription ↗</button></div>
|
<article class="panel inscribe"><div class="panel-title"><span class="step">03</span><h2>Inscribe a root, a birth, a badge</h2><span class="tag">INSCRIPTION LAB</span></div><label for="mime-type">Content type</label><select id="mime-type"></select><label for="body-file">Or upload a local file (16 KiB maximum)</label><input id="body-file" type="file"><label for="parent">Parent inscription (optional, immutable)</label><select id="parent"><option value="">No parent</option></select><label for="delegate">Delegate inscription ID (optional, future IDs allowed)</label><input id="delegate" placeholder="64 hex characters + i0"><label for="reinscribe">Reinscribe an owned sat (optional)</label><select id="reinscribe"><option value="">New sat</option></select><label for="pointer">Advanced pointer (zero-based output sat position)</label><input id="pointer" inputmode="numeric" placeholder="Default first sat"><button id="recursive-demo" class="quiet">Use recursive demo</button><p class="muted">Recursive HTML/SVG scripts use local fetch and ord.render(text) in an isolated worker; ord.id is the requested inscription. No DOM or network access.</p><label for="payload">What will you put on your chain?</label><textarea id="payload" placeholder="yolopreneur — the root of the tree…" rows="3" disabled></textarea><label for="metadata">JSON metadata (optional, independent of body)</label><textarea id="metadata" rows="3" placeholder='{"lineage":"birth","name":"time"}'></textarea><p id="metadata-count" class="muted">0 / 2048 CBOR bytes · ord tag 5 · JSON is authoring format only</p><label for="metaprotocol">Metaprotocol (optional, independent field)</label><input id="metaprotocol" placeholder="e.g. lineage/v0 · ord tag 7"><p class="muted">Native ord metaprotocol identifier. Metadata and inscription data remain independent.</p><div class="compose-footer"><span id="byte-count" class="muted">0 / 16384 bytes</span><button id="review" disabled>Review inscription ↗</button></div>
|
||||||
<div id="review-panel" hidden><h3>Review before signing</h3><div id="review-preview"></div><pre id="review-text"></pre><p id="review-parent"></p><pre id="review-metadata"></pre><p>Two transactions: commit + reveal. <strong>1,000 fake sats</strong> in fees; <strong>1,000 fake sats</strong> in a new wallet output. Any selected parent or reinscription output is also returned in full; reinscription appends to its existing sat stack.</p><p id="signing-note" class="muted">The next button asks your active signer to approve commit + reveal, then submits them to your private chain.</p><button id="sign" class="primary">Sign & inscribe</button> <button id="cancel-review" class="quiet">Cancel</button></div>
|
<div id="review-panel" hidden><h3>Review before signing</h3><div id="review-preview"></div><pre id="review-text"></pre><p id="review-parent"></p><pre id="review-metadata"></pre><p>Two transactions: commit + reveal. <strong>1,000 fake sats</strong> in fees; <strong>1,000 fake sats</strong> in a new wallet output. Any selected parent or reinscription output is also returned in full; reinscription appends to its existing sat stack.</p><p id="signing-note" class="muted">The next button asks your active signer to approve commit + reveal, then submits them to your private chain.</p><button id="sign" class="primary">Sign & inscribe</button> <button id="cancel-review" class="quiet">Cancel</button></div>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
@@ -53,7 +63,7 @@
|
|||||||
<button id="api-try">Try</button> <button id="api-copy" class="quiet">Copy response</button>
|
<button id="api-try">Try</button> <button id="api-copy" class="quiet">Copy response</button>
|
||||||
<pre id="api-response" aria-live="polite">Choose a path and press Try.</pre>
|
<pre id="api-response" aria-live="polite">Choose a path and press Try.</pre>
|
||||||
</section>
|
</section>
|
||||||
<details class="about"><summary>Under the hood & attribution</summary><p>Real serialized Bitcoin transactions, Schnorr signatures and Taproot commit/reveal scripts, on a deliberately simplified local UTXO chain. No proof of work, Bitcoin consensus, peer network, public broadcast, or production custody. Synthetic local sats follow FIFO input-to-output ranges. Child creation and reinscription preserve the owned sat. Fees retire the input tail; this is not Bitcoin consensus.</p><p>Built from and inspired by <a href="https://github.com/supertestnet/testnet_generator">Supertestnet’s testnet_generator</a>, <a href="https://github.com/supertestnet/inscriptions-online">inscriptions-online</a>, and <a href="https://github.com/supertestnet/vanilla-js-browser-wallet">vanilla-js-browser-wallet</a>. <a href="https://github.com/supertestnet/node_faker">node_faker</a> was evaluated for future RPC compatibility.</p><p>Transaction library: <a href="https://github.com/cmdruid/tapscript">tapscript by Christopher Scott</a> (<a href="/licenses/tapscript.txt">CC-BY-1.0</a>). <a href="/licenses/supertestnet-CC0.txt">Supertestnet CC0 license</a> · <a href="/licenses/noble-curves.txt">noble-curves license</a> · <a href="/licenses/noble-hashes.txt">noble-hashes license</a>.</p></details>
|
<details class="about"><summary>Under the hood & attribution</summary><p>Orgchain is <a href="https://supertestnet.lol/">Super Testnet</a> in lineage's clothes: the same lab and code, restyled, with a rehearsal guide on top. Its lab state lives in this browser, separate from supertestnet.lol's.</p><p>Real serialized Bitcoin transactions, Schnorr signatures and Taproot commit/reveal scripts, on a deliberately simplified local UTXO chain. No proof of work, Bitcoin consensus, peer network, public broadcast, or production custody. Synthetic local sats follow FIFO input-to-output ranges. Child creation and reinscription preserve the owned sat. Fees retire the input tail; this is not Bitcoin consensus.</p><p>Built from and inspired by <a href="https://github.com/supertestnet/testnet_generator">Supertestnet’s testnet_generator</a>, <a href="https://github.com/supertestnet/inscriptions-online">inscriptions-online</a>, and <a href="https://github.com/supertestnet/vanilla-js-browser-wallet">vanilla-js-browser-wallet</a>. <a href="https://github.com/supertestnet/node_faker">node_faker</a> was evaluated for future RPC compatibility.</p><p>Transaction library: <a href="https://github.com/cmdruid/tapscript">tapscript by Christopher Scott</a> (<a href="licenses/tapscript.txt">CC-BY-1.0</a>). <a href="licenses/supertestnet-CC0.txt">Supertestnet CC0 license</a> · <a href="licenses/noble-curves.txt">noble-curves license</a> · <a href="licenses/noble-hashes.txt">noble-hashes license</a>.</p></details>
|
||||||
<footer><span>SMALL CHAIN. BIG POSSIBILITIES.</span><button id="reset" class="quiet danger">Reset local lab</button></footer>
|
<footer><span>SMALL CHAIN. WHOLE FAMILY TREE.</span><span class="made">Part of <a href="../">Lineage</a> · <a href="https://yolopreneur.lol/">yolopreneur.lol</a> · based on <a href="https://supertestnet.lol/">Super Testnet</a></span><button id="reset" class="quiet danger">Reset local lab</button></footer>
|
||||||
</main><script type="module" src="/src/main.js"></script>
|
</main><script type="module" src="/src/main.js"></script>
|
||||||
</body></html>
|
</body></html>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
{"version":"0.2.4","url":"https://supertestnet.lol/downloads/inscriboor-extension-v0.2.4.zip"}n
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 34"><rect width="34" height="34" rx="8" fill="#f7931a"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><rect width="16" height="16" fill="#ffc21a"/><path d="M5 3v10h7" stroke="#141414" stroke-width="2.6" fill="none"/></svg>
|
||||||
|
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 181 B |
@@ -1 +1 @@
|
|||||||
<!doctype html><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'nonce-local-ord-preview'; worker-src blob:; style-src 'unsafe-inline'; connect-src 'none'; img-src data:; form-action 'none'; base-uri 'none'"><div id="markup"></div><pre id="recursive-output"></pre><script nonce="local-ord-preview" src="/recursive-preview.js"></script>
|
<!doctype html><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'nonce-local-ord-preview'; worker-src blob:; style-src 'unsafe-inline'; connect-src 'none'; img-src data:; form-action 'none'; base-uri 'none'"><div id="markup"></div><pre id="recursive-output"></pre><script nonce="local-ord-preview" src="recursive-preview.js"></script>
|
||||||
+153
@@ -0,0 +1,153 @@
|
|||||||
|
/* Orgchain: Super Testnet in lineage's clothes.
|
||||||
|
Same lab, dressed as lineage's key-ceremony sheet: raw concrete, black rule, hazard yellow for the action and for
|
||||||
|
anything live, everything in the system monospace. Restyle only: loads after style.css and repoints its tokens. */
|
||||||
|
:root {
|
||||||
|
--concrete: #e4e3dd; --slab: #f6f5f1; --ink: #141414; --ink-2: #4a4944; --ink-3: #66655f;
|
||||||
|
--signal: #ffc21a; --on-signal: #141414; --ok: #1d7a3a; --focus: #2346ff;
|
||||||
|
--band: #141414; --band-fg: #f6f5f1; --band-muted: #b0afa8; --shadow: #141414;
|
||||||
|
--mono: ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono", Menlo, Consolas, "Liberation Mono", "DejaVu Sans Mono", monospace;
|
||||||
|
--display: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
--t-xs: 0.75rem; --t-s: 0.8125rem; --t-m: 0.9375rem; --t-l: 1.25rem;
|
||||||
|
}
|
||||||
|
:root[data-theme="dark"] {
|
||||||
|
--concrete: #151514; --slab: #1e1e1c; --ink: #ecebe4; --ink-2: #b9b8b0; --ink-3: #94938b;
|
||||||
|
--ok: #62c784; --focus: #93a8ff; --band: #0b0b0a; --band-fg: #ecebe4; --band-muted: #9d9c95; --shadow: #4d4c47;
|
||||||
|
}
|
||||||
|
/* Super Testnet's own tokens, pointed at lineage's in both themes (style.css sets light values on [data-theme]) */
|
||||||
|
:root, :root[data-theme="light"], :root[data-theme="dark"] {
|
||||||
|
--orange: var(--signal); --orange-2: var(--signal);
|
||||||
|
--bg: var(--concrete); --panel: var(--slab); --panel-2: var(--concrete); --soft: var(--concrete);
|
||||||
|
--text: var(--ink); --muted: var(--ink-2); --line: var(--ink);
|
||||||
|
font-family: var(--mono);
|
||||||
|
}
|
||||||
|
:root, :root[data-theme="light"] { --danger: #b3261e; }
|
||||||
|
:root[data-theme="dark"] { --danger: #ff8a7f; }
|
||||||
|
|
||||||
|
* { border-radius: 0 !important; }
|
||||||
|
html, body { background: var(--concrete); }
|
||||||
|
body { font: 400 var(--t-m)/1.5 var(--mono); color: var(--ink); transition: none; }
|
||||||
|
::selection { background: var(--signal); color: var(--on-signal); }
|
||||||
|
a { color: var(--ink); text-decoration-thickness: 2px; text-underline-offset: 3px; }
|
||||||
|
a:hover { background: var(--signal); color: var(--on-signal); }
|
||||||
|
code { font-family: inherit; font-weight: 700; }
|
||||||
|
button:focus-visible, a:focus-visible, summary:focus-visible, .file-button:focus-visible,
|
||||||
|
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
|
||||||
|
|
||||||
|
/* header slab, as on lineage's key tree */
|
||||||
|
header.band { max-width: none; margin: 0; padding: 0; display: block; border-bottom: 3px solid var(--ink); background: var(--band); color: var(--band-fg); }
|
||||||
|
.band-in {
|
||||||
|
max-width: 1240px; margin: 0 auto; padding-block: 22px 20px;
|
||||||
|
padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px));
|
||||||
|
display: flex; flex-wrap: wrap; gap: 16px 32px; align-items: flex-end; justify-content: space-between;
|
||||||
|
}
|
||||||
|
.wordmark { margin: 0; color: var(--band-fg); font: 900 clamp(3.25rem, 11vw, 7rem)/0.82 var(--display); letter-spacing: -0.05em; text-transform: uppercase; }
|
||||||
|
.lede { margin: 12px 0 0; color: var(--band-muted); font-size: var(--t-s); max-width: 58ch; }
|
||||||
|
.lede b { color: var(--band-fg); }
|
||||||
|
.flags { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
||||||
|
.flag, button.flag {
|
||||||
|
font: 700 var(--t-xs)/1 var(--mono); letter-spacing: 0.1em; text-transform: uppercase; padding: 7px 9px 6px;
|
||||||
|
border: 2px solid var(--band-fg); background: transparent; color: var(--band-fg); box-shadow: none; text-decoration: none;
|
||||||
|
}
|
||||||
|
.flag.hz { background: var(--signal); border-color: var(--signal); color: var(--on-signal); }
|
||||||
|
a.flag:hover, button.flag:hover:not(:disabled) { background: var(--band-fg); color: var(--band); border-color: var(--band-fg); transform: none; }
|
||||||
|
button.flag:active:not(:disabled) { transform: none; }
|
||||||
|
|
||||||
|
/* blocks with ink tabs */
|
||||||
|
.blk { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
|
||||||
|
.blk > .panel { align-self: stretch; }
|
||||||
|
.tab {
|
||||||
|
margin: 0; background: var(--ink); color: var(--slab); font: 700 var(--t-xs)/1 var(--mono);
|
||||||
|
letter-spacing: 0.14em; text-transform: uppercase; padding: 8px 11px 7px; display: flex; gap: 12px; max-width: 100%;
|
||||||
|
}
|
||||||
|
.tab .sub { font-weight: 400; letter-spacing: 0.06em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
.rehearse { margin: 40px 0 0; }
|
||||||
|
.moves { margin: 0; padding: 0 0 0 1.6em; display: grid; gap: 10px; font-size: var(--t-s); line-height: 1.6; max-width: 96ch; }
|
||||||
|
.moves li::marker { font-weight: 700; }
|
||||||
|
.moves b, .panel .later b { color: var(--ink); }
|
||||||
|
.panel .later { margin: 16px 0 0; padding: 10px 12px; border: 2px dashed var(--ink); font-size: var(--t-s); color: var(--ink-2); max-width: 96ch; }
|
||||||
|
|
||||||
|
.notice { margin-top: 28px; background: transparent; border: 2px dashed var(--ink); padding: 10px 12px; font-size: var(--t-s); color: var(--ink-2); }
|
||||||
|
.notice strong { color: var(--ink); }
|
||||||
|
#status { color: var(--ink); font: 700 var(--t-s)/1.5 var(--mono); padding: 16px 0; }
|
||||||
|
#status::before { content: "\25B8 "; }
|
||||||
|
#status.error { color: var(--danger); }
|
||||||
|
|
||||||
|
/* panels: slabs with a hard ink shadow */
|
||||||
|
.panel { background: var(--slab); border: 3px solid var(--ink); box-shadow: 8px 8px 0 var(--shadow); padding: 22px; }
|
||||||
|
.workspace { gap: 28px; }
|
||||||
|
.panel-title { gap: 12px; margin-bottom: 18px; flex-wrap: wrap; }
|
||||||
|
.panel-title h2, #indexes > h2, #api-explorer > h2 { font: 700 var(--t-m)/1.3 var(--mono); letter-spacing: 0.04em; text-transform: uppercase; margin: 0; }
|
||||||
|
.step { background: var(--ink); color: var(--slab); border: 0; padding: 7px 9px 6px; font: 700 var(--t-xs)/1 var(--mono); letter-spacing: 0.1em; }
|
||||||
|
.tag { border: 2px solid var(--ink); color: var(--ink); font: 700 0.6875rem/1 var(--mono); letter-spacing: 0.1em; text-transform: uppercase; padding: 5px 7px 4px; }
|
||||||
|
.panel p { font-size: var(--t-s); color: var(--ink-2); }
|
||||||
|
.label, .chain-kicker { font: 700 var(--t-xs)/1.2 var(--mono) !important; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2); }
|
||||||
|
h3 { font: 700 var(--t-m)/1.3 var(--mono); text-transform: uppercase; letter-spacing: 0.04em; }
|
||||||
|
|
||||||
|
/* form */
|
||||||
|
label { font: 700 var(--t-xs)/1.3 var(--mono); letter-spacing: 0.06em; color: var(--ink-2); margin: 16px 0 6px; }
|
||||||
|
input, textarea, select { background: var(--concrete); border: 2px solid var(--ink); color: var(--ink); font: 400 var(--t-s)/1.4 var(--mono); padding: 9px 10px; }
|
||||||
|
input:focus, textarea:focus, select:focus { border-color: var(--ink); outline: 3px solid var(--focus); outline-offset: 2px; }
|
||||||
|
input[type=file] { border-style: dashed; background: transparent; }
|
||||||
|
.file-button { color: var(--ink); font-weight: 700; text-decoration-thickness: 2px; }
|
||||||
|
.wallet-footer { border-top: 2px dashed var(--ink-3); }
|
||||||
|
.install-help summary { cursor: pointer; font-weight: 700; }
|
||||||
|
|
||||||
|
/* buttons, as on the key tree */
|
||||||
|
button {
|
||||||
|
font: 700 var(--t-s)/1 var(--mono); letter-spacing: 0.06em; text-transform: uppercase; padding: 10px 12px 9px;
|
||||||
|
background: var(--slab); color: var(--ink); border: 2px solid var(--ink); box-shadow: 3px 3px 0 var(--shadow); transition: none;
|
||||||
|
}
|
||||||
|
button:hover:not(:disabled) { background: var(--concrete); border-color: var(--ink); transform: none; }
|
||||||
|
button:active:not(:disabled) { transform: translate(3px, 3px); box-shadow: none; }
|
||||||
|
button:disabled { opacity: 0.45; box-shadow: none; }
|
||||||
|
button.primary { background: var(--signal); color: var(--on-signal); border-color: var(--ink); }
|
||||||
|
button.primary:hover:not(:disabled) { background: var(--signal); filter: brightness(1.05); }
|
||||||
|
.quiet { background: transparent; font-size: var(--t-xs); box-shadow: 2px 2px 0 var(--shadow); }
|
||||||
|
button.danger, .danger { color: var(--danger); }
|
||||||
|
|
||||||
|
/* numbers */
|
||||||
|
.balance { font: 700 2.4rem/1 var(--mono); letter-spacing: -0.02em; }
|
||||||
|
.balance small { color: var(--ink-2); font: 700 var(--t-xs)/1 var(--mono); letter-spacing: 0.1em; }
|
||||||
|
.chain-stats strong { font: 700 2.5rem/1 var(--mono); }
|
||||||
|
pre { background: var(--concrete); border: 2px solid var(--ink); font: 400 var(--t-xs)/1.6 var(--mono); }
|
||||||
|
|
||||||
|
/* sections */
|
||||||
|
.section-title { margin: 52px 0 18px; }
|
||||||
|
.eyebrow { display: inline-block; background: var(--ink); color: var(--slab); padding: 8px 11px 7px; font: 700 var(--t-xs)/1 var(--mono); letter-spacing: 0.14em; margin: 0 0 10px; }
|
||||||
|
.section-title h2 { font: 900 clamp(1.6rem, 3.4vw, 2.4rem)/1 var(--display); letter-spacing: -0.03em; text-transform: uppercase; }
|
||||||
|
#collection-count { background: var(--signal); color: var(--on-signal); font: 700 var(--t-s)/1 var(--mono); padding: 5px 8px 4px; vertical-align: middle; }
|
||||||
|
.empty { border: 2px dashed var(--ink); color: var(--ink-2); font-size: var(--t-s); }
|
||||||
|
.collectible { background: var(--slab); border: 3px solid var(--ink); box-shadow: 6px 6px 0 var(--shadow); }
|
||||||
|
.collectible pre { font: 400 1rem/1.5 var(--mono); border: 0; background: transparent; }
|
||||||
|
.inscription-preview { border: 2px solid var(--ink); }
|
||||||
|
|
||||||
|
/* chain board: pending is live, so it wears the signal */
|
||||||
|
.chain-board { background: var(--slab); border: 3px solid var(--ink); box-shadow: 8px 8px 0 var(--shadow); }
|
||||||
|
.chain-kicker { color: var(--ink); }
|
||||||
|
.mempool-empty { border: 2px dashed var(--ink); color: var(--ink-2); }
|
||||||
|
.mempool-card { background: var(--signal); color: var(--on-signal); border: 2px solid var(--ink); text-transform: none; letter-spacing: 0; }
|
||||||
|
.mempool-card strong { color: var(--on-signal); }
|
||||||
|
.mempool-card span { color: var(--on-signal); }
|
||||||
|
.chain-divider { border-left: 3px solid var(--ink); }
|
||||||
|
.chain-divider span { color: var(--ink-2); font: 700 var(--t-xs)/1 var(--mono); letter-spacing: 0.1em; }
|
||||||
|
.block-card { background: var(--concrete); border: 2px solid var(--ink); text-transform: none; letter-spacing: 0; font-weight: 400; }
|
||||||
|
.block-card:before { border-top: 3px solid var(--ink); opacity: 1; }
|
||||||
|
.block-card .block-accent { color: var(--on-signal); background: var(--signal); display: inline-block; padding: 2px 5px; }
|
||||||
|
.inspector h2 { font: 700 var(--t-l)/1.25 var(--mono); }
|
||||||
|
#protocol-events article { border-bottom: 1px dashed var(--ink-3); }
|
||||||
|
#indexes, #api-explorer { margin-top: 2.5rem; }
|
||||||
|
|
||||||
|
/* about + footer */
|
||||||
|
.about { border-top: 3px solid var(--ink); color: var(--ink-2); font-size: var(--t-s); }
|
||||||
|
.about summary { color: var(--ink); font: 700 var(--t-xs)/1.4 var(--mono); letter-spacing: 0.1em; text-transform: uppercase; }
|
||||||
|
footer { border-top: 3px solid var(--ink); font: 700 var(--t-xs)/1.4 var(--mono); letter-spacing: 0.12em; color: var(--ink); flex-wrap: wrap; gap: 12px; }
|
||||||
|
footer .made { color: var(--ink-2); font-weight: 400; letter-spacing: 0.04em; }
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.band-in { padding-block: 18px 16px; }
|
||||||
|
.panel, .chain-board { box-shadow: 5px 5px 0 var(--shadow); padding: 18px; }
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) { button:active:not(:disabled) { transform: none; } }
|
||||||
|
|
||||||
|
/* long ids and JSON wrap instead of widening the page */
|
||||||
|
.moves, .moves code, .collectible, .inspector, #review-panel, #status { overflow-wrap: anywhere; }
|
||||||
+4
-3
@@ -1,5 +1,6 @@
|
|||||||
import { RECURSIVE_DEMO } from './recursion.js';
|
import { RECURSIVE_DEMO } from './recursion.js';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
|
import './lineage.css';
|
||||||
import { encodeMetadata, parseMetadataJSON } from './adapters/metadata.js';
|
import { encodeMetadata, parseMetadataJSON } from './adapters/metadata.js';
|
||||||
import { MetadataIndex, deriveProtocol } from './adapters/metadata-index.js';
|
import { MetadataIndex, deriveProtocol } from './adapters/metadata-index.js';
|
||||||
import { LocalOrdAPI } from './adapters/local-ord-api.js';
|
import { LocalOrdAPI } from './adapters/local-ord-api.js';
|
||||||
@@ -14,11 +15,11 @@ import { STORAGE_KEY, readLab, mutateLab, decodeLab, encodeLab } from './storage
|
|||||||
const $ = id => document.getElementById(id);
|
const $ = id => document.getElementById(id);
|
||||||
const btc = sats => (sats / 1e8).toFixed(8);
|
const btc = sats => (sats / 1e8).toFixed(8);
|
||||||
const short = id => `${id.slice(0, 12)}…${id.slice(-8)}`;
|
const short = id => `${id.slice(0, 12)}…${id.slice(-8)}`;
|
||||||
const THEME_KEY = 'super-testnet-theme';
|
const THEME_KEY = 'orgchain-theme';
|
||||||
let fileBytes = null, fileLoading = false, fileRevision = 0;
|
let fileBytes = null, fileLoading = false, fileRevision = 0;
|
||||||
let lab, busy = false, reviewed = null, failed = false;
|
let lab, busy = false, reviewed = null, failed = false;
|
||||||
let inscriboorProvider = null;
|
let inscriboorProvider = null;
|
||||||
const INSCRIBOOR_RELEASE = { version: '0.2.4', url: '/downloads/inscriboor-extension-v0.2.4.zip' };
|
const INSCRIBOOR_RELEASE = { version: '0.2.4', url: 'https://supertestnet.lol/downloads/inscriboor-extension-v0.2.4.zip' };
|
||||||
|
|
||||||
const message = (text, error = false) => { $('status').textContent = text; $('status').classList.toggle('error', error); };
|
const message = (text, error = false) => { $('status').textContent = text; $('status').classList.toggle('error', error); };
|
||||||
const el = (tag, text, className) => { const node = document.createElement(tag); if (text !== undefined) node.textContent = text; if (className) node.className = className; return node; };
|
const el = (tag, text, className) => { const node = document.createElement(tag); if (text !== undefined) node.textContent = text; if (className) node.className = className; return node; };
|
||||||
@@ -46,7 +47,7 @@ function setTheme(theme, persist = false) {
|
|||||||
}
|
}
|
||||||
function initTheme() {
|
function initTheme() {
|
||||||
const saved = localStorage.getItem(THEME_KEY);
|
const saved = localStorage.getItem(THEME_KEY);
|
||||||
setTheme(saved === 'light' || saved === 'dark' ? saved : 'dark');
|
setTheme(saved === 'light' || saved === 'dark' ? saved : (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'));
|
||||||
}
|
}
|
||||||
function download(name, contents) {
|
function download(name, contents) {
|
||||||
const url = URL.createObjectURL(new Blob([contents], { type: 'application/json' }));
|
const url = URL.createObjectURL(new Blob([contents], { type: 'application/json' }));
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ export function preview(item, api = null) {
|
|||||||
node.title = `${type} recursive preview`; node.referrerPolicy = 'no-referrer';
|
node.title = `${type} recursive preview`; node.referrerPolicy = 'no-referrer';
|
||||||
const payload = recursivePayload(template.innerHTML, scripts, item.id);
|
const payload = recursivePayload(template.innerHTML, scripts, item.id);
|
||||||
node.onload = () => { node.cleanup?.(); node.cleanup = connectRecursion(node, api, payload); };
|
node.onload = () => { node.cleanup?.(); node.cleanup = connectRecursion(node, api, payload); };
|
||||||
node.src = '/recursive-preview.html'; node.dataset.previewUrl = ''; node.className = 'inscription-preview';
|
node.src = 'recursive-preview.html'; node.dataset.previewUrl = ''; node.className = 'inscription-preview';
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
const csp = "default-src 'none'; style-src 'unsafe-inline'; script-src 'none'; form-action 'none'; base-uri 'none'";
|
const csp = "default-src 'none'; style-src 'unsafe-inline'; script-src 'none'; form-action 'none'; base-uri 'none'";
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
// Orgchain is served from lineage.yolopreneur.lol/orgchain/: relative asset URLs work at any sub-path.
|
||||||
|
export default defineConfig({ base: './' });
|
||||||
Reference in new issue
Block a user