igneum/site/live.html
igneum-labs 7e44748295 site: the simple nav, the miner and app pages, the live devnet redrawn, one design system for every page (not deployed)
Nav sitewide: Litepaper, Miner, App, Wallet, Live devnet, Ledger and the
Download button; the rest in the sheet and the footer. /miner is the
product page for the installers: the shipped app in its frame, the card
picker with the live time to a block, the downloads with sizes, HiveOS,
the fee in full view, three real shots. /app is new: the Igneum Ember app
page by page (Overview, Cards with Ember, the chain drawn live by the
module the app ships, Earnings, Prove, Settings, phone width, what keeps
it mining), light and dark, every shot a real capture or a render from
the RTX 5090 Windows rig's live state with the hostname painted out.
/live is redrawn to show the system working: the step scene, six live
cells, finality in plain words, miner lanes, provers paid, recent blocks
landing, the light client in one line, the DAG below. site.css carries
the shared product components (frames, download list, lines, your-card
line, phone download bar); yourcard.js reads the network rate. The
ledger and wallet pages no longer overflow at 390 px.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 07:44:15 +00:00

362 lines
31 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Igneum live devnet</title>
<meta name="description" content="The Igneum devnet as it happens: every block, the miners, the provers paid and the finality rule, read from a node every two seconds.">
<link rel="canonical" href="https://igneum.network/live">
<meta name="theme-color" content="#0C0C0E">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Igneum">
<meta property="og:title" content="Igneum live devnet">
<meta property="og:description" content="The Igneum devnet as it happens: every block, the miners, the provers paid and the finality rule, read from a node every two seconds.">
<meta property="og:url" content="https://igneum.network/live">
<meta property="og:image" content="https://igneum.network/og-small.png?v=3">
<meta property="og:image:width" content="256">
<meta property="og:image:height" content="256">
<meta property="og:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Igneum live devnet">
<meta name="twitter:description" content="The Igneum devnet as it happens: every block, the miners, the provers paid and the finality rule, read from a node every two seconds.">
<meta name="twitter:image" content="https://igneum.network/og-small.png?v=3">
<meta name="twitter:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Crect width='1024' height='1024' fill='%230C0C0E'/%3E%3Cg transform='translate(166.95 166.95) scale(6.901)'%3E%3Cpolygon points='50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34' fill='%23F2541B'/%3E%3Cpolygon points='50,42 59,58 50,82 41,58' fill='%230C0C0E'/%3E%3C/g%3E%3C/svg%3E" type="image/svg+xml">
<link rel="icon" href="/favicon.ico" sizes="48x48">
<link rel="icon" href="/favicon-32.png" type="image/png" sizes="32x32">
<link rel="icon" href="/icon-192.png" type="image/png" sizes="192x192">
<link rel="icon" href="/icon-512.png" type="image/png" sizes="512x512">
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
<link rel="manifest" href="/site.webmanifest">
<!-- head:start -->
<link rel="preload" href="/fonts/unbounded-900.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/plex-sans-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/site.css">
<style>
/* Shared by every page: the head partial, injected by the build between the head markers. Edit the partial, not the page. */
/* Fonts, self-hosted (latin subsets, OFL): Unbounded 500/700/900, IBM Plex Sans 400/500/600, IBM Plex Mono 400/500. Fallbacks carry size and ascent overrides so the swap does not move the layout. The tokens, type and components are in /site.css (docs/plans/site-ui-3.md). */
@font-face{font-family:'Unbounded';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/unbounded-500.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Unbounded';font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/unbounded-700.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Unbounded';font-style:normal;font-weight:900;font-display:swap;src:url(/fonts/unbounded-900.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/plex-sans-400.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/plex-sans-500.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/plex-sans-600.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/plex-mono-400.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/plex-mono-500.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Unbounded Fallback';src:local('Arial Black'),local('Arial-Black'),local('Impact');size-adjust:114%;ascent-override:87.5%;descent-override:21.5%;line-gap-override:0%}
@font-face{font-family:'Plex Sans Fallback';src:local('Arial'),local('Helvetica Neue'),local('Helvetica');size-adjust:100.5%;ascent-override:102%;descent-override:27.4%;line-gap-override:0%}
@font-face{font-family:'Plex Mono Fallback';src:local('Courier New'),local('Menlo');size-adjust:100%;ascent-override:102.5%;descent-override:27.5%;line-gap-override:0%}
</style>
<script>
/* theme before first paint: the footer control stores "light" or "dark" under igneum-theme; nothing stored means the system setting */
(function(){try{var t=localStorage.getItem("igneum-theme");if(t==="light"||t==="dark")document.documentElement.setAttribute("data-theme",t);}catch(e){}})();
</script>
<!-- head:end -->
<style>
/* live page block (7 Oct 2026: redrawn to show the system working); tokens and components are in /site.css */
.lhead{padding:var(--s-6) 0 var(--s-5)}
.lhead .wrap{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:var(--s-3) var(--s-5)}
.lhead h1{font-size:var(--t-h1);margin:var(--s-2) 0 0}
.lhead{padding-bottom:var(--s-4)}
.lhead p{margin:var(--s-3) 0 0;color:var(--ink-2);max-width:60ch}
.bleed{width:100%;padding:0 var(--gutter)}
.bleed canvas{width:100%;height:min(54vh,520px);min-height:300px;display:block;border-radius:var(--r-card);background:var(--row);border:1px solid var(--line)}
.caption{margin:var(--s-3) auto 0;font:400 13px/1.5 var(--f-mono);color:var(--bone);min-height:1.5em;max-width:var(--max);padding:0 var(--gutter)}
.caption.muted{color:var(--ash)}
.strip{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:var(--s-3);margin-top:var(--s-6)}
@media (max-width:1000px){.strip{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:600px){.strip{grid-template-columns:repeat(2,minmax(0,1fr))}}
.cell{background:var(--graphite);border:1px solid var(--line);border-radius:var(--r-row);padding:var(--s-4);min-width:0}
.cell .k{font:500 var(--t-xs)/1.4 var(--f-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--ash)}
.cell .v{font:700 clamp(20px,2.2vw,28px)/1.1 var(--f-display);color:var(--bone);margin-top:6px;overflow-wrap:anywhere}
.cell .v.state{font:500 var(--t-base)/1.3 var(--f-mono);color:var(--ash)}
.cell .s{font:400 var(--t-sm)/1.4 var(--f-mono);color:var(--ash);margin-top:4px}
.fin{display:flex;align-items:center;gap:var(--s-3);margin:var(--s-5) 0 0;padding:var(--s-4) var(--s-5);border:1px solid var(--line);border-radius:var(--r-row);background:var(--row);color:var(--ink-2);font-size:var(--t-md)}
.fin b{color:var(--bone)}
.three{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4);margin-top:var(--s-5)}
@media (max-width:1000px){.three{grid-template-columns:1fr}}
.three h2{font-size:var(--t-h3);margin-bottom:var(--s-3)}
.lanes{display:flex;flex-direction:column}
.lane{display:grid;grid-template-columns:84px minmax(0,1fr) 72px;gap:12px;align-items:center;padding:8px 0;border-bottom:1px solid var(--line);font:400 13px/1.4 var(--f-mono);color:var(--ink-2)}
.lane:last-child{border-bottom:0}
.lane .id{color:var(--molten-text)}.lane .n{text-align:right;white-space:nowrap}
.bar{height:6px;border-radius:3px;background:var(--line);overflow:hidden;min-width:40px}
.bar i{display:block;height:100%;background:var(--ember)}
.kv2{display:grid;grid-template-columns:1fr auto;gap:6px 12px;font:400 13px/1.5 var(--f-mono);color:var(--ink-2)}
.kv2 b{color:var(--bone);font-weight:500;text-align:right;white-space:nowrap}
.blocks{display:flex;flex-direction:column;font:400 13px/1.4 var(--f-mono);color:var(--ink-2)}
.blocks div{display:grid;grid-template-columns:minmax(72px,auto) minmax(0,1fr) auto;gap:10px;padding:7px 0;border-bottom:1px solid var(--line);align-items:baseline}
.blocks div>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.blocks div:last-child{border-bottom:0}
.blocks .w{color:var(--ash);white-space:nowrap}.blocks .w.hot{color:var(--molten-text)}.blocks .num{color:var(--bone)}
.blocks div.new{animation:land .9s ease-out}
@keyframes land{0%{background:var(--ember-12)}100%{background:transparent}}
@media (prefers-reduced-motion:reduce){.blocks div.new{animation:none}}
.lc{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--s-2) var(--s-4);margin-top:var(--s-5);padding:var(--s-3) var(--s-4);border:1px solid var(--line);border-radius:var(--r-row);background:var(--row);font-size:var(--t-base);color:var(--ink-2)}
.lc .tick{width:28px;height:28px;border-radius:8px;background:var(--ember);display:grid;place-items:center;flex:none;color:var(--ember-ink)}
.lc [data-lc]{color:var(--bone)}
@media (max-width:700px){.lc{grid-template-columns:auto minmax(0,1fr)}.lc .state{grid-column:2}}
.scene{position:relative}
#dag{display:block;width:100%;height:clamp(280px,38vw,420px);border-radius:var(--r-row);background:var(--row);border:1px solid var(--line);touch-action:pan-y}
.tip{position:absolute;left:0;top:0;pointer-events:none;background:var(--graphite);border:1px solid var(--line-2);border-radius:var(--r-row);padding:10px 12px;font:400 12px/1.5 var(--f-mono);color:var(--ink-2);white-space:nowrap;z-index:5}
.tip[hidden]{display:none}
.dl-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--s-3);margin-top:var(--s-6);padding-top:var(--s-5);border-top:1px solid var(--line)}
</style>
</head>
<body>
<!-- nav:start -->
<a class="skip" href="#main">Skip to content</a>
<nav class="nav" aria-label="Main">
<div class="wrap">
<a href="/" class="brand" aria-label="Igneum home">
<svg class="mark" viewBox="0 0 1024 1024" width="28" height="28" aria-hidden="true"><rect width="1024" height="1024" rx="160" fill="#0C0C0E"></rect><g transform="translate(166.95 166.95) scale(6.901)"><polygon points="50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34" fill="#F2541B"></polygon><polygon points="50,42 59,58 50,82 41,58" fill="#0C0C0E"></polygon></g></svg>
<span class="word">IGNEUM</span>
</a>
<div class="links" id="nav-links">
<a href="/litepaper" data-nav="litepaper">Litepaper</a>
<a href="/miner" data-nav="miner">Miner</a>
<a href="/app" data-nav="app">App</a>
<a href="/wallet" data-nav="wallet">Wallet</a>
<a href="/live" data-nav="live" aria-current="page">Live devnet</a>
<a href="/ledger" data-nav="ledger">Ledger</a>
</div>
<a href="/miner#get" class="btn primary small cta">Download</a>
<button class="burger" id="nav-burger" type="button" aria-expanded="false" aria-controls="nav-sheet" aria-label="Menu"><span class="bars"></span></button>
<div class="nav-sheet" id="nav-sheet">
<a href="/litepaper" data-nav="litepaper">Litepaper</a>
<a href="/miner" data-nav="miner">Miner</a>
<a href="/app" data-nav="app">App</a>
<a href="/wallet" data-nav="wallet">Wallet</a>
<a href="/live" data-nav="live">Live devnet</a>
<a href="/ledger" data-nav="ledger">Ledger</a>
<a href="/bench" data-nav="bench">Engineering log</a>
<a href="/evidence" data-nav="evidence">Evidence</a>
<a href="/explorer">Explorer</a>
<a href="https://github.com/igneum-network/spec" rel="noopener">GitHub</a>
<a href="/miner#get" class="btn primary">Download the miner</a>
</div>
</div>
</nav>
<script>
(function(){
// the menu: open on the button, closed by any link, Escape (focus back on the button) or a resize past 900 px
var n=document.querySelector('.nav'),b=document.getElementById('nav-burger'),s=document.getElementById('nav-sheet');if(!n||!b||!s)return;
function set(o){n.classList.toggle('open',o);b.setAttribute('aria-expanded',o?'true':'false');document.documentElement.style.overflow=o?'hidden':'';}
b.addEventListener('click',function(){set(!n.classList.contains('open'));});
s.addEventListener('click',function(e){if(e.target.closest('a'))set(false);});
document.addEventListener('keydown',function(e){if(e.key==='Escape'&&n.classList.contains('open')){set(false);b.focus();}});
var mq=window.matchMedia('(min-width:901px)');if(mq.addEventListener)mq.addEventListener('change',function(){set(false);});
})();
</script>
<!-- nav:end -->
<main id="main">
<header class="lhead" id="top">
<div class="wrap">
<div>
<div class="state" id="live-state"><span class="dot off"></span>connecting to the devnet observer</div>
<h1>The chain, as it happens.</h1>
</div>
<a href="/miner#get" class="btn primary">Download the miner</a>
</div>
</header>
<div class="bleed">
<canvas id="steps" aria-label="The live devnet, step by step: every square is a real block moving left as time passes; its outline, quarter cells, fill and ring show mined, shards being proven, proven and locked checkpoint"></canvas>
</div>
<p class="caption mono" id="steps-caption" aria-live="polite">Connecting to the devnet observer.</p>
<section class="sec" style="padding-top:0">
<div class="wrap">
<div class="strip" aria-live="polite">
<div class="cell"><div class="k">Hash rate</div><div class="v tick" id="s-hash">pending</div><div class="s">network estimate</div></div>
<div class="cell"><div class="k">Blocks, 10 min</div><div class="v tick" id="s-b10">pending</div><div class="s">target 1 a second</div></div>
<div class="cell"><div class="k">Latest block</div><div class="v tick" id="s-last">pending</div><div class="s" id="s-last-s">pending</div></div>
<div class="cell"><div class="k">Shards proven, paid</div><div class="v tick" id="s-paid">pending</div><div class="s" id="s-paid-s">pending</div></div>
<div class="cell"><div class="k">Vote keys, 10 min</div><div class="v tick" id="s-keys">pending</div><div class="s">a card runs several</div></div>
<div class="cell"><div class="k">Last lock</div><div class="v tick" id="s-lock">pending</div><div class="s" id="s-lock-s">pending</div></div>
</div>
<p class="fin" id="fin"><span class="dot off"></span><span>Reading the finality rule.</span></p>
<p class="note">One node is read every 2 s; nothing here is a replay. Every square in the scene is a real block: its outline, fill and ring are its state. Fees since DAA 210,000: <a href="/litepaper#economics">the adopted fee table</a>.</p>
<div class="three">
<div class="card">
<div class="viz-head"><h2>Miners</h2><div class="eyebrow" id="miners-count">last 10 min</div></div>
<div class="lanes" id="miners"><div class="empty">No blocks in the last 10 minutes.</div></div>
<p class="note" id="miners-more">Every vote key with a block in the last 10 minutes; a card runs several.</p>
</div>
<div class="card">
<div class="viz-head"><h2>Provers paid</h2><div class="eyebrow" id="prov-state">pending</div></div>
<div class="kv2" id="prov">
<span>shards proven and paid, all time</span><b id="p-total">pending</b>
<span>paid in the last 10 min</span><b id="p-10">pending</b>
<span>blocks fully proven, 10 min</span><b id="p-full">pending</b>
<span>proofs land behind the tip</span><b id="p-lag">pending</b>
</div>
<p class="note">Every chain block is split into shards; a card proves one, posts it, and is paid on the chain.</p>
</div>
<div class="card">
<div class="viz-head"><h2>Recent blocks</h2><div class="eyebrow">the last eight</div></div>
<div class="blocks" id="blocks"><div class="empty">No blocks yet.</div></div>
<p class="note">Number, miner, state. A number arrives once the block is planned onto the chain.</p>
</div>
</div>
<div class="lc" id="light-client">
<span class="tick"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7"></path></svg></span>
<span>This tab checks the chain itself: checkpoint <span data-lc="checkpoint">checking</span>, <span data-lc="tab">checking</span>. <span data-lc="line" class="muted"></span></span>
<span class="state" data-lc="badge"><span class="dot off"></span><span data-lc="badge-text">PREVIEW</span></span>
<span hidden data-lc="proof"></span><span hidden data-lc="system"></span>
<script type="module" src="/verify/verify.js"></script>
</div>
<div class="card viz" style="margin-top:var(--s-5)" aria-label="Block DAG, finality and proving, live">
<div class="viz-head">
<div class="state" id="dag-state"><span class="dot off"></span>the DAG</div>
<div class="viz-stats mono"><span>on screen <b id="c-screen">0</b></span><span>chain <b id="c-chain">0</b></span><span><span id="c-window">120 s</span> on screen</span><button type="button" class="btn small" id="dag-pause">Pause</button></div>
</div>
<div class="scene"><canvas id="dag" aria-label="The devnet's block DAG, live: blocks by time and miner lane, parent edges, the selected chain, checkpoint bands with their lock weight, proofs filling blocks as segments are paid"></canvas><div class="tip" id="dag-tip" hidden></div><div class="chip-zoom" id="dag-chip" hidden>scroll to zoom · Esc to release</div></div>
<div class="legend">
<span><i class="sw" style="border:2px solid var(--line-2)"></i>pending</span>
<span><i class="sw" style="border:2px solid var(--bone)"></i>included</span>
<span><i class="sw" style="border:2px solid var(--ember)"></i>selected chain</span>
<span><i class="sw" style="border:2px solid var(--line-2);opacity:.45"></i>excluded</span>
<span><i class="sw" style="background:var(--ember)"></i>proven</span>
<span><i class="sw" style="border:3px solid var(--ember);border-radius:50%;background:transparent"></i>locked checkpoint</span>
<span><i class="sw" style="width:0;height:12px;border-left:2px solid var(--ember);border-radius:0"></i>finality band, locked, with its weight</span>
</div>
<p class="note" style="margin-top:var(--s-3)">One lane per miner, the busiest first; the rest share the last lane. Hover or tap a block for its hash, miner, blue score, parents and proof state. Ctrl or cmd and scroll, a pinch, or a click into the scene zooms the window. <a href="/explorer">The explorer</a> has every block.</p>
</div>
<div class="dl-row">
<p class="yourcard" data-yourcard style="margin:0;flex:1 1 420px">Your card: pending</p>
<a href="/miner#get" class="btn primary">Download the miner</a>
</div>
</div>
</section>
</main>
<!-- footer:start -->
<footer class="foot">
<div class="wrap">
<div class="foot-grid">
<div class="foot-brand">
<a href="/" class="brand" aria-label="Igneum home"><svg class="mark" viewBox="0 0 1024 1024" width="26" height="26" aria-hidden="true"><rect width="1024" height="1024" rx="160" fill="#0C0C0E"></rect><g transform="translate(166.95 166.95) scale(6.901)"><polygon points="50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34" fill="#F2541B"></polygon><polygon points="50,42 59,58 50,82 41,58" fill="#0C0C0E"></polygon></g></svg><span class="word">IGNEUM</span></a>
<p>Mined by GPUs. Proven by fire.</p>
</div>
<nav class="foot-col" aria-label="Read">
<div class="eyebrow">Read</div>
<a href="/litepaper">Litepaper</a>
<a href="/litepaper#limits">What Igneum does not claim</a>
<a href="/litepaper#randomx">Igneum vs RandomX</a>
<a href="/litepaper#shoulders">Built on the shoulders</a>
<a href="/bench">Engineering log</a>
<a href="/evidence">Evidence</a>
<a href="/ledger">Ledger: every criticism</a>
</nav>
<nav class="foot-col" aria-label="Run">
<div class="eyebrow">Run</div>
<a href="/miner">The miner</a>
<a href="/app">The app</a>
<a href="/wallet">The wallet</a>
<a href="/miners">GPU bench table</a>
<a href="/miner#fee">The dev fee</a>
<a href="/faucet">Testnet faucet</a>
</nav>
<nav class="foot-col" aria-label="Follow">
<div class="eyebrow">Follow</div>
<a href="/live">Live devnet</a>
<a href="/explorer">Explorer</a>
<a href="/litepaper#roadmap">Journey</a>
<a href="/metamask">Add Igneum to MetaMask</a>
<a href="https://github.com/igneum-network/spec" rel="noopener"><svg viewBox="0 0 24 24" width="15" height="15" fill="currentColor" aria-hidden="true"><path d="M12 .5C5.7.5.5 5.7.5 12c0 5.1 3.3 9.4 7.9 10.9.6.1.8-.3.8-.6v-2.1c-3.2.7-3.9-1.4-3.9-1.4-.5-1.3-1.3-1.7-1.3-1.7-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.7 1.3 3.4 1 .1-.8.4-1.3.7-1.6-2.6-.3-5.3-1.3-5.3-5.7 0-1.3.5-2.3 1.2-3.1-.1-.3-.5-1.5.1-3.1 0 0 1-.3 3.2 1.2.9-.3 1.9-.4 2.9-.4s2 .1 2.9.4c2.2-1.5 3.2-1.2 3.2-1.2.6 1.6.2 2.8.1 3.1.8.8 1.2 1.8 1.2 3.1 0 4.4-2.7 5.4-5.3 5.7.4.4.8 1.1.8 2.2v3.2c0 .3.2.7.8.6 4.6-1.5 7.9-5.8 7.9-10.9C23.5 5.7 18.3.5 12 .5z"></path></svg>GitHub, spec and vectors</a>
<a href="/miner#get">Miner downloads: devnet build</a>
<a href="mailto:hello@igneum.network">Report a flaw: hello@igneum.network</a>
<a href="https://github.com/igneum-network/spec/issues" rel="noopener">Or open an issue on the spec</a>
</nav>
</div>
<div class="foot-base">
<span class="foot-imprint">Igneum Labs LTD · Unit IH-00-01-01-OF-01, Level 01, Innovation One, Dubai International Financial Centre · <a href="mailto:hello@igneum.network">hello@igneum.network</a></span>
<span>© 2026 Igneum. Nothing on this page is an offer to sell anything.</span>
<span class="theme" role="group" aria-label="Theme"><button type="button" data-theme-set="system" aria-pressed="true">System</button><button type="button" data-theme-set="light" aria-pressed="false">Light</button><button type="button" data-theme-set="dark" aria-pressed="false">Dark</button></span>
<span class="mono">igneum.network</span>
</div>
</div>
</footer>
<script>
(function(){
// theme control: stores light or dark under igneum-theme; system clears it. The head applied the stored value before paint.
var bs=document.querySelectorAll('[data-theme-set]');if(!bs.length)return;
function cur(){try{var t=localStorage.getItem('igneum-theme');return t==='light'||t==='dark'?t:'system';}catch(e){return 'system';}}
function paint(){var c=cur();bs.forEach(function(b){b.setAttribute('aria-pressed',b.getAttribute('data-theme-set')===c?'true':'false');});}
bs.forEach(function(b){b.addEventListener('click',function(){var v=b.getAttribute('data-theme-set');try{if(v==='system')localStorage.removeItem('igneum-theme');else localStorage.setItem('igneum-theme',v);}catch(e){}
if(v==='system')document.documentElement.removeAttribute('data-theme');else document.documentElement.setAttribute('data-theme',v);paint();});});
paint();
})();
</script>
<!-- footer:end -->
<script src="/scenes/feed.js"></script>
<script src="/live-steps.js"></script>
<script src="/live-dag.js" defer></script>
<script src="/yourcard.js" defer></script>
<script>
(function(){
function $(id){return document.getElementById(id);}
var fmtN=function(v){return v===null||v===undefined?'pending':Number(v).toLocaleString('en-GB');};
function fmtHash(h){if(h===null||h===undefined||!(h>0))return 'pending';return h>=1e9?(h/1e9).toFixed(1)+' GH/s':(h/1e6).toFixed(1)+' MH/s';}
function rel(ms){var s=Math.max(0,Math.round(ms/1000));if(s<60)return s+' s ago';var m=Math.floor(s/60);if(m<60)return m+' min ago';var h=Math.floor(m/60);if(h<24)return h+' h ago';return Math.floor(h/24)+' d ago';}
function esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
// a counter that changed glows for half a second: motion only from a real change
function set(id,text){var el=$(id);if(!el||el.textContent===text)return;el.textContent=text;el.classList.add('flash');setTimeout(function(){el.classList.remove('flash');},60);}
var cap=$('steps-caption'),lastTs=null,seen={};
function onState(s,r){var el=$('live-state');el.className='state '+(s==='live'?'live':s==='failed'?'bad':'');el.innerHTML='<span class="dot '+(s==='live'?'live':s==='failed'?'bad':'off')+'"></span>'+(s==='live'?'live devnet':s==='connecting'?'connecting to the devnet observer':esc(r||s));
if(s==='live')return;cap.classList.add('muted');cap.textContent=s==='connecting'?'Connecting to the devnet observer.':s==='stale'?(r.charAt(0).toUpperCase()+r.slice(1))+'. The scene holds the last stored blocks.':'Live feed unavailable. The scene holds its last blocks.';}
function onData(d){var s=d.state,pv=d.proving,fn=d.finality,now=new Date(d.now).getTime();
set('s-hash',fmtHash(s.hashes_per_second_estimate));
var bpm=s.blocks_per_minute||[],b10=bpm.slice(-10).reduce(function(a,p){return a+(p[1]||0);},0);set('s-b10',fmtN(b10));
var newest=null;(d.blocks||[]).forEach(function(b){if(!newest||b.ts>newest.ts)newest=b;});
if(newest){lastTs=newest.ts;$('s-last-s').textContent=newest.number?'block '+fmtN(newest.number)+(newest.chain?', on the selected chain':''):'block '+newest.hash+', not yet planned';}
if(pv&&pv.supported&&pv.active){set('s-paid',fmtN(pv.paid_shards_total));$('s-paid-s').textContent=fmtN(pv.shards_paid_10m||0)+' in the last 10 min';$('prov-state').textContent='live';
$('p-total').textContent=fmtN(pv.paid_shards_total);$('p-10').textContent=fmtN(pv.shards_paid_10m||0);$('p-full').textContent=fmtN(pv.blocks_fully_proven_10m||0)+' of '+fmtN(pv.blocks_10m||0);$('p-lag').textContent=pv.median_proof_lag_s?'a median '+Math.round(pv.median_proof_lag_s)+' s':'pending';}
else{var w=pv&&pv.supported?'proving not active':'no proving layer';$('s-paid').textContent=w;$('s-paid').className='v state';$('s-paid-s').textContent='';$('prov-state').textContent=w;}
set('s-keys',fmtN(s.miners_10m!==null&&s.miners_10m!==undefined?s.miners_10m:(d.miners||[]).length));
// finality: the last lock, and the rule in plain words
var fin=$('fin'),lock=null;if(fn&&fn.checkpoints)fn.checkpoints.forEach(function(c){if(c.state==='locked'&&(!lock||c.index>lock.index))lock=c;});
if(fn&&fn.supported&&!fn.active){set('s-lock',fn.latest_locked_index?'#'+fmtN(fn.latest_locked_index):'none');$('s-lock-s').textContent='finality paused';
fin.innerHTML='<span class="dot off"></span><span><b>Finality is paused.</b> Under two thirds of the 30-day weight is signing, so no checkpoint locks until it returns. The chain keeps growing; the last lock stands.</span>';}
else if(lock){set('s-lock','#'+fmtN(lock.index));var t=lock.locked_at?new Date(String(lock.locked_at).replace(' ','T')).getTime():NaN;$('s-lock-s').textContent=isNaN(t)?'locked':'locked '+rel(now-t);
var pct=lock.fraction_total?Math.round(lock.fraction_total*100):(lock.signed&&lock.total?Math.round(lock.signed/lock.total*100):null);
fin.innerHTML='<span class="dot live"></span><span><b>Finality is live.</b> Checkpoint #'+fmtN(lock.index)+' locked'+(isNaN(t)?'':' '+rel(now-t))+(pct?' with '+pct+'% of all 30-day weight signing':'')+'. A checkpoint locks when two thirds of all weight signs it, every 30 seconds.</span>';}
else{set('s-lock',fn&&fn.supported?'none yet':'no rule');$('s-lock-s').textContent=fn&&fn.supported?'window filling':'';fin.innerHTML='<span class="dot off"></span><span><b>No lock yet.</b> The 30-day weight window is filling; the first checkpoint locks once it is full.</span>';}
// miners: top five lanes with a bar each
var mel=$('miners');if(d.miners&&d.miners.length){var top=d.miners.slice(0,5),max=Math.max(1,top[0].blocks),rest=d.miners.length-top.length;
$('miners-count').textContent=d.miners.length+' vote keys';
mel.innerHTML=top.map(function(m){return '<div class="lane"><span class="id">'+esc(m.id)+'</span><div class="bar"><i style="width:'+Math.round(m.blocks/max*100)+'%"></i></div><span class="n">'+m.blocks+' blocks</span></div>';}).join('');
$('miners-more').textContent=(rest>0?'and '+rest+' more. ':'')+'Every vote key with a block in the last 10 minutes; a card runs several.';}
else{mel.innerHTML='<div class="empty">No blocks in the last 10 minutes.</div>';}
// recent blocks: the last eight by time, newest first; a block seen for the first time lands with a glow
var list=(d.blocks||[]).slice().sort(function(a,b){return b.ts-a.ts;}).slice(0,8),bel=$('blocks');
if(list.length){bel.innerHTML=list.map(function(b){var word=b.locked?'locked':b.proven?'proven':b.color==='red'?'excluded':b.chain?'on the chain':b.color==='blue'?'included':'pending';var fresh=!seen[b.hash];seen[b.hash]=1;
return '<div'+(fresh&&Object.keys(seen).length>8?' class="new"':'')+'><span class="num">'+(b.number?fmtN(b.number):esc(b.hash))+'</span><span>'+esc(b.miner||'')+'</span><span class="w'+(word==='locked'||word==='proven'?' hot':'')+'">'+word+'</span></div>';}).join('');}
if(window.IgneumYourCard)IgneumYourCard.update(s.hashes_per_second_estimate);
lastD=d;sceneCounters(d);if(dag)dag.push(d);
}
// the latest-block cell ticks every second between reads
setInterval(function(){if(lastTs){var el=$('s-last');el.textContent=rel(Date.now()-lastTs);}},1000);
var c=$('steps');
if(c&&window.IgneumFeed&&window.IgneumSteps){var steps=IgneumSteps.mount(c,{caption:cap});IgneumFeed.start({window:300,subs:[steps],onState:onState,onData:onData});}
// the DAG below, fed by the same reads
var dag=null,lastD=null;
function sceneCounters(d){var w=dag?dag.getWindow():120,cut=new Date(d.now).getTime()-w*1000,on=0,chain=0;(d.blocks||[]).forEach(function(b){if(b.ts>=cut){on++;if(b.chain)chain++;}});$('c-screen').textContent=on;$('c-chain').textContent=chain;}
function mountDag(){if(dag||!window.IgneumDag)return;dag=IgneumDag.mount($('dag'),{poll:false,window:120,tooltip:$('dag-tip'),chip:$('dag-chip'),pauseButton:$('dag-pause'),
onWindow:function(w){$('c-window').textContent=w+' s';},
onState:function(st,reason){var el=$('dag-state');el.className='state '+(st==='live'?'live':st==='failed'?'bad':'');el.innerHTML='<span class="dot '+(st==='live'?'live':st==='failed'?'bad':'off')+'"></span>'+(st==='live'?'the DAG, live':st==='connecting'?'the DAG':esc(reason||st));}});
if(lastD)dag.push(lastD);}
if(window.IgneumDag)mountDag();else{var ms=document.querySelector('script[src="/live-dag.js"]');if(ms)ms.addEventListener('load',mountDag);}
})();
</script>
</body>
</html>