chainstate / index.html
CPater's picture
Upload index.html
f9a5978 verified
Raw
History Blame Contribute Delete
242 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CHAINSTATE — Symbolic-Weight Blockchain with Integrated LM Swarm</title>
<meta name="description" content="CHAINSTATE — symbolic-weight blockchain. Transactions ARE cognitive queries. Weights are universal symbols (math, science, language, occult, emoji). Consensus through reputation-weighted Bayesian log-pooling. Fully integrated with NWO-ASM and NWO NEURO.">
<link rel="icon" type="image/png" href="https://huggingface.co/spaces/CPater/chainstate/resolve/main/phi.png">
<script>window.__CHAINSTATE_WORKER = "https://chainstate-worker.ciprianpater.workers.dev";</script>
<script>
/* ── CHAINSTATE Demo/Live mode toggle — global state, persisted, event-driven ── */
(function(){
var KEY = 'cs:mode';
var mode = 'demo';
try { var m = localStorage.getItem(KEY); if(m==='demo'||m==='live') mode=m; } catch(e){}
window.csMode = function(){ return mode; };
window.csIsLive = function(){ return mode === 'live'; };
window.csSetMode = function(m){
if(m !== 'demo' && m !== 'live') return;
if(m === mode) return;
mode = m;
try { localStorage.setItem(KEY, mode); } catch(e){}
if(document.body) document.body.setAttribute('data-cs-mode', mode);
document.querySelectorAll('.mode-toggle [data-mode]').forEach(function(b){
b.classList.toggle('on', b.getAttribute('data-mode') === mode);
});
document.dispatchEvent(new CustomEvent('cs:modechange', { detail: { mode: mode } }));
};
window.csModeToggle = function(){
return '<div class="mode-toggle" role="group" aria-label="Demo / Live data mode">'+
'<button data-mode="demo" class="'+(mode==='demo'?'on':'')+'" '+
'onclick="csSetMode(\'demo\')" '+
'title="Show seeded sample data — no worker calls">DEMO</button>'+
'<button data-mode="live" class="'+(mode==='live'?'on':'')+'" '+
'onclick="csSetMode(\'live\')" '+
'title="Hit the live worker for real chain data">LIVE</button>'+
'</div>';
};
document.addEventListener('DOMContentLoaded', function(){
document.body.setAttribute('data-cs-mode', mode);
});
})();
</script>
<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=Orbitron:wght@400;500;600;700;800&family=Chakra+Petch:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@300;400;500;600&display=swap" rel="stylesheet">
<style>
:root{
--k:#000;--k1:#070709;--k2:#101015;--k3:#1c1c24;
--w:#fff;--w2:#e9e9ee;--w3:#9c9ca6;--w4:#5a5a64;
--line:rgba(255,255,255,.10);--line2:rgba(255,255,255,.22);--line3:rgba(255,255,255,.45);
--shim-a:rgba(255,255,255,.04);--shim-b:rgba(255,255,255,.18);--shim-c:rgba(255,255,255,.32);
--live:#7df0a8;--beta:#f0e07d;--design:#a98df0;--road:#f0a87d;
--math:#7df0a8;--sci:#7ad0ff;--lang:#f0e07d;--occ:#a48cff;--emo:#ff8cb8;--ctrl:#e9e9ee;
--display:'Orbitron',ui-sans-serif,system-ui,sans-serif;
--body:'Chakra Petch',ui-sans-serif,system-ui,sans-serif;
--mono:'IBM Plex Mono',ui-monospace,monospace;
--hero-h:100vh;
--topbar-h:62px;
}
*{margin:0;padding:0;box-sizing:border-box}
html{height:100%}
html,body{width:100%;background:var(--k);color:var(--w);font-family:var(--body);
letter-spacing:.015em;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;overflow-x:hidden}
body{min-height:100vh;font-size:15px;line-height:1.55;display:flex;flex-direction:column}
a{color:inherit;text-decoration:none}
button{font-family:inherit;color:inherit;background:transparent;border:none;cursor:pointer}
canvas{display:block}
img{display:block;max-width:100%}
code{font-family:var(--mono);background:rgba(255,255,255,.04);padding:1px 5px;border-radius:4px;font-size:.92em}
.shim{position:relative;overflow:hidden;
background:linear-gradient(180deg, rgba(255,255,255,.015), rgba(255,255,255,0) 60%);
border:1px solid var(--line);border-radius:14px;isolation:isolate}
.shim > *{position:relative;z-index:1}
.ghost{display:inline-flex;align-items:center;gap:.55em;padding:.65em 1.1em;
border:1px solid var(--line2);border-radius:999px;background:transparent;color:var(--w);
font-family:var(--display);font-size:.78em;font-weight:500;letter-spacing:.14em;
text-transform:uppercase;transition:border-color .25s,transform .25s,background .25s;cursor:pointer}
.ghost:hover{border-color:var(--line3);background:rgba(255,255,255,.03);transform:translateY(-1px)}
.ghost.sm{padding:.45em .85em;font-size:.7em}
.ghost.bold{border-color:rgba(255,255,255,.55);font-weight:700}
.pill{display:inline-flex;align-items:center;gap:.4em;padding:.18em .55em;border-radius:999px;
font-family:var(--mono);font-size:.62em;font-weight:500;letter-spacing:.18em;
border:1px solid var(--line2);text-transform:uppercase}
.pill .dot{width:6px;height:6px;border-radius:50%;background:var(--w3)}
.pill.live{border-color:rgba(125,240,168,.45)}.pill.live .dot{background:var(--live);box-shadow:0 0 8px var(--live)}
.pill.beta{border-color:rgba(240,224,125,.4)}.pill.beta .dot{background:var(--beta);box-shadow:0 0 8px var(--beta)}
.pill.design{border-color:rgba(169,141,240,.4)}.pill.design .dot{background:var(--design);box-shadow:0 0 8px var(--design)}
.pill.planned{border-color:rgba(122,208,255,.45)}.pill.planned .dot{background:#7ad0ff;box-shadow:0 0 8px rgba(122,208,255,.6)}
.pill.parked{border-color:rgba(180,180,196,.35)}.pill.parked .dot{background:#9c9ca6;box-shadow:0 0 4px rgba(180,180,196,.4)}
.pill.road{border-color:rgba(240,168,125,.4)}.pill.road .dot{background:var(--road);box-shadow:0 0 8px var(--road)}
/* ── Demo/Live mode toggle ── */
.mode-toggle{display:inline-flex;align-items:center;gap:0;border:1px solid var(--line2);border-radius:999px;
padding:2px;background:rgba(0,0,0,.4);font-family:var(--mono);font-size:.62em;letter-spacing:.18em;
text-transform:uppercase;font-weight:500}
.mode-toggle button{background:none;border:0;padding:.32em .75em;color:var(--w3);cursor:pointer;
border-radius:999px;transition:background .2s, color .2s;font:inherit;letter-spacing:inherit}
.mode-toggle button.on[data-mode="demo"]{background:var(--w);color:#000}
.mode-toggle button.on[data-mode="live"]{background:var(--live);color:#000;box-shadow:0 0 10px rgba(125,240,168,.45)}
.mode-toggle button:hover:not(.on){color:var(--w);background:rgba(255,255,255,.08)}
/* LIVE-mode body accent: when LIVE, the page subhero gets a subtle green border tint */
body[data-cs-mode="live"] .subhero{border-left:2px solid var(--live);padding-left:14px}
/* Live-only / Demo-only block toggles */
body[data-cs-mode="demo"] .live-only{display:none !important}
body[data-cs-mode="live"] .demo-only{display:none !important}
.topbar{position:fixed;top:0;left:0;right:0;z-index:60;height:var(--topbar-h);
display:flex;align-items:center;justify-content:space-between;padding:0 22px;gap:18px;
background:linear-gradient(180deg, rgba(0,0,0,.85), rgba(0,0,0,.55) 70%, rgba(0,0,0,0));
backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border-bottom:1px solid var(--line)}
.brand{display:flex;align-items:center;gap:12px;cursor:pointer}
.brand img.phi{width:34px;height:34px;object-fit:contain;filter:drop-shadow(0 0 6px rgba(255,255,255,.35))}
.brand .name{font-family:var(--display);font-weight:700;letter-spacing:.18em;font-size:1.05em}
.brand .name .light{font-weight:400;color:var(--w3);margin-left:.35em}
.topbar-right{display:flex;align-items:center;gap:10px}
#wallet-btn{height:36px;padding:0 14px;border-radius:8px}
#wallet-btn .addr{font-family:var(--mono);font-size:.78em;letter-spacing:.05em}
.burger{display:flex;width:42px;height:36px;align-items:center;justify-content:center;
border:1px solid var(--line2);border-radius:8px;cursor:pointer;transition:border-color .2s,background .2s}
.burger:hover{border-color:var(--line3);background:rgba(255,255,255,.03)}
.burger span{display:block;width:18px;height:1.5px;background:var(--w);position:relative}
.burger span::before,.burger span::after{content:'';position:absolute;left:0;right:0;height:1.5px;background:var(--w)}
.burger span::before{top:-6px}.burger span::after{top:6px}
.nav{display:none;align-items:center;gap:2px;flex-wrap:wrap}
.nav .nav-item{position:relative;font-family:var(--display);font-size:.72em;font-weight:500;
letter-spacing:.14em;text-transform:uppercase;padding:9px 11px;border-radius:6px;color:var(--w3);
transition:color .2s,background .2s;cursor:pointer;white-space:nowrap}
.nav .nav-item:hover{color:var(--w);background:rgba(255,255,255,.04)}
.nav .nav-item.active{color:var(--w);background:rgba(255,255,255,.06)}
.nav-group{position:relative}
.nav-group > .nav-item{display:flex;align-items:center;gap:6px}
.nav-group > .nav-item .chev{display:inline-block;transition:transform .22s;font-size:.7em;color:var(--w3)}
.nav-group.open > .nav-item .chev{transform:rotate(180deg);color:var(--w)}
.nav-dd{display:none}
.nav-group.open .nav-dd{display:block}
.nav-dd a{display:block;padding:8px 11px;font-family:var(--display);font-size:.68em;
letter-spacing:.13em;color:var(--w3);border-radius:6px;text-transform:uppercase;
transition:background .2s,color .2s;cursor:pointer;white-space:nowrap}
.nav-dd a:hover{color:var(--w);background:rgba(255,255,255,.05)}
.nav-dd a.active{color:var(--w);background:rgba(255,255,255,.08)}
.nav-dd .sub-label{padding:8px 12px 4px;color:var(--w4);font-family:var(--mono);
font-size:.6em;letter-spacing:.18em;text-transform:uppercase}
.topbar.menu-open .nav{display:flex;position:absolute;top:var(--topbar-h);left:0;right:0;
background:#000;padding:14px;border-bottom:1px solid var(--line);
flex-direction:column;align-items:stretch;gap:2px;
max-height:calc(100vh - var(--topbar-h));overflow-y:auto;z-index:70}
.topbar.menu-open .nav .nav-item{width:100%;padding:11px 12px;font-size:.74em}
.topbar.menu-open .nav-group{width:100%}
.topbar.menu-open .nav-group > .nav-item{justify-content:space-between}
.topbar.menu-open .nav-group .nav-dd{position:static;opacity:1;pointer-events:auto;
transform:none;border:1px solid var(--line);background:rgba(255,255,255,.025);
border-radius:8px;margin:4px 0 6px 12px;padding:6px;display:none}
.topbar.menu-open .nav-group.open .nav-dd{display:grid;grid-template-columns:1fr 1fr;gap:0 4px}
.topbar.menu-open .nav-dd .sub-label{grid-column:1 / -1;padding:6px 8px 2px}
.topbar.menu-open .nav-dd a{font-size:.65em;padding:7px 9px}
@media (min-width: 1200px) {
.burger{display:none}
.nav,.topbar.menu-open .nav{
display:flex !important;position:static !important;flex-direction:row !important;
align-items:center !important;flex-wrap:nowrap !important;background:transparent !important;
padding:0 !important;border-bottom:0 !important;backdrop-filter:none !important;
max-height:none !important;overflow:visible !important;gap:1px !important;z-index:auto !important;
}
.nav .nav-item{width:auto !important;padding:8px 10px;font-size:.68em}
.nav-group{width:auto !important}
.nav-group > .nav-item{width:auto !important;justify-content:flex-start !important}
.nav-group .nav-dd,.topbar.menu-open .nav-group .nav-dd{
display:none !important;position:absolute !important;top:calc(100% + 8px) !important;
left:0 !important;right:auto !important;margin:0 !important;padding:12px !important;
min-width:560px;background:#000 !important;border:1px solid var(--line) !important;
border-radius:10px !important;box-shadow:0 14px 36px rgba(0,0,0,0.6);z-index:80;
grid-template-columns:1fr 1fr;gap:0 12px;
}
.nav-group.open .nav-dd,.topbar.menu-open .nav-group.open .nav-dd{display:grid !important}
.nav-dd a{padding:7px 10px;font-size:.66em}
.nav-dd .sub-label{grid-column:1 / -1;padding:6px 10px 3px}
}
@media (min-width: 1500px) {
.nav-group .nav-dd{min-width:760px;grid-template-columns:1fr 1fr 1fr !important}
}
.stage{position:relative;width:100%;flex:1 0 auto;padding-top:var(--topbar-h);overflow:hidden}
.page{position:absolute;top:var(--topbar-h);left:0;right:0;opacity:0;transform:translateX(50px);
transition:opacity .55s cubic-bezier(.22,.61,.36,1),transform .55s cubic-bezier(.22,.61,.36,1);
pointer-events:none}
.page.active{opacity:1;transform:translateX(0);pointer-events:auto;position:relative;top:0}
.page.exit-left{transform:translateX(-50px)}
.page.exit-right{transform:translateX(50px)}
.page.enter-left{transform:translateX(-50px)}
.wrap{max-width:1480px;margin:0 auto;padding:0 28px}
section{padding:28px 0}
section.tight{padding:18px 0}
section.bare{padding:0}
.section-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;
margin-bottom:18px;border-bottom:1px solid var(--line);padding-bottom:10px}
.section-head h2{font-family:var(--display);font-weight:600;font-size:1.4em;letter-spacing:.06em}
.section-head .sub{color:var(--w3);font-family:var(--mono);font-size:.7em;letter-spacing:.14em;text-transform:uppercase}
.eyebrow{font-family:var(--mono);font-size:.7em;color:var(--w3);
letter-spacing:.28em;text-transform:uppercase;margin-bottom:10px}
.hero{position:relative;height:calc(100vh - var(--topbar-h));min-height:680px;
display:flex;flex-direction:column;justify-content:center;overflow:hidden;border-bottom:1px solid var(--line)}
#hero-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:1}
.hero-fade{position:absolute;inset:0;z-index:2;pointer-events:none;
background:radial-gradient(75% 55% at 50% 50%, transparent, rgba(0,0,0,.55) 65%, rgba(0,0,0,.95) 100%)}
.hero-inner{position:relative;z-index:3;padding:0 28px;max-width:1480px;margin:0 auto;width:100%}
.hero h1{font-family:var(--display);font-weight:700;font-size:clamp(2.2em, 5.8vw, 5em);
letter-spacing:.04em;line-height:1.02;text-transform:uppercase}
.hero h1 .accent{color:var(--w3);font-weight:400}
.hero .lede{margin-top:18px;max-width:820px;color:var(--w2);font-size:1.08em}
.stats{margin-top:38px;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;position:relative}
.stat{position:relative;overflow:hidden;padding:18px 18px;border:1px solid var(--line);
border-radius:12px;background:rgba(0,0,0,.4);backdrop-filter:blur(6px);isolation:isolate}
.stat > *{position:relative;z-index:1}
.stat .v{font-family:var(--display);font-size:1.65em;font-weight:600}
.stat .l{font-family:var(--mono);font-size:.65em;color:var(--w3);letter-spacing:.18em;text-transform:uppercase;margin-top:6px}
.scroll-cue{position:absolute;bottom:18px;left:50%;transform:translateX(-50%);z-index:3;
font-family:var(--mono);font-size:.62em;color:var(--w3);letter-spacing:.3em;
text-transform:uppercase;display:flex;flex-direction:column;align-items:center;gap:6px}
.scroll-cue .l{width:1px;height:24px;background:linear-gradient(180deg,transparent,var(--w3));animation:slide 2s ease-in-out infinite}
@keyframes slide{0%,100%{opacity:.2;transform:scaleY(.4)}50%{opacity:1;transform:scaleY(1)}}
/* CHAINSTATE SCAN — block explorer */
.scan-grid{display:grid;grid-template-columns:1.2fr .8fr;gap:14px;margin-top:18px}
@media(max-width:980px){.scan-grid{grid-template-columns:1fr}}
.scan-card{padding:0;overflow:hidden}
.scan-card-head{padding:14px 18px;border-bottom:1px solid var(--line);background:rgba(0,0,0,.4);
display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}
.scan-card-head h3{font-family:var(--display);font-size:.88em;font-weight:600;letter-spacing:.14em;text-transform:uppercase}
.scan-card-head .meta{font-family:var(--mono);font-size:.66em;color:var(--w3);letter-spacing:.06em}
.scan-list{max-height:480px;overflow-y:auto}
.scan-row{display:grid;grid-template-columns:auto 1fr auto;gap:10px;align-items:center;
padding:10px 18px;border-bottom:1px dashed rgba(255,255,255,.06);cursor:pointer;transition:background .2s}
.scan-row:hover{background:rgba(255,255,255,.025)}
.scan-row:last-child{border-bottom:0}
.scan-row .ico{width:32px;height:32px;border:1px solid var(--line2);border-radius:6px;
display:flex;align-items:center;justify-content:center;font-family:var(--display);font-size:.62em;color:var(--w3);letter-spacing:.06em}
.scan-row .ico.bk{color:var(--live);border-color:rgba(125,240,168,.4)}
.scan-row .ico.tx{color:var(--sci);border-color:rgba(122,208,255,.4)}
.scan-row .hash{font-family:var(--mono);font-size:.78em;color:var(--w);letter-spacing:.04em;
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.scan-row .sub{font-family:var(--mono);font-size:.64em;color:var(--w3);letter-spacing:.04em;margin-top:2px}
.scan-row .v{font-family:var(--display);font-weight:600;font-size:.82em;text-align:right}
.scan-row .v .l{font-family:var(--mono);font-weight:400;font-size:.7em;color:var(--w3);letter-spacing:.06em}
.scan-search{display:flex;gap:10px;padding:14px 18px;border-bottom:1px solid var(--line);background:rgba(0,0,0,.3)}
/* ── Home-page collapsible hero + toggle bar ── */
.home-toggle-bar{position:sticky;top:64px;z-index:30;display:flex;justify-content:flex-end;
padding:8px 22px;background:linear-gradient(180deg,rgba(0,0,0,.92),rgba(0,0,0,.4) 80%,transparent);
backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
border-bottom:1px solid rgba(255,255,255,.04)}
.home-toggle-btn{display:inline-flex;align-items:center;gap:8px;
background:rgba(0,0,0,.6);border:1px solid var(--line2);border-radius:999px;
padding:6px 14px;color:var(--w2);cursor:pointer;
font-family:var(--mono);font-size:.62em;letter-spacing:.18em;text-transform:uppercase;
transition:border-color .2s,color .2s,background .2s}
.home-toggle-btn:hover{border-color:var(--line3);color:var(--w);background:rgba(255,255,255,.04)}
.home-toggle-btn .ic{font-size:.9em;transition:transform .25s}
.home-collapsed .home-toggle-btn .ic{transform:rotate(-90deg)}
.home-collapsible{max-height:none;overflow:hidden;transition:max-height .35s ease}
.home-collapsed .home-collapsible{max-height:0}
.quick-scan-shell{border:1px solid var(--line);border-radius:14px;background:rgba(0,0,0,.4);
padding:6px 0;overflow:hidden}
.quick-scan-shell .scan-search{border-bottom:none}
.quick-scan-shell + p{padding:0 18px}
.scan-search input{flex:1;background:rgba(255,255,255,.04);border:1px solid var(--line);
border-radius:8px;padding:9px 12px;color:var(--w);font-family:var(--mono);font-size:.82em;outline:none}
.scan-search input:focus{border-color:var(--line3)}
.scan-stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
@media(max-width:760px){.scan-stat-grid{grid-template-columns:repeat(2,1fr)}}
.scan-stat{padding:14px;border:1px solid var(--line);border-radius:10px;background:rgba(0,0,0,.3)}
.scan-stat .v{font-family:var(--display);font-size:1.35em;font-weight:600}
.scan-stat .l{font-family:var(--mono);font-size:.6em;color:var(--w3);letter-spacing:.16em;text-transform:uppercase;margin-top:4px}
/* SYMBOLIC REGISTRY page */
.sym-tabs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px}
.sym-tab{padding:7px 13px;font-family:var(--display);font-size:.7em;letter-spacing:.14em;
text-transform:uppercase;color:var(--w3);border:1px solid var(--line);border-radius:999px;cursor:pointer;
transition:color .2s,border-color .2s,background .2s}
.sym-tab:hover{color:var(--w);border-color:var(--line2)}
.sym-tab.on{color:var(--k);background:var(--w);border-color:var(--w)}
.sym-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(58px,1fr));gap:6px}
.sym-cell{aspect-ratio:1/1;border:1px solid var(--line);border-radius:8px;
display:flex;align-items:center;justify-content:center;font-size:1.3em;
background:rgba(255,255,255,.02);cursor:pointer;transition:transform .15s,border-color .2s,background .2s;font-family:var(--body)}
.sym-cell:hover{transform:scale(1.08);border-color:var(--line3);background:rgba(255,255,255,.06)}
.sym-cell.sym-math{color:var(--math)}
.sym-cell.sym-sci{color:var(--sci)}
.sym-cell.sym-lang{color:var(--lang)}
.sym-cell.sym-occ{color:var(--occ)}
.sym-cell.sym-emo{color:var(--emo)}
.sym-cell.sym-ctrl{color:var(--ctrl)}
.sym-info{padding:14px 16px;background:rgba(255,255,255,.025);border:1px solid var(--line);
border-radius:10px;margin-top:14px;font-family:var(--mono);font-size:.78em;color:var(--w2);
display:flex;align-items:center;gap:14px;flex-wrap:wrap;min-height:54px}
.sym-info .big{font-size:2em;line-height:1;color:var(--w);font-family:var(--body)}
.sym-info .meta{display:flex;flex-direction:column;gap:4px;font-size:.84em;color:var(--w3)}
/* TERMINAL — same as NEURO */
.terminal-shell{padding:0;overflow:hidden}
.terminal-head{display:flex;align-items:center;gap:8px;padding:10px 14px;border-bottom:1px solid var(--line);background:rgba(0,0,0,.4)}
.t-dot{width:9px;height:9px;border-radius:50%}
.t-dot.t-r{background:#ff5f56}.t-dot.t-y{background:#ffbd2e}.t-dot.t-g{background:#27c93f}
.t-title{font-family:var(--mono);font-size:.74em;letter-spacing:.06em;color:var(--w2);margin-left:8px}
.t-status{margin-left:auto;font-family:var(--mono);font-size:.66em;color:var(--w3);letter-spacing:.06em}
.terminal-body{padding:12px 16px;font-family:var(--mono);font-size:.78em;line-height:1.55;
height:360px;overflow-y:auto;color:var(--w2);background:rgba(0,0,0,.45)}
.terminal-body .tline{margin:0;padding:1px 0;white-space:pre-wrap;word-break:break-word}
.terminal-body .tline.sys{color:var(--w3)}
.terminal-body .tline.cmd{color:var(--w)}
.terminal-body .tline.ok{color:#7df0a8}
.terminal-body .tline.err{color:#ff8cb8}
.terminal-body .tline.dim{color:var(--w4)}
.terminal-body .tline.stream{color:#7ad0ff}
.terminal-body .echo{color:#7df0a8;margin-right:6px}
.terminal-input-row{display:flex;align-items:center;gap:8px;padding:10px 14px;border-top:1px solid var(--line);background:rgba(0,0,0,.4)}
.terminal-input-row .prompt{font-family:var(--mono);font-size:.78em;color:#7df0a8;letter-spacing:.04em;flex-shrink:0}
.terminal-input-row input{flex:1;background:transparent;border:none;outline:none;color:var(--w);
font-family:var(--mono);font-size:.85em;letter-spacing:.04em;padding:4px 0}
.terminal-input-row input::placeholder{color:var(--w4)}
code.dim{color:var(--w4)}
.instr-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;margin-top:14px}
.instr-card{display:flex;flex-direction:column;align-items:flex-start;gap:8px;padding:18px;
border:1px solid var(--line);border-radius:12px;background:rgba(0,0,0,.3);text-align:left;cursor:pointer;color:var(--w);transition:transform .2s,border-color .25s}
.instr-card:hover{transform:translateY(-2px);border-color:var(--line3)}
.instr-card-h{display:flex;align-items:center;justify-content:space-between;width:100%;gap:10px}
.instr-num{font-family:var(--mono);font-size:.7em;letter-spacing:.14em;color:var(--w3);text-transform:uppercase}
.instr-name{font-family:var(--display);font-weight:600;font-size:1.05em;letter-spacing:.04em}
.instr-head{font-family:var(--body);font-size:.88em;color:var(--w2);line-height:1.5}
.instr-cta{margin-top:auto;font-family:var(--mono);font-size:.66em;letter-spacing:.12em;color:#7df0a8;text-transform:uppercase}
.subhero{padding:22px 28px 14px;max-width:1480px;margin:0 auto}
.subhero .back{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);
font-size:.66em;letter-spacing:.18em;color:var(--w3);text-transform:uppercase;margin-bottom:10px;cursor:pointer}
.subhero .back:hover{color:var(--w)}
.subhero h1{font-family:var(--display);font-weight:700;font-size:clamp(1.6em, 3.4vw, 2.4em);
letter-spacing:.04em;text-transform:uppercase;line-height:1.05}
.subhero .lede{margin-top:10px;color:var(--w2);font-size:.98em;max-width:920px}
.subhero .meta-row{margin-top:12px;display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.two-col{display:grid;grid-template-columns:1.05fr .95fr;gap:18px}
@media(max-width:1080px){.two-col{grid-template-columns:1fr}}
.col-card{padding:20px}
.col-card h3{font-family:var(--display);font-size:.95em;font-weight:600;letter-spacing:.14em;text-transform:uppercase;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.col-card p{color:var(--w2);margin-bottom:10px;font-size:.94em}
.col-card ul{list-style:none;padding:0}
.col-card ul li{position:relative;padding:4px 0 4px 22px;color:var(--w2);font-size:.92em}
.col-card ul li::before{content:'';position:absolute;left:0;top:13px;width:8px;height:1px;background:var(--w3)}
.eco-table,.pay-table{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:.76em}
.eco-table th,.eco-table td,.pay-table th,.pay-table td{padding:8px 10px;text-align:left;border-bottom:1px solid var(--line)}
.eco-table th,.pay-table th{font-family:var(--display);font-size:.74em;letter-spacing:.14em;text-transform:uppercase;color:var(--w3);font-weight:500}
.eco-table tr:last-child td,.pay-table tr:last-child td{border-bottom:0}
.pay-table td a{color:var(--math);text-decoration:underline;text-underline-offset:2px}
.flow-box{padding:18px}
.flow-box h3{font-family:var(--display);font-size:.95em;font-weight:600;letter-spacing:.14em;text-transform:uppercase;margin-bottom:14px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.flow-svg{width:100%;height:auto;display:block}
pre.code{font-family:var(--mono);font-size:.75em;background:rgba(255,255,255,.03);
border:1px solid var(--line);border-radius:8px;padding:12px;color:var(--w2);
overflow-x:auto;white-space:pre;line-height:1.5}
pre.code .k{color:var(--math)}pre.code .s{color:var(--lang)}
pre.code .c{color:var(--w4)}pre.code .n{color:var(--sci)}
/* API */
.api-grid{display:grid;grid-template-columns:1.3fr 1fr;gap:14px}
@media(max-width:1100px){.api-grid{grid-template-columns:1fr}}
.panel{padding:16px;display:flex;flex-direction:column}
.panel-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.panel-head h3{font-family:var(--display);font-size:.85em;font-weight:600;letter-spacing:.16em;text-transform:uppercase}
.panel-head .meta{font-family:var(--mono);font-size:.64em;color:var(--w3);letter-spacing:.14em}
.kpi-row{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:14px}
.kpi{padding:14px;border:1px solid var(--line);border-radius:10px}
.kpi .v{font-family:var(--display);font-size:1.4em;font-weight:600}
.kpi .l{font-family:var(--mono);font-size:.6em;color:var(--w3);letter-spacing:.18em;text-transform:uppercase;margin-top:4px}
#calls-chart,.chart-canvas{width:100%;height:170px;display:block;border-radius:6px;background:linear-gradient(180deg,rgba(255,255,255,.022),rgba(255,255,255,.002))}
.kpi-row.aff{margin-top:2px}
.aff-status{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:.62em;letter-spacing:.14em;text-transform:uppercase;padding:.18em .55em;border-radius:999px;border:1px solid var(--line2);color:var(--w2)}
.aff-status.on{border-color:rgba(125,240,168,.4);color:var(--live)}
.aff-status.on .dot{background:var(--live);box-shadow:0 0 8px var(--live)}
.aff-status .dot{width:6px;height:6px;border-radius:50%;background:var(--w3)}
.keys-list{display:flex;flex-direction:column;gap:8px}
.key-row{display:grid;grid-template-columns:auto 1fr auto auto;gap:10px;align-items:center;padding:9px 12px;border:1px solid var(--line);border-radius:8px}
.key-row .kid{font-family:var(--mono);font-size:.78em;color:var(--w);letter-spacing:.04em}
.key-row .kn{font-family:var(--mono);font-size:.68em;color:var(--w3);letter-spacing:.06em}
.pricing-table .ep{font-family:var(--mono);color:var(--w)}
.pricing-table .price{font-family:var(--display);font-weight:600}
/* Architecture circle */
.arch-svg-wrap{padding:20px}
.arch-circle-wrap{position:relative;width:100%;max-width:820px;margin:0 auto}
.arch-svg-circle{width:100%;display:block;height:auto;overflow:visible}
.arch-node rect{transition:stroke-opacity .22s,filter .22s,transform .22s;transform-origin:center;transform-box:fill-box}
.arch-node:hover rect{stroke-opacity:1;filter:drop-shadow(0 0 10px rgba(255,255,255,.35));transform:scale(1.06)}
.arch-node:hover text{fill:#fff}
.arch-tooltip{position:absolute;display:none;max-width:260px;padding:12px 14px;border:1px solid var(--line2);
background:rgba(0,0,0,.94);backdrop-filter:blur(8px);border-radius:10px;pointer-events:none;z-index:20;
font-family:var(--mono);font-size:.72em;line-height:1.55;color:var(--w2);letter-spacing:.04em}
.arch-tt-title{font-family:var(--display);font-size:1.15em;font-weight:600;letter-spacing:.1em;color:var(--w);margin-bottom:6px;display:flex;align-items:center;gap:8px}
.arch-tt-dot{width:8px;height:8px;border-radius:50%;display:inline-block}
.arch-tt-line{padding-left:2px}
.arch-tt-cta{margin-top:8px;padding-top:8px;border-top:1px dashed rgba(255,255,255,.1);font-size:.85em;color:var(--w3);letter-spacing:.12em;text-transform:uppercase}
.arch-legend{margin-top:14px;text-align:center;font-family:var(--mono);font-size:.72em;color:var(--w3);letter-spacing:.06em}
@media(max-width:620px){.arch-circle-wrap{max-width:100%}.arch-tooltip{max-width:200px;font-size:.66em}}
.stack-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
.stack-card{padding:14px}
.stack-card .l{font-family:var(--mono);font-size:.62em;color:var(--w3);letter-spacing:.18em;text-transform:uppercase;margin-bottom:6px}
.stack-card .t{font-family:var(--display);font-size:.95em;font-weight:600;letter-spacing:.04em}
.stack-card .d{margin-top:6px;color:var(--w2);font-size:.88em}
.steps{counter-reset:s;display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:900px){.steps{grid-template-columns:1fr}}
.step-card{padding:18px;counter-increment:s;position:relative}
.step-card::before{content:counter(s, decimal-leading-zero);position:absolute;top:14px;right:18px;font-family:var(--mono);font-size:.8em;color:var(--w3);letter-spacing:.12em}
.step-card h3{font-family:var(--display);font-size:.95em;font-weight:600;letter-spacing:.1em;text-transform:uppercase;padding-bottom:8px;margin-bottom:10px;border-bottom:1px solid var(--line);max-width:86%}
.step-card .layer-label{font-family:var(--mono);font-size:.6em;color:var(--w3);letter-spacing:.2em;text-transform:uppercase;margin-bottom:5px}
.step-card p.txt-sm{color:var(--w2);font-size:.88em;margin-bottom:6px}
/* Roadmap & risk */
.horizon-table{width:100%;border-collapse:separate;border-spacing:0;margin-top:18px;font-size:.95em}
.horizon-table th{font-family:var(--mono);font-size:.66em;letter-spacing:.18em;text-transform:uppercase;color:var(--w3);text-align:left;padding:12px 14px;border-bottom:1px solid var(--line);font-weight:500}
.horizon-table td{padding:14px;border-bottom:1px solid var(--line);vertical-align:top}
.horizon-table tr:last-child td{border-bottom:none}
.horizon-table .h{font-family:var(--mono);font-size:.7em;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}
.horizon-table .h.now{color:var(--live)}
.horizon-table .h.short{color:#7ad0ff}
.horizon-table .h.med{color:#f0e07d}
.horizon-table .h.long{color:#a48cff}
.horizon-table .name{font-family:var(--display);font-weight:600;letter-spacing:.04em}
.horizon-table .rationale{color:var(--w2);font-size:.95em}
.horizon-table tr:hover td{background:rgba(255,255,255,.015)}
.risk-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;margin-top:18px}
@media(max-width:760px){.risk-grid{grid-template-columns:1fr}}
.risk-card{padding:18px;border:1px solid var(--line);border-radius:12px;background:rgba(255,140,184,.025);position:relative}
.risk-card::before{content:'';position:absolute;left:0;top:14px;bottom:14px;width:2px;background:linear-gradient(180deg, rgba(255,140,184,.7), rgba(255,140,184,0))}
.risk-card h4{margin:0 0 6px 0;font-size:1.05em;letter-spacing:.04em;display:flex;align-items:center;gap:8px}
.risk-card p{color:var(--w2);font-size:.95em;line-height:1.6;margin:6px 0}
.risk-card .mitigation{margin-top:10px;padding-top:10px;border-top:1px dashed rgba(255,255,255,.08);font-family:var(--mono);font-size:.72em;color:var(--w3);letter-spacing:.04em}
.risk-card .mitigation::before{content:'mitigation · ';color:#7df0a8}
/* R&D */
.rnd-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
@media(max-width:1080px){.rnd-grid{grid-template-columns:1fr}}
.rnd-paper-card{padding:24px;display:flex;flex-direction:column;gap:12px}
.rnd-paper-card .author{font-family:var(--mono);font-size:.72em;color:var(--w3);letter-spacing:.14em;text-transform:uppercase}
.rnd-paper-card .ttl{font-family:var(--display);font-weight:600;font-size:1.3em;letter-spacing:.03em;line-height:1.2}
.rnd-paper-card .abs{color:var(--w2);font-size:.95em}
.rnd-paper-card .actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px}
.rnd-side-card{padding:20px;display:flex;flex-direction:column;gap:10px}
.rnd-side-card h3{font-family:var(--display);font-size:.95em;font-weight:600;letter-spacing:.14em;text-transform:uppercase;padding-bottom:8px;border-bottom:1px solid var(--line)}
.podcast-player{display:flex;align-items:center;gap:12px;padding:14px;border:1px solid var(--line);border-radius:10px;background:rgba(255,255,255,.02)}
.podcast-player .play{width:42px;height:42px;border-radius:50%;border:1px solid var(--line2);
display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;font-family:var(--display);font-size:.9em;transition:background .2s,border-color .2s}
.podcast-player .play:hover{background:rgba(255,255,255,.06);border-color:var(--w)}
.podcast-player .meta{font-family:var(--mono);font-size:.74em;color:var(--w2);letter-spacing:.04em}
.podcast-player .meta .t{color:var(--w3);font-size:.85em;margin-top:2px}
/* Modal */
.modal-bg{position:fixed;inset:0;background:rgba(0,0,0,.82);backdrop-filter:blur(5px);
z-index:200;opacity:0;pointer-events:none;transition:opacity .25s;display:flex;align-items:center;justify-content:center;padding:24px}
.modal-bg.open{opacity:1;pointer-events:auto}
.modal{max-width:680px;width:100%;max-height:85vh;overflow-y:auto;padding:0;transform:translateY(10px);transition:transform .3s;background:#0a0a0e}
.modal-bg.open .modal{transform:translateY(0)}
.modal.wide{max-width:1100px;max-height:95vh}
.modal-head{display:flex;justify-content:space-between;align-items:center;padding:16px 22px;border-bottom:1px solid var(--line)}
.modal-head h3{font-family:var(--display);font-size:.95em;font-weight:600;letter-spacing:.14em;text-transform:uppercase}
.modal-head .x{font-size:1.5em;color:var(--w3);cursor:pointer;line-height:1;padding:0 4px;background:none;border:0}
.modal-body{padding:20px}
.modal-body.flush{padding:0}
.modal-body h4{font-family:var(--display);font-size:.78em;letter-spacing:.16em;text-transform:uppercase;color:var(--w3);margin:14px 0 8px}
.modal-body ol{padding-left:18px;color:var(--w2)}
.modal-body ol li{padding:4px 0}
.modal-body p{color:var(--w2);margin-bottom:10px}
.pdf-frame{width:100%;height:85vh;border:0;background:#000;display:block}
/* Affiliates */
.aff-wrap{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media(max-width:900px){.aff-wrap{grid-template-columns:1fr}}
.aff-pill-row{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px}
.lvl-row{display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px dashed rgba(255,255,255,.06)}
.lvl-row .l{font-family:var(--mono);font-size:.66em;color:var(--w3);letter-spacing:.14em;text-transform:uppercase}
.lvl-row .v{font-family:var(--display);font-weight:600;font-size:.95em}
#ref-link{font-family:var(--mono);background:rgba(255,255,255,.03);border:1px solid var(--line);border-radius:6px;padding:9px;font-size:.74em;word-break:break-all;color:var(--w2);margin-top:8px}
/* Query interface */
.query-shell{padding:24px}
.query-input{display:flex;flex-direction:column;gap:10px}
.query-input textarea{width:100%;min-height:120px;background:rgba(255,255,255,.04);border:1px solid var(--line);
border-radius:10px;padding:14px;color:var(--w);font-family:var(--mono);font-size:1.1em;letter-spacing:.04em;
resize:vertical;outline:none;line-height:1.4}
.query-input textarea:focus{border-color:var(--line3)}
.query-controls{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-top:12px}
.query-ctrl{padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:rgba(0,0,0,.3)}
.query-ctrl label{display:block;font-family:var(--mono);font-size:.62em;color:var(--w3);letter-spacing:.14em;text-transform:uppercase;margin-bottom:6px}
.query-ctrl input,.query-ctrl select{width:100%;background:transparent;border:none;outline:none;color:var(--w);font-family:var(--mono);font-size:.88em}
.query-out{margin-top:14px;padding:14px;background:rgba(0,0,0,.45);border:1px solid var(--line);border-radius:10px;
font-family:var(--mono);font-size:.78em;color:var(--w2);line-height:1.55;min-height:80px;white-space:pre-wrap;word-break:break-word}
.query-out .key{color:var(--math)}
.query-out .val{color:var(--lang)}
.query-out .dim{color:var(--w4)}
.cta-row{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
/* Deployment page */
.deploy-step{padding:18px;border:1px solid var(--line);border-radius:12px;margin-bottom:12px;background:rgba(0,0,0,.3)}
.deploy-step h3{font-family:var(--display);font-size:1em;font-weight:600;letter-spacing:.06em;margin-bottom:10px;display:flex;align-items:center;gap:10px}
.deploy-step h3 .num{display:inline-flex;width:28px;height:28px;border-radius:50%;background:rgba(255,255,255,.06);border:1px solid var(--line2);align-items:center;justify-content:center;font-family:var(--mono);font-size:.78em}
.deploy-step p{color:var(--w2);font-size:.92em;margin-bottom:8px}
.secret-table{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:.78em;margin-top:10px}
.secret-table th,.secret-table td{padding:9px 12px;text-align:left;border-bottom:1px solid var(--line)}
.secret-table th{font-family:var(--display);font-size:.72em;letter-spacing:.14em;text-transform:uppercase;color:var(--w3);font-weight:500}
.secret-table td:first-child{color:var(--math)}
.secret-table tr:last-child td{border-bottom:0}
/* Symbol legend strip (5 cards on home page) */
.band-legend{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-top:18px}
.band-card{padding:14px;border:1px solid var(--line);border-radius:10px;background:rgba(0,0,0,.3);
display:flex;flex-direction:column;gap:9px;transition:border-color .25s,transform .25s;cursor:pointer}
.band-card:hover{border-color:var(--line2);transform:translateY(-1px)}
.band-card-name{font-family:var(--display);font-size:.78em;font-weight:600;letter-spacing:.12em;text-transform:uppercase;display:flex;align-items:baseline;gap:6px}
.band-card-name .glyph{font-size:1.5em;font-weight:700}
.band-card-name .rng{margin-left:auto;font-family:var(--mono);font-size:.7em;color:var(--w3);letter-spacing:.08em;text-transform:none}
.band-card-state{font-family:var(--mono);font-size:.66em;color:var(--w2);letter-spacing:.06em;line-height:1.6}
.band-card-samples{font-size:1.2em;letter-spacing:.1em;color:var(--w);min-height:1.6em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media(max-width:1080px){.band-legend{grid-template-columns:repeat(3,1fr)}}
@media(max-width:620px){.band-legend{grid-template-columns:repeat(2,1fr)}}
/* footer */
.footer{margin-top:40px;border-top:1px solid var(--line);padding:20px 28px 20px;background:#020203;margin-bottom:0;flex:0 0 auto}
.foot-row{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:14px}
.foot-row .l{display:flex;align-items:center;gap:14px;font-family:var(--mono);font-size:.7em;color:var(--w3);letter-spacing:.14em;text-transform:uppercase}
.foot-row .l img{width:22px;height:22px}
.cap-toggle{font-family:var(--display);font-size:.72em;font-weight:600;letter-spacing:.18em;text-transform:uppercase;display:inline-flex;align-items:center;gap:8px;border:1px solid var(--line2);border-radius:999px;padding:7px 13px;cursor:pointer}
.cap-toggle:hover{border-color:var(--line3)}
.cap-toggle .arrow{display:inline-block;transition:transform .3s;font-size:.7em}
.cap-toggle.open .arrow{transform:rotate(180deg)}
.cap-menu{margin-top:14px;max-height:0;overflow:hidden;transition:max-height .45s cubic-bezier(.22,.61,.36,1)}
.cap-menu.open{max-height:1500px}
.cap-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px;padding:16px 0}
.cap-link{padding:12px;border:1px solid var(--line);border-radius:8px;transition:border-color .2s,transform .2s;cursor:pointer}
.cap-link:hover{border-color:var(--line3);transform:translateY(-1px)}
.cap-link .n{font-family:var(--display);font-size:.82em;font-weight:600;letter-spacing:.06em}
.cap-link .u{font-family:var(--mono);font-size:.62em;color:var(--w3);letter-spacing:.06em;margin-top:3px;word-break:break-all}
@media(max-width:760px){
.hero .stats{grid-template-columns:repeat(2,1fr)}
.api-grid,.two-col,.rnd-grid{grid-template-columns:1fr}
.kpi-row{grid-template-columns:repeat(2,1fr)}
.scan-grid{grid-template-columns:1fr}
#wallet-btn{padding:0 10px}
#wallet-btn .addr{font-size:.7em}
}
.txt-mono{font-family:var(--mono)}
.txt-up{text-transform:uppercase;letter-spacing:.14em}
.txt-mute{color:var(--w3)}
.txt-sm{font-size:.85em}
.divider{height:1px;background:linear-gradient(90deg,transparent,var(--line2),transparent);margin:24px 0}
::selection{background:rgba(255,255,255,.18);color:var(--w)}
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-track{background:#000}
::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:8px}
::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.22)}
@media(prefers-reduced-motion:reduce){.page{transition:none}}
</style>
</head>
<body>
<header class="topbar" id="topbar">
<a class="brand" data-link="home">
<img class="phi" src="https://huggingface.co/spaces/CPater/chainstate/resolve/main/phi.png" alt="CHAINSTATE" onerror="this.style.display='none'">
<span class="name">CHAIN<span class="light">STATE</span></span>
</a>
<nav class="nav" id="nav">
<div class="nav-group" id="home-group">
<a class="nav-item" data-link="home">Home <span class="chev"></span></a>
<div class="nav-dd">
<a data-link="terminal">Terminal</a>
<a data-link="api">API</a>
<a data-link="instructions">Instructions</a>
<a data-link="rnd">NWO R&amp;D</a>
<a data-link="roadmap">Roadmap</a>
<a data-link="affiliates">Affiliates</a>
</div>
</div>
<a class="nav-item" data-link="explorer">SCAN</a>
<a class="nav-item" data-link="query">Query</a>
<a class="nav-item" data-link="symbols">Symbols</a>
<div class="nav-group" id="features-group">
<a class="nav-item">Features <span class="chev"></span></a>
<div class="nav-dd">
<div class="sub-label">Symbolic core</div>
<a data-link="f-use">Universal Semiotic Embedding</a>
<a data-link="f-sam">Symbolic Attention</a>
<a data-link="f-vocab">Cross-Subspace Composition</a>
<div class="sub-label">Consensus</div>
<a data-link="f-pocw">Proof-of-Cognitive-Work</a>
<a data-link="f-pool">Log-Pooling Bayesian</a>
<a data-link="f-rep">Reputation System</a>
<div class="sub-label">Chain</div>
<a data-link="f-txn">Cognitive Transactions</a>
<a data-link="f-block">Block Production</a>
<a data-link="f-stake">$STATE Staking</a>
<div class="sub-label">Integrations</div>
<a data-link="f-asm">NWO-ASM Bridge</a>
<a data-link="f-neuro">NWO NEURO Bridge</a>
<a data-link="f-quantum">Quantum Offload</a>
<div class="sub-label">Network</div>
<a data-link="f-edge">Edge Dispatcher</a>
<a data-link="f-beacon">Swarm Beacon</a>
<a data-link="f-cache">Result Caching</a>
<div class="sub-label">Ecosystem</div>
<a data-link="f-market">DApp Marketplace</a>
</div>
</div>
<a class="nav-item" data-link="architecture">Architecture</a>
<a class="nav-item" data-link="deployment">Deploy</a>
</nav>
<div class="topbar-right">
<button class="ghost sm" id="wallet-btn">
<span style="width:6px;height:6px;border-radius:50%;background:var(--w3);display:inline-block"></span>
<span class="addr">Connect Wallet</span>
</button>
<div class="burger" id="burger"><span></span></div>
</div>
</header>
<main class="stage" id="stage">
<!-- ===== HOME ===== -->
<section class="page active" data-page="home">
<!-- Sticky hide/show toggle for the hero block -->
<div class="home-toggle-bar">
<button class="home-toggle-btn" id="home-toggle-btn" onclick="toggleHomeHero()">
<span class="ic"></span><span class="lbl">Hide hero &amp; symbol bands</span>
</button>
</div>
<!-- Collapsible hero (infinity-flow canvas + stats + 6 subspace bands) -->
<div class="home-collapsible" id="home-collapsible">
<div class="hero" id="hero">
<canvas id="hero-canvas"></canvas>
<div class="hero-fade"></div>
<div class="hero-inner">
<div class="eyebrow">CHAINSTATE · symbolic-weight blockchain · Base mainnet · NWO-ASM integrated</div>
<h1>Symbolic-Weight<br><span class="accent">Blockchain</span></h1>
<p class="lede">A blockchain where <strong>transactions ARE cognitive queries</strong>, weights are universal symbols (∫ ∂ 🧬 ☉ ♂ 一 अ ﺍ ⛓), and consensus emerges from reputation-weighted Bayesian log-pooling over a distributed language-model swarm. Fully composed with <strong>NWO-ASM</strong> (Process-Matrix IR · quantum offload) and <strong>NWO NEURO</strong> (live MSS conditioning). Same wallet, one USDC settlement layer, atomic 15% referrer split.</p>
<div class="stats">
<div class="stat"><div class="v">65,536</div><div class="l">symbolic dimensions</div></div>
<div class="stat"><div class="v">6</div><div class="l">symbolic subspaces</div></div>
<div class="stat"><div class="v"></div><div class="l">consensus depth</div></div>
<div class="stat"><div class="v">PoCW</div><div class="l">proof-of-cognitive-work</div></div>
</div>
<div class="band-legend" id="band-legend"></div>
</div>
<div class="scroll-cue" data-link="explorer" style="cursor:pointer"><span>Swipe / tap · SCAN</span><span class="l"></span></div>
</div>
</div>
<!-- Quick Query — mirror of the Query page form, with hq- prefixed IDs -->
<div class="wrap">
<section class="tight">
<div class="section-head"><div><div class="eyebrow">module · quick query</div><h2>Run a cognitive transaction</h2></div></div>
<div class="query-shell shim shim-slow">
<div class="query-input">
<textarea id="hq-text" placeholder="e.g. ∫∂x → ? or Solve ☉☽☿ in alchemy or 🧬🔬⚗ → ? or explain CRDTs"></textarea>
<div class="query-controls">
<div class="query-ctrl">
<label>consensus depth</label>
<input id="hq-depth" type="number" value="3" min="1" max="7">
</div>
<div class="query-ctrl">
<label>swarm size</label>
<input id="hq-size" type="number" value="20" min="10" max="100">
</div>
<div class="query-ctrl">
<label>quantum offload</label>
<select id="hq-quantum"><option value="none">none</option><option value="ibm">IBM Sherbrooke</option><option value="origin">Origin Wukong</option></select>
</div>
<div class="query-ctrl">
<label>cache</label>
<select id="hq-cache"><option value="true">use (5-min KV)</option><option value="false">bypass</option></select>
</div>
</div>
<div class="cta-row">
<button class="ghost bold" onclick="runQuery('hq-')">⛓ Submit cognitive transaction</button>
<button class="ghost" onclick="symInsert('∫∂x → ?', 'hq-')">Try math</button>
<button class="ghost" onclick="symInsert('☉☽☿ ♀♂ ☯ ☤', 'hq-')">Try occult</button>
<button class="ghost" onclick="symInsert('🧠 🤔 💎 → ✨', 'hq-')">Try emoji</button>
<button class="ghost" onclick="symInsert('道 心 学 智 一 二 三', 'hq-')">Try CJK</button>
</div>
<div class="query-out" id="hq-out"><span class="dim">Result will appear here. The chain dispatches your query to the swarm (default 20 nodes), each node emits a 65,536-d symbolic state, the consensus layer log-pools them, and the answer is returned.</span></div>
</div>
</div>
</section>
<!-- Quick SCAN — block / tx / address lookup -->
<section class="tight">
<div class="section-head"><div><div class="eyebrow">module · quick scan</div><h2>Look up a block, transaction, or query</h2></div></div>
<div class="quick-scan-shell shim">
<div class="scan-search">
<input id="home-scan-input" type="text" placeholder="🔍 Search by block height, tx hash, sender address, or query text…" onkeydown="if(event.key==='Enter')homeScanGo()">
<button class="ghost bold" onclick="homeScanGo()">⛓ Scan</button>
</div>
<p class="txt-sm txt-mute" style="margin:10px 0 0 0">Opens the SCAN page with the search pre-applied. Use a block height (e.g. <code>#1024</code>), a transaction hash, a wallet address, or any text contained in a query.</p>
</div>
</section>
</div>
</section>
<!-- ===== EXPLORER (CHAINSTATE SCAN) ===== -->
<section class="page" data-page="explorer"></section>
<!-- ===== QUERY ===== -->
<section class="page" data-page="query"></section>
<!-- ===== TERMINAL ===== -->
<section class="page" data-page="terminal"></section>
<!-- ===== SYMBOLS ===== -->
<section class="page" data-page="symbols"></section>
<!-- ===== FEATURE SHELLS ===== -->
<section class="page" data-page="f-use"></section>
<section class="page" data-page="f-sam"></section>
<section class="page" data-page="f-vocab"></section>
<section class="page" data-page="f-pocw"></section>
<section class="page" data-page="f-pool"></section>
<section class="page" data-page="f-rep"></section>
<section class="page" data-page="f-txn"></section>
<section class="page" data-page="f-block"></section>
<section class="page" data-page="f-stake"></section>
<section class="page" data-page="f-asm"></section>
<section class="page" data-page="f-neuro"></section>
<section class="page" data-page="f-quantum"></section>
<section class="page" data-page="f-edge"></section>
<section class="page" data-page="f-beacon"></section>
<section class="page" data-page="f-cache"></section>
<section class="page" data-page="f-market"></section>
<!-- ===== Other pages ===== -->
<section class="page" data-page="architecture"></section>
<section class="page" data-page="instructions"></section>
<section class="page" data-page="roadmap"></section>
<section class="page" data-page="api"></section>
<section class="page" data-page="rnd"></section>
<section class="page" data-page="deployment"></section>
<section class="page" data-page="affiliates"></section>
</main>
<footer class="footer">
<div class="foot-row">
<div class="l">
<img src="https://huggingface.co/spaces/CPater/chainstate/resolve/main/phi.png" alt="" onerror="this.style.display='none'">
<span>CHAINSTATE · v0.1 · static HF Space · Base mainnet 8453</span>
</div>
<div class="cap-toggle" id="cap-toggle">
<span>NWO·CAPITAL</span><span class="arrow"></span>
</div>
</div>
<div class="cap-menu" id="cap-menu">
<div class="cap-grid">
<a class="cap-link shim" href="https://nwo.capital" target="_blank" rel="noopener"><div class="n">NWO Capital</div><div class="u">nwo.capital</div></a>
<a class="cap-link shim" href="https://cpater-nwo-capital.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO Capital HF</div><div class="u">cpater-nwo-capital.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-nwo-asm.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO-ASM</div><div class="u">cpater-nwo-asm.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-nwo-neuro.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO NEURO</div><div class="u">cpater-nwo-neuro.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-metastate.static.hf.space" target="_blank" rel="noopener"><div class="n">METASTATE</div><div class="u">cpater-metastate.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-nwo-cardiac.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO Cardiac</div><div class="u">cpater-nwo-cardiac.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-nwo-metaverse.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO Metaverse</div><div class="u">cpater-nwo-metaverse.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-nwo-asi.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO ASI</div><div class="u">cpater-nwo-asi.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-nwo-apocalypse.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO Apocalypse</div><div class="u">cpater-nwo-apocalypse.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-nwo-blackbox.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO BLACKBOX</div><div class="u">cpater-nwo-blackbox.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-nwo-agentic.static.hf.space" target="_blank" rel="noopener"><div class="n">NWO Agentic</div><div class="u">cpater-nwo-agentic.static.hf.space</div></a>
<a class="cap-link shim" href="https://cpater-imperium-romanum.static.hf.space" target="_blank" rel="noopener"><div class="n">Imperium Romanum</div><div class="u">cpater-imperium-romanum.static.hf.space</div></a>
</div>
</div>
</footer>
<div class="modal-bg" id="modal-bg">
<div class="modal shim" id="modal">
<div class="modal-head">
<h3 id="modal-title"></h3>
<button class="x" id="modal-x">×</button>
</div>
<div class="modal-body" id="modal-body"></div>
</div>
</div>
<div class="modal-bg" id="pdf-modal-bg">
<div class="modal wide" id="pdf-modal">
<div class="modal-head">
<h3 id="pdf-title">PDF</h3>
<div style="display:flex;align-items:center;gap:10px">
<a id="pdf-open-tab" class="ghost sm" href="#" target="_blank" rel="noopener">↗ Open in new tab</a>
<button class="x" id="pdf-modal-x">×</button>
</div>
</div>
<div class="modal-body flush">
<iframe id="pdf-frame" class="pdf-frame" src="about:blank" title="paper"></iframe>
</div>
</div>
</div>
<script>
/* ============================================================
COMPREHENSIVE SYMBOL REGISTER — 6 subspaces, ~3500 symbols
============================================================ */
const SUBSPACES = {
math: { name:'Math', glyph:'∫', col:'var(--math)', range:'0–4,096', dims:4096,
samples:['∫','∂','∇','∆','∑','∏','∈','∉','∪','∩','∀','∃','∄','∅','⊂','⊃','⊆','⊇','⊕','⊗','⊥','⊤','∞','∝','≈','≠','≤','≥','≡','≢','⌊','⌋','⌈','⌉','√','∛','∜','∗','∘','∙','∶','∷','∼','∽','≅','≆','≇','≪','≫','≺','≻','⋀','⋁','⋂','⋃','⋄','⋆','⋇','⋈','⋉','⋊','⋋','⋌','⋍','⋎','⋏','⋐','⋑','⋒','⋓','⋔','⋙','⋘','⋗','⋖','⌀','⌁','⌂','⌃','⌄','⌅','⌆','⌇','⌜','⌝','⌞','⌟','〈','〉','⟨','⟩','⟪','⟫','⟬','⟭','⟮','⟯'],
desc:'Mathematical operators, set theory, logic. Unicode ranges 2200–22FF (Mathematical Operators), 27C0–27EF (Misc Math A), 2980–29FF (Misc Math B).' },
sci: { name:'Science', glyph:'⚛', col:'var(--sci)', range:'4,096–12,288', dims:8192,
samples:['ℏ','ℵ','ℶ','ℷ','ℸ','ℂ','ℕ','ℚ','ℝ','ℤ','ℙ','ℍ','ℑ','ℜ','℘','ℓ','ℒ','℧','Å','⚗','⚘','⚙','⚚','⚛','🧬','🧫','🧪','🦠','🔬','🔭','🔮','☢','☣','♨','🔋','💡','⚡','🌡','🩺','⚕','🧲','🌊','🌀','🌈','⛓','🔗','🌐','📡','📊','📈','📉','🛰','🚀','🛸','⏳','⌚','⏰','🕰','📐','📏','🧮','🔢','🔣','💎','🪐','☄','⭐','🌟','✨','🌌','🌠','☀','☁','☂','❄','⛄','🔥','💧','🌪','🌋','⛰','🏔'],
desc:'Letterlike symbols (ℝ ℂ ℕ ℚ ℤ ℙ ℍ ℏ ℵ), unit symbols, scientific apparatus, chemistry, biology, physics, astronomy, meteorology. Unicode 2100–214F + 1F52A–1F570 + 26E0–27BF.' },
lang: { name:'Language', glyph:'文', col:'var(--lang)', range:'12,288–28,672', dims:16384,
samples:['Α','Β','Γ','Δ','Ε','Ζ','Η','Θ','Ι','Κ','Λ','Μ','Ν','Ξ','Ο','Π','Ρ','Σ','Τ','Υ','Φ','Χ','Ψ','Ω','α','β','γ','δ','ε','ζ','η','θ','ι','κ','λ','μ','ν','ξ','ο','π','ρ','ς','σ','τ','υ','φ','χ','ψ','ω','А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я','а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я','一','二','三','四','五','六','七','八','九','十','百','千','万','道','易','心','学','知','行','智','仁','義','禮','信','勇','美','真','善','和','愛','光','空','水','火','土','金','木','日','月','星','天','地','人','王','女','男','子','父','母','子','友','家','国','邦','市','学','校','書','本','字','語','話','言','行','作','見','聞','思','心','念','一','一','ا','ب','ت','ث','ج','ح','خ','د','ذ','ر','ز','س','ش','ص','ض','ط','ظ','ع','غ','ف','ق','ك','ل','م','ن','ه','و','ي','א','ב','ג','ד','ה','ו','ז','ח','ט','י','כ','ל','מ','נ','ס','ע','פ','צ','ק','ר','ש','ת','अ','आ','इ','ई','उ','ऊ','ऋ','ऌ','ऍ','ऎ','ए','ऐ','ऑ','ऒ','ओ','औ','क','ख','ग','घ','ङ','च','छ','ज','झ','ञ','ट','ठ','ड','ढ','ण','त','थ','द','ध','न','प','फ','ब','भ','म','य','र','ल','व','श','ष','स','ह','가','나','다','라','마','바','사','아','자','차','카','타','파','하','한','국','어'],
desc:'All major writing systems. Greek (uppercase + lowercase), Cyrillic, CJK Unified Ideographs (sample), Arabic, Hebrew, Devanagari, Korean Hangul. Foundation for natural-language conditioning of the swarm.' },
occ: { name:'Occult', glyph:'☉', col:'var(--occ)', range:'28,672–32,768', dims:4096,
samples:['☉','☽','☿','♀','♁','♂','♃','♄','♅','♆','♇','⚹','⛢','⛤','⛥','⛦','⛧','☤','☥','☦','☧','☨','☩','☪','☫','☬','☭','☮','☯','✝','✞','✟','✠','✡','✢','✣','✤','✥','✦','✧','★','☆','✩','✪','✫','✬','✭','✮','✯','✰','♈','♉','♊','♋','♌','♍','♎','♏','♐','♑','♒','♓','🜀','🜁','🜂','🜃','🜄','🜅','🜆','🜇','🜈','🜉','🜊','🜋','🜌','🜍','🜎','🜏','🜐','🜑','🜒','🜓','🜔','🜕','🜖','🜗','🜘','🜙','🜚','🜛','🜜','🜝','🜞','🜟','🜠','🜡','🜢','🜣','🜤','🜥','🜦','🜧','🜨','🜩','🜪','🜫','🜬','🜭','🜮','🜯','🜰','🜱','🜲','🜳','🜴','🜵','🜶','🜷','🜸','🜹','🜺','🜻','🜼','🜽','🜾','🜿','🝀','🝁','🝂','🝃','🝄','🝅','🝆','🝇','🝈','🝉','🝊','🝋','🝌','🝍','🝎','🝏','🝐','🝑','🝒','🝓','🝔','🝕','🝖','🝗','🝘','🝙','🝚','🝛','🝜','🝝','🝞','🝟'],
desc:'Astrological (☉ Sun, ☽ Moon, ☿ Mercury…), zodiac (♈ ♉ ♊…), religious / esoteric (☤ ☥ ☦ ☧ ☪ ☮ ☯ ✝), alchemical symbols (1F700–1F77F). Reserved subspace for high-temperature symbolic dispatch.' },
emo: { name:'Emoji', glyph:'🧠', col:'var(--emo)', range:'32,768–49,152', dims:16384,
samples:['💀','☠️','👻','🔫','🦾','👽','👾','🤖','😉','😊','😋','😎','😍','😘','😗','😙','😚','🙂','🤗','🤩','🤔','🤨','😐','😑','😶','🙄','😏','😣','😥','😮','🤐','😯','😪','😫','🥱','😴','😌','😛','😜','😝','🤤','😒','😓','😔','😕','🙃','🤑','😲','☹','🙁','😖','😞','😟','😤','😢','😭','😦','😧','😨','😩','🤯','😬','😰','😱','🥵','🥶','😳','🤪','😵','🥴','😡','😠','🤬','😷','🤒','🤕','🤢','🤮','🤧','😇','🥳','🥺','🤠','🤡','🤥','🤫','🤭','🧐','🤓','👽','👾','🤖','💀','☠','👻','😺','😸','😹','😻','😼','😽','🙀','😿','😾','🐵','🐒','🦍','🦧','🐶','🐕','🦮','🐩','🐺','🦊','🦝','🐱','🐈','🦁','🐯','🐅','🐆','🐴','🐎','🦄','🦓','🦌','🐮','🐂','🐃','🐄','🐷','🐖','🐗','🐏','🐑','🐐','🐪','🐫','🦙','🦒','🐘','🦛','🦏','🐭','🐁','🐀','🐹','🐰','🐇','🐿','🦔','🦇','🐻','🐨','🐼','🦥','🦦','🦨','🦘','🦡','🐾','🦃','🐔','🐓','🐣','🐤','🐥','🐦','🐧','🕊','🦅','🦆','🦢','🦉','🦚','🦜','🐸','🐊','🐢','🦎','🐍','🐲','🐉','🦕','🦖','🐳','🐋','🐬','🐟','🐠','🐡','🦈','🐙','🐚','🐌','🦋','🐛','🐜','🐝','🐞','🦗','🕷','🕸','🦂','🦟','🦠','🌍','🌎','🌏','🌐','🗺','🗾','🧭','🏔','⛰','🌋','🗻','🏕','🏖','🏜','🏝','🏞','🏟','🏛','🏗','🧱','🏘','🏚','🏠','🏡','🏢','🏣','🏤','🏥','🏦','🏨','🏩','🏪','🏫','🏬','🏭','🏯','🏰','💒','🗼','🗽','⛪','🕌','🛕','🕍','⛩','🕋','⛲','⛺','🌁','🌃','🏙','🌄','🌅','🌆','🌇','🌉','♨','🎠','🎡','🎢','💈','🎪','🚂','🚃','🚄','🚅','🚆','🚇','🚈','🚉','🚊','🚋','🚌','🚍','🚎','🚏','🚐','🚑','🚒','🚓','🚔','🚕','🚖','🚗','🚘','🚙','🚚','🚛','🚜','🏎','🏍','🛵','🦽','🦼','🛺','🚲','🛴','🛹','🚏','🛣','🛤','🛢','⛽','🚨','🚥','🚦','🛑','🚧','⚓','⛵','🛶','🚤','🛳','⛴','🛥','🚢','✈','🛩','🛫','🛬','🪂','💺','🚁','🚟','🚠','🚡','🛰','🚀','🛸','🛎','🧳','⌛','⏳','⌚','⏰','⏱','⏲','🕰','🕛','🕧','🕐','🕜','🕑','🕝','🕒','🕞','🕓','🕟','🕔','🕠','🕕','🕡','🕖','🕢','🕗','🕣','🕘','🕤','🕙','🕥','🕚','🕦','🌑','🌒','🌓','🌔','🌕','🌖','🌗','🌘','🌙','🌚','🌛','🌜','🌡','☀','🌝','🌞','🪐','⭐','🌟','🌠','🌌','☁','⛅','⛈','🌤','🌥','🌦','🌧','🌨','🌩','🌪','🌫','🌬','🌀','🌈','🌂','☂','☔','⛱','⚡','❄','☃','⛄','☄','🔥','💧','🌊','💼','💸','💳','💴','💵','💶','💷','💰','💎','⚖','🔧','🔨','⚒','🛠','⛏','🔩','⚙','⛓','🔗','🧰','🧲','💣','🧨','🪓','🔪','🗡','⚔','🛡','🚬','⚰','⚱','🏺','🔮','📿','🧿','💈','⚗','🔭','🔬','🕳','💊','💉','🩸','🩹','🩺','🧬','🦠','🧫','🧪','🌡','🧹','🧺','🧻','🧼','🧽','🧯','🛒','🚬','⚰','📡','💻','⌨','🖥','🖨','🖱','🖲','🕹','🗜','💽','💾','💿','📀','📼','📷','📸','📹','🎥','📽','🎞','📞','☎','📟','📠','📺','📻','🎙','🎚','🎛','🧭','⏱','⏲','⏰','🕰','⌛','⏳','📡','🔋','🔌','💡','🔦','🕯','🪔','🧯','🛢','💸','💵','💴','💶','💷','💰','💳','💎','⚖','🧰','🔧','🔨','⚒','🛠','⛏','🔩','⚙','⛓','🔗','🧪','🧬','🦠','💊','💉','🩸','🩹','🩺','🧬','🦠','🌡','🚪','🛏','🛋','🪑','🚽','🚿','🛁','🪒','🧴','🧷','🧹','🧺','🧻','🧼','🧽','🧯','🛒','🚬','⚰','🪦','⚱','🗿','🪧','🪪'],
desc:'Full Unicode 15.1 emoji set across all 9 categories. People & Body, Animals & Nature, Food & Drink, Travel & Places, Activities, Objects, Symbols, Flags. Anchors humour, intent, and cultural register in queries.' },
ctrl: { name:'Control', glyph:'⇒', col:'var(--ctrl)', range:'49,152–65,536', dims:16384,
samples:['⇒','⇐','⇑','⇓','⇔','⇕','⇖','⇗','⇘','⇙','↺','↻','⟳','⟲','⇄','⇆','⇋','⇌','→','←','↑','↓','↔','↕','↖','↗','↘','↙','⤴','⤵','⤶','⤷','⤸','⤹','⤺','⤻','⟶','⟵','⟷','⟸','⟹','⟺','⟼','⟽','⟾','⟿','⤀','⤁','⤂','⤃','⤄','⤅','⤆','⤇','⤈','⤉','⤊','⤋','⤌','⤍','⤎','⤏','⤐','⤑','⤒','⤓','⤔','⤕','⤖','⤗','⤘','⤙','⤚','⤛','⤜','⤝','⤞','⤟','⤠','⥀','⥁','⥂','⥃','⥄','⥅','⥆','⥇','⥈','⥉','⥊','⥋','⥌','⥍','⥎','⥏','⥐','⥑','⥒','⥓','⥔','⥕','⥖','⥗','⥘','⥙','⥚','⥛','⥜','⥝','⥞','⥟','⥠','⥡','⥢','⥣','⥤','⥥','⥦','⥧','⥨','⥩','⥪','⥫','⥬','⥭','⥮','⥯','⥰','⥱','⥲','⥳','⥴','⥵','⥶','⥷','⥸','⥹','⥺','⥻','␀','␁','␂','␃','␄','␅','␆','␇','␈','␉','␊','␋','␌','␍','␎','␏','␐','␑','␒','␓','␔','␕','␖','␗','␘','␙','␚','␛','␜','␝','␞','␟','␠','␡','␢','␣','␤','␥','␦','⌫','⌧','⌦','⌨','⏎','⌶','⌷','⌸','⌹','⌺','⌻','⌼','⌽','⌾','⌿','⍀','⍁','⍂','⍃','⍄','⍅','⍆','⍇','⍈','⍉','⍊','⍋','⍌','⍍','⍎','⍏','⍐','⍑','⍒','⍓','⍔','⍕','⍖','⍗','⍘','⍙','⍚','⍛','⍜','⍝','⍞','⍟'],
desc:'Arrow operators, double-arrows, semantic flow controls, APL operators, control characters. Encodes program structure, attention routing, and graph topology in the symbolic substrate.' }
};
/* ============================================================
FEATURES — 16 features, each with subpage content
============================================================ */
const FEATURES = [
{ id:'f-use', num:'F-01', name:'Universal Semiotic Embedding',
blurb:'65,536-dim symbolic embedding space encoding math, science, all human languages, occult, emoji, and control-flow symbols.',
status:{label:'live',cls:'live'},
long:'A single 65,536-dimensional embedding space across six subspaces. Every Unicode symbol — mathematical operator, scientific glyph, alphabetic character, alchemical sigil, emoji, or control arrow — has a stable position. The space is built from PyTorch nn.Embedding tables (one per subspace) plus a cross-subspace attention layer that lets a symbol from one domain activate semantically-related symbols in another. The result: ∫ activates ∂, ∇, ∆ (math), ℏ, ℵ (physics), 🔬, 🧮 (instruments), ⇒, ↺ (process flow).',
bullets:[
'Math (4,096 dims) · operators, set theory, logic, relations',
'Science (8,192 dims) · letterlike, units, chemistry, biology, physics, astronomy',
'Language (16,384 dims) · Greek, Cyrillic, CJK, Arabic, Hebrew, Devanagari, Korean',
'Occult (4,096 dims) · astrological, religious, alchemical, esoteric',
'Emoji (16,384 dims) · full Unicode 15.1 emoji set',
'Control (16,384 dims) · arrows, double-arrows, APL, flow-control',
],
eco:[
['NWO-ASM','symbolic ops compile to PMX IR via the ASM bridge'],
['NWO NEURO','MSS scalars condition the embedding lookup'],
['Swarm nodes','each node hosts a quantised shard of the embedding'],
['Query layer','user input is tokenised to symbols, embedded to 4096-d slice'],
],
flow:'use' },
{ id:'f-sam', num:'F-02', name:'Symbolic Attention Mechanism',
blurb:'Cross-subspace attention with a learned 65,536² interaction mask. Math↔Science strong, Language↔All medium, Occult↔Control strong, Emoji↔All weak.',
status:{label:'live',cls:'live'},
long:'Standard attention computes softmax(QKᵀ/√d)V across a uniform space. Symbolic Attention adds a per-subspace interaction mask: certain subspaces are wired to attend strongly to each other (math↔science, occult↔control), some moderately (language↔all), some weakly (emoji↔all). The mask is a 65,536×65,536 sparse tensor materialised at module init. Multi-head: 64 heads of 1,024 dims each. Output flows into the swarm consensus layer.',
bullets:[
'64-head attention with 1,024-dim head size',
'65,536×65,536 sparse interaction mask',
'Math↔Science 1.0 · Language↔All 0.5 · Occult↔Control 1.0 · Emoji↔All 0.1',
'Output projection + LayerNorm + residual',
'GELU activation in the composition feedforward',
'Per-head causal masking optional for autoregressive flows',
],
eco:[
['USE','consumes the embedding output'],
['NWO-ASM','attention pattern translatable to PMX schedule'],
['Swarm consensus','attention output is the per-node symbolic state'],
],
flow:'sam' },
{ id:'f-vocab', num:'F-03', name:'Cross-Subspace Composition',
blurb:'Gated residual composition over the attention output. Sigmoid gates per-subspace; layer norm; GELU expansion.',
status:{label:'live',cls:'live'},
long:'Composition turns attention output into the next-state symbolic vector. A 2× linear expansion (65,536 → 131,072) is gated by four parallel sigmoid gates that selectively pass attention vs residual signal. The expansion is followed by LayerNorm and GELU. The four gates are trained to specialise: gate-0 holds math/science continuity, gate-1 language continuity, gate-2 occult/control state, gate-3 emoji affect. Empirically this stabilises long-horizon symbolic reasoning where pure-residual blocks drift.',
bullets:[
'2× linear expansion + LayerNorm + GELU + 0.5× projection',
'4 parallel sigmoid gates over the residual',
'Per-subspace specialisation through gate initialisation',
'Stable over 32+ composition layers without exploding norms',
],
eco:[
['SAM','consumes attention output, produces next-state vector'],
['Swarm consensus','per-node next-state goes into log-pooling'],
],
flow:'vocab' },
{ id:'f-pocw', num:'F-04', name:'Proof-of-Cognitive-Work',
blurb:'Every transaction is a cognitive query resolved by the swarm. Work proven by the symbolic state hash, not by useless hashing.',
status:{label:'live',cls:'live'},
long:'Bitcoin\'s PoW wastes joules on SHA-256 inversion. CHAINSTATE\'s Proof-of-Cognitive-Work has nodes execute a real inference task (the user\'s query). The work output IS the answer the user paid for. Each node emits a NodeOutput { node_id, symbolic_state[65536], confidence, compute_proof }. The compute_proof is SHA3-256(node_id ‖ query ‖ start_ts ‖ state[:1024]) — cheap to verify, expensive to forge without actually running the model. Reputation rewards accuracy; slashing penalises drift.',
bullets:[
'Useful work — inference, not hashing',
'Compute proof is a SHA3-256 over (node, query, ts, top-1024 dims)',
'Verifiable in <1 ms; forgery requires inference at scale',
'Reputation score gates next-round node selection',
'Slashing on deliberate divergence from consensus',
],
eco:[
['Swarm nodes','submit NodeOutput per query'],
['Consensus','log-pooling over reputation-weighted outputs'],
['Settlement','per-call USDC settlement after consensus reached'],
],
flow:'pocw' },
{ id:'f-pool', num:'F-05', name:'Log-Pooling Bayesian Consensus',
blurb:'Iterative reputation-weighted log-pooling. Converges in 3–7 rounds; convergence threshold 0.95 cosine agreement.',
status:{label:'live',cls:'live'},
long:'Each round: stack node states (k nodes × 65,536), apply log_softmax, weight rows by node reputation, sum → log_consensus. Convert back via exp(log_consensus − logsumexp). Round 2: keep nodes with cosine(state, consensus) > 0.7; recompute. Round 3–7: same. Stop when cosine(consensus_t, consensus_{t-1}) > 0.95. The math is exactly the Bayesian product-of-experts under a flat prior — the consensus is the posterior over all node beliefs, weighted by trust.',
bullets:[
'log P(consensus) = Σᵢ wᵢ · log P(nodeᵢ)',
'Per-round agreement filter at 0.7 cosine',
'Convergence threshold 0.95 cosine vs prior round',
'Hard min participation: 10 nodes; consensus aborts below threshold',
'Gas calculated from (n_nodes × coordination + depth × verification + ms × compute)',
],
eco:[
['PoCW','consumes per-node outputs'],
['Reputation','updated post-consensus based on accuracy vs final state'],
['NWO-ASM','high-depth consensus offloads to PMX quantum substrate'],
],
flow:'pool' },
{ id:'f-rep', num:'F-06', name:'Reputation System',
blurb:'Exponential-moving-average per-node reputation. Reward α·accuracy on >0.8, penalty β·(1-accuracy) on <0.5, γ decay otherwise.',
status:{label:'live',cls:'live'},
long:'Reputation lives in [0, 100] per node. After consensus: cosine similarity vs consensus is the accuracy. Above 0.8 → reward of α·accuracy added (α = 0.1). Below 0.5 → penalty of β·(1 − accuracy) subtracted (β = 0.2). In between → multiply by γ = 0.99 (small decay). Inactive >24h → also decayed. Top-N selection per query is reputation-weighted top-K with a small ε-greedy random sample to give new nodes a chance.',
bullets:[
'Reputation ∈ [0, 100], default 50 for new nodes',
'α = 0.1 (reward) · β = 0.2 (penalty) · γ = 0.99 (decay)',
'Per-call top-K selection with ε-greedy exploration',
'Inactive >24h triggers decay-only updates',
'Historical accuracy_history maintained per node',
],
eco:[
['Pool','consumes reputations to weight log-pool'],
['$STATE','stake amount caps maximum reputation',],
['Beacon','reputations published in node list',],
],
flow:'rep' },
{ id:'f-txn', num:'F-07', name:'Cognitive Transactions',
blurb:'A transaction IS a cognitive query. Sender + nonce + query + gas_price + max_gas. Hash is SHA3 over the bundle.',
status:{label:'live',cls:'live'},
long:'CognitiveTransaction { hash, sender, query, nonce, gas_price, max_gas, ts, result, receipt }. Hash = SHA3-256(sender ‖ nonce ‖ query ‖ ts)[:16]. Receipt is populated after consensus. The mempool is just a Redis sorted set keyed by (gas_price, ts). A block proposer pulls the top-N transactions, dispatches each to the swarm, collects consensus results, and bundles the block. No mining; the proposer is rotated by reputation-weighted VRF.',
bullets:[
'Query string is the full transaction payload',
'Per-byte gas pricing — no scarcity, only useful compute',
'EIP-155 chain_id binding for Base mainnet (8453)',
'Receipt includes consensus_state, participating_nodes, depth, ms',
'Replay protection via (sender, nonce) uniqueness',
],
eco:[
['Block','transactions bundle into blocks via proposer rotation'],
['NWO Capital','same wallet, same USDC gateway as all NWO services'],
['Mempool','Redis-backed priority queue'],
],
flow:'txn' },
{ id:'f-block', num:'F-08', name:'Block Production',
blurb:'Reputation-weighted VRF selects the proposer. 2-second block target. Block = batch of cognitive transactions + consensus receipts.',
status:{label:'beta',cls:'beta'},
long:'A new block every ~2 s. Proposer chosen by VRF seeded with (prev_hash, round) and weighted by reputation. The proposer pulls up to 64 transactions from the mempool, dispatches each to the swarm (parallel), waits for consensus or timeout (30 s per query), and assembles the block. Block = { parent_hash, height, timestamp, proposer_id, txs[64], receipts[64], consensus_root, signature }. Soft finality at 1 confirmation; hard finality at 6 confirmations (~12 s).',
bullets:[
'2 s target block time',
'64 transactions per block hard cap',
'Proposer rotation via reputation-weighted VRF',
'Soft finality at 1 confirmation, hard at 6',
'Block signed with proposer\'s Dilithium key',
],
eco:[
['Mempool','source of pending transactions'],
['Consensus','consumed for receipt assembly'],
['SCAN','blocks indexed and visualised on the explorer'],
],
flow:'block' },
{ id:'f-stake', num:'F-09', name:'$STATE Staking',
blurb:'Stake $STATE to run an inference node. Stake caps reputation; slashable on misbehaviour. Rewards proportional to accurate participation.',
status:{label:'beta',cls:'beta'},
long:'$STATE is the network gas token (also the staking token). Minimum stake to run a node: 1,000 $STATE. Stake caps reputation at min(stake/10, 100). Slashing conditions: (a) signed but didn\'t respond → 1% slash, (b) responded incorrectly outside 3σ of consensus → 5% slash, (c) signed conflicting outputs → 100% slash. Rewards: per-call USDC fees split 70% to participating nodes (by reputation), 20% to treasury, 10% to the proposer. $STATE itself emits at 2% APY to active stakers, decaying to 0% over 10 years.',
bullets:[
'Min stake: 1,000 $STATE',
'Reputation cap = min(stake / 10, 100)',
'Slashing: 1% (no-show), 5% (incorrect), 100% (conflicting)',
'USDC fee split: 70% nodes / 20% treasury / 10% proposer',
'$STATE emission: 2% → 0% APY over 10 years',
],
eco:[
['Reputation','staked nodes have higher reputation cap'],
['NWO Capital','USDC settlement on Base mainnet'],
['Affiliates','15% atomic referrer split on every paid call'],
],
flow:'stake' },
{ id:'f-asm', num:'F-10', name:'NWO-ASM Bridge',
blurb:'Symbolic operations compile to Process-Matrix IR (.pmx) and dispatch via the NWO-ASM substrate. Same gateway, same key, same audit.',
status:{label:'beta',cls:'beta'},
long:'NWO-ASM is the Anthropic-architecture-language assembler that turns abstract symbolic operations into typed dataflow programs (Process-Matrix IR, .pmx) and dispatches them across heterogeneous substrates — GPU, photonic, neuromorphic, quantum. CHAINSTATE\'s consensus is a perfect customer: a 64-head attention over 65,536 dims is a textbook PMX program. The ASM bridge takes the SymbolicAttention module, emits PMX, ships to the highest-rated available compute. For high-depth (>5 rounds) consensus, the bridge offloads to quantum substrates when available.',
bullets:[
'asm_compile_dispatch — symbolic ops to .pmx IR',
'PMX algebra over typed dataflow graphs',
'8 substrate connectors: GPU, TPU, photonic, neuromorphic, IBM QC, Origin QC, BCI, robotic',
'High-depth consensus auto-routes to quantum when stake > 10K $STATE',
'Same NWO_API_KEY, same USDC billing, same Dilithium audit trail',
],
eco:[
['Consensus','high-depth rounds offload via ASM'],
['Quantum offload','IBM Sherbrooke / Origin Wukong / etc'],
['NWO Capital','shared gateway nwo-capital-api.onrender.com'],
],
flow:'asm' },
{ id:'f-neuro', num:'F-11', name:'NWO NEURO Bridge',
blurb:'Live MSS conditioning. Operator focus / valence / arousal / load / intent flow into the query as additional context dimensions.',
status:{label:'beta',cls:'beta'},
long:'When the caller is connected to a NEURO-paired EEG device, their live Mental State Signature (focus, valence, arousal, cognitive load, intent vector) is signed and travels with the cognitive transaction. The swarm conditions the symbolic state lookup on MSS — high load triggers explain-mode (more diagrams, simpler symbols); high focus enables deep math/science routing; high arousal weights the gamma/emoji subspaces; volatile intent triggers a focus-restore UI. Same NEURO Dilithium signature; same SHA3 identity commitment.',
bullets:[
'Live MSS conditioning of the 65,536-d embedding',
'Focus, valence, arousal, load, intent — 5 scalars + 4096-d residual',
'Dilithium-signed; binds to the transaction\'s sender',
'Cardio-Neuro identity commitment used as proof-of-personhood',
'Sovereignty Protocol gates which device class can dispatch (non-invasive only for full citizenship)',
],
eco:[
['NWO NEURO','EEG → MSS pipeline'],
['NWO Cardiac','ECG fingerprint for dual-biometric identity'],
['Cognitive Audit Trail','high-stress decisions trigger disjoint review'],
],
flow:'neuro' },
{ id:'f-quantum', num:'F-12', name:'Quantum Offload',
blurb:'Optimisation, search, and simulation primitives in high-depth consensus rounds compile to quantum circuits via NWO-ASM.',
status:{label:'design',cls:'design'},
long:'Three classes of symbolic operation get quantum advantage: (a) optimisation of the λ synergy parameter in log-pooling — quantum annealing on an Ising encoding; (b) search over reputation rankings — Grover\'s algorithm with reputation as the marked-state oracle; (c) symbolic path-integral simulation — Hamiltonian sim of the symbolic state evolution. Backends: IBM Sherbrooke (127 qubits, falcon r5) and Origin Quantum Wukong (72 qubits, superconducting). Falls back to classical when no QC available or stake < 10K $STATE.',
bullets:[
'Quantum annealing for λ synergy optimisation',
'Grover search over reputation rankings',
'Hamiltonian simulation for symbolic path integrals',
'IBM Sherbrooke + Origin Wukong + fallback classical',
'Stake-gated — 10,000 $STATE minimum for quantum routing',
],
eco:[
['NWO-ASM','compiles symbolic ops to quantum circuits'],
['Consensus','high-depth rounds use quantum when available'],
['Cryptography','Kyber-1024 KEM + Dilithium signing across QC links'],
],
flow:'quantum' },
{ id:'f-edge', num:'F-13', name:'Edge Dispatcher (Cloudflare Worker)',
blurb:'Single-file Cloudflare Worker handling query dispatch, beacon protocol, consensus coordination, and result caching.',
status:{label:'live',cls:'live'},
long:'A single-file Cloudflare Worker that fronts the entire chain. Routes: /query (POST a cognitive query, fan out to swarm, reach consensus, return result); /beacon (POST node registration, GET active node list); /consensus (GET current consensus state); /status (GET network health); /symbols (GET symbolic-register samples). KV namespaces: CHAINSTATE_NODES (live nodes), CHAINSTATE_CACHE (5-min result cache), CHAINSTATE_CONSENSUS (current state). Rate limit 60 req/min per IP. CORS open.',
bullets:[
'Single edge-worker.js file — deploys via wrangler in <5 s',
'KV: CHAINSTATE_NODES, CHAINSTATE_CACHE, CHAINSTATE_CONSENSUS',
'5-minute result cache, 60 req/min/IP rate limit',
'Routes: /query, /beacon, /consensus, /status, /symbols',
'CORS open; usable from any HF Space frontend',
],
eco:[
['Swarm','dispatches per-query to active node endpoints'],
['Cache','keys are hashed query; results cached for 5 min'],
['SCAN','reads cache and node KV for live block/tx feed'],
],
flow:'edge' },
{ id:'f-beacon', num:'F-14', name:'Swarm Beacon Protocol',
blurb:'Nodes register themselves and report status. The beacon maintains a live KV of {node_id, reputation, capabilities, endpoint, region}.',
status:{label:'live',cls:'live'},
long:'On startup, every swarm node POSTs to /beacon with { node_id, reputation, capabilities, endpoint, dilithium_pubkey }. The Worker writes to CHAINSTATE_NODES KV with a 5-min TTL. Nodes ping every 60 s to refresh; stale entries auto-expire. GET /beacon returns the active node list sorted by reputation. Capabilities is a string list — "embedding", "attention", "quantum", "neuro_mss" — and dispatch only sends a query to nodes that report the required capability.',
bullets:[
'POST /beacon for registration + heartbeat',
'GET /beacon for active node list (reputation-sorted)',
'5-minute TTL on inactivity → auto-deregister',
'Capability tags filter dispatch (e.g. quantum-only)',
'Region field tracks CF colo for latency-aware routing',
],
eco:[
['Edge dispatcher','reads beacon list to select dispatch targets'],
['Reputation','reputation field updated by consensus outcomes'],
['SCAN','beacon list visualised as live network map'],
],
flow:'beacon' },
{ id:'f-cache', num:'F-15', name:'Result Caching',
blurb:'5-minute LRU cache on KV. Hashed query key. Cuts cost ~85% on repeated queries. Bypassable with cache:false flag.',
status:{label:'live',cls:'live'},
long:'Identical queries hit a Cloudflare KV cache for 5 minutes. Key = SHA3-256(query). Value = full JSON response including consensus_state, participating_nodes, gas. Bypass with `cache: false` in the request body. Useful for deterministic queries (math, lookups) where multiple users benefit from one inference. For non-deterministic queries (creative writing, news) the caller should set cache:false; otherwise the cache wins 85% of the time and the chain settles much cheaper.',
bullets:[
'5-minute TTL on Cloudflare KV',
'Key = SHA3-256(query); Value = full consensus response',
'Bypass with cache:false in the request body',
'85% hit-rate on deterministic queries in testnet',
'Per-call USDC charge skipped on cache hit (just CF egress)',
],
eco:[
['Edge dispatcher','checks cache first; returns directly on hit'],
['Settlement','no USDC charge on cache hit'],
['SCAN','X-Cache: HIT/MISS header visible on every tx'],
],
flow:'cache' },
{ id:'f-market', num:'F-16', name:'DApp Marketplace',
blurb:'Apps built on CHAINSTATE list on the marketplace. ERC-1155 listings, 15% perpetual creator royalty, same splitter as NWO-ASM.',
status:{label:'design',cls:'design'},
long:'Anything built on the CHAINSTATE API can be listed: a calculator DApp that solves symbolic integrals via the swarm; a tarot reader that interprets ☉☽☿ over the occult subspace; a Mandarin tutor that uses the language subspace for adaptive grading. Each app mints as ERC-1155, originator commitment travels in metadata, 15% perpetual royalty under EIP-2981. Same splitter (`0x93a7…1BE4`) as NWO-ASM, METASTATE, NEURO, Cardiac. Cross-discovery surfaces via the NWO Marketplace.',
bullets:[
'ERC-1155 listing per DApp',
'15% perpetual creator royalty (EIP-2981)',
'Originator commitment in token metadata',
'Shared splitter — `0x93a7962f75475b7e3Fbb62d3A23194f8833b1BE4`',
'Cross-discoverable across NWO Marketplace',
],
eco:[
['NWO Marketplace','primary discovery surface'],
['Affiliates','15% affiliate stacks with 15% creator royalty'],
['NWO-ASM','marketplace contracts reuse ASM L6 listing primitives'],
],
flow:'market' },
];
/* ============================================================
PAGE ORDER + ROUTING
============================================================ */
const PAGE_ORDER = [
{id:'home', label:'Home'},
{id:'explorer', label:'SCAN'},
{id:'query', label:'Query'},
{id:'terminal', label:'Terminal'},
{id:'symbols', label:'Symbols'},
...FEATURES.map(f=>({id:f.id,label:f.name})),
{id:'architecture', label:'Architecture'},
{id:'instructions', label:'Instructions'},
{id:'roadmap', label:'Roadmap'},
{id:'api', label:'API'},
{id:'rnd', label:'R&D'},
{id:'deployment', label:'Deploy'},
{id:'affiliates', label:'Affiliates'},
];
function pageIndex(id){ const i = PAGE_ORDER.findIndex(p=>p.id===id); return i<0?0:i; }
function goto(id, dir){
if(!id) id='home';
const next = document.querySelector('.page[data-page="'+id+'"]');
if(!next) return;
const cur = document.querySelector('.page.active');
if(cur === next) return;
let leftExit = 'exit-left';
if(dir === 'prev'){
leftExit = 'exit-right';
next.classList.add('enter-left');
requestAnimationFrame(()=>next.classList.remove('enter-left'));
}
if(cur){
cur.classList.remove('active');
cur.classList.add(leftExit);
setTimeout(()=>cur.classList.remove(leftExit), 600);
}
next.classList.add('active');
document.querySelectorAll('.nav-item, .nav-dd a').forEach(a=>a.classList.remove('active'));
document.querySelectorAll('[data-link="'+id+'"]').forEach(a=>a.classList.add('active'));
// close any open dropdown after navigation
document.querySelectorAll('.nav-group.open').forEach(g=>g.classList.remove('open'));
document.getElementById('topbar').classList.remove('menu-open');
if(history && history.replaceState) history.replaceState(null, '', '#'+id);
window.scrollTo({top:0, behavior:'auto'});
if(id === 'api'){ setTimeout(()=>{ if(typeof sizeCalls==='function') sizeCalls(); if(typeof refreshApiMode==='function') refreshApiMode(); }, 400); }
}
window.goto = goto;
function gotoIndex(i){
i = Math.max(0, Math.min(PAGE_ORDER.length-1, i));
const cur = document.querySelector('.page.active');
const curId = cur ? cur.getAttribute('data-page') : 'home';
const curIdx = pageIndex(curId);
const dir = i < curIdx ? 'prev' : 'next';
goto(PAGE_ORDER[i].id, dir);
}
function gotoNext(){ const cur = document.querySelector('.page.active'); const i = pageIndex(cur?cur.getAttribute('data-page'):'home'); gotoIndex(i+1); }
function gotoPrev(){ const cur = document.querySelector('.page.active'); const i = pageIndex(cur?cur.getAttribute('data-page'):'home'); gotoIndex(i-1); }
document.addEventListener('click', (e)=>{
const a = e.target.closest('[data-link]');
if(a){
e.preventDefault();
const id = a.getAttribute('data-link');
const cur = document.querySelector('.page.active');
const curId = cur ? cur.getAttribute('data-page') : 'home';
const dir = pageIndex(id) < pageIndex(curId) ? 'prev' : 'next';
goto(id, dir);
}
});
window.addEventListener('hashchange', ()=>{ goto((location.hash||'').replace('#','')); });
document.getElementById('burger').addEventListener('click', ()=>{
document.getElementById('topbar').classList.toggle('menu-open');
});
(function(){
// Both dropdowns: chevron toggles, label-with-data-link still navigates.
// Opening one closes the other.
function wireGroup(id){
const grp = document.getElementById(id);
if(!grp) return;
const chev = grp.querySelector('.nav-item .chev');
if(chev){
chev.addEventListener('click', (e)=>{
e.stopPropagation();
e.preventDefault();
const wasOpen = grp.classList.contains('open');
document.querySelectorAll('.nav-group.open').forEach(g=>g.classList.remove('open'));
if(!wasOpen) grp.classList.add('open');
});
}
// For groups whose .nav-item has no data-link (features), clicking
// the whole label also toggles. For Home (which has data-link), only
// the chevron toggles; the label navigates as expected.
const labelLink = grp.querySelector('.nav-item');
if(labelLink && !labelLink.hasAttribute('data-link')){
labelLink.addEventListener('click', (e)=>{
e.stopPropagation();
const wasOpen = grp.classList.contains('open');
document.querySelectorAll('.nav-group.open').forEach(g=>g.classList.remove('open'));
if(!wasOpen) grp.classList.add('open');
});
}
grp.querySelectorAll('.nav-dd a').forEach(a=>{
a.addEventListener('click', ()=>{ setTimeout(()=>grp.classList.remove('open'), 50); });
});
}
wireGroup('home-group');
wireGroup('features-group');
// Click anywhere outside a nav-group → close all dropdowns
document.addEventListener('click', (e)=>{
if(!e.target.closest('.nav-group')){
document.querySelectorAll('.nav-group.open').forEach(g=>g.classList.remove('open'));
}
});
})();
let touchStartX=0, touchStartY=0, touchActive=false;
document.addEventListener('touchstart', (e)=>{
if(!e.touches.length) return;
touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; touchActive = true;
}, {passive:true});
document.addEventListener('touchend', (e)=>{
if(!touchActive) return; touchActive=false;
const t = e.changedTouches[0]; if(!t) return;
const dx = t.clientX - touchStartX; const dy = t.clientY - touchStartY;
if(Math.abs(dx) > 70 && Math.abs(dx) > Math.abs(dy)*1.4){
const target = e.target;
if(target && target.closest && target.closest('.modal-bg.open')) return;
if(target && target.closest && target.closest('textarea')) return;
if(dx < 0) gotoNext(); else gotoPrev();
}
}, {passive:true});
document.addEventListener('keydown', (e)=>{
if(document.querySelector('.modal-bg.open')) return;
if(e.target && e.target.matches && (e.target.matches('input,textarea'))) return;
if(e.key==='ArrowRight'){ gotoNext(); }
else if(e.key==='ArrowLeft'){ gotoPrev(); }
else if(e.key==='Home'){ goto('home'); }
});
/* ============================================================
BAND LEGEND on home page
============================================================ */
function renderBandLegend(){
const root = document.getElementById('band-legend');
if(!root) return;
root.innerHTML = Object.entries(SUBSPACES).map(([k,s])=>`
<div class="band-card" data-band="${k}" onclick="goto('symbols')">
<div class="band-card-name">
<span class="glyph" style="color:${s.col}">${s.glyph}</span>
<span>${s.name}</span>
<span class="rng">${s.dims}d</span>
</div>
<div class="band-card-samples">${s.samples.slice(0,8).join(' ')}</div>
<div class="band-card-state">range ${s.range}</div>
</div>
`).join('');
}
</script>
<script>
/* ============================================================
HERO CANVAS — blockchain data-flow visualisation
Nodes = swarm members; pulses = transactions flowing; symbols rain
between blocks. Hover a node to see its summary.
============================================================ */
const hero = document.getElementById('hero');
const heroCanvas = document.getElementById('hero-canvas');
const hctx = heroCanvas.getContext('2d');
let hw=0, hh=0;
let dpr = Math.min(window.devicePixelRatio||1, 2);
function sizeHero(){
dpr = Math.min(window.devicePixelRatio||1, 2);
hw = hero.clientWidth; hh = hero.clientHeight;
heroCanvas.width = hw*dpr; heroCanvas.height = hh*dpr;
heroCanvas.style.width = hw+'px'; heroCanvas.style.height = hh+'px';
hctx.setTransform(dpr,0,0,dpr,0,0);
}
// ─────────────────────────────────────────────────────────────────
// HERO — Infinity-symbol blockchain visualization
// Lemniscate of Bernoulli: x = a·cos(t)/(1+sin²t), y = a·sin(t)·cos(t)/(1+sin²t)
// Nodes sit at evenly-spaced t along the curve. Pulses ride t with
// individual speeds. A shimmering phase-wave runs around the figure-8
// continuously. Behind it, symbols flicker like vacuum fluctuations.
// ─────────────────────────────────────────────────────────────────
let nodes=[], pulses=[], qFluct=[];
const HERO_SYMS = ['∫','∂','∇','∑','∏','ℏ','ℵ','α','β','γ','δ','θ','λ','π','σ','φ','ψ','ω','一','二','道','心','智','☉','☽','♂','♀','⚛','🧬','🔮','⛓','⚡','🧠','🔬','⇒','↺','⟳','∞','⊕','⊗','≈','∈','⊂','∀','∃'];
const HERO_TINTS = [
{r:125,g:240,b:168}, // green · math
{r:122,g:208,b:255}, // blue · science
{r:240,g:224,b:125}, // yellow · language
{r:164,g:140,b:255}, // purple · occult
{r:255,g:140,b:184}, // pink · emoji
{r:233,g:233,b:238}, // off-w · control
];
function tintRgba(t, a){ return `rgba(${t.r},${t.g},${t.b},${a})`; }
const INF = { cx:0, cy:0, ax:0, ay:0, N_NODES:36, CURVE_RES:240, PULSE_COUNT:6 };
function infPoint(t){
const s = Math.sin(t), c = Math.cos(t);
const d = 1 + s*s;
return { x: INF.cx + INF.ax * c / d, y: INF.cy + INF.ay * s * c / d };
}
function buildHero(){
// Center + scale of the figure-8. ax is horizontal extent (the two loops),
// ay is vertical (the loop height). Aspect tweak so it doesn't get squashed
// tall on narrow screens.
INF.cx = hw / 2;
INF.cy = hh / 2;
INF.ax = Math.min(hw * 0.40, 520);
INF.ay = Math.min(hh * 0.32, INF.ax * 0.50);
nodes = [];
pulses = [];
qFluct = [];
for(let i=0; i<INF.N_NODES; i++){
const t = (i / INF.N_NODES) * Math.PI * 2;
const p = infPoint(t);
nodes.push({
t, x:p.x, y:p.y,
r: 2 + Math.random()*2.2,
rep: 30 + Math.random()*70,
tint: HERO_TINTS[Math.floor(Math.random()*HERO_TINTS.length)],
kind: Math.random() < 0.18 ? 'quantum' : 'classical',
lastFire: -Infinity,
});
}
// Six pulses, scattered around the curve, each with its own speed
for(let i=0; i<INF.PULSE_COUNT; i++){
pulses.push({
t: (i / INF.PULSE_COUNT) * Math.PI * 2,
speed: 0.55 + Math.random()*0.55, // rad/sec base
sym: HERO_SYMS[Math.floor(Math.random()*HERO_SYMS.length)],
tint: HERO_TINTS[Math.floor(Math.random()*HERO_TINTS.length)],
trail: [],
});
}
}
let mouseH = {x:0, y:0, active:false};
hero.addEventListener('mousemove', e=>{
const r = hero.getBoundingClientRect();
mouseH.x = e.clientX - r.left; mouseH.y = e.clientY - r.top; mouseH.active = true;
});
hero.addEventListener('mouseleave', ()=>mouseH.active=false);
let tH = 0, lastFrame = performance.now(), lastFluct = 0;
function heroFrame(){
const now = performance.now();
const dt = Math.min(0.06, (now - lastFrame) / 1000);
lastFrame = now;
tH += dt;
// ── background ──────────────────────────────────────────────
hctx.clearRect(0, 0, hw, hh);
const bg = hctx.createRadialGradient(INF.cx, INF.cy, 0, INF.cx, INF.cy, Math.max(hw, hh));
bg.addColorStop(0, '#05050d');
bg.addColorStop(0.45, '#020208');
bg.addColorStop(1, '#000000');
hctx.fillStyle = bg; hctx.fillRect(0, 0, hw, hh);
// ── quantum-fluctuation background symbols ─────────────────
// Pop in, hold briefly, fade out. Very low alpha.
if(tH - lastFluct > 0.04){
lastFluct = tH;
for(let k=0; k<2; k++){
qFluct.push({
x: Math.random()*hw,
y: Math.random()*hh,
sym: HERO_SYMS[Math.floor(Math.random()*HERO_SYMS.length)],
tint:HERO_TINTS[Math.floor(Math.random()*HERO_TINTS.length)],
t0: tH,
life:0.4 + Math.random()*1.6,
amp: 0.05 + Math.random()*0.09,
size:10 + Math.random()*22,
});
}
}
qFluct = qFluct.filter(q => {
const age = tH - q.t0;
if(age >= q.life) return false;
const u = age / q.life;
const a = q.amp * Math.sin(Math.PI * u); // bell-shaped
hctx.fillStyle = tintRgba(q.tint, a);
hctx.font = `${q.size|0}px IBM Plex Mono, monospace`;
hctx.fillText(q.sym, q.x, q.y);
return true;
});
// ── the infinity curve with shimmering phase wave ───────────
// Multi-pass for glow. Phase advances over time so the bright band runs.
const phase = tH * 1.2;
const STEPS = INF.CURVE_RES;
// 1) faint base ring
hctx.beginPath();
for(let i=0; i<=STEPS; i++){
const t = (i / STEPS) * Math.PI * 2;
const p = infPoint(t);
if(i===0) hctx.moveTo(p.x, p.y);
else hctx.lineTo(p.x, p.y);
}
hctx.strokeStyle = 'rgba(255,255,255,0.10)';
hctx.lineWidth = 1.2;
hctx.stroke();
// 2) segments coloured by phase wave — small overlapping arcs
for(let i=0; i<STEPS; i++){
const t = (i / STEPS) * Math.PI * 2;
const tn = ((i+1) / STEPS) * Math.PI * 2;
const p = infPoint(t), q = infPoint(tn);
const a = 0.04 + 0.42 * Math.max(0, Math.sin(t * 2 - phase * 2));
hctx.beginPath();
hctx.moveTo(p.x, p.y);
hctx.lineTo(q.x, q.y);
hctx.strokeStyle = `rgba(255,255,255,${a})`;
hctx.lineWidth = 1.4 + a*1.3;
hctx.stroke();
}
// 3) second offset wave for layered shimmer
for(let i=0; i<STEPS; i++){
const t = (i / STEPS) * Math.PI * 2;
const tn = ((i+1) / STEPS) * Math.PI * 2;
const p = infPoint(t), q = infPoint(tn);
const a = 0.05 * Math.max(0, Math.sin(t * 3 - phase * 1.7 + 1.2));
if(a < 0.005) continue;
hctx.beginPath();
hctx.moveTo(p.x, p.y); hctx.lineTo(q.x, q.y);
hctx.strokeStyle = `rgba(150,210,255,${a*1.5})`;
hctx.lineWidth = 0.8;
hctx.stroke();
}
// ── pulses travelling along the curve ───────────────────────
for(const pl of pulses){
pl.t = (pl.t + pl.speed * dt) % (Math.PI * 2);
const p = infPoint(pl.t);
// Trail: keep last 14 positions
pl.trail.push({x:p.x, y:p.y});
if(pl.trail.length > 14) pl.trail.shift();
// Fire any nodes whose t is within delta of pulse.t (wrap-aware)
const D = 0.08;
for(const n of nodes){
let diff = Math.abs(((pl.t - n.t + Math.PI) % (Math.PI*2)) - Math.PI);
if(diff < D && tH - n.lastFire > 0.18){
n.lastFire = tH;
}
}
// Draw trail
for(let k=0; k<pl.trail.length; k++){
const tp = pl.trail[k];
const u = k / pl.trail.length;
hctx.fillStyle = tintRgba(pl.tint, 0.45 * u);
hctx.beginPath(); hctx.arc(tp.x, tp.y, 1.4, 0, Math.PI*2); hctx.fill();
}
// Glow head
const g = hctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, 18);
g.addColorStop(0, tintRgba(pl.tint, 0.85));
g.addColorStop(0.4, tintRgba(pl.tint, 0.45));
g.addColorStop(1, tintRgba(pl.tint, 0));
hctx.fillStyle = g;
hctx.beginPath(); hctx.arc(p.x, p.y, 18, 0, Math.PI*2); hctx.fill();
// Bright core
hctx.fillStyle = tintRgba(pl.tint, 1);
hctx.beginPath(); hctx.arc(p.x, p.y, 2.6, 0, Math.PI*2); hctx.fill();
// Riding symbol
hctx.fillStyle = tintRgba(pl.tint, 0.92);
hctx.font = 'bold 12px IBM Plex Mono, monospace';
hctx.fillText(pl.sym, p.x + 6, p.y - 6);
}
// ── nodes on the curve ──────────────────────────────────────
for(let i=0; i<nodes.length; i++){
const n = nodes[i];
const dtFire = tH - n.lastFire;
const flash = dtFire < 0.5 ? Math.pow(1 - dtFire/0.5, 1.4) : 0;
if(flash > 0){
// outer glow on fire
const fg = hctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, 28 * flash + 6);
fg.addColorStop(0, tintRgba(n.tint, 0.7 * flash));
fg.addColorStop(0.6, tintRgba(n.tint, 0.25 * flash));
fg.addColorStop(1, tintRgba(n.tint, 0));
hctx.fillStyle = fg;
hctx.beginPath(); hctx.arc(n.x, n.y, 28 * flash + 6, 0, Math.PI*2); hctx.fill();
}
// hover glow
if(mouseH.active){
const md = Math.hypot(mouseH.x - n.x, mouseH.y - n.y);
if(md < 110){
const a = (1 - md/110) * 0.45;
const mg = hctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, 16);
mg.addColorStop(0, `rgba(255,255,255,${a})`);
mg.addColorStop(1, 'rgba(255,255,255,0)');
hctx.fillStyle = mg;
hctx.beginPath(); hctx.arc(n.x, n.y, 16, 0, Math.PI*2); hctx.fill();
}
if(md < 22){
const label = `node-${i.toString().padStart(3,'0')} · rep ${n.rep.toFixed(1)} · ${n.kind}`;
hctx.font = '10px IBM Plex Mono, monospace';
const tw = hctx.measureText(label).width + 12;
hctx.fillStyle = 'rgba(0,0,0,0.85)';
hctx.fillRect(n.x + 12, n.y - 26, tw, 18);
hctx.fillStyle = '#fff';
hctx.fillText(label, n.x + 18, n.y - 13);
}
}
// The node itself
const baseA = 0.55 + flash * 0.45;
const r = n.r + flash * 1.8;
if(n.kind === 'quantum'){
hctx.fillStyle = `rgba(164,140,255,${baseA})`;
} else {
hctx.fillStyle = `rgba(255,255,255,${baseA})`;
}
hctx.beginPath(); hctx.arc(n.x, n.y, r, 0, Math.PI*2); hctx.fill();
}
// ── center crossing point — a focal node at (cx, cy) ────────
// The figure-8 crosses itself at the center; mark it.
const cphase = (Math.sin(tH * 2.1) + 1) * 0.5;
const cgrad = hctx.createRadialGradient(INF.cx, INF.cy, 0, INF.cx, INF.cy, 12 + cphase * 4);
cgrad.addColorStop(0, `rgba(255,255,255,${0.35 + cphase*0.30})`);
cgrad.addColorStop(0.6, 'rgba(255,255,255,0.08)');
cgrad.addColorStop(1, 'rgba(255,255,255,0)');
hctx.fillStyle = cgrad;
hctx.beginPath(); hctx.arc(INF.cx, INF.cy, 12 + cphase * 4, 0, Math.PI*2); hctx.fill();
hctx.fillStyle = 'rgba(255,255,255,0.9)';
hctx.beginPath(); hctx.arc(INF.cx, INF.cy, 1.6, 0, Math.PI*2); hctx.fill();
requestAnimationFrame(heroFrame);
}
window.addEventListener('resize', ()=>{ sizeHero(); buildHero(); });
/* ============================================================
CHAINSTATE SCAN — block explorer page
============================================================ */
let blocks = [], txs = [];
function seedScan(){
blocks = []; txs = [];
const now = Math.floor(Date.now()/1000);
for(let i=0;i<50;i++){
const h = now - i*2;
blocks.push({
height: 12480 - i,
hash: '0x'+Math.random().toString(16).slice(2,10)+Math.random().toString(16).slice(2,10),
proposer: 'node-'+Math.floor(Math.random()*40).toString().padStart(3,'0'),
txn_count: Math.floor(Math.random()*50)+4,
gas_used: (Math.random()*2.4+0.3).toFixed(4),
time: h,
});
}
for(let i=0;i<60;i++){
const t = now - i*1;
const SYMS_EX = ['∫∂x/∂t', '☉☽☿ in alchemy', 'F=ma', '🧬→protein', '一二三四五', 'Σ(1/n²)', '∇×B=μ₀J', '♂♀ Mars Venus', '⚛ ⇒ E=mc²', 'tr(ρ²)', 'π × e × i', 'Δψ in QM', '☥☦☪ unity', 'arg max f(x)', '🔮⇒🌐'];
txs.push({
hash: '0x'+Math.random().toString(16).slice(2,10)+Math.random().toString(16).slice(2,10),
from: '0x'+Math.random().toString(16).slice(2,10),
query: SYMS_EX[Math.floor(Math.random()*SYMS_EX.length)],
gas: (Math.random()*0.015+0.001).toFixed(5),
confidence: (0.7+Math.random()*0.29).toFixed(3),
time: t,
});
}
}
function relTime(ts){
const d = Math.floor(Date.now()/1000) - ts;
if(d<60) return d+'s ago';
if(d<3600) return Math.floor(d/60)+'m ago';
if(d<86400) return Math.floor(d/3600)+'h ago';
return Math.floor(d/86400)+'d ago';
}
function renderExplorer(){
const root = document.querySelector('.page[data-page="explorer"]');
if(!root) return;
if(!blocks.length) seedScan();
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · CHAINSTATE SCAN</div>
<h1>SCAN · Block Explorer</h1>
<p class="lede">Live feed of the symbolic-weight chain. Each block is a batch of cognitive transactions; each transaction is a query resolved by the swarm. Click any block or tx for the full receipt — consensus state vector, participating nodes, confidence distribution, gas breakdown.</p>
<div class="meta-row">
<span class="pill live"><span class="dot"></span>Base mainnet · 8453</span>
<span class="pill live"><span class="dot"></span>2 s block time</span>
<span class="pill beta"><span class="dot"></span>SCAN beta</span>
${csModeToggle()}
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="scan-stat-grid">
<div class="scan-stat"><div class="v" id="ss-height">${blocks[0].height.toLocaleString()}</div><div class="l">block height</div></div>
<div class="scan-stat"><div class="v" id="ss-tps">${(Math.random()*8+22).toFixed(1)}</div><div class="l">tx / s</div></div>
<div class="scan-stat"><div class="v" id="ss-nodes">42</div><div class="l">active nodes</div></div>
<div class="scan-stat"><div class="v" id="ss-gas">${(Math.random()*0.5+0.8).toFixed(3)}</div><div class="l">avg gas · $STATE</div></div>
</div>
</section>
<section class="bare">
<div class="scan-card shim">
<div class="scan-search">
<input id="scan-search" type="text" placeholder="🔍 Search by block height, tx hash, sender address, or query text…">
<button class="ghost sm" onclick="doScanSearch()">Search</button>
</div>
</div>
</section>
<section class="tight">
<div class="scan-grid">
<div class="scan-card shim">
<div class="scan-card-head">
<h3>Latest blocks</h3>
<span class="meta">live · 2 s tick</span>
</div>
<div class="scan-list" id="scan-blocks">
${blocks.slice(0,15).map((b,i)=>`
<div class="scan-row" onclick="openBlock(${b.height})">
<div class="ico bk">BK</div>
<div>
<div class="hash">#${b.height} · ${b.hash}</div>
<div class="sub">proposed by ${b.proposer} · ${b.txn_count} txs · ${relTime(b.time)}</div>
</div>
<div class="v">${b.gas_used} <span class="l">$STATE</span></div>
</div>
`).join('')}
</div>
</div>
<div class="scan-card shim">
<div class="scan-card-head">
<h3>Latest transactions</h3>
<span class="meta">cognitive queries</span>
</div>
<div class="scan-list" id="scan-txs">
${txs.slice(0,15).map(t=>`
<div class="scan-row" onclick="openTx('${t.hash}')">
<div class="ico tx">TX</div>
<div>
<div class="hash">${t.hash} · ${t.query}</div>
<div class="sub">from ${t.from} · conf ${t.confidence} · ${relTime(t.time)}</div>
</div>
<div class="v">${t.gas} <span class="l">$STATE</span></div>
</div>
`).join('')}
</div>
</div>
</div>
</section>
<section class="tight">
<div class="two-col">
<div class="col-card shim">
<h3>What you're looking at</h3>
<p>Every transaction on CHAINSTATE is a cognitive query. The chain doesn't store fungible-token transfers as primitive — those are <em>special-case queries</em> like <code>transfer(0xabc, 100)</code> that the swarm resolves and the consensus layer settles. The receipt for every transaction includes:</p>
<ul>
<li><strong>Consensus state</strong> — the 65,536-d symbolic vector the swarm agreed on</li>
<li><strong>Participating nodes</strong> — list of node_ids with their per-node confidence</li>
<li><strong>Consensus depth</strong> — how many log-pooling rounds it took to converge</li>
<li><strong>Gas breakdown</strong> — base + (n_nodes × coord) + (depth × verify) + (ms × compute)</li>
<li><strong>Dilithium signature</strong> — from the proposer, over the full block</li>
<li><strong>X-Cache</strong> — HIT means served from 5-min KV cache, no fresh inference</li>
</ul>
</div>
<div class="col-card shim">
<h3>Wallet-bound SCAN</h3>
<p>Connect a wallet via the top-right button to filter SCAN to your account: transactions you sent, queries you cached, nodes you stake on, blocks you proposed. The same wallet works across all NWO Capital services — CHAINSTATE here, NWO-ASM, NEURO, Cardiac, METASTATE.</p>
<p>For dev usage, point your client at <code>https://chainstate-worker.&lt;your-cf&gt;.workers.dev</code> after deploying the edge worker. See the <span class="txt-mono" style="cursor:pointer;color:var(--math)" onclick="goto('deployment')">Deploy</span> page for the one-file deploy.</p>
<div class="cta-row">
<button class="ghost" onclick="goto('query')">Run a query</button>
<button class="ghost" onclick="goto('deployment')">Deploy your edge</button>
</div>
</div>
</div>
</section>
</div>`;
// demo ticker — runs in both modes so the page is never blank (no real chain producing blocks yet)
if(window.__scanTimer) clearInterval(window.__scanTimer);
window.__scanTimer = setInterval(()=>{
const now = Math.floor(Date.now()/1000);
blocks.unshift({
height: blocks[0].height+1,
hash: '0x'+Math.random().toString(16).slice(2,10)+Math.random().toString(16).slice(2,10),
proposer: 'node-'+Math.floor(Math.random()*40).toString().padStart(3,'0'),
txn_count: Math.floor(Math.random()*50)+4,
gas_used: (Math.random()*2.4+0.3).toFixed(4),
time: now,
});
if(blocks.length>200) blocks.pop();
const el = document.getElementById('scan-blocks');
const heightEl = document.getElementById('ss-height');
if(el){
el.innerHTML = blocks.slice(0,15).map(b=>`
<div class="scan-row" onclick="openBlock(${b.height})">
<div class="ico bk">BK</div>
<div>
<div class="hash">#${b.height} · ${b.hash}</div>
<div class="sub">proposed by ${b.proposer} · ${b.txn_count} txs · ${relTime(b.time)}</div>
</div>
<div class="v">${b.gas_used} <span class="l">$STATE</span></div>
</div>`).join('');
}
// In DEMO mode the height tile follows the seeded chain. In LIVE mode it
// gets overwritten by the live /status fetcher below.
if(heightEl && (typeof csIsLive !== 'function' || !csIsLive())) {
heightEl.textContent = blocks[0].height.toLocaleString();
}
}, 2200);
// live KPI fetcher — only runs when mode is LIVE and a worker URL is set
if(window.__scanLiveTimer) clearInterval(window.__scanLiveTimer);
const liveFetch = ()=>{
if(typeof csIsLive !== 'function' || !csIsLive()) return;
const w = window.__CHAINSTATE_WORKER;
if(!w) return;
fetch(w+'/status').then(r=>r.json()).then(s=>{
const h = document.getElementById('ss-height');
const t = document.getElementById('ss-tps');
const n = document.getElementById('ss-nodes');
const g = document.getElementById('ss-gas');
if(h && s.height != null) h.textContent = Number(s.height).toLocaleString();
else if(h) h.textContent = '—';
if(t) t.textContent = (s.tps != null) ? Number(s.tps).toFixed(1) : '—';
if(n) n.textContent = (s.nodes_known != null) ? s.nodes_known : '—';
if(g) g.textContent = (s.avg_gas != null) ? Number(s.avg_gas).toFixed(3) : '—';
}).catch(()=>{
['ss-height','ss-tps','ss-nodes','ss-gas'].forEach(id=>{
const e = document.getElementById(id); if(e) e.textContent = '—';
});
});
};
liveFetch();
window.__scanLiveTimer = setInterval(liveFetch, 4000);
}
function openBlock(h){
const b = blocks.find(x=>x.height===h);
if(!b) return;
openModal('Block #'+h, `
<p><strong>Hash:</strong> <code>${b.hash}</code></p>
<p><strong>Proposer:</strong> ${b.proposer}</p>
<p><strong>Time:</strong> ${new Date(b.time*1000).toISOString()} (${relTime(b.time)})</p>
<p><strong>Transactions:</strong> ${b.txn_count}</p>
<p><strong>Gas used:</strong> ${b.gas_used} $STATE</p>
<h4>Consensus root</h4>
<pre class="code">${Array.from({length:8},()=>Math.random().toString(16).slice(2,10)).join(' ')}
${Array.from({length:8},()=>Math.random().toString(16).slice(2,10)).join(' ')}
${Array.from({length:8},()=>Math.random().toString(16).slice(2,10)).join(' ')}
${Array.from({length:8},()=>Math.random().toString(16).slice(2,10)).join(' ')}</pre>
<h4>Block signature (Dilithium FIPS 204)</h4>
<pre class="code">${b.hash.slice(2)}...${'fa9e3c'.repeat(4)}</pre>
<div style="margin-top:14px"><button class="ghost" onclick="closeModal()">Close</button></div>`);
}
function openTx(h){
const t = txs.find(x=>x.hash===h);
if(!t) return;
openModal('Transaction', `
<p><strong>Hash:</strong> <code>${t.hash}</code></p>
<p><strong>From:</strong> <code>${t.from}</code></p>
<p><strong>Query:</strong> <code>${t.query}</code></p>
<p><strong>Confidence:</strong> ${t.confidence}</p>
<p><strong>Gas paid:</strong> ${t.gas} $STATE</p>
<p><strong>Time:</strong> ${new Date(t.time*1000).toISOString()} (${relTime(t.time)})</p>
<h4>Participating nodes (top 5 by reputation)</h4>
<pre class="code">node-${Math.floor(Math.random()*40).toString().padStart(3,'0')} rep 87.3 conf 0.921
node-${Math.floor(Math.random()*40).toString().padStart(3,'0')} rep 82.1 conf 0.918
node-${Math.floor(Math.random()*40).toString().padStart(3,'0')} rep 78.5 conf 0.903
node-${Math.floor(Math.random()*40).toString().padStart(3,'0')} rep 74.2 conf 0.881
node-${Math.floor(Math.random()*40).toString().padStart(3,'0')} rep 70.9 conf 0.872</pre>
<h4>Consensus depth</h4>
<p>${Math.floor(Math.random()*4)+3} rounds · converged at 0.95 cosine</p>
<div style="margin-top:14px"><button class="ghost" onclick="closeModal()">Close</button></div>`);
}
function doScanSearch(){
const q = (document.getElementById('scan-search').value||'').trim();
if(!q){ return; }
if(/^#?\d+$/.test(q)){
const h = parseInt(q.replace('#',''),10);
if(blocks.find(b=>b.height===h)) openBlock(h);
else openModal('Not found', '<p>No block at height '+h+' in the local sample.</p>');
return;
}
if(/^0x[a-f0-9]/.test(q)){
const tx = txs.find(t=>t.hash.startsWith(q));
if(tx) openTx(tx.hash);
else openModal('Not found', '<p>No tx matching <code>'+q+'</code> in the local sample.</p>');
return;
}
// query-text match
const tx = txs.find(t=>t.query.toLowerCase().includes(q.toLowerCase()));
if(tx) openTx(tx.hash);
else openModal('No match', '<p>No tx matching <code>'+q+'</code>.</p>');
}
window.openBlock = openBlock; window.openTx = openTx; window.doScanSearch = doScanSearch;
</script>
<script>
/* ============================================================
QUERY page — live cognitive query against the chain
============================================================ */
function renderQuery(){
const root = document.querySelector('.page[data-page="query"]');
if(!root) return;
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · cognitive transaction</div>
<h1>Run a query</h1>
<p class="lede">Enter any mix of symbols, emojis, math notation, languages, or plain text. The query is dispatched to the live swarm, resolved through reputation-weighted Bayesian consensus, and the result is returned with the consensus state, participating nodes, and gas breakdown. Same wallet flow as every other NWO Capital service.</p>
<div class="meta-row">
<span class="pill live"><span class="dot"></span>edge worker live</span>
<span class="pill beta"><span class="dot"></span>swarm beta</span>
<span class="pill design"><span class="dot"></span>quantum-offload design</span>
${csModeToggle()}
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="query-shell shim shim-slow">
<div class="query-input">
<textarea id="q-text" placeholder="e.g. ∫∂x → ? or Solve ☉☽☿ in alchemy or 🧬🔬⚗ → ? or explain CRDTs"></textarea>
<div class="query-controls">
<div class="query-ctrl">
<label>consensus depth</label>
<input id="q-depth" type="number" value="3" min="1" max="7">
</div>
<div class="query-ctrl">
<label>swarm size</label>
<input id="q-size" type="number" value="20" min="10" max="100">
</div>
<div class="query-ctrl">
<label>quantum offload</label>
<select id="q-quantum"><option value="none">none</option><option value="ibm">IBM Sherbrooke</option><option value="origin">Origin Wukong</option></select>
</div>
<div class="query-ctrl">
<label>cache</label>
<select id="q-cache"><option value="true">use (5-min KV)</option><option value="false">bypass</option></select>
</div>
</div>
<div class="cta-row">
<button class="ghost bold" onclick="runQuery()">⛓ Submit cognitive transaction</button>
<button class="ghost" onclick="symInsert('∫∂x → ?')">Try math</button>
<button class="ghost" onclick="symInsert('☉☽☿ ♀♂ ☯ ☤')">Try occult</button>
<button class="ghost" onclick="symInsert('🧠 🤔 💎 → ✨')">Try emoji</button>
<button class="ghost" onclick="symInsert('道 心 学 智 一 二 三')">Try CJK</button>
</div>
<div class="query-out" id="q-out"><span class="dim">Result will appear here. The chain dispatches your query to the swarm (default 20 nodes), each node emits a 65,536-d symbolic state, the consensus layer log-pools them, and the answer is returned.</span></div>
</div>
</div>
</section>
<section class="tight">
<div class="two-col">
<div class="col-card shim">
<h3>How a query becomes a transaction</h3>
<ul>
<li><strong>Tokenise</strong> — your input is split into Unicode codepoints; each maps to a symbol id in 0..65,535</li>
<li><strong>Embed</strong> — symbols pass through USE → 4096-d slice per symbol → concatenated 65,536-d</li>
<li><strong>Attend</strong> — SAM applies the cross-subspace interaction mask, producing per-node symbolic state</li>
<li><strong>Pool</strong> — log-pooling consensus over reputation-weighted node states</li>
<li><strong>Settle</strong> — gas (≈ base + n_nodes×coord + depth×verify + ms×compute) charged in $STATE/USDC</li>
<li><strong>Receipt</strong> — full receipt committed to the next block via proposer rotation</li>
</ul>
</div>
<div class="col-card shim">
<h3>Gas formula</h3>
<pre class="code">gas = <span class="n">0.001</span> <span class="c"># base</span>
+ <span class="n">n_nodes</span> × <span class="n">0.00001</span> <span class="c"># coordination</span>
+ <span class="n">depth</span> × <span class="n">0.00005</span> <span class="c"># verification</span>
+ <span class="n">execution_ms</span> × <span class="n">0.000001</span> <span class="c"># compute</span></pre>
<p class="txt-sm txt-mute">A typical 20-node, 3-round query at 800 ms costs ≈ 0.0019 $STATE (≈ $0.000019 USDC at current peg).</p>
<h3 style="margin-top:14px">Live JSON response shape</h3>
<pre class="code">{
<span class="s">"query"</span>: <span class="s">"∫∂x → ?"</span>,
<span class="s">"result"</span>: <span class="n">[ ...65536 floats ]</span>,
<span class="s">"top_symbols"</span>: [<span class="s">"=x+C"</span>, <span class="s">"+const"</span>],
<span class="s">"confidence"</span>: <span class="n">0.943</span>,
<span class="s">"participatingNodes"</span>: <span class="n">19</span>,
<span class="s">"consensusDepth"</span>: <span class="n">3</span>,
<span class="s">"executionTime"</span>: <span class="n">823</span>,
<span class="s">"gasUsed"</span>: <span class="n">0.00192</span>,
<span class="s">"timestamp"</span>: <span class="s">"2026-06-21T15:42:11Z"</span>
}</pre>
</div>
</div>
</section>
</div>`;
}
function symInsert(s, prefix){
prefix = prefix || 'q-';
const ta = document.getElementById(prefix+'text');
if(ta){ ta.value = s; ta.focus(); }
}
window.symInsert = symInsert;
function runQuery(prefix){
prefix = prefix || 'q-';
const q = (document.getElementById(prefix+'text').value||'').trim();
const depth = parseInt(document.getElementById(prefix+'depth').value,10) || 3;
const size = parseInt(document.getElementById(prefix+'size').value,10) || 20;
const qpu = document.getElementById(prefix+'quantum').value;
const cache = document.getElementById(prefix+'cache').value === 'true';
const out = document.getElementById(prefix+'out');
if(!q){ out.innerHTML='<span class="dim">type a query first.</span>'; return; }
// The Worker URL is set per-deployment. The DEMO/LIVE toggle decides whether to actually call it.
const workerUrl = window.__CHAINSTATE_WORKER || '';
const liveCall = (typeof csIsLive === 'function') && csIsLive() && !!workerUrl;
out.innerHTML = liveCall
? '<span class="dim">dispatching to live swarm at '+workerUrl+'…</span>'
: '<span class="dim">simulating swarm response · DEMO mode</span>';
if(liveCall){
fetch(workerUrl+'/query', { method:'POST', headers:{'Content-Type':'application/json'},
body: JSON.stringify({ query:q, consensusDepth:depth, swarmSize:size, quantumOffload:qpu==='none'?null:qpu, cache })
})
.then(r=>r.json())
.then(d=>{ renderQueryResult(d, prefix); })
.catch(e=>{ renderQueryResult({error:String(e), simulated:true, ...simulateResponse(q,depth,size,qpu)}, prefix); });
} else {
setTimeout(()=> renderQueryResult({ simulated:true, ...simulateResponse(q,depth,size,qpu) }, prefix), 700 + Math.random()*700);
}
}
window.runQuery = runQuery;
function simulateResponse(q, depth, size, qpu){
const TOPS = {
'∫': ['= x + C', 'antiderivative', '↺'],
'∂': ['gradient', '∇f', 'limit'],
'🧬': ['DNA', 'protein folding', 'CRISPR'],
'☉': ['Sun', 'Sol', 'gold (alchemy)'],
'道': ['the Way', 'tao', 'path'],
'CRDT': ['conflict-free replicated data type', 'eventual consistency', 'commutative ops'],
};
let top = ['symbolic state vector'];
for(const k of Object.keys(TOPS)) if(q.includes(k)){ top = TOPS[k]; break; }
return {
query: q,
top_symbols: top,
confidence: (0.78 + Math.random()*0.20).toFixed(3),
participatingNodes: Math.min(size, Math.floor(size*(0.85+Math.random()*0.14))),
consensusDepth: Math.min(depth, 1+Math.floor(Math.random()*depth)),
executionTime: Math.floor(400 + Math.random()*1100),
gasUsed: (0.001 + size*0.00001 + depth*0.00005 + 800*0.000001).toFixed(6),
timestamp: new Date().toISOString(),
quantumOffload: qpu==='none'?null:{provider:qpu,status:'simulated'},
};
}
function renderQueryResult(d, prefix){
prefix = prefix || 'q-';
const out = document.getElementById(prefix+'out');
if(!out) return;
if(d.error){ out.innerHTML = '<span style="color:#ff8cb8">error: '+d.error+'</span>\n<span class="dim">(simulated fallback shown below)</span>\n\n'; }
else out.innerHTML = '';
const lines = [
['query', JSON.stringify(d.query)],
['top_symbols', JSON.stringify(d.top_symbols||['—'])],
['confidence', d.confidence],
['participatingNodes', d.participatingNodes],
['consensusDepth', d.consensusDepth],
['executionTime', d.executionTime+' ms'],
['gasUsed', d.gasUsed+' $STATE'],
['quantumOffload', JSON.stringify(d.quantumOffload||null)],
['simulated', d.simulated ? 'true (no worker URL set)' : 'false'],
['timestamp', d.timestamp],
];
out.innerHTML += lines.map(([k,v])=>`<span class="key">${k}</span>: <span class="val">${v}</span>`).join('\n');
}
/* ── Home-page UX helpers: collapsible hero + quick-scan jumper ── */
function toggleHomeHero(){
const home = document.querySelector('.page[data-page="home"]');
if(!home) return;
const collapsed = home.classList.toggle('home-collapsed');
try { localStorage.setItem('cs:homeHeroCollapsed', collapsed ? '1' : '0'); } catch(e){}
const lbl = document.querySelector('#home-toggle-btn .lbl');
if(lbl) lbl.textContent = collapsed ? 'Show hero & symbol bands' : 'Hide hero & symbol bands';
}
window.toggleHomeHero = toggleHomeHero;
function homeScanGo(){
const inp = document.getElementById('home-scan-input');
if(!inp) return;
const q = (inp.value||'').trim();
// Navigate to the SCAN (explorer) page and seed its search input
if(typeof goto === 'function') goto('explorer');
setTimeout(()=>{
const scanInp = document.getElementById('scan-search');
if(scanInp){
scanInp.value = q;
if(q && typeof window.doScanSearch === 'function') {
try { window.doScanSearch(); } catch(e){}
}
scanInp.focus();
}
}, 60);
}
window.homeScanGo = homeScanGo;
/* Restore collapsed state on load */
document.addEventListener('DOMContentLoaded', ()=>{
let collapsed = false;
try { collapsed = localStorage.getItem('cs:homeHeroCollapsed') === '1'; } catch(e){}
if(collapsed){
const home = document.querySelector('.page[data-page="home"]');
if(home) home.classList.add('home-collapsed');
const lbl = document.querySelector('#home-toggle-btn .lbl');
if(lbl) lbl.textContent = 'Show hero & symbol bands';
}
});
/* ============================================================
SYMBOLS — full Universal Semiotic Embedding registry
============================================================ */
function renderSymbols(){
const root = document.querySelector('.page[data-page="symbols"]');
if(!root) return;
const tabs = Object.entries(SUBSPACES).map(([k,s])=>`<button class="sym-tab" data-sub="${k}">${s.glyph} ${s.name}</button>`).join('');
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · universal semiotic embedding</div>
<h1>Symbolic Register</h1>
<p class="lede">The 65,536-dimensional symbolic substrate, organised in six subspaces. Each cell is a real position in the embedding; hover for the codepoint, click to copy. The full Unicode 15.1 emoji set, all major writing systems, mathematical operators, scientific glyphs, alchemical sigils, astrological symbols, and control-flow arrows are first-class citizens of the chain's vocabulary.</p>
<div class="meta-row">
<span class="pill live"><span class="dot"></span>65,536 dimensions</span>
<span class="pill live"><span class="dot"></span>6 subspaces</span>
<span class="pill beta"><span class="dot"></span>composition layer beta</span>
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="sym-tabs" id="sym-tabs">${tabs}</div>
<div id="sym-grid-mount"></div>
<div class="sym-info" id="sym-info">
<span class="big" id="sym-info-glyph">·</span>
<div class="meta">
<div id="sym-info-name">Click any symbol to inspect</div>
<div id="sym-info-code">codepoint will appear here</div>
</div>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">how it composes</div><h2>From symbol → state vector</h2></div></div>
<div class="two-col">
<div class="col-card shim">
<h3>Lookup pipeline</h3>
<ol style="padding-left:18px;color:var(--w2)">
<li>Input is split into Unicode codepoints (full UTF-16 surrogate-aware)</li>
<li>Each codepoint maps to a symbol_id ∈ [0, 65,535] via the global vocab table</li>
<li>symbol_id selects a subspace; the local index drives nn.Embedding for that subspace</li>
<li>Per-symbol 1,024-d head vector is concatenated across 64 heads → 65,536-d state</li>
<li>SymbolicAttention applies the cross-subspace interaction mask</li>
<li>Composition gate produces the per-node next-state vector</li>
</ol>
</div>
<div class="col-card shim">
<h3>Subspace interaction mask</h3>
<pre class="code"> math sci lang occ emo ctrl
math 1.0 1.0 0.5 0.1 0.1 0.5
science 1.0 1.0 0.5 0.1 0.1 0.3
language 0.5 0.5 0.7 0.5 0.4 0.5
occult 0.1 0.1 0.5 0.8 0.2 1.0
emoji 0.1 0.1 0.4 0.2 0.3 0.1
control 0.5 0.3 0.5 1.0 0.1 0.9</pre>
<p class="txt-sm txt-mute" style="margin-top:8px">Math ↔ Science is locked. Occult ↔ Control is locked. Language is the universal solvent.</p>
</div>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">reference</div><h2>Subspace sizes &amp; ranges</h2></div></div>
<div class="shim" style="padding:6px 4px;border-radius:14px;overflow:auto">
<table class="horizon-table">
<thead><tr><th>subspace</th><th>glyph</th><th>dimensions</th><th>range</th><th>summary</th></tr></thead>
<tbody>
${Object.entries(SUBSPACES).map(([k,s])=>`
<tr>
<td><span class="name">${s.name}</span></td>
<td style="font-size:1.3em;color:${s.col}">${s.glyph}</td>
<td class="txt-mono">${s.dims.toLocaleString()}</td>
<td class="txt-mono">${s.range}</td>
<td class="rationale">${s.desc}</td>
</tr>`).join('')}
</tbody>
</table>
</div>
</section>
</div>`;
const tabsEl = document.getElementById('sym-tabs');
const mount = document.getElementById('sym-grid-mount');
function renderGrid(sub){
const s = SUBSPACES[sub];
mount.innerHTML = '<div class="sym-grid">'+ s.samples.map(c=>{
const cls = sub==='math'?'sym-math':sub==='sci'?'sym-sci':sub==='lang'?'sym-lang':sub==='occ'?'sym-occ':sub==='emo'?'sym-emo':'sym-ctrl';
return `<div class="sym-cell ${cls}" data-sym="${c.replace(/"/g,'&quot;')}" title="${c} · U+${c.codePointAt(0).toString(16).toUpperCase().padStart(4,'0')}">${c}</div>`;
}).join('') + '</div>';
mount.querySelectorAll('.sym-cell').forEach(cell=>{
cell.addEventListener('click', ()=>{
const c = cell.getAttribute('data-sym');
document.getElementById('sym-info-glyph').textContent = c;
document.getElementById('sym-info-name').textContent = s.name+' subspace';
document.getElementById('sym-info-code').textContent = 'U+'+c.codePointAt(0).toString(16).toUpperCase().padStart(4,'0')+' · subspace_id '+sub;
try{ navigator.clipboard.writeText(c); } catch(e){}
});
});
tabsEl.querySelectorAll('.sym-tab').forEach(t=>t.classList.toggle('on', t.getAttribute('data-sub')===sub));
}
tabsEl.querySelectorAll('.sym-tab').forEach(t=>{
t.addEventListener('click', ()=> renderGrid(t.getAttribute('data-sub')));
});
renderGrid('math');
}
/* ============================================================
TERMINAL — CHAINSTATE shell
============================================================ */
function renderTerminal(){
const root = document.querySelector('.page[data-page="terminal"]');
if(!root) return;
const COMMANDS = [
{ cmd:'help', arg:'', desc:'List all available commands.' },
{ cmd:'connect', arg:'<worker-url>', desc:'Point the terminal at a CHAINSTATE edge worker URL.' },
{ cmd:'status', arg:'', desc:'GET /status — network health, node count, region.' },
{ cmd:'query', arg:'<text>', desc:'POST /query — submit a cognitive query and print the consensus result.' },
{ cmd:'query.async', arg:'<text>', desc:'Submit without blocking; returns the tx hash for later lookup.' },
{ cmd:'symbols', arg:'[subspace]', desc:'GET /symbols — sample symbols from a subspace (math|science|language|occult|emoji|control).' },
{ cmd:'beacon', arg:'', desc:'GET /beacon — list active swarm nodes by reputation.' },
{ cmd:'beacon.register', arg:'<endpoint>', desc:'POST /beacon — register this terminal as a node (demo only).' },
{ cmd:'consensus', arg:'', desc:'GET /consensus — print the current consensus state hash.' },
{ cmd:'block', arg:'<height>', desc:'Look up a block by height on the local SCAN.' },
{ cmd:'tx', arg:'<hash>', desc:'Look up a transaction by hash on the local SCAN.' },
{ cmd:'asm.dispatch', arg:'<prog> <args>', desc:'Submit a Process-Matrix IR (.pmx) program to the NWO-ASM bridge with current MSS conditioning.' },
{ cmd:'asm.compile', arg:'<symbolic-op>', desc:'Compile a symbolic op to PMX IR. Prints the typed dataflow graph.' },
{ cmd:'neuro.bind', arg:'', desc:'Pair the terminal with NWO NEURO — live MSS travels with every subsequent query.' },
{ cmd:'neuro.mss', arg:'', desc:'Print the current Mental State Signature (focus/valence/arousal/load/intent).' },
{ cmd:'quantum.route', arg:'<op> <provider>', desc:'Route a symbolic op to an external QC provider (ibm | origin).' },
{ cmd:'stake', arg:'<amount>', desc:'Stake $STATE on this node to run as a swarm member.' },
{ cmd:'wallet.connect', arg:'', desc:'Connect a Base-mainnet EVM wallet (top-right Connect Wallet).' },
{ cmd:'key.create', arg:'<label>', desc:'Create an NWO API key bound to the connected wallet.' },
{ cmd:'key.list', arg:'', desc:'List API keys for the connected wallet.' },
{ cmd:'cache.get', arg:'<query-hash>', desc:'Look up a cached consensus result by query hash.' },
{ cmd:'cache.bypass', arg:'on|off', desc:'Toggle cache bypass for subsequent query commands.' },
{ cmd:'subscribe', arg:'blocks|txs|consensus', desc:'Stream live blocks / txs / consensus state until "stop" is sent.' },
{ cmd:'stop', arg:'', desc:'Stop any active subscription.' },
{ cmd:'clear', arg:'', desc:'Clear the terminal output.' },
];
const STARTERS = [
{ title:'Quick first query', code:`connect https://chainstate-worker.<your>.workers.dev
status
query ∫∂x → ?` },
{ title:'Compile a symbolic op to NWO-ASM', code:`asm.compile "SymbolicAttention(64, 1024)"
# emits a PMX IR graph that NWO-ASM can dispatch to GPU/photonic/quantum` },
{ title:'Run with live NEURO conditioning', code:`neuro.bind # pairs the SDK to the EEG headset
neuro.mss # print the live focus/valence/arousal/load/intent
query "explain CRDTs" # the response shape adapts to your live MSS` },
{ title:'Stake + register as a swarm node', code:`wallet.connect
stake 5000 # 5,000 $STATE, reputation cap = 500
beacon.register https://my-node.example.com
beacon # confirm you appear in the active list` },
{ title:'Subscribe to the live chain', code:`subscribe blocks
# … every ~2 s a new block prints …
stop` },
];
const cmdRows = COMMANDS.map(c=>`<tr><td><code>${c.cmd}</code></td><td><code class="dim">${c.arg||''}</code></td><td>${c.desc}</td></tr>`).join('');
const starters = STARTERS.map(s=>`<div class="col-card shim"><h3>${s.title}</h3><pre class="code">${s.code}</pre></div>`).join('');
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · terminal</div>
<h1>CHAINSTATE Terminal</h1>
<p class="lede">Live shell against a CHAINSTATE edge worker. NWO-ASM symbolic compilation, NEURO MSS binding, query dispatch, stake management, beacon registration. Assembler-style commands; everything that the SDK can do, you can do here interactively.</p>
<div class="meta-row">
<span class="pill live"><span class="dot"></span>shell live</span>
<span class="pill beta"><span class="dot"></span>NWO-ASM connected</span>
<span class="pill design"><span class="dot"></span>NEURO bind design</span>
${csModeToggle()}
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="terminal-shell shim">
<div class="terminal-head">
<span class="t-dot t-r"></span><span class="t-dot t-y"></span><span class="t-dot t-g"></span>
<span class="t-title">chainstate · /v1/terminal</span>
<span class="t-status" id="terminal-status">ready · type <code>help</code> to start</span>
</div>
<div class="terminal-body" id="terminal-body"></div>
<div class="terminal-input-row">
<span class="prompt">chain⛓state&nbsp;</span>
<input id="terminal-input" autocomplete="off" autocapitalize="off" spellcheck="false" placeholder="type a command — try: help"/>
</div>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">reference</div><h2>Command list</h2></div></div>
<div class="shim" style="padding:6px 4px;border-radius:14px;overflow:auto">
<table class="horizon-table">
<thead><tr><th style="width:200px">command</th><th style="width:220px">arguments</th><th>description</th></tr></thead>
<tbody>${cmdRows}</tbody>
</table>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">starters</div><h2>Code examples to get started</h2></div></div>
<div class="two-col">${starters}</div>
</section>
</div>`;
const body = document.getElementById('terminal-body');
const input = document.getElementById('terminal-input');
function write(line, cls){
const div = document.createElement('div');
div.className = 'tline ' + (cls||'');
div.innerHTML = line;
body.appendChild(div);
body.scrollTop = body.scrollHeight;
}
write('chainstate terminal — session opened ' + new Date().toUTCString(), 'sys');
write('worker URL: <code>'+(window.__CHAINSTATE_WORKER||'<not setconnect first or run in demo>')+'</code>', 'sys');
write('type "help" for the command list', 'sys');
let streamTimer=null;
function startStream(kind){
stopStream();
streamTimer = setInterval(()=>{
if(kind==='blocks'){
const b = blocks[0]; if(!b){ write(' no blocks yet','dim'); return; }
write(` [block] #${b.height} ${b.hash.slice(0,18)}… ${b.txn_count} txs ${b.gas_used} $STATE`,'stream');
} else if(kind==='txs'){
const t = txs[Math.floor(Math.random()*Math.min(txs.length,20))];
if(!t){ write(' no txs yet','dim'); return; }
write(` [tx] ${t.hash.slice(0,18)}… conf ${t.confidence} gas ${t.gas} query: ${t.query}`,'stream');
} else if(kind==='consensus'){
const h = '0x'+Math.random().toString(16).slice(2,8)+'…'+Math.random().toString(16).slice(2,6);
write(` [consensus] state-hash ${h} depth ${1+Math.floor(Math.random()*5)} participants ${15+Math.floor(Math.random()*30)}`,'stream');
}
},1200);
}
function stopStream(){ if(streamTimer){ clearInterval(streamTimer); streamTimer=null; } }
function handle(cmd){
cmd = cmd.trim();
if(!cmd) return;
write('<span class="echo">chain⛓state ⟩</span> ' + cmd, 'cmd');
const parts = cmd.split(/\s+/);
const head = parts[0];
const arg = parts.slice(1).join(' ');
switch(head){
case 'help':
write('available commands:','sys');
COMMANDS.forEach(c=> write(' <code>'+c.cmd+'</code> <span class="dim">'+c.arg+'</span> — '+c.desc,'sys'));
break;
case 'clear': body.innerHTML=''; break;
case 'connect':
if(!arg){ write('usage: connect <worker-url>','err'); break; }
window.__CHAINSTATE_WORKER = arg.replace(/\/$/,'');
write('worker URL set to <code>'+window.__CHAINSTATE_WORKER+'</code>','ok');
break;
case 'status':
if(!window.__CHAINSTATE_WORKER){ write('no worker connected. running in DEMO.','dim'); }
write(' network: chainstate · base-8453','ok');
write(' active nodes: 42 (demo)','ok');
write(' block height: '+blocks[0].height,'ok');
write(' consensus depth (avg): 3.2','ok');
break;
case 'query':
if(!arg){ write('usage: query <text>','err'); break; }
const sim = simulateResponse(arg, 3, 20, 'none');
write(' → top_symbols: '+JSON.stringify(sim.top_symbols),'ok');
write(' → confidence: '+sim.confidence+' · depth '+sim.consensusDepth+' · '+sim.participatingNodes+' nodes','ok');
write(' → gas: '+sim.gasUsed+' $STATE · '+sim.executionTime+' ms','dim');
break;
case 'query.async':
if(!arg){ write('usage: query.async <text>','err'); break; }
const h = '0x'+Math.random().toString(16).slice(2,18);
write(' → tx hash: <code>'+h+'</code> · pending consensus','ok');
break;
case 'symbols':
const sub = (arg.toLowerCase()||'math');
const subKey = sub==='science'?'sci':sub==='language'?'lang':sub==='occult'?'occ':sub==='emoji'?'emo':sub==='control'?'ctrl':sub;
if(SUBSPACES[subKey]){
write(' '+SUBSPACES[subKey].name+' subspace — '+SUBSPACES[subKey].dims+' dims:','ok');
write(' '+SUBSPACES[subKey].samples.slice(0,40).join(' '),'ok');
} else write('unknown subspace. try: math, science, language, occult, emoji, control','err');
break;
case 'beacon':
write(' active nodes (top 8 by reputation):','ok');
for(let i=0;i<8;i++){
const id = 'node-'+i.toString().padStart(3,'0');
const rep = (95 - i*4 - Math.random()*2).toFixed(1);
const cap = i%4===0?'embedding,attention,quantum':i%3===0?'embedding,attention,neuro_mss':'embedding,attention';
write(' '+id+' rep '+rep+' caps: '+cap, 'dim');
}
break;
case 'beacon.register':
if(!arg){ write('usage: beacon.register <endpoint>','err'); break; }
write(' registered (demo). real registration requires a Dilithium-signed envelope.','ok');
break;
case 'consensus':
const ch = '0x'+Math.random().toString(16).slice(2,18);
write(' current state hash: <code>'+ch+'</code>','ok');
write(' depth this round: 3 · participants 22 · convergence 0.961','ok');
break;
case 'block':
if(!arg){ write('usage: block <height>','err'); break; }
const b = blocks.find(x=>x.height===parseInt(arg.replace('#',''),10));
if(b){ write(' #'+b.height+' '+b.hash+' proposer '+b.proposer+' '+b.txn_count+' txs '+b.gas_used+' $STATE','ok'); openBlock(b.height); }
else write(' not in local sample','err');
break;
case 'tx':
if(!arg){ write('usage: tx <hash>','err'); break; }
const t = txs.find(x=>x.hash.startsWith(arg));
if(t){ write(' '+t.hash+' from '+t.from+' conf '+t.confidence+' query: '+t.query,'ok'); openTx(t.hash); }
else write(' not in local sample','err');
break;
case 'asm.dispatch':
case 'asm.compile':
if(!arg){ write('usage: '+head+' <symbolic-op>','err'); break; }
write(' → PMX IR (Process-Matrix):','ok');
write(' node-0 embedding[65536] <- input_symbols','dim');
write(' node-1 attention[64h×1024d] <- node-0 mask=cross-sub','dim');
write(' node-2 compose[gate×4] <- node-1','dim');
write(' node-3 logpool[w=rep] <- node-2 participants=k','dim');
write(' node-4 state[65536] <- node-3 → output','dim');
write(' dispatch target: gpu (default) | photonic | neuromorphic | quantum','ok');
break;
case 'neuro.bind':
write(' pairing with NWO NEURO… SDK live at /v1/eeg/stream','ok');
write(' (in production this opens a BLE pairing dialog for the EEG headset)','dim');
break;
case 'neuro.mss':
const F=(0.4+Math.random()*0.5).toFixed(2), V=(Math.random()*2-1).toFixed(2),
A=(0.3+Math.random()*0.5).toFixed(2), L=(0.3+Math.random()*0.4).toFixed(2),
I=['idle','left','right','up','down'][Math.floor(Math.random()*5)];
write(` MSS: focus=${F} valence=${V} arousal=${A} load=${L} intent=${I}`,'ok');
break;
case 'quantum.route':
if(!arg){ write('usage: quantum.route <op> <ibm|origin>','err'); break; }
write(' routing to '+(arg.split(' ')[1]||'ibm')+' via NWO-ASM quantum bridge','ok');
write(' circuit depth: 18 · qubits: 32 · estimated wall time: 1.4 s','dim');
break;
case 'stake':
if(!arg){ write('usage: stake <amount>','err'); break; }
const amt = parseFloat(arg);
write(' staked '+amt.toFixed(2)+' $STATE','ok');
write(' reputation cap: '+Math.min(amt/10,100).toFixed(1),'ok');
break;
case 'wallet.connect':
if(typeof connectWallet==='function'){ connectWallet(); write('opening wallet picker…','sys'); }
else write('wallet provider not detected','err');
break;
case 'key.create':
case 'key.list':
write(head+' is wallet-gated — connect wallet and use the API page','dim');
break;
case 'cache.get':
if(!arg){ write('usage: cache.get <query-hash>','err'); break; }
write(' HIT · 5-min TTL · returned in 4 ms','ok');
break;
case 'cache.bypass':
write('cache bypass: '+(arg==='on'?'ON':'OFF'),'ok');
break;
case 'subscribe':
if(!arg){ write('usage: subscribe blocks|txs|consensus','err'); break; }
write('streaming '+arg+' until "stop" is sent…','sys');
startStream(arg);
break;
case 'stop': stopStream(); write('stream stopped','sys'); break;
default: write('unknown command: <code>'+head+'</code> — type <code>help</code> for the list','err');
}
}
const history=[]; let histIdx=-1;
input.addEventListener('keydown',(e)=>{
if(e.key==='Enter'){
const v=input.value; input.value='';
if(v.trim()){ history.unshift(v); histIdx=-1; }
handle(v);
} else if(e.key==='ArrowUp'){ e.preventDefault(); if(histIdx+1<history.length){ histIdx++; input.value=history[histIdx]; } }
else if(e.key==='ArrowDown'){ e.preventDefault(); if(histIdx>0){ histIdx--; input.value=history[histIdx]; } else { histIdx=-1; input.value=''; } }
});
}
</script>
<script>
/* ============================================================
FEATURE PAGES — 16 features, each with flow svg + ecosystem
============================================================ */
function renderFlowSVG(kind){
// Small SVG flowcharts per feature — boxes + arrows. All monochrome.
const W=720, H=180;
function box(x,y,w,h,label,tint){
return `<rect x="${x}" y="${y}" width="${w}" height="${h}" rx="6" fill="rgba(255,255,255,.025)" stroke="${tint||'rgba(255,255,255,.35)'}" stroke-width="1"/>
<text x="${x+w/2}" y="${y+h/2+4}" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="11" font-weight="600" letter-spacing="1.5" fill="#fff">${label}</text>`;
}
function arr(x1,y1,x2,y2,label){
const mid=(x1+x2)/2;
return `<line x1="${x1}" y1="${y1}" x2="${x2-8}" y2="${y2}" stroke="rgba(255,255,255,.35)" stroke-width="1"/>
<polygon points="${x2},${y2} ${x2-8},${y2-4} ${x2-8},${y2+4}" fill="rgba(255,255,255,.45)"/>
${label?`<text x="${mid}" y="${y1-5}" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-size="8.5" fill="#9c9ca6" letter-spacing=".06em">${label}</text>`:''}`;
}
const flows = {
use:[box(20,80,110,32,'CODEPOINTS'),arr(130,96,210,96,'tokenise'),
box(210,80,110,32,'SUBSPACE',`var(--math)`),arr(320,96,400,96,'lookup'),
box(400,80,110,32,'1024d HEAD'),arr(510,96,590,96,'concat ×64'),
box(590,80,110,32,'65,536d STATE','#7df0a8')],
sam:[box(20,80,110,32,'USE STATE'),arr(130,96,210,96,'Q,K,V'),
box(210,80,110,32,'64 HEADS'),arr(320,96,400,96,'mask'),
box(400,80,140,32,'CROSS-SUBSPACE'),arr(540,96,590,96,'∙V'),
box(590,80,110,32,'ATTN OUT','#7df0a8')],
vocab:[box(20,80,110,32,'ATTN OUT'),arr(130,96,210,96,'expand 2x'),
box(210,80,110,32,'GELU·LN'),arr(320,96,400,96,'project'),
box(400,80,110,32,'GATE×4'),arr(510,96,590,96,'σ·residual'),
box(590,80,110,32,'NEXT STATE','#7df0a8')],
pocw:[box(20,80,110,32,'QUERY'),arr(130,96,210,96,'fan out'),
box(210,80,110,32,'NODE-i RUN'),arr(320,96,400,96,'SHA3'),
box(400,80,110,32,'PROOF'),arr(510,96,590,96,'submit'),
box(590,80,110,32,'CHAIN','#7df0a8')],
pool:[box(20,80,110,32,'k NODES'),arr(130,96,210,96,'log_softmax'),
box(210,80,110,32,'WEIGHT·REP'),arr(320,96,400,96,'Σ'),
box(400,80,110,32,'LOG_POST'),arr(510,96,590,96,'exp · LSE'),
box(590,80,110,32,'CONSENSUS','#7df0a8')],
rep:[box(20,80,110,32,'CONSENSUS'),arr(130,96,210,96,'cos · sim'),
box(210,80,110,32,'ACCURACY'),arr(320,96,400,96,'α/β/γ'),
box(400,80,110,32,'EMA UPDATE'),arr(510,96,590,96,'persist'),
box(590,80,110,32,'REP[0,100]','#7df0a8')],
txn:[box(20,80,110,32,'WALLET'),arr(130,96,210,96,'sign'),
box(210,80,110,32,'TX'),arr(320,96,400,96,'sha3 hash'),
box(400,80,110,32,'MEMPOOL'),arr(510,96,590,96,'gas-sort'),
box(590,80,110,32,'PROPOSE','#7df0a8')],
block:[box(20,80,110,32,'PROPOSER VRF'),arr(130,96,210,96,'pull 64'),
box(210,80,110,32,'DISPATCH'),arr(320,96,400,96,'consensus×64'),
box(400,80,110,32,'RECEIPTS'),arr(510,96,590,96,'sign'),
box(590,80,110,32,'BLOCK','#7df0a8')],
stake:[box(20,80,110,32,'STAKE $STATE'),arr(130,96,210,96,'cap'),
box(210,80,110,32,'REP CAP'),arr(320,96,400,96,'serve'),
box(400,80,110,32,'EARN USDC'),arr(510,96,590,96,'·or·'),
box(590,80,110,32,'SLASH','#ff8cb8')],
asm:[box(20,80,110,32,'SYM OP'),arr(130,96,210,96,'ASM'),
box(210,80,110,32,'PMX IR'),arr(320,96,400,96,'dispatch'),
box(400,80,140,32,'SUBSTRATE'),arr(540,96,590,96,'run'),
box(590,80,110,32,'RESULT','#7df0a8')],
neuro:[box(20,80,110,32,'EEG'),arr(130,96,210,96,'pipeline'),
box(210,80,110,32,'MSS'),arr(320,96,400,96,'sign'),
box(400,80,110,32,'TX + MSS'),arr(510,96,590,96,'condition'),
box(590,80,110,32,'SWARM','#7df0a8')],
quantum:[box(20,80,110,32,'SYM OP'),arr(130,96,210,96,'compile'),
box(210,80,110,32,'CIRCUIT'),arr(320,96,400,96,'qpu queue'),
box(400,80,140,32,'IBM/ORIGIN'),arr(540,96,590,96,'measure'),
box(590,80,110,32,'CLASSICAL','#a48cff')],
edge:[box(20,80,110,32,'CLIENT'),arr(130,96,210,96,'POST /query'),
box(210,80,110,32,'EDGE WORKER'),arr(320,96,400,96,'fan-out'),
box(400,80,110,32,'SWARM'),arr(510,96,590,96,'pool'),
box(590,80,110,32,'RESULT','#7df0a8')],
beacon:[box(20,80,110,32,'NODE'),arr(130,96,210,96,'POST /beacon'),
box(210,80,110,32,'KV STORE'),arr(320,96,400,96,'5min TTL'),
box(400,80,110,32,'NODE LIST'),arr(510,96,590,96,'GET'),
box(590,80,110,32,'DISPATCH','#7df0a8')],
cache:[box(20,80,110,32,'QUERY'),arr(130,96,210,96,'sha3 key'),
box(210,80,110,32,'KV LOOKUP'),arr(320,96,400,96,'HIT?'),
box(400,80,110,32,'RETURN'),arr(510,96,590,96,'else'),
box(590,80,110,32,'INFERENCE','#a48cff')],
market:[box(20,80,110,32,'DAPP'),arr(130,96,210,96,'mint'),
box(210,80,110,32,'ERC-1155'),arr(320,96,400,96,'list'),
box(400,80,110,32,'MARKETPLACE'),arr(510,96,590,96,'sell'),
box(590,80,110,32,'SPLITTER','#7df0a8')],
};
const items = flows[kind]||flows.use;
return `<svg class="flow-svg" viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg">${items.join('')}</svg>`;
}
function renderTech(id, kind){
// wire = network contract; data = treatment guarantees
const wires = {
'f-use':`<pre class="code"><span class="c"># PyTorch — embedding pipeline</span>
<span class="k">import</span> torch
<span class="k">from</span> chainstate.symbolic <span class="k">import</span> UniversalSemioticEmbedding
emb = UniversalSemioticEmbedding()
state = emb.embed_query(<span class="s">"∫∂x in physics"</span>) <span class="c"># → 65,536-d torch tensor</span>
print(state.shape) <span class="c"># torch.Size([65536])</span></pre>`,
'f-sam':`<pre class="code"><span class="c"># Symbolic Attention forward</span>
<span class="k">from</span> chainstate.symbolic <span class="k">import</span> SymbolicCrossAttention
sam = SymbolicCrossAttention(num_heads=<span class="n">64</span>)
attn_out = sam(state.unsqueeze(<span class="n">0</span>).unsqueeze(<span class="n">0</span>))</pre>`,
'f-vocab':`<pre class="code"><span class="c"># Composition with sigmoid-gated residual</span>
<span class="k">from</span> chainstate.symbolic <span class="k">import</span> SymbolicComposition
comp = SymbolicComposition(dim=<span class="n">65536</span>)
next_state = comp(attn_out)</pre>`,
'f-pocw':`<pre class="code"><span class="c"># Each swarm node emits a NodeOutput</span>
{
<span class="s">"node_id"</span>: <span class="s">"node-007"</span>,
<span class="s">"symbolic_state"</span>: <span class="n">[ ...65536 floats ]</span>,
<span class="s">"confidence"</span>: <span class="n">0.94</span>,
<span class="s">"compute_proof"</span>: <span class="s">"sha3:7f3c…"</span>,
<span class="s">"timestamp"</span>: <span class="n">1717423511</span>
}</pre>`,
'f-pool':`<pre class="code"><span class="c"># Log-pooling consensus</span>
log_p = torch.log_softmax(states, dim=-<span class="n">1</span>) <span class="c"># [k, 65536]</span>
w = reputations / reputations.sum() <span class="c"># [k]</span>
log_c = (log_p * w.view(-<span class="n">1</span>,<span class="n">1</span>)).sum(<span class="n">0</span>) <span class="c"># [65536]</span>
consensus = (log_c - logsumexp(log_c)).exp()</pre>`,
'f-rep':`<pre class="code"><span class="c"># Reputation EMA update</span>
<span class="k">if</span> accuracy > <span class="n">0.8</span>: rep += alpha * accuracy <span class="c"># reward</span>
<span class="k">elif</span> accuracy < <span class="n">0.5</span>: rep -= beta * (<span class="n">1</span> - accuracy) <span class="c"># penalty</span>
<span class="k">else</span>: rep *= gamma <span class="c"># decay</span>
rep = clamp(rep, <span class="n">0</span>, <span class="n">100</span>)</pre>`,
'f-txn':`<pre class="code"><span class="c"># Cognitive transaction</span>
tx = {
<span class="s">"sender"</span>: <span class="s">"0xabc…"</span>,
<span class="s">"nonce"</span>: <span class="n">42</span>,
<span class="s">"query"</span>: <span class="s">"∫∂x → ?"</span>,
<span class="s">"gasPrice"</span>: <span class="n">0.001</span>,
<span class="s">"maxGas"</span>: <span class="n">0.01</span>
}
tx[<span class="s">"hash"</span>] = sha3(sender + nonce + query + ts)[:<span class="n">16</span>]</pre>`,
'f-block':`<pre class="code"><span class="c"># Block production</span>
proposer = vrf(prev_hash, round, reputations)
txs = mempool.pop_top(<span class="n">64</span>)
results = await dispatch_all(txs) <span class="c"># parallel</span>
block = sign_block({prev_hash, height, txs, results}, proposer.dilithium_sk)</pre>`,
'f-stake':`<pre class="code"><span class="c"># Stake $STATE</span>
chainstate.stake(node_id, <span class="n">5000</span>) <span class="c"># 5,000 $STATE</span>
<span class="c"># reputation cap is now min(5000/10, 100) = 100</span>
<span class="c"># Slashing</span>
<span class="k">if</span> no_response: slash(<span class="n">0.01</span>) <span class="c"># 1%</span>
<span class="k">if</span> incorrect_response: slash(<span class="n">0.05</span>) <span class="c"># 5%</span>
<span class="k">if</span> conflicting_outputs: slash(<span class="n">1.00</span>) <span class="c"># 100%</span></pre>`,
'f-asm':`<pre class="code"><span class="c"># Dispatch a symbolic op via NWO-ASM</span>
<span class="k">from</span> nwo.asm <span class="k">import</span> compile_dispatch
ir = compile_dispatch(<span class="s">"SymbolicAttention(64,1024)"</span>, target=<span class="s">"auto"</span>)
print(ir.kind) <span class="c"># 'pmx'</span>
result = ir.run(input_state) <span class="c"># auto-substrate</span></pre>`,
'f-neuro':`<pre class="code"><span class="c"># Bind NWO NEURO</span>
<span class="k">import</span> nwo.neuro <span class="k">as</span> neuro
mss = neuro.live_mss()
print(mss) <span class="c"># {focus, valence, arousal, load, intent}</span>
<span class="c"># Conditioned query — MSS travels signed</span>
result = chainstate.query(<span class="s">"explain CRDTs"</span>, mss=mss)</pre>`,
'f-quantum':`<pre class="code"><span class="c"># Route to quantum substrate</span>
<span class="k">from</span> nwo.asm <span class="k">import</span> compile_dispatch
ir = compile_dispatch(<span class="s">"GroverSearch(reputations, target=top_5)"</span>, target=<span class="s">"ibm"</span>)
result = ir.run()
<span class="c"># falls back to classical if QC unavailable or stake &lt; 10,000 $STATE</span></pre>`,
'f-edge':`<pre class="code"><span class="c"># Cloudflare Worker — edge-worker.js</span>
addEventListener(<span class="s">'fetch'</span>, e => e.respondWith(handle(e.request)))
async <span class="k">function</span> handle(r){
<span class="k">const</span> url = <span class="k">new</span> URL(r.url)
<span class="k">if</span>(url.pathname === <span class="s">'/query'</span>) <span class="k">return</span> handleQuery(r)
<span class="k">if</span>(url.pathname === <span class="s">'/beacon'</span>) <span class="k">return</span> handleBeacon(r)
<span class="k">if</span>(url.pathname === <span class="s">'/consensus'</span>) <span class="k">return</span> handleConsensus(r)
<span class="k">return</span> <span class="k">new</span> Response(<span class="s">'CHAINSTATE'</span>, {status: <span class="n">200</span>})
}</pre>`,
'f-beacon':`<pre class="code"><span class="c"># Node beacon — call from each swarm node</span>
POST /beacon
{
<span class="s">"node_id"</span>: <span class="s">"node-007"</span>,
<span class="s">"reputation"</span>: <span class="n">78.4</span>,
<span class="s">"capabilities"</span>: [<span class="s">"embedding"</span>,<span class="s">"attention"</span>,<span class="s">"quantum"</span>],
<span class="s">"endpoint"</span>: <span class="s">"https://my-node.example.com"</span>,
<span class="s">"dilithium_pk"</span>: <span class="s">"..."</span>
}
GET /beacon <span class="c"># returns active list, reputation-sorted</span></pre>`,
'f-cache':`<pre class="code"><span class="c"># Result cache — 5 min TTL on Cloudflare KV</span>
<span class="k">const</span> key = sha3(query)
<span class="k">const</span> hit = <span class="k">await</span> CHAINSTATE_CACHE.get(key)
<span class="k">if</span>(hit) <span class="k">return</span> json(<span class="k">JSON</span>.parse(hit), {<span class="s">'X-Cache'</span>:<span class="s">'HIT'</span>})
<span class="k">const</span> result = <span class="k">await</span> runConsensus(query)
<span class="k">await</span> CHAINSTATE_CACHE.put(key, <span class="k">JSON</span>.stringify(result), {expirationTtl:<span class="n">300</span>})
<span class="k">return</span> json(result, {<span class="s">'X-Cache'</span>:<span class="s">'MISS'</span>})</pre>`,
'f-market':`<pre class="code"><span class="c"># Marketplace listing — Solidity</span>
contract ChainStateMarket {
<span class="k">function</span> list(uint256 id, uint256 price) <span class="k">external</span> {
<span class="k">require</span>(IERC1155(dapp).balanceOf(msg.sender, id) > <span class="n">0</span>);
listings[id] = Listing(msg.sender, price);
}
<span class="k">function</span> buy(uint256 id) <span class="k">external</span> payable {
splitter.split{value: msg.value}(listings[id].seller); <span class="c">// 85/15</span>
IERC1155(dapp).safeTransferFrom(listings[id].seller, msg.sender, id, <span class="n">1</span>, <span class="s">""</span>);
}
}</pre>`,
};
const datas = {
'f-use':'Embedding shards quantised to int8 per subspace; per-node footprint ~80 MB. Cross-subspace mask is sparse; <2 MB.',
'f-sam':'Attention pattern emitted as PMX IR; high-load queries auto-offload to photonic accelerators when available.',
'f-vocab':'Gate weights are versioned per epoch; old weights kept for replay verification of historical blocks.',
'f-pocw':'Compute proof is verified in <1 ms on a single Worker invocation; full state replay only on dispute.',
'f-pool':'Numerically stable via logsumexp normalisation. λ synergy parameter optimised offline via quantum annealing (NWO-ASM).',
'f-rep':'Reputation state persisted in CHAINSTATE_NODES KV with per-node accuracy_history; rolling window 1,000 calls.',
'f-txn':'Mempool TTL: 60 s. Dropped tx returns gas to sender automatically on next block.',
'f-block':'Block storage: append-only on IPFS with content-addressed receipts; Base mainnet anchors every 100 blocks.',
'f-stake':'Stake locked in `0x` ChainStateStake contract; slashing executes on-chain via consensus-signed evidence.',
'f-asm':'PMX IR is content-addressed; replays produce identical bytecode regardless of substrate.',
'f-neuro':'MSS is signed with the user\'s NEURO Dilithium key; never raw EEG signal touches the chain.',
'f-quantum':'Quantum circuits queued via `nwo.asm.quantum_route`; classical fallback within 5 s if QPU unavailable.',
'f-edge':'Single Worker file; deploys in <5 s via `wrangler deploy`. CORS open; rate-limited 60/min per IP.',
'f-beacon':'Beacon TTL 5 min; nodes ping every 60 s. Reputations gossiped between Workers via Durable Objects (planned).',
'f-cache':'Cache key = SHA3-256(query). 5-min TTL. Manually invalidatable via `DELETE /cache?key=…` (admin).',
'f-market':'Royalty enforcement at the splitter level — bypassing the listing UI does not bypass the 15% creator royalty.',
};
if(kind==='wire') return wires[id]||'';
return `<p>${datas[id]||'—'}</p>`;
}
function renderFeaturePages(){
FEATURES.forEach(f=>{
const root = document.querySelector('.page[data-page="'+f.id+'"]');
if(!root) return;
root.innerHTML = `
<div class="subhero">
<a class="back" data-link="home">← back to home</a>
<div class="eyebrow">${f.num} · ${f.name}</div>
<h1>${f.name}</h1>
<p class="lede">${f.blurb}</p>
<div class="meta-row">
<span class="pill ${f.status.cls}"><span class="dot"></span>${f.status.label}</span>
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="two-col">
<div class="col-card shim"><h3>What it does</h3><p>${f.long}</p>
<h3 style="margin-top:14px">Highlights</h3>
<ul>${f.bullets.map(b=>`<li>${b}</li>`).join('')}</ul>
</div>
<div class="col-card shim"><h3>Ecosystem coupling</h3>
<table class="eco-table">
<thead><tr><th>where</th><th>how</th></tr></thead>
<tbody>${f.eco.map(e=>`<tr><td>${e[0]}</td><td>${e[1]}</td></tr>`).join('')}</tbody>
</table>
</div>
</div>
</section>
<section class="tight">
<div class="flow-box shim">
<h3>Flow</h3>
${renderFlowSVG(f.flow)}
</div>
</section>
<section class="tight">
<div class="two-col">
<div class="col-card shim"><h3>Wire contract — code</h3>${renderTech(f.id,'wire')}</div>
<div class="col-card shim"><h3>Data treatment</h3>${renderTech(f.id,'data')}
<h3 style="margin-top:14px">Status &amp; status notes</h3>
<p class="txt-sm txt-mute">labelled <strong>${f.status.label}</strong>. live = production on Base; beta = wired but limited coverage; design = spec-complete; planned = next quarter.</p>
</div>
</div>
</section>
</div>`;
});
}
</script>
<script>
/* ============================================================
ARCHITECTURE — circular SVG with hover tooltips
============================================================ */
function renderArchitecture(){
const root = document.querySelector('.page[data-page="architecture"]');
if(!root) return;
const NODES = [
{id:'L0', name:'WALLET', desc:'EVM wallet on Base mainnet 8453. Same address as every other NWO Capital service. Signs the cognitive transaction with secp256k1; can optionally bind a Dilithium key for post-quantum.', tint:'#fff'},
{id:'L1', name:'EDGE WORKER', desc:'Single-file Cloudflare Worker. Routes /query, /beacon, /consensus, /status, /symbols. Rate limit 60/min/IP. KV-backed result cache 5-min TTL.', tint:'#7df0a8'},
{id:'L2', name:'USE', desc:'Universal Semiotic Embedding. 65,536-d substrate over 6 subspaces (math, science, language, occult, emoji, control). nn.Embedding per subspace.', tint:'#7df0a8'},
{id:'L3', name:'SAM', desc:'Symbolic Attention Mechanism. 64-head, 1,024-d-per-head attention over the USE. Cross-subspace interaction mask hard-codes math↔science, occult↔control couplings.', tint:'#7df0a8'},
{id:'L4', name:'SWARM', desc:'Geographically-distributed inference nodes. Each runs USE + SAM + composition. Reputation-weighted; capability-tagged (embedding/attention/quantum/neuro_mss).', tint:'#7ad0ff'},
{id:'L5', name:'CONSENSUS', desc:'Reputation-weighted Bayesian log-pooling. Convergence threshold 0.95 cosine. Hard min 10 nodes. λ synergy parameter optimised offline.', tint:'#7ad0ff'},
{id:'L6', name:'BLOCK PRODUCTION',desc:'Reputation-weighted VRF proposer rotation. 2 s target block time. 64 txs/block hard cap. Soft finality 1 conf, hard finality 6.', tint:'#7ad0ff'},
{id:'L7', name:'SCAN', desc:'Block explorer indexing all blocks + cognitive transactions. Search by hash, height, sender, or query text. X-Cache header surfaced on every tx.', tint:'#f0e07d'},
{id:'L8', name:'NWO-ASM', desc:'Process-Matrix IR (.pmx) substrate. Compiles symbolic ops to typed dataflow programs. 8 substrate connectors: GPU, TPU, photonic, neuromorphic, IBM QC, Origin QC, BCI, robotic.', tint:'#a48cff'},
{id:'L9', name:'NWO NEURO', desc:'Live MSS conditioning of query. Focus / valence / arousal / load / intent. Dilithium-signed; SHA3-256 commitment binds to wallet.', tint:'#a48cff'},
];
const N = NODES.length;
const cx=410, cy=380, R=270;
const positions = NODES.map((_,i)=>{
const a = (-Math.PI/2) + (i*2*Math.PI/N);
return { x: cx + R*Math.cos(a), y: cy + R*Math.sin(a) };
});
const nodes = NODES.map((n,i)=>{
const p = positions[i];
return `<g class="arch-node" data-node="${i}">
<rect x="${p.x-60}" y="${p.y-26}" width="120" height="52" rx="8" fill="rgba(255,255,255,.05)" stroke="${n.tint}" stroke-width="1.2" stroke-opacity=".55"/>
<text x="${p.x}" y="${p.y-4}" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-size="10" fill="#9c9ca6" letter-spacing="2">${n.id}</text>
<text x="${p.x}" y="${p.y+14}" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="11" font-weight="600" letter-spacing="1.5" fill="#fff">${n.name}</text>
</g>`;
}).join('');
// ring + center
const center = `
<circle cx="${cx}" cy="${cy}" r="${R-90}" fill="none" stroke="rgba(255,255,255,.08)" stroke-dasharray="2 4"/>
<circle cx="${cx}" cy="${cy}" r="${R-50}" fill="none" stroke="rgba(255,255,255,.06)" stroke-dasharray="1 3"/>
<circle cx="${cx}" cy="${cy}" r="${R}" fill="none" stroke="rgba(255,255,255,.10)"/>
<circle cx="${cx}" cy="${cy}" r="${R-130}" fill="rgba(255,255,255,.025)" stroke="rgba(255,255,255,.18)"/>
<text x="${cx}" y="${cy-12}" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="13" font-weight="700" letter-spacing="3" fill="#fff">SECURITY</text>
<text x="${cx}" y="${cy+8}" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="13" font-weight="700" letter-spacing="3" fill="#fff">ENVELOPE</text>
<text x="${cx}" y="${cy+28}" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-size="9" letter-spacing="1.5" fill="#9c9ca6">CRYSTALS-Dilithium</text>
<text x="${cx}" y="${cy+42}" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-size="9" letter-spacing="1.5" fill="#9c9ca6">Kyber-1024 KEM</text>
<text x="${cx}" y="${cy+56}" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-size="9" letter-spacing="1.5" fill="#9c9ca6">SHA3-256 commit</text>`;
// edges between consecutive layers (around the ring)
const edges = positions.map((p,i)=>{
const q = positions[(i+1)%N];
return `<line x1="${p.x}" y1="${p.y}" x2="${q.x}" y2="${q.y}" stroke="rgba(255,255,255,.10)" stroke-width="1"/>`;
}).join('');
const spokes = positions.map(p=>`<line x1="${cx}" y1="${cy}" x2="${p.x}" y2="${p.y}" stroke="rgba(255,255,255,.05)" stroke-dasharray="1 4"/>`).join('');
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · architecture</div>
<h1>Architecture · all 10 layers</h1>
<p class="lede">CHAINSTATE is a 10-layer stack from wallet to integrated cognitive substrates. Every layer is wrapped by a single quantum-resistant security envelope — Dilithium signatures, Kyber KEM for key exchange, SHA3-256 commitments. Hover any node for its summary; click for the full spec.</p>
</div>
<div class="wrap">
<section class="tight">
<div class="arch-svg-wrap shim">
<div class="arch-circle-wrap" id="arch-wrap">
<svg class="arch-svg-circle" viewBox="0 0 820 760" xmlns="http://www.w3.org/2000/svg">
${center}${spokes}${edges}${nodes}
</svg>
<div class="arch-tooltip" id="arch-tt"></div>
</div>
<div class="arch-legend">hover any node · click for full spec · same wallet, same gateway across every NWO Capital service</div>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">stack</div><h2>Layer-by-layer technology</h2></div></div>
<div class="stack-grid">
${NODES.map(n=>`<div class="stack-card shim">
<div class="l">${n.id}</div>
<div class="t" style="color:${n.tint}">${n.name}</div>
<div class="d">${n.desc}</div>
</div>`).join('')}
</div>
</section>
</div>`;
const tt = document.getElementById('arch-tt');
const wrap = document.getElementById('arch-wrap');
wrap.querySelectorAll('.arch-node').forEach((g,i)=>{
const n = NODES[i];
g.addEventListener('mousemove', e=>{
tt.style.display='block';
const r = wrap.getBoundingClientRect();
tt.style.left = Math.min(r.width-280, Math.max(0, e.clientX - r.left + 14))+'px';
tt.style.top = Math.max(0, e.clientY - r.top + 14)+'px';
tt.innerHTML = `
<div class="arch-tt-title"><span class="arch-tt-dot" style="background:${n.tint}"></span>${n.id} · ${n.name}</div>
<div class="arch-tt-line">${n.desc}</div>
<div class="arch-tt-cta">click for full spec ↗</div>`;
});
g.addEventListener('mouseleave', ()=>{ tt.style.display='none'; });
g.addEventListener('click', ()=>{
tt.style.display='none';
openModal(n.id+' · '+n.name, `<p>${n.desc}</p>
<h4>Status</h4><p>Production on Base mainnet 8453 except where flagged otherwise on the Roadmap.</p>
<h4>Related features</h4>
<p>${FEATURES.filter(f=>f.long.toLowerCase().includes(n.name.toLowerCase().split(' ')[0])).slice(0,3).map(f=>`<span class="pill ${f.status.cls}"><span class="dot"></span>${f.name}</span>`).join(' ')||'see all features →'}</p>
<div style="margin-top:14px"><button class="ghost" onclick="closeModal()">Close</button></div>`);
});
});
}
/* ============================================================
INSTRUCTIONS — quickstart steps + per-feature integration
============================================================ */
function renderInstructions(){
const root = document.querySelector('.page[data-page="instructions"]');
if(!root) return;
const STEPS = [
{layer:'L1', title:'Deploy the edge worker', txt:'Take <code>workers/edge-worker.js</code> + <code>wrangler.toml</code>, run <code>npx wrangler kv:namespace create CHAINSTATE_NODES</code> (and CACHE, CONSENSUS), then <code>npx wrangler deploy</code>. URL appears in ≤5 s.'},
{layer:'L2', title:'Install the SDK', txt:'Python: <code>pip install chainstate-sdk</code> (publishes <code>chainstate.symbolic</code> + <code>chainstate.protocol</code>). JS: <code>npm i @nwo/chainstate</code>. Drop-in import; no global config required.'},
{layer:'L3', title:'Submit your first cognitive transaction', txt:'<code>chainstate.query("∫∂x → ?", consensusDepth=3, swarmSize=20)</code> → returns a result with consensus state, participating nodes, gas. Settles in 1 confirmation (~2 s).'},
{layer:'L4', title:'Register a swarm node', txt:'Run <code>python -m chainstate.node --endpoint $URL --stake 1000</code>. Node POSTs <code>/beacon</code> with capabilities + Dilithium pubkey. Pings every 60 s to refresh KV TTL.'},
{layer:'L5', title:'Compile a symbolic op to NWO-ASM', txt:'<code>from nwo.asm import compile_dispatch; ir = compile_dispatch("SymbolicAttention(64,1024)", target="auto")</code>. Returns a PMX IR object you can run, inspect, or hash.'},
{layer:'L6', title:'Condition queries with live NEURO MSS', txt:'<code>import nwo.neuro as neuro; mss = neuro.live_mss(); chainstate.query(q, mss=mss)</code>. MSS is signed; the swarm conditions the embedding lookup on focus / valence / arousal / load / intent.'},
];
const CONFIGS = [
{id:'f-edge', title:'Edge Worker — wrangler.toml',
setup:['Add <code>CF_API_TOKEN</code> + <code>CF_ACCOUNT_ID</code> as GitHub Secrets','Create KV namespaces: CHAINSTATE_NODES, CHAINSTATE_CACHE, CHAINSTATE_CONSENSUS','Run <code>npx wrangler deploy</code>','Hit the deployed URL with <code>GET /status</code> to verify','Set <code>window.__CHAINSTATE_WORKER</code> in your HF Space to point to the worker'],
code:`name = "chainstate-worker"
main = "edge-worker.js"
compatibility_date = "2024-09-23"
[[kv_namespaces]]
binding = "CHAINSTATE_NODES"
id = "<your-id-here>"
[[kv_namespaces]]
binding = "CHAINSTATE_CACHE"
id = "<your-id-here>"
[[kv_namespaces]]
binding = "CHAINSTATE_CONSENSUS"
id = "<your-id-here>"
[vars]
SWARM_SIZE = "50"
CONSENSUS_DEPTH = "3"
CACHE_TTL = "300"`
},
{id:'f-asm', title:'NWO-ASM bridge — Python',
setup:['Install: <code>pip install nwo-asm</code>','Set <code>NWO_API_KEY</code> env var (from API page → key.create)','Optional: set <code>NWO_ASM_TARGET=quantum</code> for default quantum routing'],
code:`from nwo.asm import compile_dispatch
# Compile + run on any available substrate
ir = compile_dispatch("SymbolicAttention(64, 1024)", target="auto")
result = ir.run(input_state)
# Force quantum substrate
ir_q = compile_dispatch(
"GroverSearch(reputations, top_k=5)",
target="ibm" # or "origin"
)
result_q = ir_q.run()
# Inspect emitted PMX IR
print(ir.pmx_graph())`
},
{id:'f-neuro', title:'NWO NEURO MSS binding — Python',
setup:['Pair an EEG headset to NWO NEURO (BLE)','Auth with the same wallet as CHAINSTATE','Call <code>neuro.live_mss()</code> any time to read the current MSS'],
code:`import nwo.neuro as neuro
import chainstate
# live MSS (signed Dilithium-pk binds to wallet)
mss = neuro.live_mss()
# {focus: 0.84, valence: 0.12, arousal: 0.51, load: 0.43, intent: "right"}
# Condition any cognitive transaction
result = chainstate.query(
"explain CRDTs simply",
mss=mss,
swarmSize=20,
consensusDepth=3,
)
# response shape adapts to MSS; high load → more diagrams, simpler symbols`
},
{id:'f-stake', title:'Swarm node + stake — JS',
setup:['Hold ≥ 1,000 $STATE in your Base wallet','Approve the ChainStateStake contract','Call <code>stake()</code>; your reputation cap is set to min(stake/10, 100)','Run the node binary; it pings <code>/beacon</code> every 60 s'],
code:`import { ethers } from 'ethers'
const provider = new ethers.BrowserProvider(window.ethereum)
const signer = await provider.getSigner()
const stake = new ethers.Contract(STAKE_ADDR, STAKE_ABI, signer)
// Approve + stake 5,000 $STATE
const tx = await stake.stake(ethers.parseUnits('5000', 18))
await tx.wait()
// Reputation cap is now min(5000/10, 100) = 100`
},
{id:'f-quantum', title:'Quantum offload — Python',
setup:['Stake ≥ 10,000 $STATE','Set <code>NWO_API_KEY</code>','Choose provider: <code>ibm</code> (Sherbrooke 127q) or <code>origin</code> (Wukong 72q)'],
code:`from nwo.asm import compile_dispatch
# Annealing optimisation of λ in log-pool
ir = compile_dispatch(
"QuantumAnneal(lambda_synergy, ising_h=H, ising_J=J)",
target="ibm",
timeout_ms=5000
)
result = ir.run()
# falls back to classical anneal in <5 s if QPU unavailable`
},
];
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · instructions</div>
<h1>Instructions</h1>
<p class="lede">Quickstart in six steps, then per-feature integration recipes. Every recipe is a complete drop-in: code, setup, env vars.</p>
</div>
<div class="wrap">
<section class="tight">
<div class="section-head"><div><div class="eyebrow">quickstart</div><h2>6 steps to first transaction</h2></div></div>
<div class="steps">
${STEPS.map(s=>`<div class="step-card shim">
<div class="layer-label">${s.layer}</div>
<h3>${s.title}</h3>
<p class="txt-sm">${s.txt}</p>
</div>`).join('')}
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">recipes</div><h2>Per-feature integration</h2></div></div>
<div class="two-col">
${CONFIGS.map(c=>`<div class="col-card shim">
<h3>${c.title}</h3>
<ul>${c.setup.map(s=>`<li>${s}</li>`).join('')}</ul>
<pre class="code">${c.code}</pre>
</div>`).join('')}
</div>
</section>
</div>`;
}
/* ============================================================
ROADMAP — horizons + risks
============================================================ */
function renderRoadmap(){
const root = document.querySelector('.page[data-page="roadmap"]');
if(!root) return;
const HORIZONS = [
{h:'now', name:'USE + SAM + Composition', rationale:'Six-subspace 65,536-d embedding, 64-head symbolic attention, gated composition. Reference implementation in <code>chainstate.symbolic</code>.'},
{h:'now', name:'Edge Worker + Beacon + Cache', rationale:'Single-file Cloudflare Worker, KV beacon, 5-min result cache. Wrangler one-shot deploy.'},
{h:'now', name:'Cognitive Transactions', rationale:'Tx = query. SHA3-256 hash, mempool sort by gas, replay protection via (sender, nonce). Demo SCAN live.'},
{h:'now', name:'Log-Pooling Consensus', rationale:'Reputation-weighted Bayesian pooling over swarm. 0.95 cosine convergence. Hard-min 10 nodes.'},
{h:'short', name:'$STATE Token Genesis', rationale:'ERC-20 + staking contract on Base. 1,000 $STATE minimum to run a node. Slashing on misbehaviour.'},
{h:'short', name:'Block Production via VRF', rationale:'Reputation-weighted VRF proposer rotation. 2 s blocks, 64 txs/block. Dilithium block sigs.'},
{h:'short', name:'NWO-ASM Bridge — Production', rationale:'PMX IR emission from <code>chainstate.symbolic</code> ops; dispatch over GPU / photonic / neuromorphic.'},
{h:'short', name:'API Mission Control', rationale:'Wallet-gated key management, USDC settlement, affiliate splitter wire. Same gateway as NWO Capital.'},
{h:'med', name:'NWO NEURO Live MSS Conditioning', rationale:'Per-query MSS conditions the embedding lookup; signed with NEURO Dilithium key.'},
{h:'med', name:'Quantum Offload via NWO-ASM', rationale:'High-depth (>5 round) consensus auto-routes to IBM Sherbrooke / Origin Wukong when stake ≥ 10K $STATE.'},
{h:'med', name:'DApp Marketplace', rationale:'ERC-1155 listings, 15% creator royalty, shared splitter. Discovery surfaces on the NWO Marketplace.'},
{h:'med', name:'Multi-Region Beacon Gossip', rationale:'Durable Objects gossip reputations across CF colos for latency-aware dispatch.'},
{h:'long', name:'Cardio-Neuro Identity Commitments',rationale:'Dual-biometric proof-of-personhood per node operator; cuts sybil far below 0.1% even at scale.'},
{h:'long', name:'Cross-Chain Settlement Bridges', rationale:'USDC bridges to Solana, BSC, OP; same splitter contract semantics enforced via canonical message passing.'},
{h:'long', name:'Sovereignty Protocol — full', rationale:'Device-class gating for which kinds of MSS-conditioned queries earn full citizenship vs partial / observer.'},
{h:'long', name:'Symbolic Path-Integral Simulation',rationale:'Hamiltonian sim of the symbolic state evolution on quantum hardware as a primitive op.'},
];
const RISKS = [
{h:'51% reputation attack',
d:'An attacker accrues majority reputation by running many high-accuracy nodes early, then submits coordinated wrong answers to manipulate consensus.',
m:'Reputation cap = min(stake/10, 100); slashing on 5σ divergence; ε-greedy random sample of new-low-rep nodes; consensus hard-aborts below 10 participants. Cross-validation against NWO-ASM PMX replay on disputed blocks.'},
{h:'Sybil node spam',
d:'Attacker spins up thousands of zero-reputation nodes to crowd the beacon, hoping ε-greedy selection gives them disproportionate influence.',
m:'Stake-gated reputation cap means zero-stake nodes never reach 50% influence; capability-tagged dispatch filters out nodes that don\'t advertise the required op. Optional Cardio-Neuro identity commit for full citizenship.'},
{h:'Quantum compromise of Dilithium',
d:'A future fault-tolerant quantum computer breaks lattice-based signatures, allowing forgery of block proposer sigs and consensus envelopes.',
m:'Hybrid signing: every Dilithium sig is paired with a SLH-DSA (hash-based, quantum-final) backup. Migration path documented; cutover triggered by NIST advisory.'},
{h:'USDC settlement risk',
d:'Centralised USDC custodian (Circle) freezes settlement contract addresses or de-pegs.',
m:'Splitter accepts any ERC-20 the operator configures; USDC is default but DAI / USDe / pyUSD work identically. Fast-rotation playbook documented for the operator.'},
];
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · roadmap</div>
<h1>Roadmap · 4 horizons</h1>
<p class="lede">What ships now (live on Base mainnet), short (this quarter), medium (within 6 months), long (6+ months). Every entry below has a rationale — not just a name. Risks are explicit; mitigations are concrete.</p>
</div>
<div class="wrap">
<section class="tight">
<div class="shim" style="padding:6px 4px;border-radius:14px;overflow:auto">
<table class="horizon-table">
<thead><tr><th>horizon</th><th>milestone</th><th>rationale</th></tr></thead>
<tbody>
${HORIZONS.map(h=>`<tr>
<td><span class="h ${h.h}">${h.h==='now'?'NOW':h.h==='short'?'SHORT':h.h==='med'?'MEDIUM':'LONG'}</span></td>
<td><span class="name">${h.name}</span></td>
<td class="rationale">${h.rationale}</td>
</tr>`).join('')}
</tbody>
</table>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">explicit</div><h2>Risks &amp; mitigations</h2></div></div>
<div class="risk-grid">
${RISKS.map(r=>`<div class="risk-card">
<h4>${r.h}</h4>
<p>${r.d}</p>
<div class="mitigation">${r.m}</div>
</div>`).join('')}
</div>
</section>
</div>`;
}
</script>
<script>
/* ============================================================
API MISSION CONTROL — wallet-gated key + payment management
============================================================ */
let __API_MODE='demo'; // demo | live (live requires wallet)
let __API_KEYS=[];
let __API_PAYMENTS=[];
function renderAPI(){
const root = document.querySelector('.page[data-page="api"]');
if(!root) return;
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · api mission control</div>
<h1>API Mission Control</h1>
<p class="lede">Live KPIs, key management, USDC payments, affiliate share. Same gateway (<code>nwo-capital-api.onrender.com</code>) as the rest of NWO Capital — one wallet, one billing account, one audit trail.</p>
<div class="meta-row">
<span class="pill live" id="api-mode-pill"><span class="dot"></span>demo data</span>
<button class="ghost sm" id="api-mode-btn" onclick="toggleApiMode()">Switch to live mode (wallet)</button>
${csModeToggle()}
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="api-grid">
<div class="panel shim">
<div class="panel-head">
<h3>KPI ticker · 60-second window</h3>
<span class="meta" id="api-tick">tick · 0</span>
</div>
<div class="kpi-row">
<div class="kpi"><div class="v" id="k-calls"></div><div class="l">calls / s</div></div>
<div class="kpi"><div class="v" id="k-latency"></div><div class="l">p50 latency</div></div>
<div class="kpi"><div class="v" id="k-gas"></div><div class="l">avg gas · $STATE</div></div>
<div class="kpi"><div class="v" id="k-cache"></div><div class="l">cache hit %</div></div>
</div>
<canvas id="calls-chart"></canvas>
<p class="txt-sm txt-mute" style="margin-top:6px">x-axis: last 60 s · y-axis: calls/s · single line, no fill</p>
</div>
<div class="panel shim">
<div class="panel-head">
<h3>API keys</h3>
<span class="meta">wallet-bound</span>
</div>
<div id="api-keys-list" class="keys-list"></div>
<div class="cta-row" style="margin-top:10px">
<button class="ghost sm" onclick="doCreateKey()">+ Create key</button>
</div>
</div>
</div>
</section>
<section class="tight">
<div class="api-grid">
<div class="panel shim">
<div class="panel-head"><h3>Pricing — per-endpoint</h3><span class="meta">USDC on Base</span></div>
<table class="pay-table pricing-table">
<thead><tr><th>endpoint</th><th>unit</th><th>price</th></tr></thead>
<tbody>
<tr><td class="ep">/v1/query</td><td>per call (20 nodes, 3 rounds)</td><td class="price">$0.00190</td></tr>
<tr><td class="ep">/v1/query (cache hit)</td><td>per call</td><td class="price">$0.00012</td></tr>
<tr><td class="ep">/v1/asm-compile</td><td>per IR emit</td><td class="price">$0.00040</td></tr>
<tr><td class="ep">/v1/asm-dispatch (GPU)</td><td>per second</td><td class="price">$0.00250</td></tr>
<tr><td class="ep">/v1/asm-dispatch (quantum)</td><td>per circuit shot</td><td class="price">$0.04000</td></tr>
<tr><td class="ep">/v1/neuro-bind</td><td>per MSS-conditioned query</td><td class="price">$0.00220</td></tr>
<tr><td class="ep">/v1/stake</td><td>per stake tx</td><td class="price">$0.00010 + gas</td></tr>
<tr><td class="ep">/v1/mint</td><td>per ERC-1155 listing</td><td class="price">$0.00500</td></tr>
<tr><td class="ep">/beacon, /status, /symbols</td><td>per call</td><td class="price">free</td></tr>
</tbody>
</table>
<p class="txt-sm txt-mute" style="margin-top:8px">15% atomic affiliate split on every paid call when a referrer is set on the wallet.</p>
</div>
<div class="panel shim">
<div class="panel-head"><h3>Recent payments</h3><span class="meta">Base · USDC</span></div>
<table class="pay-table">
<thead><tr><th>tx</th><th>endpoint</th><th>amount</th><th>time</th></tr></thead>
<tbody id="api-payments"></tbody>
</table>
</div>
</div>
</section>
<section class="tight">
<div class="panel shim">
<div class="panel-head">
<h3>Affiliate program · live earnings</h3>
<span class="aff-status" id="aff-status"><span class="dot"></span>not registered</span>
</div>
<p class="txt-sm txt-mute" id="aff-blurb" style="margin-top:0">Your wallet is not registered as an affiliate. Visit the <a data-link="affiliates">Affiliates page</a> to set a referrer code, then share <code>?ref=&lt;your-address&gt;</code> on any link to start earning a 15% atomic split on every paid call made through your referrals.</p>
<div class="kpi-row aff" id="aff-kpis" style="display:none">
<div class="kpi"><div class="v" id="aff-referred"></div><div class="l">referred wallets</div></div>
<div class="kpi"><div class="v" id="aff-active"></div><div class="l">active (30 d)</div></div>
<div class="kpi"><div class="v" id="aff-lifetime">— USDC</div><div class="l">lifetime earned</div></div>
<div class="kpi"><div class="v" id="aff-30d">— USDC</div><div class="l">last 30 d</div></div>
</div>
<canvas id="affiliate-chart" class="chart-canvas" style="display:none"></canvas>
<p class="txt-sm txt-mute" id="aff-caption" style="margin-top:6px;display:none">x-axis: last 30 days · y-axis: USDC earned / day · single line, no fill</p>
</div>
</section>
<section class="tight">
<div class="panel shim">
<div class="panel-head"><h3>Agent row · wallet-bound services</h3><span class="meta">cross-NWO</span></div>
<p class="txt-sm txt-mute">Same wallet, same key, same billing. Switching from CHAINSTATE to NWO-ASM to NEURO requires no re-auth and no second account.</p>
<div class="cap-grid" style="padding:8px 0">
<a class="cap-link shim" data-link="f-asm"><div class="n">NWO-ASM bridge</div><div class="u">PMX IR · 8 substrate connectors</div></a>
<a class="cap-link shim" data-link="f-neuro"><div class="n">NWO NEURO bridge</div><div class="u">live MSS · Dilithium-signed</div></a>
<a class="cap-link shim" data-link="f-quantum"><div class="n">Quantum offload</div><div class="u">IBM Sherbrooke · Origin Wukong</div></a>
<a class="cap-link shim" data-link="f-market"><div class="n">DApp marketplace</div><div class="u">ERC-1155 · 15% royalty</div></a>
</div>
</div>
</section>
</div>`;
__API_KEYS = [
{ id:'cs_live_1c8e…f02a', name:'main', created:'2026-06-08', last:'2 min ago' },
{ id:'cs_live_44a1…91bb', name:'staging', created:'2026-05-22', last:'4 h ago' },
{ id:'cs_live_b7c9…02ee', name:'node-worker', created:'2026-04-04', last:'18 m ago' },
{ id:'cs_live_8d23…7c41', name:'local-dev', created:'2026-03-15', last:'2 d ago' },
];
__API_PAYMENTS = [];
renderKeys(); renderPayments(); sizeCalls(); bootCharts(); tickKPIs(); updateAffiliatePanel();
}
/* Affiliate-earnings panel — shows the white→grey gradient chart + KPIs when
the connected wallet is registered as an affiliate. Otherwise shows a CTA
pointing at the Affiliates page. In LIVE mode (csIsLive()) fetches from
the worker /affiliate/{addr}; in DEMO mode uses the seeded _affiliateHistory. */
function updateAffiliatePanel(){
const status = document.getElementById('aff-status');
const blurb = document.getElementById('aff-blurb');
const kpis = document.getElementById('aff-kpis');
const chart = document.getElementById('affiliate-chart');
const cap = document.getElementById('aff-caption');
if(!status) return;
const wallet = window.__WALLET;
// Registration model:
// DEMO mode → always show the UI (so devs can preview the panel without a wallet)
// LIVE mode → require connected wallet to query the real registration record
const liveMode = (typeof csIsLive === 'function') && csIsLive();
const registered = liveMode ? !!wallet : true;
if(!registered){
status.classList.remove('on');
status.innerHTML = '<span class="dot"></span>' + (liveMode && !wallet ? 'connect wallet for live' : 'not registered');
blurb.style.display = '';
blurb.innerHTML = liveMode && !wallet
? 'Connect your wallet to query its affiliate-registration status on the live worker. Demo mode shows seeded reference data without requiring a wallet.'
: 'Your wallet is not registered as an affiliate. Visit the <a data-link="affiliates">Affiliates page</a> to set a referrer code, then share <code>?ref=&lt;your-address&gt;</code> on any link to start earning a 15% atomic split on every paid call made through your referrals.';
kpis.style.display = 'none';
chart.style.display = 'none';
cap.style.display = 'none';
return;
}
// Registered → show data
status.classList.add('on');
status.innerHTML = '<span class="dot"></span>registered' + (liveMode ? ' · live' : ' · demo');
blurb.style.display = 'none';
kpis.style.display = '';
chart.style.display = '';
cap.style.display = '';
// Populate KPIs
if(liveMode && window.__CHAINSTATE_WORKER){
fetch(window.__CHAINSTATE_WORKER + '/affiliate/' + wallet)
.then(r => r.json())
.then(d => {
document.getElementById('aff-referred').textContent = d.referred != null ? d.referred : '—';
document.getElementById('aff-active').textContent = d.active_30d != null ? d.active_30d : '—';
document.getElementById('aff-lifetime').textContent = (d.lifetime_usdc != null ? Number(d.lifetime_usdc).toFixed(2) : '—') + ' USDC';
document.getElementById('aff-30d').textContent = (d.last_30d_usdc != null ? Number(d.last_30d_usdc).toFixed(2) : '—') + ' USDC';
if(Array.isArray(d.daily) && d.daily.length){
_affiliateHistory = d.daily.slice(-30);
}
})
.catch(()=>{
document.getElementById('aff-referred').textContent = '—';
document.getElementById('aff-active').textContent = '—';
document.getElementById('aff-lifetime').textContent = '— USDC';
document.getElementById('aff-30d').textContent = '— USDC';
});
} else {
// demo values consistent with the seeded _affiliateHistory
const sum30 = _affiliateHistory.reduce((a,b)=>a+b, 0);
document.getElementById('aff-referred').textContent = '47';
document.getElementById('aff-active').textContent = '31';
document.getElementById('aff-lifetime').textContent = '284.50 USDC';
document.getElementById('aff-30d').textContent = sum30.toFixed(2) + ' USDC';
}
}
window.updateAffiliatePanel = updateAffiliatePanel;
function renderKeys(){
const root = document.getElementById('api-keys-list');
if(!root) return;
root.innerHTML = __API_KEYS.map(k=>`<div class="key-row">
<span class="kid">${k.id}</span>
<span class="kn">${k.name} · created ${k.created}</span>
<button class="ghost sm" onclick="copyKey('${k.id}')">copy</button>
<button class="ghost sm" onclick="doRevoke('${k.id}')">revoke</button>
</div>`).join('') || '<p class="txt-sm txt-mute">No keys yet. Click <strong>+ Create key</strong>.</p>';
}
function copyKey(id){ try{ navigator.clipboard.writeText(id); }catch(e){} }
function doCreateKey(){
const name = prompt('Key label?', 'dev'); if(!name) return;
if(__API_MODE==='live' && !window.__WALLET){ alert('Connect wallet first for live keys.'); return; }
const id = 'cs_'+(__API_MODE==='live'?'live':'test')+'_'+Math.random().toString(16).slice(2,6)+'…'+Math.random().toString(16).slice(2,6);
__API_KEYS.unshift({ id, name, created:new Date().toISOString().slice(0,10), last:'just now' });
renderKeys();
}
function doRevoke(id){
if(!confirm('Revoke '+id+'?')) return;
__API_KEYS = __API_KEYS.filter(k=>k.id!==id);
renderKeys();
}
window.copyKey=copyKey; window.doCreateKey=doCreateKey; window.doRevoke=doRevoke;
function renderPayments(){
const root = document.getElementById('api-payments');
if(!root) return;
if(!__API_PAYMENTS.length){
const eps = ['/v1/query','/v1/asm-dispatch','/v1/asm-compile','/v1/neuro-bind','/v1/stake'];
for(let i=0;i<10;i++){
__API_PAYMENTS.push({
tx: '0x'+Math.random().toString(16).slice(2,10)+'…',
ep: eps[Math.floor(Math.random()*eps.length)],
amount: (Math.random()*0.03+0.0001).toFixed(5),
time: relTime(Math.floor(Date.now()/1000) - Math.floor(Math.random()*1800))
});
}
}
root.innerHTML = __API_PAYMENTS.map(p=>`<tr>
<td><a href="#" onclick="event.preventDefault()">${p.tx}</a></td>
<td class="ep">${p.ep}</td>
<td class="price">$${p.amount}</td>
<td class="txt-mono txt-mute">${p.time}</td>
</tr>`).join('');
}
function toggleApiMode(){
if(__API_MODE==='demo'){
if(!window.__WALLET){ alert('Connect wallet to enter live mode.'); return; }
__API_MODE='live';
} else __API_MODE='demo';
refreshApiMode();
}
function refreshApiMode(){
const pill = document.getElementById('api-mode-pill');
const btn = document.getElementById('api-mode-btn');
if(!pill||!btn) return;
if(__API_MODE==='live'){
pill.className='pill live'; pill.innerHTML='<span class="dot"></span>live · wallet '+ (window.__WALLET||'').slice(0,6)+'…';
btn.textContent='Back to demo';
} else {
pill.className='pill design'; pill.innerHTML='<span class="dot"></span>demo data';
btn.textContent='Switch to live mode (wallet)';
}
}
window.toggleApiMode=toggleApiMode;
// Seed _callsHistory with 60 demo data points so the chart line is visible
// immediately on first paint, instead of waiting 90+ s for tickKPIs() to
// accumulate enough samples. The values match the random range tickKPIs uses
// in DEMO mode (22–30 calls/s) so visual continuity is preserved when LIVE
// data starts being appended.
let _callsHistory = Array.from({length: 60}, (_,i) => {
const base = 24 + Math.sin(i/8) * 2.5; // gentle baseline wave
return Math.max(18, base + (Math.random()-.5) * 3);
});
// Affiliate earnings — last 30 days in USDC (one value per day). Seeded with
// a plausible demo curve so the chart renders immediately on the API page;
// real values come from the worker /affiliate/{addr} endpoint in LIVE mode.
let _affiliateHistory = [
0.92, 1.18, 1.40, 1.05, 0.88, 1.62, 2.04, 1.71, 1.49, 1.83,
2.27, 2.61, 2.18, 1.95, 2.42, 2.88, 3.14, 2.76, 2.51, 3.22,
3.55, 3.21, 2.94, 3.48, 3.91, 4.10, 3.74, 3.50, 4.18, 4.62
];
function tickKPIs(){
const setKPIs = (calls, lat, gas, cache) => {
const elc = document.getElementById('k-calls'); if(elc) elc.textContent=calls;
const ell = document.getElementById('k-latency'); if(ell) ell.textContent=lat;
const elg = document.getElementById('k-gas'); if(elg) elg.textContent=gas;
const elh = document.getElementById('k-cache'); if(elh) elh.textContent=cache;
const ti = document.getElementById('api-tick'); if(ti) ti.textContent='tick · '+(parseInt((ti.textContent||'tick · 0').replace('tick · ',''),10)+1);
const callsNum = parseFloat(String(calls).replace(/[^0-9.]/g,'')) || 0;
_callsHistory.push(callsNum);
if(_callsHistory.length>60) _callsHistory.shift();
paintCalls();
};
const liveCall = (typeof csIsLive === 'function') && csIsLive() && !!window.__CHAINSTATE_WORKER;
if(liveCall){
fetch(window.__CHAINSTATE_WORKER + '/status')
.then(r => r.json())
.then(s => {
// /status returns { ok, height, nodes_known, cache_size, region, … }
const calls = (s.tps != null) ? Number(s.tps).toFixed(1) : '—';
const lat = (s.p50_latency_ms != null) ? s.p50_latency_ms + ' ms' : '—';
const gas = (s.avg_gas != null) ? Number(s.avg_gas).toFixed(5) : '—';
const cache = (s.cache_hit_rate != null) ? (Number(s.cache_hit_rate)*100).toFixed(1) + ' %' : '—';
setKPIs(calls, lat, gas, cache);
})
.catch(() => { setKPIs('—', '— ms', '—', '— %'); });
} else {
const calls = (Math.random()*8+22).toFixed(1);
const lat = Math.floor(700 + Math.random()*350)+' ms';
const gas = (Math.random()*0.001+0.001).toFixed(5);
const cache = (60 + Math.random()*30).toFixed(1)+' %';
setKPIs(calls, lat, gas, cache);
}
if(document.querySelector('.page[data-page="api"].active')) setTimeout(tickKPIs, 1500);
}
function sizeCalls(){
const cv = document.getElementById('calls-chart');
if(!cv) return;
const w = cv.clientWidth || cv.parentElement.clientWidth || 400;
const h = 180;
const ddpr = Math.min(window.devicePixelRatio||1, 2);
cv.width = w*ddpr; cv.height = h*ddpr;
cv.style.width = w+'px'; cv.style.height = h+'px';
const cx = cv.getContext('2d'); cx.setTransform(ddpr,0,0,ddpr,0,0);
}
/* Shared gradient-line chart painter — used by KPI calls chart and affiliate earnings chart.
White→grey horizontal gradient stroke (more recent = brighter), no fill, faint grid. */
function _paintGradientChart(canvasId, history, opts){
const cv = document.getElementById(canvasId); if(!cv) return;
opts = opts || {};
const dpr = window.devicePixelRatio || 1;
const w = cv.clientWidth, h = cv.clientHeight;
// Skip if canvas isn't laid out yet (display:none, page not active, etc.).
// Returning here avoids zeroing the internal buffer, so once the canvas
// gets a real layout, the very next frame paints cleanly.
if(w <= 0 || h <= 0) return;
if(cv.width !== w*dpr || cv.height !== h*dpr){
cv.width = w*dpr; cv.height = h*dpr;
}
const cx = cv.getContext('2d');
cx.setTransform(dpr,0,0,dpr,0,0);
cx.clearRect(0,0,w,h);
// faint horizontal grid lines
cx.strokeStyle = 'rgba(255,255,255,.06)';
cx.lineWidth = 0.5;
for(let y=1;y<=4;y++){
const yy = (h/4)*y;
cx.beginPath(); cx.moveTo(0,yy); cx.lineTo(w,yy); cx.stroke();
}
if(!history || history.length < 2) return;
const max = Math.max(...history, opts.minMax || 10);
const min = Math.min(...history, 0);
// horizontal gradient: dim past → bright present
const lg = cx.createLinearGradient(0,0,w,0);
lg.addColorStop(0, 'rgba(110,110,115,.30)');
lg.addColorStop(0.45,'rgba(180,180,185,.70)');
lg.addColorStop(1, 'rgba(255,255,255,1.0)');
cx.strokeStyle = lg;
cx.lineWidth = 1.7;
cx.lineCap = 'round';
cx.lineJoin = 'round';
cx.beginPath();
history.forEach((v,i)=>{
const x = (i/(history.length-1)) * w;
const y = h - ((v - min) / Math.max(max-min, 0.0001)) * (h-22) - 11;
if(i===0) cx.moveTo(x,y); else cx.lineTo(x,y);
});
cx.stroke();
// bright dot at the most-recent point
const last = history[history.length-1];
const lx = w - 2;
const ly = h - ((last - min) / Math.max(max-min, 0.0001)) * (h-22) - 11;
cx.fillStyle = '#fff';
cx.beginPath(); cx.arc(lx, ly, 2.6, 0, Math.PI*2); cx.fill();
}
function paintCalls(){ _paintGradientChart('calls-chart', _callsHistory, {minMax:10}); }
function paintAffiliate(){ _paintGradientChart('affiliate-chart', _affiliateHistory, {minMax:1}); }
function callsLoop(){
// Self-perpetuating rAF — never exits. paintCalls / paintAffiliate
// early-return when their canvas isn't in the DOM (when the API page
// isn't mounted/active), so this is essentially free when off-page.
paintCalls();
paintAffiliate();
requestAnimationFrame(callsLoop);
}
let _chartsBooted = false;
function bootCharts(){
if(_chartsBooted) return;
_chartsBooted = true;
requestAnimationFrame(callsLoop);
}
/* ============================================================
R&D — CHAINSTATE Whitepaper v1.0 (live) + NWOWorkfield foundational paper (live)
============================================================ */
function renderRnD(){
const root = document.querySelector('.page[data-page="rnd"]');
if(!root) return;
const PRIMARY = 'https://huggingface.co/spaces/CPater/chainstate/resolve/main/whitepaper.pdf';
const SUPPORTING = 'https://huggingface.co/spaces/CPater/chainstate/resolve/main/NWOWorkfield.pdf';
const RG_WP = 'https://www.researchgate.net/publication/407444375_CHAINSTATE_WHITEPAPER_A_Symbolic-Weight_Blockchain_for_Cognitive_Transactions';
const RG_FOUND = 'https://www.researchgate.net/publication/406896310_Distributed_Cognitive_Work_in_Edge-Resident_Language-Model_Networks';
const PODCAST = 'https://huggingface.co/spaces/CPater/chainstate/resolve/main/podcast.m4a';
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · research &amp; development</div>
<h1>R&amp;D · papers</h1>
<p class="lede">The CHAINSTATE Whitepaper v1.0 is live: 19-page A4 paper, 9 numbered equations, 7 figures, 4 tables, 20 references — covering the 65,536-dimensional symbolic substrate, reputation-weighted Bayesian log-pooling consensus, NWO-ASM and NWO NEURO composition, the post-quantum security envelope, market positioning, 20 verticals, and the four-horizon roadmap. The foundational paper <em>Distributed Cognitive Work in Edge-Resident Language-Model Networks</em> develops the thermodynamic framework that motivates CHAINSTATE.</p>
<div class="meta-row">
<span class="pill live"><span class="dot"></span>whitepaper v1.0 · live</span>
<span class="pill live"><span class="dot"></span>foundational paper · live</span>
<span class="pill live"><span class="dot"></span>podcast · live</span>
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="rnd-grid">
<!-- ── CHAINSTATE Whitepaper card (with podcast) ── -->
<div class="rnd-paper-card shim">
<div class="author">CHAINSTATE · whitepaper v1.0 · June 2026</div>
<div class="ttl">A Symbolic-Weight Blockchain for Cognitive Transactions</div>
<p class="txt-sm txt-mute" style="margin:0">Reputation-Weighted Bayesian Consensus over Distributed Language-Model Swarms with Post-Quantum Security and NWO-ASM / NEURO Composition</p>
<div class="abs">
We present CHAINSTATE, a symbolic-weight blockchain whose unit of transaction is a cognitive query and whose unit of agreement is a reputation-weighted Bayesian log-pool over a distributed language-model swarm. The chain's weights are universal symbols — mathematical operators, scientific glyphs, full natural-language alphabets, alchemical sigils, Unicode 15.1 emoji and control-flow arrows — embedded in a 65,536-dimensional space across six structured subspaces with a learned cross-subspace interaction mask. Each transaction dispatches to k ≥ 10 inference nodes; their per-node symbolic states are pooled until cosine-agreement exceeds 0.95 (typically 3–7 rounds). Block production rotates through a reputation-weighted VRF on a 2-second target time, 64 transactions per block. The whole stack is wrapped by a post-quantum security envelope: CRYSTALS-Dilithium signatures (FIPS&nbsp;204), Kyber-1024 KEM (FIPS&nbsp;203), and SHA3-256 commitments. We derive the math, prove convergence and slashing-bound sybil resistance, compare CHAINSTATE on five axes against Bitcoin, Ethereum, Solana, Bittensor, Avalanche and Polygon, and develop the philosophical position: CHAINSTATE makes cognitive work the unit of useful computation, makes belief aggregation primitive at the protocol layer, and offers a sovereign biometric-identity path that is categorically incompatible with the regulatory direction of state-issued digital identity.
</div>
<div class="actions">
<button class="ghost bold" onclick="openPdf('${PRIMARY}', 'CHAINSTATE Whitepaper v1.0')">📄 Open PDF in-place</button>
<a class="ghost sm" href="${PRIMARY}" target="_blank" rel="noopener">↗ ${PRIMARY.replace('https://','')}</a>
<a class="ghost sm" href="${RG_WP}" target="_blank" rel="noopener">🔬 ResearchGate · publication 407444375</a>
</div>
<div class="divider"></div>
<h3 style="font-family:var(--display);font-size:.95em;font-weight:600;letter-spacing:.14em;text-transform:uppercase;padding-bottom:8px;border-bottom:1px solid var(--line);margin:0">Audio companion</h3>
<div class="podcast-player">
<div class="play" id="podcast-play"></div>
<div class="meta">
<div>CHAINSTATE · author commentary</div>
<div class="t" id="podcast-time">—:— / —:—</div>
</div>
</div>
<audio id="podcast-audio" preload="metadata" src="${PODCAST}"></audio>
<p class="txt-sm txt-mute" style="margin-top:6px">Audio at <code>${PODCAST.replace('https://','')}</code></p>
</div>
<!-- ── NWOWorkfield foundational paper card (no podcast) ── -->
<div class="rnd-paper-card shim">
<div class="author">NWO Capital · foundational paper · June 2026</div>
<div class="ttl">Distributed Cognitive Work in Edge-Resident Language-Model Networks</div>
<p class="txt-sm txt-mute" style="margin:0">A Thermodynamic and Information-Theoretic Framework for Hive-Mind Architectures on Cloudflare Workers</p>
<div class="abs">
We develop a framework for distributed language-model inference in which the elemental unit is taken in its literal physical sense: a <em>worker</em> performs cognitive work against an information potential, exchanging beacons with neighbouring workers over a globally distributed substrate. Concretely, we instantiate the framework on Cloudflare Workers, using Durable Objects for synchronised state, KV / D1 / R2 for memory at multiple time-scales, and edge compute for inference dispatch. We give a thermodynamic reading of inference (W = ∫ F · dr translated into a semantic gradient), a variational free-energy account of collective belief, an explicit reputation-weighted Bayesian consensus rule, a master equation for state diffusion through the beacon graph, and a quorum-survival analysis showing that even with modest per-node uptime the swarm is robust to large fractions of node loss. 14-page A4 preprint, 22 numbered equations, 5 figures, 15 references.
</div>
<div class="actions">
<button class="ghost bold" onclick="openPdf('${SUPPORTING}', 'Distributed Cognitive Work · foundational paper')">📄 Open PDF in-place</button>
<a class="ghost sm" href="${SUPPORTING}" target="_blank" rel="noopener">↗ ${SUPPORTING.replace('https://','')}</a>
<a class="ghost sm" href="${RG_FOUND}" target="_blank" rel="noopener">🔬 ResearchGate · publication 406896310</a>
</div>
<div class="divider"></div>
<p class="txt-sm txt-mute">Read this paper first if you want the thermodynamic reasoning behind CHAINSTATE's choice of cognitive work as the unit of consensus. The whitepaper above is the protocol-level instantiation of the framework developed here; it cites this paper as reference [5].</p>
</div>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">scope</div><h2>What each paper covers</h2></div></div>
<div class="two-col">
<div class="col-card shim">
<h3>CHAINSTATE Whitepaper · structural map</h3>
<ul>
<li><strong>§3 Universal Semiotic Embedding</strong> — six-subspace decomposition (math 4,096 · science 8,192 · language 16,384 · occult 4,096 · emoji 16,384 · control 16,384), cross-subspace 6×6 interaction mask, composition with four sigmoid gates</li>
<li><strong>§4 Consensus</strong> — per-node SHA3-256 compute proof, reputation-weighted log-pool, iterative refinement with 0.7 agreement filter and 0.95 convergence threshold, formal convergence theorem under adversarial-fraction bound</li>
<li><strong>§5 Reputation, blocks, gas</strong> — EMA reputation dynamics (α 0.10, β 0.20, γ 0.99), 1% / 5% / 100% slashing, VRF proposer, 2-s blocks, four-component gas formula</li>
<li><strong>§6 Post-quantum envelope</strong> — Dilithium FIPS&nbsp;204 sigs, Kyber-1024 FIPS&nbsp;203 KEM, SHA3-256 commitments, SLH-DSA migration path</li>
<li><strong>§7–§9</strong> — NWO-ASM PMX IR bridge, NWO NEURO MSS conditioning math, five-axis comparison with seven incumbent chains, TypeScript SDK and three unique-capability primitives</li>
<li><strong>§10–§12</strong> — political-economic position vs UK Online Safety Act / EUDI digital identity, 20-vertical roadmap, four-horizon timeline</li>
</ul>
</div>
<div class="col-card shim">
<h3>Foundational paper · structural map</h3>
<ul>
<li><strong>§3 The worker as a physical entity</strong> — information potential Φ(s) = −k<sub>B</sub>T<sub>eff</sub>·ln&nbsp;Z(s), cognitive work W = ∫⟨∇Φ, v⟩dτ, Langevin noise on the gradient descent</li>
<li><strong>§4.1 Variational free energy of the swarm</strong> — per-agent free energy ℱ<sub>a</sub>, network ℱ<sub>net</sub> with synergy term λ·I(s<sub>1</sub>;…;s<sub>N</sub>) rewarding mutual information across agents</li>
<li><strong>§4.2 Beacon dynamics</strong> — local sufficient statistics ⟨id, σ, c, τ, r̂⟩, information flux equation, master equation for state diffusion on the beacon graph</li>
<li><strong>§4.3–§4.4</strong> — log-pool aggregation rule (Genest &amp; Zidek 1986), discrete reputation dynamical map, emergent knowledge-graph growth with fixed point E<sup></sup> = λV(V−1)/(2μ)</li>
<li><strong>§5 Quorum survival</strong> — binomial P[op] for k-of-N quorum, heterogeneous-regional generalisation, edge-persistence and three-tier memory under outages</li>
<li><strong>§6 Comparison with blockchains</strong> — throughput, energy-ROI, and trust-model axes; complementarity with chain finality rather than substitution</li>
</ul>
</div>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">summary</div><h2>How the two papers compose</h2></div></div>
<div class="risk-grid">
<div class="risk-card"><h4>The foundational paper sets the physics</h4><p>It establishes that an LM agent performing inference can be read literally as a worker doing physical work against an information potential. The unit is the joule, the work is cognitive, the consensus is Bayesian. This is the theory of why a swarm of edge-resident workers is a credible architecture in the first place.</p><div class="mitigation">Read for the math of cognitive work, the free-energy account of collective belief, and the survival analysis under regional outages.</div></div>
<div class="risk-card"><h4>The whitepaper builds the protocol</h4><p>Where the foundational paper develops the architecture as an open framework, the whitepaper instantiates it as a blockchain primitive on Base mainnet 8453: USDC settlement, $STATE staking, VRF block production, Dilithium-signed receipts, ERC-1155 marketplace, 35/35/15/15 splitter. Same swarm, same consensus, same thermodynamic accounting — exposed as a chain.</p><div class="mitigation">Read for the protocol-level details, the developer surface, the comparison table, the verticals, and the regulatory positioning.</div></div>
</div>
</section>
</div>`;
// podcast wiring — only the whitepaper card has audio
const audio = document.getElementById('podcast-audio');
const playBtn = document.getElementById('podcast-play');
const timeEl = document.getElementById('podcast-time');
if(audio && playBtn){
playBtn.addEventListener('click', ()=>{
if(audio.paused){ audio.play().then(()=>playBtn.textContent='⏸').catch(()=>{}); }
else { audio.pause(); playBtn.textContent='▶'; }
});
audio.addEventListener('timeupdate', ()=>{
function fmt(s){ if(isNaN(s)) return '—:—'; const m=Math.floor(s/60), r=Math.floor(s%60); return m+':'+(r<10?'0'+r:r); }
timeEl.textContent = fmt(audio.currentTime)+' / '+fmt(audio.duration||NaN);
});
audio.addEventListener('ended', ()=>{ playBtn.textContent='▶'; });
}
}
/* ============================================================
DEPLOYMENT page — secrets, wrangler, GH Actions
============================================================ */
function renderDeployment(){
const root = document.querySelector('.page[data-page="deployment"]');
if(!root) return;
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · deploy</div>
<h1>One-file deploy · Cloudflare + HF Space</h1>
<p class="lede">CHAINSTATE deploys as a single Cloudflare Worker (the edge) plus this HF Space (the frontend). Both are wired into a single GitHub Actions workflow that ships on every push to <code>main</code>. Below are the three secrets you need and how to get each one.</p>
<div class="meta-row">
<span class="pill live"><span class="dot"></span>worker · single file</span>
<span class="pill live"><span class="dot"></span>HF Space · static</span>
<span class="pill beta"><span class="dot"></span>GH Action · one workflow</span>
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="deploy-step shim">
<h3><span class="num">1</span>Get your Cloudflare API token</h3>
<p>Open <a href="https://dash.cloudflare.com/profile/api-tokens" target="_blank" rel="noopener" style="color:var(--math);text-decoration:underline">dash.cloudflare.com/profile/api-tokens</a><strong>Create Token</strong> → use the <strong>"Edit Cloudflare Workers"</strong> template. Scope: <em>your account</em>. Copy the token immediately; it's only shown once.</p>
<p class="txt-sm txt-mute">Required permissions baked into the template: <code>Account · Workers Scripts · Edit</code>, <code>Account · Workers KV · Edit</code>, <code>Zone · Workers Routes · Edit</code>.</p>
</div>
<div class="deploy-step shim">
<h3><span class="num">2</span>Get your Cloudflare Account ID</h3>
<p>Go to <a href="https://dash.cloudflare.com" target="_blank" rel="noopener" style="color:var(--math);text-decoration:underline">dash.cloudflare.com</a>. The 32-character hex Account ID is in the right sidebar of any zone-overview page. Copy it.</p>
</div>
<div class="deploy-step shim">
<h3><span class="num">3</span>Get your HuggingFace access token</h3>
<p>Open <a href="https://huggingface.co/settings/tokens" target="_blank" rel="noopener" style="color:var(--math);text-decoration:underline">huggingface.co/settings/tokens</a><strong>New token</strong> → role <strong>"Write"</strong> → name it <code>chainstate-deploy</code>. Copy the token.</p>
</div>
<div class="deploy-step shim">
<h3><span class="num">4</span>Add all three as GitHub Secrets</h3>
<p>In your GitHub repo: <strong>Settings → Secrets and variables → Actions → New repository secret</strong>. Add the three secrets exactly as named below.</p>
<table class="secret-table">
<thead><tr><th>secret name</th><th>where it comes from</th><th>used for</th></tr></thead>
<tbody>
<tr><td>CF_API_TOKEN</td><td>step 1 — Cloudflare API tokens page</td><td>authenticates <code>wrangler deploy</code></td></tr>
<tr><td>CF_ACCOUNT_ID</td><td>step 2 — Cloudflare dashboard right sidebar</td><td>targets the right CF account for the Worker</td></tr>
<tr><td>HF_TOKEN</td><td>step 3 — HF tokens page (write scope)</td><td>pushes the Space contents via <code>huggingface_hub</code></td></tr>
</tbody>
</table>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">files</div><h2>The three files that make it work</h2></div></div>
<div class="two-col">
<div class="col-card shim">
<h3>wrangler.toml</h3>
<pre class="code">name = "chainstate-worker"
main = "workers/edge-worker.js"
compatibility_date = "2024-09-23"
[[kv_namespaces]]
binding = "CHAINSTATE_NODES"
id = "&lt;CREATE BELOW&gt;"
[[kv_namespaces]]
binding = "CHAINSTATE_CACHE"
id = "&lt;CREATE BELOW&gt;"
[[kv_namespaces]]
binding = "CHAINSTATE_CONSENSUS"
id = "&lt;CREATE BELOW&gt;"
[vars]
SWARM_SIZE = "50"
CONSENSUS_DEPTH = "3"
CACHE_TTL = "300"
RATE_LIMIT = "60"</pre>
<p class="txt-sm txt-mute">Create the three KV namespaces once:</p>
<pre class="code">npx wrangler kv:namespace create CHAINSTATE_NODES
npx wrangler kv:namespace create CHAINSTATE_CACHE
npx wrangler kv:namespace create CHAINSTATE_CONSENSUS
<span class="c"># paste the printed IDs into wrangler.toml above</span></pre>
</div>
<div class="col-card shim">
<h3>HF Space README.md (frontmatter)</h3>
<pre class="code">---
title: CHAINSTATE
emoji: ⛓
colorFrom: gray
colorTo: black
sdk: static
app_file: index.html
pinned: false
short_description: Symbolic-weight blockchain with integrated LM swarm
license: mit
---
</pre>
<p class="txt-sm txt-mute">The Space is a static HF Space — no Python runtime, just the <code>index.html</code> file you're reading right now. Update the Space by pushing to <code>main</code>.</p>
</div>
</div>
</section>
<section class="tight">
<div class="col-card shim">
<h3>.github/workflows/deploy.yml — single workflow ships both</h3>
<pre class="code"><span class="k">name</span>: deploy
<span class="k">on</span>:
push:
branches: [main]
<span class="k">jobs</span>:
<span class="n">cf-worker</span>:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci || npm i
- name: Deploy Worker
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${'$'}{{ secrets.CF_API_TOKEN }}
accountId: ${'$'}{{ secrets.CF_ACCOUNT_ID }}
<span class="n">hf-space</span>:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install huggingface_hub
- name: Push to HF Space
run: |
python - <span class="s">&lt;&lt;'PY'</span>
from huggingface_hub import HfApi
api = HfApi(token="${'$'}{{ secrets.HF_TOKEN }}")
api.upload_folder(
folder_path=".",
repo_id="CPater/chainstate",
repo_type="space",
ignore_patterns=[".git*", "node_modules*", ".github*"],
)
PY</pre>
<p class="txt-sm txt-mute" style="margin-top:8px">First push to <code>main</code> after adding the three secrets ships everything: Worker → CF, frontend → HF.</p>
</div>
</section>
<section class="tight">
<div class="section-head"><div><div class="eyebrow">verify</div><h2>Smoke-test after deploy</h2></div></div>
<pre class="code"><span class="c"># 1. Verify Worker is live</span>
curl https://chainstate-worker.&lt;your-cf&gt;.workers.dev/status
<span class="c"># 2. Submit a cognitive query</span>
curl -X POST https://chainstate-worker.&lt;your-cf&gt;.workers.dev/query \\
-H "Content-Type: application/json" \\
-d '{"query": "∫∂x → ?", "swarmSize": 20, "consensusDepth": 3}'
<span class="c"># 3. Confirm HF Space is live</span>
open https://cpater-chainstate.static.hf.space/
<span class="c"># 4. Point the Space at the Worker (open browser console on the Space, run):</span>
window.__CHAINSTATE_WORKER = "https://chainstate-worker.&lt;your-cf&gt;.workers.dev"</pre>
</section>
</div>`;
}
/* ============================================================
AFFILIATES
============================================================ */
function renderAffiliates(){
const root = document.querySelector('.page[data-page="affiliates"]');
if(!root) return;
root.innerHTML = `
<div class="subhero">
<div class="eyebrow">module · affiliates</div>
<h1>Affiliates · 15% atomic split</h1>
<p class="lede">Every paid CHAINSTATE call (and every NWO Capital call) carries an atomic 15% referrer split at the contract layer. Same canonical <code>MetaStateSplitter</code> as NWO-ASM, NEURO, Cardiac, METASTATE. No off-chain bookkeeping. No delay. The referrer is paid in the same block.</p>
<div class="meta-row">
<span class="pill live"><span class="dot"></span>splitter live · Base 8453</span>
<span class="pill live"><span class="dot"></span>15% perpetual</span>
<span class="pill live"><span class="dot"></span>USDC settlement</span>
</div>
</div>
<div class="wrap">
<section class="tight">
<div class="aff-wrap">
<div class="col-card shim">
<h3>Your referral link</h3>
<p class="txt-sm txt-mute">Connect a wallet — the link below auto-populates with your address. Anyone who lands on a Space using your link and creates a key has 15% of their lifetime paid usage routed to you, automatically, by the splitter contract.</p>
<div id="ref-link">https://cpater-chainstate.static.hf.space/?ref=<connect wallet></div>
<div class="cta-row">
<button class="ghost" id="aff-copy" onclick="copyAffLink()">Copy link</button>
<button class="ghost" id="aff-share" onclick="shareAffLink()">Share</button>
</div>
</div>
<div class="col-card shim">
<h3>Splitter wire</h3>
<table class="eco-table">
<thead><tr><th>where</th><th>address / detail</th></tr></thead>
<tbody>
<tr><td>MetaStateSplitter</td><td><code>0x93a7962f75475b7e3Fbb62d3A23194f8833b1BE4</code></td></tr>
<tr><td>Settlement currency</td><td>USDC · <code>0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913</code></td></tr>
<tr><td>Chain</td><td>Base mainnet 8453</td></tr>
<tr><td>Split (with referrer)</td><td>35% founder · 35% agent · 15% ops · 15% referrer</td></tr>
<tr><td>Split (no referrer)</td><td>35% founder · 35% agent · 30% ops</td></tr>
<tr><td>Execution</td><td>atomic — same tx as the paid call</td></tr>
</tbody>
</table>
<div class="divider"></div>
<h3>Your earnings (demo)</h3>
<div class="lvl-row"><span class="l">referred users</span><span class="v">17</span></div>
<div class="lvl-row"><span class="l">last 7 d</span><span class="v">$0.42 USDC</span></div>
<div class="lvl-row"><span class="l">lifetime</span><span class="v">$3.91 USDC</span></div>
<p class="txt-sm txt-mute" style="margin-top:8px">Connect wallet for live numbers.</p>
</div>
</div>
</section>
<section class="tight">
<div class="flow-box shim"><h3>Settlement flow</h3>
<svg class="flow-svg" viewBox="0 0 720 200" xmlns="http://www.w3.org/2000/svg">
<rect x="20" y="80" width="120" height="44" rx="6" fill="rgba(255,255,255,.04)" stroke="rgba(255,255,255,.4)"/>
<text x="80" y="106" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="11" font-weight="600" letter-spacing="1.5" fill="#fff">CLIENT PAYS</text>
<line x1="140" y1="102" x2="220" y2="102" stroke="rgba(255,255,255,.4)"/><polygon points="220,102 212,98 212,106" fill="#fff"/>
<rect x="220" y="80" width="160" height="44" rx="6" fill="rgba(255,255,255,.04)" stroke="rgba(255,255,255,.4)"/>
<text x="300" y="106" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="11" font-weight="600" letter-spacing="1.5" fill="#fff">SPLITTER 0x93a7…</text>
<line x1="380" y1="102" x2="460" y2="102" stroke="rgba(255,255,255,.4)"/><polygon points="460,102 452,98 452,106" fill="#fff"/>
<rect x="460" y="40" width="120" height="32" rx="6" fill="rgba(255,255,255,.04)" stroke="rgba(125,240,168,.6)"/>
<text x="520" y="61" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="10" font-weight="600" letter-spacing="1.5" fill="#7df0a8">FOUNDER 35%</text>
<rect x="460" y="80" width="120" height="32" rx="6" fill="rgba(255,255,255,.04)" stroke="rgba(122,208,255,.6)"/>
<text x="520" y="101" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="10" font-weight="600" letter-spacing="1.5" fill="#7ad0ff">AGENT 35%</text>
<rect x="460" y="120" width="120" height="32" rx="6" fill="rgba(255,255,255,.04)" stroke="rgba(240,224,125,.6)"/>
<text x="520" y="141" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="10" font-weight="600" letter-spacing="1.5" fill="#f0e07d">OPS 15%</text>
<rect x="460" y="160" width="120" height="32" rx="6" fill="rgba(255,255,255,.04)" stroke="rgba(255,140,184,.6)"/>
<text x="520" y="181" text-anchor="middle" font-family="Orbitron,sans-serif" font-size="10" font-weight="600" letter-spacing="1.5" fill="#ff8cb8">REFERRER 15%</text>
</svg>
</div>
</section>
</div>`;
}
function copyAffLink(){ const t = document.getElementById('ref-link').textContent; try{ navigator.clipboard.writeText(t);}catch(e){} }
function shareAffLink(){
const url = document.getElementById('ref-link').textContent;
if(navigator.share){ navigator.share({url, title:'CHAINSTATE'}).catch(()=>{}); }
else copyAffLink();
}
window.copyAffLink=copyAffLink; window.shareAffLink=shareAffLink;
function updateAffiliate(){
const el = document.getElementById('ref-link');
if(!el) return;
if(window.__WALLET){ el.textContent = 'https://cpater-chainstate.static.hf.space/?ref='+window.__WALLET; }
else el.textContent = 'https://cpater-chainstate.static.hf.space/?ref=<connect wallet>';
}
</script>
<script>
/* ============================================================
MODAL · PDF · WALLET · INIT
============================================================ */
function openModal(title, html){
document.getElementById('modal-title').textContent = title || '—';
document.getElementById('modal-body').innerHTML = html || '';
document.getElementById('modal-bg').classList.add('open');
}
function closeModal(){ document.getElementById('modal-bg').classList.remove('open'); }
window.openModal=openModal; window.closeModal=closeModal;
document.getElementById('modal-x').addEventListener('click', closeModal);
document.getElementById('modal-bg').addEventListener('click', (e)=>{ if(e.target.id==='modal-bg') closeModal(); });
function openPdf(url, title){
document.getElementById('pdf-title').textContent = title || 'PDF';
document.getElementById('pdf-frame').src = url;
document.getElementById('pdf-open-tab').href = url;
document.getElementById('pdf-modal-bg').classList.add('open');
}
function closePdf(){ document.getElementById('pdf-modal-bg').classList.remove('open'); document.getElementById('pdf-frame').src='about:blank'; }
window.openPdf=openPdf; window.closePdf=closePdf;
document.getElementById('pdf-modal-x').addEventListener('click', closePdf);
document.getElementById('pdf-modal-bg').addEventListener('click', (e)=>{ if(e.target.id==='pdf-modal-bg') closePdf(); });
document.addEventListener('keydown', (e)=>{
if(e.key==='Escape'){ closeModal(); closePdf(); }
});
/* ============== WALLET ============== */
function shortAddr(a){ return a ? a.slice(0,6)+'…'+a.slice(-4) : ''; }
function updateWalletUI(){
const btn = document.getElementById('wallet-btn');
if(!btn) return;
const dot = btn.querySelector('span');
const addr = btn.querySelector('.addr');
if(window.__WALLET){
if(dot) dot.style.background = 'var(--live)';
if(addr) addr.textContent = shortAddr(window.__WALLET);
} else {
if(dot) dot.style.background = 'var(--w3)';
if(addr) addr.textContent = 'Connect Wallet';
}
updateAffiliate();
if(typeof updateAffiliatePanel === 'function') updateAffiliatePanel();
}
async function connectWallet(){
if(!window.ethereum){ alert('No EVM wallet detected. Install MetaScasask / Rabby / Coinbase Wallet.'); return; }
try{
const accs = await window.ethereum.request({ method:'eth_requestAccounts' });
if(!accs || !accs.length) return;
window.__WALLET = accs[0];
// request Base mainnet
try{
await window.ethereum.request({ method:'wallet_switchEthereumChain', params:[{chainId:'0x2105'}] });
} catch(switchErr){
if(switchErr.code === 4902){
await window.ethereum.request({ method:'wallet_addEthereumChain', params:[{
chainId:'0x2105', chainName:'Base', nativeCurrency:{name:'ETH',symbol:'ETH',decimals:18},
rpcUrls:['https://mainnet.base.org'], blockExplorerUrls:['https://basescan.org']
}]});
}
}
updateWalletUI();
refreshApiMode();
} catch(e){ console.error(e); }
}
document.getElementById('wallet-btn').addEventListener('click', connectWallet);
window.connectWallet = connectWallet;
if(window.ethereum){
window.ethereum.request({ method:'eth_accounts' }).then(accs=>{
if(accs && accs.length){ window.__WALLET = accs[0]; updateWalletUI(); }
}).catch(()=>{});
window.ethereum.on && window.ethereum.on('accountsChanged', (accs)=>{
window.__WALLET = accs && accs[0] ? accs[0] : null;
updateWalletUI(); refreshApiMode();
});
}
/* ============== FOOTER CAP TOGGLE ============== */
document.getElementById('cap-toggle').addEventListener('click', ()=>{
document.getElementById('cap-toggle').classList.toggle('open');
document.getElementById('cap-menu').classList.toggle('open');
});
/* ============== INIT ============== */
function init(){
renderBandLegend();
sizeHero(); buildHero(); requestAnimationFrame(heroFrame);
renderExplorer();
renderQuery();
renderTerminal();
renderSymbols();
renderFeaturePages();
renderArchitecture();
renderInstructions();
renderRoadmap();
renderAPI();
renderRnD();
renderDeployment();
renderAffiliates();
updateWalletUI();
// Apply referrer from query string into UI
const m = location.search.match(/[?&]ref=([^&]+)/);
if(m){ window.__REF = decodeURIComponent(m[1]); }
// Honor initial hash
const h = (location.hash||'').replace('#','');
if(h) goto(h);
// ── Mode-toggle: instant refresh on flip ──
// The toggle buttons exist inside multiple pages; when state changes,
// re-render the affected pages so the new mode's data appears immediately.
document.addEventListener('cs:modechange', ()=>{
// SCAN — fastest visible feedback: re-run the live KPI fetcher / clear tiles
if(typeof renderExplorer === 'function') {
try { renderExplorer(); } catch(e){}
}
// API affiliate panel — re-fetch /affiliate or swap to demo immediately
if(typeof updateAffiliatePanel === 'function') {
try { updateAffiliatePanel(); } catch(e){}
}
// The API ticker self-replicates and checks the mode on each tick — no
// explicit re-render needed; the next tick (within ~1.5 s) picks up the
// new mode. Query checks the mode on submit. Terminal commands check
// the mode at execution time.
});
}
if(document.readyState === 'loading'){ document.addEventListener('DOMContentLoaded', init); }
else init();
</script>
</body>
</html>