diff options
Diffstat (limited to 'website/app')
| -rw-r--r-- | website/app/app.js | 26 | ||||
| -rw-r--r-- | website/app/index.html | 105 | ||||
| -rw-r--r-- | website/app/styles.css | 1 |
3 files changed, 132 insertions, 0 deletions
diff --git a/website/app/app.js b/website/app/app.js new file mode 100644 index 000000000..ea1791839 --- /dev/null +++ b/website/app/app.js @@ -0,0 +1,26 @@ +const tabs = [...document.querySelectorAll('[role="tab"]')]; +const panels = [...document.querySelectorAll('[role="tabpanel"]')]; + +tabs.forEach((tab) => tab.addEventListener('click', () => { + tabs.forEach((item) => item.setAttribute('aria-selected', String(item === tab))); + panels.forEach((panel) => { + const active = panel.id === tab.dataset.panel; + panel.hidden = !active; + panel.classList.toggle('active', active); + }); +})); + +fetch('/api/node/get_info', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: '{}' +}).then((response) => { + if (!response.ok) throw new Error('node unavailable'); + return response.json(); +}).then((info) => { + document.querySelector('#node-state').textContent = info.status === 'OK' ? 'Online' : info.status; + document.querySelector('#height').textContent = Number(info.height).toLocaleString(); + document.querySelector('#peers').textContent = Number(info.incoming_connections_count || 0) + Number(info.outgoing_connections_count || 0); +}).catch(() => { + document.querySelector('#node-state').textContent = 'Unavailable'; +}); diff --git a/website/app/index.html b/website/app/index.html new file mode 100644 index 000000000..50fd1af63 --- /dev/null +++ b/website/app/index.html @@ -0,0 +1,105 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content="Monzero beta asset, NFT and non-custodial swap workspace."> + <meta name="theme-color" content="#07110f"> + <title>Monzero Studio — Assets, NFTs and swaps</title> + <link rel="stylesheet" href="styles.css"> +</head> +<body> + <header> + <a class="brand" href="https://monzero.org"><span>MZ</span> MONZERO</a> + <nav aria-label="Product navigation"> + <a href="https://monzero.org/explorer/">Explorer</a> + <a href="https://code.monzero.org/">Source</a> + <a href="https://monzero.org">Network</a> + </nav> + </header> + + <main> + <section class="intro"> + <div> + <p class="eyebrow">Protocol laboratory · Testnet first</p> + <h1>Create without pretending.</h1> + <p>Monzero Studio is the future non-custodial workspace for fixed-supply tokens, NFTs, collections and atomic swaps. Transaction submission stays locked until the corresponding consensus and wallet code is available.</p> + </div> + <aside class="network-card"> + <span class="label">Current public node</span> + <strong id="node-state">Checking…</strong> + <dl> + <div><dt>Height</dt><dd id="height">—</dd></div> + <div><dt>Peers</dt><dd id="peers">—</dd></div> + <div><dt>Asset protocol</dt><dd class="amber">Inactive</dd></div> + </dl> + </aside> + </section> + + <section class="workspace"> + <div class="tabs" role="tablist" aria-label="Studio tools"> + <button role="tab" aria-selected="true" data-panel="token">Token creator</button> + <button role="tab" aria-selected="false" data-panel="nft">NFT studio</button> + <button role="tab" aria-selected="false" data-panel="collections">Collections</button> + <button role="tab" aria-selected="false" data-panel="swap">Atomic swap</button> + </div> + + <article class="panel active" id="token" role="tabpanel"> + <div class="panel-copy"><p class="eyebrow">Fixed supply</p><h2>Issue a token</h2><p>Supply is created once. No administrator mint, freeze, blacklist or clawback authority exists in V1.</p></div> + <form> + <label>Name <input type="text" maxlength="64" placeholder="Example Token" disabled></label> + <label>Symbol <input type="text" maxlength="12" placeholder="EXM" disabled></label> + <div class="split"><label>Atomic supply <input type="number" placeholder="1000000" disabled></label><label>Decimals <input type="number" min="0" max="11" placeholder="8" disabled></label></div> + <label>Metadata content hash <input type="text" placeholder="32-byte hash" disabled></label> + <button type="button" disabled>Awaiting testnet RPC</button> + </form> + </article> + + <article class="panel" id="nft" role="tabpanel" hidden> + <div class="panel-copy"><p class="eyebrow">One indivisible unit</p><h2>Mint an NFT</h2><p>Only a bounded metadata hash is committed to consensus. Images and descriptions remain off-chain and untrusted.</p></div> + <form> + <label>Title <input type="text" maxlength="96" placeholder="Artifact 001" disabled></label> + <label>Collection ID <input type="text" placeholder="Optional collection asset ID" disabled></label> + <label>Metadata URI <input type="url" placeholder="ipfs://…" disabled></label> + <label>Metadata content hash <input type="text" placeholder="32-byte hash" disabled></label> + <button type="button" disabled>Awaiting testnet RPC</button> + </form> + </article> + + <article class="panel" id="collections" role="tabpanel" hidden> + <div class="panel-copy"><p class="eyebrow">Authenticated membership</p><h2>Create a collection</h2><p>Members require a signature from the collection controller over the exact member asset ID.</p></div> + <form> + <label>Collection name <input type="text" maxlength="96" placeholder="Monzero Originals" disabled></label> + <label>Metadata URI <input type="url" placeholder="ipfs://…" disabled></label> + <label>Metadata content hash <input type="text" placeholder="32-byte hash" disabled></label> + <button type="button" disabled>Awaiting testnet RPC</button> + </form> + </article> + + <article class="panel" id="swap" role="tabpanel" hidden> + <div class="panel-copy"><p class="eyebrow">Non-custodial only</p><h2>Atomic swap</h2><p>No deposits and no operator custody. Swap activation requires an audited protocol ensuring either both sides settle or neither side does.</p></div> + <form> + <div class="split"><label>You offer <input type="text" placeholder="Amount and asset ID" disabled></label><label>You request <input type="text" placeholder="Amount and asset ID" disabled></label></div> + <label>Counterparty or signed offer <input type="text" placeholder="Public offer payload" disabled></label> + <label>Expiry height <input type="number" placeholder="Block height" disabled></label> + <button type="button" disabled>Swap protocol not active</button> + </form> + </article> + </section> + + <section class="gate"> + <p class="eyebrow">Activation gates</p> + <h2>What remains before funds are accepted.</h2> + <ol> + <li><span>01</span>Persistent, reorg-safe asset state</li> + <li><span>02</span>Confidential ownership and conservation proofs</li> + <li><span>03</span>Wallet scanning, restoration and signing</li> + <li><span>04</span>Adversarial testnet and independent review</li> + </ol> + </section> + </main> + + <footer><span>Monzero Studio beta</span><span>No deposits · No custody · No active issuance</span></footer> + <script src="app.js"></script> +</body> +</html> diff --git a/website/app/styles.css b/website/app/styles.css new file mode 100644 index 000000000..c90f26581 --- /dev/null +++ b/website/app/styles.css @@ -0,0 +1 @@ +:root{--bg:#06100e;--surface:#0b1815;--ink:#ebf7f2;--muted:#8da39b;--line:rgba(199,255,228,.14);--lime:#b9ff66;--mint:#62e7af;--amber:#e6ae59;--mono:ui-monospace,SFMono-Regular,Menlo,monospace;--sans:Inter,Manrope,system-ui,sans-serif}*{box-sizing:border-box}body{margin:0;background:radial-gradient(circle at 75% 10%,rgba(98,231,175,.11),transparent 30%),var(--bg);color:var(--ink);font-family:var(--sans);line-height:1.55}a{color:inherit}header{height:76px;padding:0 clamp(1.2rem,6vw,6rem);display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line)}.brand{text-decoration:none;font-size:.78rem;letter-spacing:.18em;font-weight:700}.brand span{display:inline-grid;place-items:center;width:31px;height:31px;margin-right:.65rem;border:1px solid var(--lime);border-radius:50%;color:var(--lime);font:600 .6rem var(--mono)}nav{display:flex;gap:2rem}nav a{color:var(--muted);font-size:.78rem;text-decoration:none}main{max-width:1440px;margin:auto;padding:clamp(3rem,7vw,7rem) clamp(1.2rem,6vw,6rem)}.intro{display:grid;grid-template-columns:1.2fr .65fr;gap:clamp(2rem,8vw,8rem);align-items:end;margin-bottom:5rem}.eyebrow{color:var(--mint);font:600 .64rem var(--mono);letter-spacing:.15em;text-transform:uppercase}h1{font-size:clamp(3.4rem,7vw,7.5rem);line-height:.9;letter-spacing:-.065em;margin:.8rem 0 1.8rem;max-width:900px;font-weight:520}.intro>div>p:last-child,.panel-copy p,.gate{color:var(--muted);max-width:720px}.network-card{border:1px solid var(--line);background:rgba(255,255,255,.025);padding:1.5rem}.label{display:block;color:var(--muted);font:.62rem var(--mono);text-transform:uppercase;letter-spacing:.1em}.network-card>strong{display:block;margin:.7rem 0 1.4rem;font:500 1.4rem var(--mono)}dl{margin:0;border-top:1px solid var(--line)}dl div{display:flex;justify-content:space-between;padding:.8rem 0;border-bottom:1px solid var(--line)}dt{color:var(--muted);font-size:.75rem}dd{margin:0;font:.75rem var(--mono)}.amber{color:var(--amber)}.workspace{border:1px solid var(--line);background:rgba(255,255,255,.015)}.tabs{display:grid;grid-template-columns:repeat(4,1fr);border-bottom:1px solid var(--line)}.tabs button{padding:1.1rem;border:0;border-right:1px solid var(--line);background:transparent;color:var(--muted);font:600 .68rem var(--mono);cursor:pointer}.tabs button:last-child{border:0}.tabs button[aria-selected=true]{background:rgba(185,255,102,.08);color:var(--lime)}.panel{display:grid;grid-template-columns:.7fr 1.3fr;gap:5rem;padding:clamp(1.5rem,5vw,4.5rem)}h2{font-size:clamp(2rem,4vw,4rem);line-height:1;margin:.6rem 0 1rem;letter-spacing:-.045em;font-weight:520}form{display:grid;gap:1rem}label{display:grid;gap:.45rem;color:#b5c6c0;font-size:.72rem}input{width:100%;padding:.95rem 1rem;border:1px solid var(--line);background:#081310;color:var(--ink);font:inherit}input:disabled{opacity:.6}.split{display:grid;grid-template-columns:1fr 1fr;gap:1rem}form button{padding:1rem;border:0;background:#26342f;color:#71837c;font-weight:700;cursor:not-allowed}.gate{padding:6rem 0 2rem}.gate ol{list-style:none;margin:2rem 0 0;padding:0;border-top:1px solid var(--line)}.gate li{display:flex;gap:1.2rem;padding:1.1rem 0;border-bottom:1px solid var(--line);color:var(--ink)}.gate li span{color:var(--lime);font:.7rem var(--mono)}footer{display:flex;justify-content:space-between;padding:2rem clamp(1.2rem,6vw,6rem);border-top:1px solid var(--line);color:#657a72;font:.65rem var(--mono)}@media(max-width:800px){nav{display:none}.intro,.panel{grid-template-columns:1fr;gap:2rem}.tabs{grid-template-columns:1fr 1fr}.tabs button{border-bottom:1px solid var(--line)}.split{grid-template-columns:1fr}footer{flex-direction:column;gap:.5rem}} |
