Site polish: one header and footer from partials on every page, litepaper section router fixed, self-hosted fonts, 404 page, live page idle cost

Header: site/partials/nav.html, head.html, footer.html, injected by site/build.mjs between markers in every page (the bench template too) with the active link marked; the master mark in its black square, the wordmark, Litepaper, Live devnet, Engineering log, Evidence, GitHub and the miner button, in that order everywhere; one menu script (closes on a link, a tap outside, Escape with focus back on the button, a resize past 900 px); a skip link; one focus ring and one reduced-motion rule.

Litepaper: the hash routed by a click delegate and popstate instead of the browser's fragment jump. Root cause of the tabs fault: show() scrolled to the top of the article, never to the section; in whole-paper mode the fragment jump landed on the section and the smooth scroll then dragged the reader back to the Abstract; in one-section mode a deep link scrolled while the section was still display:none and landed on the cover. Now: every section and all 29 subsection headings reachable by URL in both modes, scroll-margin from the measured bar height (nav, plus the contents row on a phone), focus moved to the heading, a re-aim after a late font batch, mode buttons stacked in the sidebar.

Pages: homepage headline capped at 9cqw so it is two lines at 390 and 1440 (was four with "fire." alone), journey inlined by the build (no fetch, no shift), dates as "4 Oct 2026"; live page legend no longer forces 420 px of width at 390, the hash-rate unit as small mono, idle redraw at 30/s with a 1.5x backing store (0.7 to 1.2% of one core idle in Chrome for Testing, taken under load), the proving line wraps on a phone; evidence sort headings are buttons, chips carry aria-pressed, a scroll hint under 1,140 px; bench contents in a sticky scroll box, og.png?v=3; 404.html; sitemap with /evidence; vercel.json caches fonts a year and images a day.

Fonts: eight latin woff2 files in site/fonts (139 KB for all, 118 KB a typical page), preloaded first-paint faces, fallback faces with size-adjust and ascent overrides from the font tables; every page lost its render-blocking fonts.googleapis.com stylesheet and the gstatic origin.

HTML per page before to after (gzip): / 17,265 to 21,810 B; /litepaper 20,556 to 24,957; /live 15,640 to 17,777; /evidence 18,899 to 22,493; /bench 94,723 to 98,289. Third-party requests before to after: 3 to 1 (jsdelivr, light client), 1 to 0, 3 to 0, 1 to 0, 1 to 0. Lighthouse before and after is queued under the measure lock (held by reliability runs since 19:16Z, load average 258) and recorded in docs/design/site-polish-2026-10-04.md when it runs.

Checks: node site/build.mjs, tools/ci/link-check.mjs (246 links, 0 broken), identity grep, and a Chrome for Testing run over every page at 390, 768 and 1440 (no overflow, no console errors, menu, router in both modes, deep links on reload, keyboard).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-04 20:57:20 +00:00
parent 14b2679f63
commit a22b1ec7bd
22 changed files with 1342 additions and 327 deletions

View file

@ -0,0 +1,101 @@
# Site polish, 4 October 2026
Branch `site-polish`. The brief: one header on every page, the litepaper's tabs fixed, every element of every page checked at 390, 768 and 1440 px in light and dark, performance measured before and after, copy law on every sentence, the build green. This file records what was broken, what changed, the numbers, and what was left alone.
## 1. What was broken
| # | Where | Fault | Root cause |
|---|---|---|---|
| 1 | Litepaper, whole-paper mode | Every contents click, pager click and back press landed on the section for a moment and then slid back to the Abstract | `show()` always scrolled to the top of `<article>`, never to the section. In one-section mode the section is the top of the article, so the fault was invisible; in whole-paper mode the browser's own fragment jump landed first and the smooth scroll then dragged the reader to the top |
| 2 | Litepaper, one-section mode | A deep link (`/litepaper#limits`) opened on the cover, not the section | The browser's fragment scroll ran while the section was still `display:none`; the router then showed the section with `scroll=false` |
| 3 | Litepaper, phone | The sticky contents row covered the heading after a jump | No `scroll-margin-top`; the hand-tuned 70 px offset did not match the row's real height (99 px) |
| 4 | Litepaper, keyboard and screen readers | After choosing a section, focus stayed in the contents list | Focus was never moved |
| 5 | Litepaper | 29 subsection headings had no ids, so only the 17 sections were addressable by URL | Never generated |
| 6 | Header, every page | Five different headers: 11 links on the homepage, 10 on the live page (section anchors into the homepage), 6 plain links on the evidence and log pages, no header at all on the litepaper (a cover with two arrow links) | Each page carried its own copy |
| 7 | Header, mobile | The menu on the live page closed on tap-outside but not on Escape and not on a link tap; the evidence, log and litepaper pages had no menu, their links wrapped | Three different scripts, two pages without one |
| 8 | Header, every page | The mark was the bare flame, not the master mark in its black square | Pre-dates the brand master of 4 October |
| 9 | Live page, phone | The page scrolled sideways to 420 px at 390 px | Three legend captions were `white-space:nowrap` spans ("one lane per miner, colour from its id; hover or tap a block") |
| 10 | Live page, phone | The hash-rate cell clipped to "264.1 M…" | 20 px Unbounded in a 125 px cell with `text-overflow:ellipsis` |
| 11 | Homepage, 390 px and 1440 px | The headline wrapped to four lines with "fire." alone on the last | `clamp(40px, 7vw, 76px)` never fitted "Mined by GPUs." in the column at either end |
| 12 | Homepage | The journey block arrived after a fetch of `journey.json`, after first paint, and pushed the page down | Rendered from a fetch |
| 13 | Every page | A render-blocking stylesheet from fonts.googleapis.com, then the woff2 files from a second origin; no font fallback metrics, so the swap moved every line | Google Fonts link in each `<head>` |
| 14 | 404 | Vercel's plain text "NOT_FOUND" | No `404.html` |
| 15 | Sitemap | `/evidence` missing; every lastmod 3 October | Not updated |
| 16 | Log page share card | `og.png?v=2` while every other page was on `?v=3` | The build template was not bumped with the pages |
| 17 | Evidence table | Column sort only by mouse (the `<th>` was the click target, not focusable); filter chips had no pressed state | Markup |
Items 9, 10, 11 and 13 were found by the checks in this round, not by eye.
## 2. What changed
### Shared chrome (one source, injected by the build)
`site/partials/head.html`, `nav.html`, `footer.html`. `site/build.mjs` injects them into every page between `<!-- head:start -->`, `<!-- nav:start -->` and `<!-- footer:start -->` markers, marks the active link with `aria-current="page"`, and inlines `journey.json` into the homepage between `<!-- journey:start -->` markers. The committed pages carry the injected copy, so they are right with or without a build; CI runs the build and the link check on every push.
- Header: the master mark (black square, no ring) at 36 px, the wordmark, five links in one order on every page (Litepaper, Live devnet, Engineering log, Evidence, GitHub) and the Get the miner button. Sticky, 68 px, blurred backdrop. Under 901 px a menu: opens on the button, closes on any link, a tap outside, Escape (focus returns to the button) or a resize past 900 px; `aria-expanded` and `aria-controls` set. A skip link to `#main` on every page.
- Footer: one footer, six Read links and four Follow links, the same everywhere. Page-specific lines (the evidence "as of" date, the log's "generated at build time") moved into the page body above it.
- Litepaper: the chrome follows the paper's scheme (light by default, dark with the system) through `--ui-*` tokens; every other page is obsidian.
- Fonts: self-hosted latin subsets in `site/fonts/` (Unbounded 500/700/900, IBM Plex Sans 400/500/600, IBM Plex Mono 400/500; OFL), 139 KB for all eight, 118 KB for a typical page, `font-display:swap`, the two first-paint faces preloaded. Fallback faces (`Unbounded Fallback` on Arial Black, `Plex Sans Fallback` on Arial, `Plex Mono Fallback` on Courier New) carry `size-adjust`, `ascent-override` and `descent-override` computed from the font tables with fonttools, so the swap does not move the layout (a deep link into the litepaper lands within 3 px before and after the fonts arrive, and is re-aimed on `document.fonts.ready`).
- Site-wide: `text-wrap:balance` on h1 to h3, `text-wrap:pretty` on paragraphs and list items; one `:focus-visible` ring; one `prefers-reduced-motion` rule that stops every animation and transition.
### Litepaper
New section router. The hash names a section or any heading inside one, in both reading modes. In-page links are routed by a click delegate (`pushState` + `go()`), never by the browser's fragment jump; back and forward replay through `popstate`; every scroll clears the sticky bar and, on a phone, the contents row (`--lp-off`, measured from the real heights; `[id]{scroll-margin-top:var(--lp-off)}` so a native jump lands in the same place); focus moves to the heading with `preventScroll`; every h3 gets an id from its text (29 added, so `/litepaper#what-is-not-here` works). The mode buttons carry `aria-pressed` and stack vertically in the desktop sidebar (they wrapped to two lines before). The cover lost its duplicate brand block and arrow links.
### Homepage
Header reduced to the five links; the in-page sections are still there for scrolling. The headline is capped at `9cqw` of its column so it is two lines at every width. Journey data is inlined by the build (no fetch, no shift); dates read "4 Oct 2026" with the day shown once per group; the toggle carries `aria-expanded`; the NOW label lists the active phases with commas and balances its lines. A preconnect to cdn.jsdelivr.net for the light client's libraries.
### Live page
Legend captions wrap. The hash-rate value shows its unit in small mono beside the number. Idle, the scene is drawn 30 times a second instead of 60 (a pointer or a pinned block gets every frame); the DAG canvas backing store is capped at 1.5x. The proving strip's "not yet activated" line breaks at its semicolon when wider than the strip on a phone. `?perf=1` exposes `window.__igneumPerf` (frames, draw milliseconds) for the next measurement.
### Evidence
Column headings are real buttons (keyboard sort, `aria-sort` kept); filter chips carry `aria-pressed`; a "scroll sideways" hint above the 1,100 px table under 1,140 px; the "as of" line moved into the page.
### Engineering log (build template)
Contents in a labelled box: sticky and scrollable beside the article on desktop, a 40 vh scroll box on a phone (57 entries). Headings land under the bar (`scroll-margin-top`). `og.png?v=3`.
### 404
`site/404.html`: the four pages as cards. Vercel serves it for any unknown path (checked locally with the same clean-URL rules; `noindex`).
### Headers and sitemap
`vercel.json`: fonts `immutable` for a year, images and the manifest a day with a week of stale-while-revalidate; HTML stays `must-revalidate`. `sitemap.xml`: `/evidence` added, lastmod 4 October.
## 3. Checks
`check.mjs` (scratchpad, Chrome for Testing 154, never the owner's Chrome) over `/`, `/litepaper`, `/live`, `/bench`, `/evidence` and a 404 path at 390, 768 and 1440 px: no horizontal overflow, no console errors, the five links in order and the right one active, the square mark present, the menu opens, closes on tap-outside and on Escape with focus back on the button; on the litepaper in both modes at 390 and 1440: a contents click, a pager click, back, a deep link to a section and to an h3 on reload, and Enter on a focused pill each land within 2 px of the measured offset with focus on the heading. `node site/build.mjs` and `tools/ci/link-check.mjs` (245 internal links, 0 broken) pass.
## 4. Numbers
Static, from the files (before = the committed site at 8fd492c, after = this branch):
| Page | HTML before (gzip) | HTML after (gzip) | Third-party requests before | After |
|---|---|---|---|---|
| / | 57,261 B (17,265) | 74,065 B (21,810) | 3 (fonts CSS, 2 preconnects) + the woff2 files | 1 (jsdelivr, light client only) |
| /litepaper | 63,628 B (20,556) | 79,208 B (24,957) | 1 + woff2 | 0 |
| /live | 47,680 B (15,640) | 56,357 B (17,777) | 3 + woff2 | 0 |
| /evidence | 56,729 B (18,899) | 69,890 B (22,493) | 1 + woff2 | 0 |
| /bench | 267,259 B (94,723) | 280,179 B (98,289) | 1 + woff2 | 0 |
The HTML grew by the inlined font-face block, the shared chrome and, on the homepage, the inlined journey (about 4 KB gzipped a page). In exchange every page lost a render-blocking stylesheet from a third origin and two DNS lookups.
Live page, idle draw cost (Chrome for Testing, 2x display, canvas in view, 10 s, `?perf=1`; taken while cargo builds and a reliability run held the Mac, so an upper bound): 1440 px, 30.0 draws/s, 69 ms of draw in 10 s = 0.7% of one core; 390 px, 30.0 draws/s, 60 ms = 0.6%. Before the change the loop drew at the display rate (60/s) with a 2x backing store, so the same work was about 2.6x this, approximate. Off screen or in a hidden tab the loop stops, as before.
Lighthouse (mobile simulation, performance only, before on a frozen copy of the committed site at port 4174, after on port 4173, Chrome for Testing 154 downloaded into the scratchpad): queued at 19:45Z under `tools/lock/with-lock.sh measure` and not run by the time this was written. The measure lock was held by reliability runs from 19:16Z onwards (pid 66963, then pid 5534 from 20:18Z) with three cargo builds beside them and a load average of 258, and a paint time taken under that is not a number. The runner is `scratchpad/lh.sh` (before and after, five pages, score, FCP, LCP, TBT, CLS, speed index, bytes, requests, render-blocking resources); run it under the measure lock on a quiet machine and paste the table here. What can be stated without a timer: every page lost its only render-blocking third-party stylesheet and the two origins behind it; the fonts a page needs are one origin, preloaded, cached a year; the homepage lost the post-paint journey fetch; the fallback metrics hold the layout within 3 px across the swap.
Deep-link landing: within 2 px of the measured offset in every case but one. In one-section mode at 1440 px the Finality section is short, "What is not here" is its last heading, and the page cannot scroll far enough to put it under the bar; it lands at the page's maximum scroll, 3 px short. A padding trick would add a blank screen under every section, so it is left as it is.
## 5. Left alone, and why
- `site/api/live.mjs`, `checkpoint.mjs`, `log.mjs`: the observer agent's. The homepage light-client card currently reads "could not verify: voter 0 key does not hash to its vote_key_hash" on production as well as locally; that is the checkpoint data, not the page, and is reported, not fixed here.
- `site/verify/`: the light client, unchanged.
- The GitHub link (`github.com/igneum-network/spec`, 200 on 4 October) stays; `docs/fud-fixes.md` X1 asked for it to go only while private.
- Download buttons: the homepage's Windows, macOS, Linux and HiveOS buttons link to `#journey` as before (no public build yet); no `dl.` URL exists on the site, the scrub replaces the host name on the log page.
- The litepaper's light scheme by default: the paper is the one light surface on purpose.
- Three glowing active phase cards on the homepage: kept, stopped under reduced motion.
- The evidence table's 1,100 px minimum width: it is a 7-column reference table; it scrolls inside its box and says so on narrow screens.

177
site/404.html Normal file
View file

@ -0,0 +1,177 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Page not found. Igneum</title>
<meta name="description" content="That page is not on igneum.network. The litepaper, the live devnet, the engineering log and the evidence page are.">
<meta name="robots" content="noindex">
<meta name="theme-color" content="#0C0C0E">
<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="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
<!-- 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>
<style>
/* Shared by every page. Source: site/partials/head.html, injected by site/build.mjs 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. */
@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%}
:root{--f-sans:'IBM Plex Sans','Plex Sans Fallback',system-ui,-apple-system,sans-serif;--f-display:'Unbounded','Unbounded Fallback',sans-serif;--f-mono:'IBM Plex Mono','Plex Mono Fallback',ui-monospace,Menlo,monospace;
/* site chrome tokens (nav, footer, skip link). Dark by default; the litepaper sets light values and resets these in dark mode */
--nav-h:68px;--ui-bg:rgba(12,12,14,.84);--ui-menu:#0C0C0E;--ui-ink:#F4F1EC;--ui-ink-2:#C9C7C2;--ui-ash:#9A9A9E;--ui-line:#2A2A30;--ui-line-2:#3A3A42;--ui-accent:#F2541B;--ui-accent-ink:#0C0C0E;--ui-hot:#FFB35C;--ui-hover:#FF6A2B;--ui-tint:rgba(242,84,27,.12)}
html{-webkit-text-size-adjust:100%}
h1,h2,h3{text-wrap:balance}
p,li,dd,figcaption{text-wrap:pretty}
a:focus-visible,button:focus-visible,summary:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--ui-accent);outline-offset:3px;border-radius:6px}
.skip{position:absolute;left:12px;top:-80px;z-index:50;background:var(--ui-accent);color:var(--ui-accent-ink);padding:10px 14px;border-radius:10px;font:600 15px/1.2 var(--f-sans);text-decoration:none}
.skip:focus{top:12px}
/* nav: one bar on every page, the mark in its black square, five links and the miner button, a menu under 901 px */
.nav{position:sticky;top:0;z-index:20;background:var(--ui-bg);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid var(--ui-line);color:var(--ui-ink)}
.nav .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:var(--nav-h)}
.nav a{color:inherit;text-decoration:none}
.brand{display:inline-flex;align-items:center;gap:10px;color:var(--ui-ink);text-decoration:none;flex:0 0 auto}
.brand .mark{display:block;flex:0 0 auto}
.brand .word{font-family:var(--f-display);font-weight:900;font-size:20px;letter-spacing:.06em;line-height:1}
.nav .links{display:flex;align-items:center;gap:clamp(14px,2vw,26px);font-size:15px;font-weight:500}
.nav .links a{color:var(--ui-ink-2);padding:4px 0;border-bottom:2px solid transparent;transition:color .15s ease,border-color .15s ease}
.nav .links a:hover,.nav .brand:hover{color:var(--ui-hot);text-decoration:none}
.nav .brand:hover{color:var(--ui-ink)}
.nav .links a[aria-current="page"]{color:var(--ui-ink);border-bottom-color:var(--ui-accent)}
.nav .links a.cta{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:8px 16px;border-radius:10px;font-weight:600;background:var(--ui-accent);color:var(--ui-accent-ink);border:1px solid var(--ui-accent);transition:background .15s ease,transform .15s ease}
.nav .links a.cta:hover{background:var(--ui-hover);border-color:var(--ui-hover);color:var(--ui-accent-ink);transform:translateY(-1px)}
.burger{display:none;background:none;border:1px solid var(--ui-line-2);color:var(--ui-ink);border-radius:10px;width:44px;height:44px;align-items:center;justify-content:center;cursor:pointer;padding:0;flex:0 0 auto}
.burger .x{display:none}.burger[aria-expanded="true"] .x{display:block}.burger[aria-expanded="true"] .bars{display:none}
@media (max-width:900px){
.nav .links{display:none;position:absolute;left:0;right:0;top:100%;background:var(--ui-menu);border-bottom:1px solid var(--ui-line);box-shadow:0 24px 40px rgba(0,0,0,.35);padding:10px var(--gutter,16px) 18px;flex-direction:column;align-items:stretch;gap:2px}
.nav .links a{padding:13px 10px;border-radius:10px;border-bottom:0;font-size:16px}
.nav .links a[aria-current="page"]{background:var(--ui-tint)}
.nav .links a.cta{margin-top:8px;min-height:48px}
.nav .links.open{display:flex}
.burger{display:inline-flex}
}
/* footer, the same on every page */
.foot{border-top:1px solid var(--ui-line);color:var(--ui-ink);margin-top:var(--sec,64px)}
.foot .wrap{padding-block:48px 32px}
.foot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:32px}
.foot-brand{display:flex;flex-direction:column;gap:12px;max-width:34ch}
.foot-brand .brand{align-self:flex-start}.foot-brand .word{font-size:16px}
.foot-brand p{color:var(--ui-ash);font-size:14px;margin:0}
.foot-col{display:flex;flex-direction:column;gap:10px;font-size:15px}
.foot-col .eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ui-ash);margin-bottom:4px}
.foot-col a{color:var(--ui-ink-2);text-decoration:none;display:inline-flex;align-items:center;gap:6px;align-self:flex-start}
.foot-col a:hover{color:var(--ui-hot);text-decoration:none}
.foot-base{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px 24px;margin-top:36px;padding-top:20px;border-top:1px solid var(--ui-line);font-size:13px;color:var(--ui-ash)}
.foot-base span{text-wrap:balance}.foot-base .mono{font-family:var(--f-mono)}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
</style>
<!-- head:end -->
<style>
:root{--obsidian:#0C0C0E;--graphite:#16161A;--line:#2A2A30;--ember:#F2541B;--molten:#FFB35C;--bone:#F4F1EC;--ash:#9A9A9E;--ink-2:#C9C7C2;
--max:1200px;--gutter:clamp(16px,4vw,32px);--sec:clamp(56px,8vw,96px);--fs-h1:clamp(32px,5.5vw,56px)}
*{box-sizing:border-box}
body{margin:0;min-height:100vh;display:flex;flex-direction:column;background:var(--obsidian);color:var(--bone);font-family:var(--f-sans);font-size:17px;line-height:1.55;-webkit-font-smoothing:antialiased}
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gutter);width:100%}
main{flex:1}
.eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ash)}
h1{font-family:var(--f-display);font-weight:900;font-size:var(--fs-h1);line-height:1.05;margin:12px 0 16px}
p{margin:0;color:var(--ink-2);max-width:52ch}
.lost{padding-block:var(--sec)}
.places{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));margin-top:32px;list-style:none;padding:0}
.places a{display:flex;flex-direction:column;gap:6px;padding:18px 20px;border:1px solid var(--line);border-radius:14px;background:var(--graphite);color:var(--bone);text-decoration:none;transition:border-color .2s ease,transform .2s ease}
.places a:hover{border-color:var(--ember);transform:translateY(-2px)}
.places b{font-weight:600}
.places span{font-size:14px;color:var(--ash)}
.foot{margin-top:0}
</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="36" height="36" aria-hidden="true"><rect width="1024" height="1024" 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>
<button class="burger" id="nav-burger" type="button" aria-expanded="false" aria-controls="nav-links" aria-label="Menu"><svg class="bars" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"></path></svg><svg class="x" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"></path></svg></button>
<div class="links" id="nav-links">
<a href="/litepaper" data-nav="litepaper">Litepaper</a>
<a href="/live" data-nav="live">Live devnet</a>
<a href="/bench" data-nav="bench">Engineering log</a>
<a href="/evidence" data-nav="evidence">Evidence</a>
<a href="https://github.com/igneum-network/spec" rel="noopener">GitHub</a>
<a href="/#mine" class="cta">Get the miner</a>
</div>
</div>
</nav>
<script>
(function(){
// the menu: open on the button, closed by any link, a tap outside, Escape (focus back on the button) or a resize past 900 px
var b=document.getElementById('nav-burger'),l=document.getElementById('nav-links');if(!b||!l)return;
function set(o){l.classList.toggle('open',o);b.setAttribute('aria-expanded',o?'true':'false');}
b.addEventListener('click',function(){set(!l.classList.contains('open'));});
l.addEventListener('click',function(e){if(e.target.closest('a'))set(false);});
document.addEventListener('click',function(e){if(l.classList.contains('open')&&!l.contains(e.target)&&!b.contains(e.target))set(false);});
document.addEventListener('keydown',function(e){if(e.key==='Escape'&&l.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" class="wrap">
<section class="lost">
<div class="eyebrow">404</div>
<h1>Nothing is mined here.</h1>
<p>That address is not on igneum.network. It may have moved, or the link had a typo. These four pages are everything the site has.</p>
<ul class="places">
<li><a href="/litepaper"><b>Litepaper</b><span>How the chain works, in 17 sections</span></a></li>
<li><a href="/live"><b>Live devnet</b><span>Blocks, miners and finality as they happen</span></a></li>
<li><a href="/bench"><b>Engineering log</b><span>Every measurement, with the commands</span></a></li>
<li><a href="/evidence"><b>Evidence</b><span>Every claim and how far it is tested</span></a></li>
</ul>
</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="30" height="30" aria-hidden="true"><rect width="1024" height="1024" 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>
</nav>
<nav class="foot-col" aria-label="Follow">
<div class="eyebrow">Follow</div>
<a href="/live">Live devnet</a>
<a href="/#journey">Journey</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="/#mine">Get the miner</a>
</nav>
</div>
<div class="foot-base">
<span>© 2026 Igneum. Nothing on this page is an offer to sell anything.</span>
<span class="mono">igneum.network</span>
</div>
</div>
</footer>
<!-- footer:end -->
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -43,7 +43,22 @@ function md(src) {
return { html: out.join('\n'), toc };
}
const mark = `<svg viewBox="0 0 100 100" width="26" height="26" aria-hidden="true"><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></svg>`;
// Shared chrome: fonts and tokens (head), the nav bar and the footer live once in site/partials/ and are injected into every
// page between HTML comment markers (<!-- head:start --> ... <!-- head:end -->, nav, footer; journey on the homepage).
// The committed pages carry the injected copy, so they are right with or without a build; the build keeps them in step.
const partial = name => readFileSync(join(here, 'partials', name), 'utf8').trim();
const HEAD = partial('head.html'), NAV = partial('nav.html'), FOOT = partial('footer.html');
function navFor(active) {
if (!active) return NAV;
const re = new RegExp(`(<a href="[^"]*" data-nav="${active}")`);
if (!re.test(NAV)) throw new Error(`nav: no link with data-nav="${active}"`);
return NAV.replace(re, '$1 aria-current="page"');
}
function inject(html, name, content, file) {
const re = new RegExp(`<!-- ${name}:start -->[\\s\\S]*?<!-- ${name}:end -->`);
if (!re.test(html)) throw new Error(`${file}: missing <!-- ${name}:start --> ... <!-- ${name}:end --> markers`);
return html.replace(re, () => `<!-- ${name}:start -->\n${content}\n<!-- ${name}:end -->`);
}
const ORIGIN = 'https://igneum.network';
const svgIcon = "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";
// Search and share metadata. Same set as the hand-written pages (index, litepaper, live); keep them in step.
@ -58,14 +73,14 @@ function meta(title, desc, path) {
<meta property="og:title" content="${t}">
<meta property="og:description" content="${d}">
<meta property="og:url" content="${url}">
<meta property="og:image" content="${ORIGIN}/og.png?v=2">
<meta property="og:image" content="${ORIGIN}/og.png?v=3">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="${t}">
<meta name="twitter:description" content="${d}">
<meta name="twitter:image" content="${ORIGIN}/og.png?v=2">
<meta name="twitter:image" content="${ORIGIN}/og.png?v=3">
<meta name="twitter:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
<link rel="icon" href="${svgIcon}" type="image/svg+xml">
<link rel="icon" href="/favicon.ico" sizes="48x48">
@ -75,60 +90,77 @@ function meta(title, desc, path) {
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
<link rel="manifest" href="/site.webmanifest">`;
}
function page(title, desc, bodyHtml, toc, note, { path = '/bench', heading = title } = {}) {
const nav = toc.filter(t => t.lvl === 2).map(t => `<li><a href="#${t.id}">${esc(t.t)}</a></li>`).join('');
function page(title, desc, bodyHtml, toc, note, { path = '/bench', heading = title, active = 'bench' } = {}) {
const h2s = toc.filter(t => t.lvl === 2);
const nav = h2s.map(t => `<li><a href="#${t.id}">${esc(t.t)}</a></li>`).join('');
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
${meta(title, desc, path)}
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Unbounded:wght@500;700;900&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap">
<!-- head:start -->
${HEAD}
<!-- head:end -->
<style>
:root{--obsidian:#0C0C0E;--graphite:#16161A;--line:#2A2A30;--ember:#F2541B;--molten:#FFB35C;--bone:#F4F1EC;--ash:#9A9A9E;--ink-2:#C9C7C2;
/* one system for every page: container, gutter, section rhythm, card and tile boxes, heading scale (same tokens as the homepage) */
--max:1200px;--gutter:clamp(16px,4vw,32px);--sec:clamp(56px,8vw,96px);--head:clamp(40px,6vw,64px);
--card-pad:clamp(18px,3vw,28px);--card-r:18px;--tile-pad:18px 20px;--tile-r:14px;--gap:24px;--gap-tile:12px;
--fs-h1:clamp(32px,5.5vw,56px);--fs-h2:clamp(28px,4.2vw,44px);--fs-h3:clamp(18px,2vw,22px);--fs-tile:clamp(20px,2.2vw,26px)}
*{box-sizing:border-box}body{margin:0;background:var(--obsidian);color:var(--bone);font-family:'IBM Plex Sans',system-ui,sans-serif;font-size:16px;line-height:1.6;padding:0}
*{box-sizing:border-box}body{margin:0;background:var(--obsidian);color:var(--bone);font-family:var(--f-sans);font-size:16px;line-height:1.6;padding:0;-webkit-font-smoothing:antialiased}
a{color:var(--ember);text-decoration:none}a:hover{text-decoration:underline}
[id]{scroll-margin-top:calc(var(--nav-h) + 16px)}
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gutter)}
header{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:16px;padding-block:18px;border-bottom:1px solid var(--line)}
.brand{display:flex;align-items:center;gap:10px;color:var(--bone)}.brand b{font-family:'Unbounded',sans-serif;font-weight:900;letter-spacing:.06em;font-size:18px}
header nav{display:flex;flex-wrap:wrap;gap:18px;font-size:14px}header nav a{color:var(--ink-2)}
h1{font-family:'Unbounded',sans-serif;font-weight:900;font-size:var(--fs-h1);line-height:1.05;margin:var(--head) 0 12px}
.note{color:var(--ash);font-size:15px;max-width:72ch;margin-bottom:32px}
.layout{display:grid;grid-template-columns:minmax(0,1fr);gap:32px;padding-bottom:var(--sec)}
@media(min-width:960px){.layout{grid-template-columns:240px minmax(0,1fr);gap:56px}}
.toc{align-self:start;font-size:14px}@media(min-width:960px){.toc{position:sticky;top:24px}}
.toc ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}.toc a{display:block;padding:7px 10px;border-radius:8px;color:var(--ink-2)}.toc a:hover{background:var(--graphite);text-decoration:none;color:var(--bone)}
.eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ash)}
h1{font-family:var(--f-display);font-weight:900;font-size:var(--fs-h1);line-height:1.05;margin:12px 0 12px}
.head{padding-top:var(--head)}
.note{color:var(--ash);font-size:15px;max-width:72ch;margin:0 0 32px}
.layout{display:grid;grid-template-columns:minmax(0,1fr);gap:32px}
@media(min-width:960px){.layout{grid-template-columns:260px minmax(0,1fr);gap:56px}}
.toc{align-self:start;font-size:14px;border:1px solid var(--line);border-radius:var(--tile-r);background:var(--graphite);padding:8px}
.toc .lbl{font-family:var(--f-mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);padding:6px 10px 8px}
.toc ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1px;counter-reset:s;max-height:40vh;overflow:auto;overscroll-behavior:contain;scrollbar-width:thin}
@media(min-width:960px){.toc{position:sticky;top:calc(var(--nav-h) + 20px)}.toc ol{max-height:calc(100vh - var(--nav-h) - 96px)}}
.toc a{display:flex;gap:10px;padding:7px 10px;border-radius:8px;color:var(--ink-2);counter-increment:s;line-height:1.35}
.toc a::before{content:counter(s,decimal-leading-zero);font-family:var(--f-mono);font-size:11px;color:var(--ash);min-width:20px;padding-top:2px}
.toc a:hover{background:var(--obsidian);text-decoration:none;color:var(--bone)}
article{max-width:78ch;min-width:0}
article h1{display:none}
article h2{font-family:'Unbounded',sans-serif;font-weight:700;font-size:var(--fs-h3);line-height:1.3;margin:44px 0 12px;padding-top:24px;border-top:1px solid var(--line)}
article h2{font-family:var(--f-display);font-weight:700;font-size:var(--fs-h3);line-height:1.3;margin:44px 0 12px;padding-top:24px;border-top:1px solid var(--line)}
article h2:first-of-type{margin-top:0;padding-top:0;border-top:0}
article h3{font-family:'Unbounded',sans-serif;font-weight:500;font-size:16px;margin:26px 0 8px}
article h3{font-family:var(--f-display);font-weight:500;font-size:16px;margin:26px 0 8px}
article h4{font-size:15px;margin:20px 0 6px;color:var(--molten)}
article p{margin:0 0 14px}article ul,article ol{margin:0 0 14px;padding-left:22px}article li{margin-bottom:6px}
article p,article li,article h2,article h3{overflow-wrap:anywhere}
code{font-family:'IBM Plex Mono',monospace;font-size:.92em;background:var(--graphite);padding:1px 5px;border-radius:4px;overflow-wrap:anywhere}
pre{margin:0 0 16px;padding:16px 18px;background:var(--graphite);border-radius:var(--card-r);font-family:'IBM Plex Mono',monospace;font-size:13px;line-height:1.55;overflow-x:auto}
.tbl{overflow-x:auto;margin:18px 0 24px;border:1px solid var(--line);border-radius:var(--card-r);background:var(--graphite)}
code{font-family:var(--f-mono);font-size:.92em;background:var(--graphite);padding:1px 5px;border-radius:4px;overflow-wrap:anywhere}
pre{margin:0 0 16px;padding:16px 18px;background:var(--graphite);border-radius:var(--card-r);font-family:var(--f-mono);font-size:13px;line-height:1.55;overflow-x:auto;-webkit-overflow-scrolling:touch}
pre code{background:none;padding:0;font-size:inherit}
.tbl{overflow-x:auto;margin:18px 0 24px;border:1px solid var(--line);border-radius:var(--card-r);background:var(--graphite);-webkit-overflow-scrolling:touch}
table{border-collapse:collapse;width:100%;min-width:560px;font-size:15px}th,td{padding:12px 14px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
th{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);font-weight:500;background:var(--obsidian)}tr:last-child td{border-bottom:0}
footer{border-top:1px solid var(--line);padding-block:32px 48px;font-size:13px;color:var(--ash)}
th{font-family:var(--f-mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);font-weight:500;background:var(--obsidian)}tr:last-child td{border-bottom:0}
.gen{color:var(--ash);font-size:13px;margin:40px 0 0;max-width:72ch}
</style>
</head>
<body>
<div class="wrap">
<header><a class="brand" href="/">${mark}<b>IGNEUM</b></a><nav><a href="/">Home</a><a href="/litepaper">Litepaper</a><a href="/live">Live devnet</a><a href="/bench">Engineering log</a><a href="/evidence">Evidence</a><a href="https://github.com/igneum-network/spec" rel="noopener">GitHub, spec and vectors</a></nav></header>
<!-- nav:start -->
${navFor(active)}
<!-- nav:end -->
<main id="main" class="wrap">
<div class="head">
<div class="eyebrow">${h2s.length} entries, newest at the bottom</div>
<h1>${esc(heading)}</h1>
<p class="note">${note}</p>
</div>
<div class="layout">
<nav class="toc" aria-label="Contents"><ol>${nav}</ol></nav>
<nav class="toc" aria-label="Contents"><div class="lbl">Contents</div><ol>${nav}</ol></nav>
<article>${bodyHtml}</article>
</div>
<footer>© 2026 Igneum. Generated from the repository at build time. Nothing on this page is an offer to sell anything.</footer>
</div>
<p class="gen">Generated from the repository at build time. Times are UTC. Machine names are model names.</p>
</main>
<!-- footer:start -->
${FOOT}
<!-- footer:end -->
</body>
</html>`;
}
@ -208,4 +240,20 @@ if (existsSync(join(docs, 'bench-log.md'))) {
writeFileSync(jp, JSON.stringify(j, null, 2) + '\n');
built.push('journey.json (' + j.log.length + ' entries)');
}
// The hand-written pages: shared head, nav (with the active link marked) and footer injected in place; the homepage also
// gets journey.json inlined so the phases and the log render without a fetch and without a layout shift.
const journey = JSON.parse(readFileSync(join(here, 'journey.json'), 'utf8'));
const PAGES = [['index.html', ''], ['litepaper.html', 'litepaper'], ['live.html', 'live'], ['evidence.html', 'evidence'], ['404.html', '']];
for (const [file, active] of PAGES) {
const p = join(here, file);
if (!existsSync(p)) throw new Error(`missing page ${file}`);
let html = readFileSync(p, 'utf8');
html = inject(html, 'head', HEAD, file);
html = inject(html, 'nav', navFor(active), file);
html = inject(html, 'footer', FOOT, file);
if (file === 'index.html') html = inject(html, 'journey', `<script type="application/json" id="journey-data">${JSON.stringify(journey).replace(/</g, '\\u003c')}</script>`, file);
writeFileSync(p, html);
built.push(file);
}
console.log('built: ' + built.join(', '));

View file

@ -28,49 +28,153 @@
<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">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Unbounded:wght@500;700;900&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap">
<!-- 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>
<style>
/* Shared by every page. Source: site/partials/head.html, injected by site/build.mjs 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. */
@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%}
:root{--f-sans:'IBM Plex Sans','Plex Sans Fallback',system-ui,-apple-system,sans-serif;--f-display:'Unbounded','Unbounded Fallback',sans-serif;--f-mono:'IBM Plex Mono','Plex Mono Fallback',ui-monospace,Menlo,monospace;
/* site chrome tokens (nav, footer, skip link). Dark by default; the litepaper sets light values and resets these in dark mode */
--nav-h:68px;--ui-bg:rgba(12,12,14,.84);--ui-menu:#0C0C0E;--ui-ink:#F4F1EC;--ui-ink-2:#C9C7C2;--ui-ash:#9A9A9E;--ui-line:#2A2A30;--ui-line-2:#3A3A42;--ui-accent:#F2541B;--ui-accent-ink:#0C0C0E;--ui-hot:#FFB35C;--ui-hover:#FF6A2B;--ui-tint:rgba(242,84,27,.12)}
html{-webkit-text-size-adjust:100%}
h1,h2,h3{text-wrap:balance}
p,li,dd,figcaption{text-wrap:pretty}
a:focus-visible,button:focus-visible,summary:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--ui-accent);outline-offset:3px;border-radius:6px}
.skip{position:absolute;left:12px;top:-80px;z-index:50;background:var(--ui-accent);color:var(--ui-accent-ink);padding:10px 14px;border-radius:10px;font:600 15px/1.2 var(--f-sans);text-decoration:none}
.skip:focus{top:12px}
/* nav: one bar on every page, the mark in its black square, five links and the miner button, a menu under 901 px */
.nav{position:sticky;top:0;z-index:20;background:var(--ui-bg);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid var(--ui-line);color:var(--ui-ink)}
.nav .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:var(--nav-h)}
.nav a{color:inherit;text-decoration:none}
.brand{display:inline-flex;align-items:center;gap:10px;color:var(--ui-ink);text-decoration:none;flex:0 0 auto}
.brand .mark{display:block;flex:0 0 auto}
.brand .word{font-family:var(--f-display);font-weight:900;font-size:20px;letter-spacing:.06em;line-height:1}
.nav .links{display:flex;align-items:center;gap:clamp(14px,2vw,26px);font-size:15px;font-weight:500}
.nav .links a{color:var(--ui-ink-2);padding:4px 0;border-bottom:2px solid transparent;transition:color .15s ease,border-color .15s ease}
.nav .links a:hover,.nav .brand:hover{color:var(--ui-hot);text-decoration:none}
.nav .brand:hover{color:var(--ui-ink)}
.nav .links a[aria-current="page"]{color:var(--ui-ink);border-bottom-color:var(--ui-accent)}
.nav .links a.cta{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:8px 16px;border-radius:10px;font-weight:600;background:var(--ui-accent);color:var(--ui-accent-ink);border:1px solid var(--ui-accent);transition:background .15s ease,transform .15s ease}
.nav .links a.cta:hover{background:var(--ui-hover);border-color:var(--ui-hover);color:var(--ui-accent-ink);transform:translateY(-1px)}
.burger{display:none;background:none;border:1px solid var(--ui-line-2);color:var(--ui-ink);border-radius:10px;width:44px;height:44px;align-items:center;justify-content:center;cursor:pointer;padding:0;flex:0 0 auto}
.burger .x{display:none}.burger[aria-expanded="true"] .x{display:block}.burger[aria-expanded="true"] .bars{display:none}
@media (max-width:900px){
.nav .links{display:none;position:absolute;left:0;right:0;top:100%;background:var(--ui-menu);border-bottom:1px solid var(--ui-line);box-shadow:0 24px 40px rgba(0,0,0,.35);padding:10px var(--gutter,16px) 18px;flex-direction:column;align-items:stretch;gap:2px}
.nav .links a{padding:13px 10px;border-radius:10px;border-bottom:0;font-size:16px}
.nav .links a[aria-current="page"]{background:var(--ui-tint)}
.nav .links a.cta{margin-top:8px;min-height:48px}
.nav .links.open{display:flex}
.burger{display:inline-flex}
}
/* footer, the same on every page */
.foot{border-top:1px solid var(--ui-line);color:var(--ui-ink);margin-top:var(--sec,64px)}
.foot .wrap{padding-block:48px 32px}
.foot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:32px}
.foot-brand{display:flex;flex-direction:column;gap:12px;max-width:34ch}
.foot-brand .brand{align-self:flex-start}.foot-brand .word{font-size:16px}
.foot-brand p{color:var(--ui-ash);font-size:14px;margin:0}
.foot-col{display:flex;flex-direction:column;gap:10px;font-size:15px}
.foot-col .eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ui-ash);margin-bottom:4px}
.foot-col a{color:var(--ui-ink-2);text-decoration:none;display:inline-flex;align-items:center;gap:6px;align-self:flex-start}
.foot-col a:hover{color:var(--ui-hot);text-decoration:none}
.foot-base{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px 24px;margin-top:36px;padding-top:20px;border-top:1px solid var(--ui-line);font-size:13px;color:var(--ui-ash)}
.foot-base span{text-wrap:balance}.foot-base .mono{font-family:var(--f-mono)}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
</style>
<!-- head:end -->
<style>
:root{--obsidian:#0C0C0E;--graphite:#16161A;--line:#2A2A30;--ember:#F2541B;--molten:#FFB35C;--bone:#F4F1EC;--ash:#9A9A9E;--ink-2:#C9C7C2;
/* one system for every page: container, gutter, section rhythm, card and tile boxes, heading scale (same tokens as the homepage) */
--max:1200px;--gutter:clamp(16px,4vw,32px);--sec:clamp(56px,8vw,96px);--head:clamp(40px,6vw,64px);
--card-pad:clamp(18px,3vw,28px);--card-r:18px;--tile-pad:18px 20px;--tile-r:14px;--gap:24px;--gap-tile:12px;
--fs-h1:clamp(32px,5.5vw,56px);--fs-h2:clamp(28px,4.2vw,44px);--fs-h3:clamp(18px,2vw,22px);--fs-tile:clamp(20px,2.2vw,26px)}
*{box-sizing:border-box}body{margin:0;background:var(--obsidian);color:var(--bone);font-family:'IBM Plex Sans',system-ui,sans-serif;font-size:16px;line-height:1.6;padding:0}
*{box-sizing:border-box}body{margin:0;background:var(--obsidian);color:var(--bone);font-family:var(--f-sans);font-size:16px;line-height:1.6;padding:0;-webkit-font-smoothing:antialiased}
a{color:var(--ember);text-decoration:none}a:hover{text-decoration:underline}
[id]{scroll-margin-top:calc(var(--nav-h) + 16px)}
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gutter)}
header{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:16px;padding-block:18px;border-bottom:1px solid var(--line)}
.brand{display:flex;align-items:center;gap:10px;color:var(--bone)}.brand b{font-family:'Unbounded',sans-serif;font-weight:900;letter-spacing:.06em;font-size:18px}
header nav{display:flex;flex-wrap:wrap;gap:18px;font-size:14px}header nav a{color:var(--ink-2)}header nav a[aria-current]{color:var(--bone)}
h1{font-family:'Unbounded',sans-serif;font-weight:900;font-size:var(--fs-h1);line-height:1.05;margin:var(--head) 0 12px}
h2{font-family:'Unbounded',sans-serif;font-weight:700;font-size:var(--fs-h3);line-height:1.3;margin:44px 0 12px;padding-top:24px;border-top:1px solid var(--line)}
/* nav and footer: shared, see site/partials */
.eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ash)}
.head{padding-top:var(--head)}
h1{font-family:var(--f-display);font-weight:900;font-size:var(--fs-h1);line-height:1.05;margin:12px 0 12px}
h2{font-family:var(--f-display);font-weight:700;font-size:var(--fs-h3);line-height:1.3;margin:44px 0 12px;padding-top:24px;border-top:1px solid var(--line)}
.note{color:var(--ash);font-size:15px;max-width:72ch;margin-bottom:20px}
.note b{color:var(--bone);font-weight:500}
.labels{display:grid;gap:var(--gap-tile);grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));margin:20px 0 28px}
.label{background:var(--graphite);border:1px solid var(--line);border-radius:var(--tile-r);padding:var(--tile-pad);min-width:0}
.label .k{font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--molten)}
.label .v{font-family:'Unbounded',sans-serif;font-weight:700;font-size:var(--fs-tile);line-height:1.1;margin:6px 0 6px;color:var(--bone)}
.label .k{font-family:var(--f-mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--molten)}
.label .v{font-family:var(--f-display);font-weight:700;font-size:var(--fs-tile);line-height:1.1;margin:6px 0 6px;color:var(--bone)}
.label p{margin:0;font-size:13px;color:var(--ash)}
.chips{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 16px}
.chip{font:inherit;font-size:13px;color:var(--ink-2);background:var(--graphite);border:1px solid var(--line);border-radius:999px;padding:6px 12px;cursor:pointer;min-height:36px}
.chip b{color:var(--bone);font-weight:600}.chip.on{border-color:var(--ember);color:var(--bone)}
.tbl{overflow-x:auto;margin:0 0 24px;border:1px solid var(--line);border-radius:var(--card-r);background:var(--graphite)}
.chip{font:inherit;font-size:13px;color:var(--ink-2);background:var(--graphite);border:1px solid var(--line);border-radius:999px;padding:6px 12px;cursor:pointer;min-height:36px;transition:border-color .15s ease,color .15s ease}
.chip b{color:var(--bone);font-weight:600}.chip:hover{border-color:var(--ink-2)}.chip.on{border-color:var(--ember);color:var(--bone)}
.tbl{overflow-x:auto;margin:0 0 24px;border:1px solid var(--line);border-radius:var(--card-r);background:var(--graphite);-webkit-overflow-scrolling:touch}
.hint{font-family:var(--f-mono);font-size:12px;color:var(--ash);margin:0 0 10px;display:none}
@media (max-width:1140px){.hint{display:block}}
table{border-collapse:collapse;width:100%;min-width:1100px;font-size:14px}th,td{padding:12px 14px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
th{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);font-weight:500;background:var(--obsidian);position:sticky;top:0;cursor:pointer;user-select:none;white-space:nowrap}
th:hover{color:var(--bone)}th[aria-sort]::after{content:' \2191';color:var(--ember)}th[aria-sort="descending"]::after{content:' \2193'}
th{font-family:var(--f-mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);font-weight:500;background:var(--obsidian);white-space:nowrap;padding:0}
th button{all:unset;display:block;box-sizing:border-box;width:100%;padding:12px 14px;cursor:pointer;color:inherit;font:inherit;letter-spacing:inherit;text-transform:inherit}
th button:hover{color:var(--bone)}th button:focus-visible{outline:2px solid var(--ember);outline-offset:-3px;border-radius:6px}
th[aria-sort] button::after{content:' \2191';color:var(--ember)}th[aria-sort="descending"] button::after{content:' \2193'}
tr:last-child td{border-bottom:0}tr[hidden]{display:none}
td.n{font-family:'IBM Plex Mono',monospace;color:var(--ash)}td.claim{min-width:220px;font-weight:500}td .where{font-weight:400;color:var(--ash);font-size:13px;margin-top:4px}
td.mono{font-family:'IBM Plex Mono',monospace;font-size:12.5px;min-width:180px}td.iv{color:var(--ash);white-space:nowrap}
.st{display:inline-block;font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.08em;text-transform:uppercase;padding:3px 8px;border-radius:999px;border:1px solid var(--line);white-space:nowrap}
td.n{font-family:var(--f-mono);color:var(--ash)}td.claim{min-width:220px;font-weight:500}td .where{font-weight:400;color:var(--ash);font-size:13px;margin-top:4px}
td.mono{font-family:var(--f-mono);font-size:12.5px;min-width:180px}td.iv{color:var(--ash);white-space:nowrap}
.st{display:inline-block;font-family:var(--f-mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;padding:3px 8px;border-radius:999px;border:1px solid var(--line);white-space:nowrap}
.st-0{color:var(--ash)}.st-1{color:var(--ink-2)}.st-2{color:var(--molten);border-color:var(--molten)}.st-3,.st-4{color:var(--ember);border-color:var(--ember)}
code{font-family:'IBM Plex Mono',monospace;font-size:.92em;background:var(--obsidian);padding:1px 5px;border-radius:4px;overflow-wrap:anywhere}
code{font-family:var(--f-mono);font-size:.92em;background:var(--obsidian);padding:1px 5px;border-radius:4px;overflow-wrap:anywhere}
.small table{min-width:560px}
footer{border-top:1px solid var(--line);padding-block:32px 48px;font-size:13px;color:var(--ash);margin-top:var(--sec)}
.asof{color:var(--ash);font-size:13px;margin:40px 0 0;max-width:72ch}
</style>
</head>
<body>
<div class="wrap">
<header><a class="brand" href="/"><svg viewBox="0 0 100 100" width="26" height="26" aria-hidden="true"><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></svg><b>IGNEUM</b></a><nav><a href="/">Home</a><a href="/litepaper">Litepaper</a><a href="/live">Live devnet</a><a href="/bench">Engineering log</a><a href="/evidence" aria-current="page">Evidence</a><a href="https://github.com/igneum-network/spec" rel="noopener">GitHub, spec and vectors</a></nav></header>
<!-- 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="36" height="36" aria-hidden="true"><rect width="1024" height="1024" 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>
<button class="burger" id="nav-burger" type="button" aria-expanded="false" aria-controls="nav-links" aria-label="Menu"><svg class="bars" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"></path></svg><svg class="x" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"></path></svg></button>
<div class="links" id="nav-links">
<a href="/litepaper" data-nav="litepaper">Litepaper</a>
<a href="/live" data-nav="live">Live devnet</a>
<a href="/bench" data-nav="bench">Engineering log</a>
<a href="/evidence" data-nav="evidence" aria-current="page">Evidence</a>
<a href="https://github.com/igneum-network/spec" rel="noopener">GitHub</a>
<a href="/#mine" class="cta">Get the miner</a>
</div>
</div>
</nav>
<script>
(function(){
// the menu: open on the button, closed by any link, a tap outside, Escape (focus back on the button) or a resize past 900 px
var b=document.getElementById('nav-burger'),l=document.getElementById('nav-links');if(!b||!l)return;
function set(o){l.classList.toggle('open',o);b.setAttribute('aria-expanded',o?'true':'false');}
b.addEventListener('click',function(){set(!l.classList.contains('open'));});
l.addEventListener('click',function(e){if(e.target.closest('a'))set(false);});
document.addEventListener('click',function(e){if(l.classList.contains('open')&&!l.contains(e.target)&&!b.contains(e.target))set(false);});
document.addEventListener('keydown',function(e){if(e.key==='Escape'&&l.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" class="wrap">
<div class="head">
<div class="eyebrow">30 claims · 5 labels · 4 Oct 2026</div>
<h1>Evidence</h1>
</div>
<p class="note">Every claim the homepage and the litepaper make, one row each, with one of five labels: <b>designed</b> (a decision, no code), <b>implemented</b> (code with passing test vectors), <b>tested by the team</b> (measured by the project on a named machine, in the engineering log), <b>reproduced externally</b> (a third party ran the published command and got the published result) and <b>reviewed independently</b> (a named outside reviewer published a finding on that version). Nothing on this chain has been reproduced externally or reviewed independently; every row says so. A label belongs to the exact version in the row, and an audit of one version never covers a newer one. The 12-node cloud network of 4 October 2026 is the project's own, so its rows are tested by the team, not reproduced externally.</p>
<div class="labels">
<div class="label"><div class="k">designed</div><div class="v">6</div><p>A decision in the design document or the specification. No code, or a stub</p></div>
@ -79,7 +183,8 @@ footer{border-top:1px solid var(--line);padding-block:32px 48px;font-size:13px;c
<div class="label"><div class="k">reproduced externally</div><div class="v">0</div><p>None yet. The repository is private until January 2027</p></div>
<div class="label"><div class="k">reviewed independently</div><div class="v">0</div><p>None yet. What review would cost and who pays is in the funding plan</p></div>
</div>
<div class="chips" role="group" aria-label="Filter by status"><button type="button" class="chip on" data-filter=""><b>30</b> all</button><button type="button" class="chip" data-filter="designed"><b>6</b> designed</button><button type="button" class="chip" data-filter="implemented"><b>3</b> implemented</button><button type="button" class="chip" data-filter="tested by the team"><b>21</b> tested by the team</button><button type="button" class="chip" data-filter="reproduced externally"><b>0</b> reproduced externally</button><button type="button" class="chip" data-filter="reviewed independently"><b>0</b> reviewed independently</button></div>
<div class="chips" role="group" aria-label="Filter by status"><button type="button" class="chip on" aria-pressed="true" data-filter=""><b>30</b> all</button><button type="button" class="chip" aria-pressed="false" data-filter="designed"><b>6</b> designed</button><button type="button" class="chip" aria-pressed="false" data-filter="implemented"><b>3</b> implemented</button><button type="button" class="chip" aria-pressed="false" data-filter="tested by the team"><b>21</b> tested by the team</button><button type="button" class="chip" aria-pressed="false" data-filter="reproduced externally"><b>0</b> reproduced externally</button><button type="button" class="chip" aria-pressed="false" data-filter="reviewed independently"><b>0</b> reviewed independently</button></div>
<p class="hint">The table is wider than this screen. Scroll it sideways.</p>
<div class="tbl"><table id="claims">
<thead><tr><th data-col="0" data-num="1">#</th><th data-col="1">Claim</th><th data-col="2" data-status="1">Status</th><th data-col="3">Version or commit</th><th data-col="4">Reproducible test</th><th data-col="5">Result, date, machine</th><th data-col="6">Independent verification</th></tr></thead>
<tbody>
@ -123,15 +228,49 @@ footer{border-top:1px solid var(--line);padding-block:32px 48px;font-size:13px;c
<tr><td>reproduced externally</td><td>reviewed independently</td><td>A named reviewer's published finding on that version. Funding for review is <code>docs/plans/funding.md</code></td></tr>
<tr><td>any</td><td>the row's status falls back</td><td>A new version of the code or rule the row names</td></tr>
</tbody></table></div>
<footer>© 2026 Igneum. Statuses are honest as of 4 October 2026 and change only through this page. Nothing on this page is an offer to sell anything.</footer>
</div>
<p class="asof">Statuses are honest as of 4 October 2026 and change only through this page.</p>
</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="30" height="30" aria-hidden="true"><rect width="1024" height="1024" 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>
</nav>
<nav class="foot-col" aria-label="Follow">
<div class="eyebrow">Follow</div>
<a href="/live">Live devnet</a>
<a href="/#journey">Journey</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="/#mine">Get the miner</a>
</nav>
</div>
<div class="foot-base">
<span>© 2026 Igneum. Nothing on this page is an offer to sell anything.</span>
<span class="mono">igneum.network</span>
</div>
</div>
</footer>
<!-- footer:end -->
<script>
(function(){
var order=["designed","implemented","tested by the team","reproduced externally","reviewed independently"];
var table=document.getElementById('claims'),tbody=table.tBodies[0],ths=table.querySelectorAll('th');
var rows=Array.prototype.slice.call(tbody.rows);
function key(tr,th){var td=tr.cells[+th.dataset.col];if(th.dataset.num)return +td.textContent;if(th.dataset.status)return order.indexOf(td.textContent.trim());return td.textContent.trim().toLowerCase();}
ths.forEach(function(th){th.addEventListener('click',function(){
// each heading becomes a real button, so sorting works from the keyboard and a screen reader hears it as a control
ths.forEach(function(th){var b=document.createElement('button');b.type='button';b.textContent=th.textContent;b.setAttribute('aria-label','Sort by '+th.textContent.trim());th.textContent='';th.appendChild(b);
b.addEventListener('click',function(){
var dir=th.getAttribute('aria-sort')==='ascending'?'descending':'ascending';
ths.forEach(function(o){o.removeAttribute('aria-sort');});th.setAttribute('aria-sort',dir);
var s=rows.slice().sort(function(a,b){var ka=key(a,th),kb=key(b,th);return (ka<kb?-1:ka>kb?1:0)*(dir==='ascending'?1:-1);});
@ -139,7 +278,7 @@ footer{border-top:1px solid var(--line);padding-block:32px 48px;font-size:13px;c
});});
var chips=document.querySelectorAll('.chip');
chips.forEach(function(c){c.addEventListener('click',function(){
chips.forEach(function(o){o.classList.toggle('on',o===c);});
chips.forEach(function(o){var on=o===c;o.classList.toggle('on',on);o.setAttribute('aria-pressed',on?'true':'false');});
var f=c.dataset.filter;rows.forEach(function(tr){tr.hidden=!!f&&tr.dataset.status!==f;});
});});
})();

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -180,6 +180,41 @@
"text": "Devnet-v4 integration: nine branches merged, 3-node test network on the merged node, Windows cross-build",
"short": "Devnet v4: nine branches merged into one node"
},
{
"date": "2026-10-03",
"text": "Igneum-node devnet v2: sustained-mining finality rule v2 on a four-miner test network, and as a follower of the live devnet",
"short": "Finality rule v2 live on a four-miner test network"
},
{
"date": "2026-10-03",
"text": "Execution layer devnet v3: revm over the selected chain, 3-node simnet, viem smoke test",
"short": "EVM execution layer: identical state on three nodes"
},
{
"date": "2026-10-03",
"text": "Weak-program census: 400,000 program runs through the CPU reference, the redundant-load finding, and the rules for M5 and M6",
"short": "Census of 400,000 programs: redundant loads found"
},
{
"date": "2026-10-03",
"text": "Proving v0: first SP1 proof of an Igneum block, Apple M5 Max CPU, loaded machine",
"short": "First SP1 proof of an Igneum block, on a laptop CPU"
},
{
"date": "2026-10-03",
"text": "Windows node package: igneumd cross-compiled for x86_64-pc-windows-gnu, two-peer sync test",
"short": "Windows node package: cross-compiled, two-peer sync"
},
{
"date": "2026-10-03",
"text": "R3.26 / M15: PoW checked after the cheap checks, cache-build cap, attack before and after",
"short": "Cache-build attack closed: 10.6 s of rebuilds to 14 ms"
},
{
"date": "2026-10-03",
"text": "Difficulty controller: devnet record, simulator, Igneum dual-lane rule, 3-node CPU test network",
"short": "Igneum dual-lane difficulty rule built and simulated"
},
{
"date": "2026-10-03",
"text": "First devnet blocks on the real lottery hash: CPU, then Metal GPU, three worker implementations",
@ -214,41 +249,6 @@
"date": "2026-10-03",
"text": "RTX 5090, memory-hard dataset",
"short": "RTX 5090 on the memory-hard dataset"
},
{
"date": "2026-10-03",
"text": "Per-identity hash rate \"decay\" on the RTX 5090: diagnosis and Metal reproduction",
"short": "RTX 5090 hash-rate decay diagnosed: a miner bug, fixed"
},
{
"date": "2026-10-03",
"text": "Igneum-node devnet v2: sustained-mining finality rule v2 on a four-miner test network, and as a follower of the live devnet",
"short": "Finality rule v2 live on a four-miner test network"
},
{
"date": "2026-10-03",
"text": "Execution layer devnet v3: revm over the selected chain, 3-node simnet, viem smoke test",
"short": "EVM execution layer: identical state on three nodes"
},
{
"date": "2026-10-03",
"text": "Weak-program census: 400,000 program runs through the CPU reference, the redundant-load finding, and the rules for M5 and M6",
"short": "Census of 400,000 programs: redundant loads found"
},
{
"date": "2026-10-03",
"text": "Proving v0: first SP1 proof of an Igneum block, Apple M5 Max CPU, loaded machine",
"short": "First SP1 proof of an Igneum block, on a laptop CPU"
},
{
"date": "2026-10-03",
"text": "Windows node package: igneumd cross-compiled for x86_64-pc-windows-gnu, two-peer sync test",
"short": "Windows node package: cross-compiled, two-peer sync"
},
{
"date": "2026-10-03",
"text": "R3.26 / M15: PoW checked after the cheap checks, cache-build cap, attack before and after",
"short": "Cache-build attack closed: 10.6 s of rebuilds to 14 ms"
}
]
}

View file

@ -28,17 +28,87 @@
<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">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Unbounded:wght@500;700;900&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap">
<link rel="preload" href="/fonts/unbounded-500.woff2" as="font" type="font/woff2" crossorigin>
<!-- 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>
<style>
/* Shared by every page. Source: site/partials/head.html, injected by site/build.mjs 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. */
@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%}
:root{--f-sans:'IBM Plex Sans','Plex Sans Fallback',system-ui,-apple-system,sans-serif;--f-display:'Unbounded','Unbounded Fallback',sans-serif;--f-mono:'IBM Plex Mono','Plex Mono Fallback',ui-monospace,Menlo,monospace;
/* site chrome tokens (nav, footer, skip link). Dark by default; the litepaper sets light values and resets these in dark mode */
--nav-h:68px;--ui-bg:rgba(12,12,14,.84);--ui-menu:#0C0C0E;--ui-ink:#F4F1EC;--ui-ink-2:#C9C7C2;--ui-ash:#9A9A9E;--ui-line:#2A2A30;--ui-line-2:#3A3A42;--ui-accent:#F2541B;--ui-accent-ink:#0C0C0E;--ui-hot:#FFB35C;--ui-hover:#FF6A2B;--ui-tint:rgba(242,84,27,.12)}
html{-webkit-text-size-adjust:100%}
h1,h2,h3{text-wrap:balance}
p,li,dd,figcaption{text-wrap:pretty}
a:focus-visible,button:focus-visible,summary:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--ui-accent);outline-offset:3px;border-radius:6px}
.skip{position:absolute;left:12px;top:-80px;z-index:50;background:var(--ui-accent);color:var(--ui-accent-ink);padding:10px 14px;border-radius:10px;font:600 15px/1.2 var(--f-sans);text-decoration:none}
.skip:focus{top:12px}
/* nav: one bar on every page, the mark in its black square, five links and the miner button, a menu under 901 px */
.nav{position:sticky;top:0;z-index:20;background:var(--ui-bg);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid var(--ui-line);color:var(--ui-ink)}
.nav .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:var(--nav-h)}
.nav a{color:inherit;text-decoration:none}
.brand{display:inline-flex;align-items:center;gap:10px;color:var(--ui-ink);text-decoration:none;flex:0 0 auto}
.brand .mark{display:block;flex:0 0 auto}
.brand .word{font-family:var(--f-display);font-weight:900;font-size:20px;letter-spacing:.06em;line-height:1}
.nav .links{display:flex;align-items:center;gap:clamp(14px,2vw,26px);font-size:15px;font-weight:500}
.nav .links a{color:var(--ui-ink-2);padding:4px 0;border-bottom:2px solid transparent;transition:color .15s ease,border-color .15s ease}
.nav .links a:hover,.nav .brand:hover{color:var(--ui-hot);text-decoration:none}
.nav .brand:hover{color:var(--ui-ink)}
.nav .links a[aria-current="page"]{color:var(--ui-ink);border-bottom-color:var(--ui-accent)}
.nav .links a.cta{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:8px 16px;border-radius:10px;font-weight:600;background:var(--ui-accent);color:var(--ui-accent-ink);border:1px solid var(--ui-accent);transition:background .15s ease,transform .15s ease}
.nav .links a.cta:hover{background:var(--ui-hover);border-color:var(--ui-hover);color:var(--ui-accent-ink);transform:translateY(-1px)}
.burger{display:none;background:none;border:1px solid var(--ui-line-2);color:var(--ui-ink);border-radius:10px;width:44px;height:44px;align-items:center;justify-content:center;cursor:pointer;padding:0;flex:0 0 auto}
.burger .x{display:none}.burger[aria-expanded="true"] .x{display:block}.burger[aria-expanded="true"] .bars{display:none}
@media (max-width:900px){
.nav .links{display:none;position:absolute;left:0;right:0;top:100%;background:var(--ui-menu);border-bottom:1px solid var(--ui-line);box-shadow:0 24px 40px rgba(0,0,0,.35);padding:10px var(--gutter,16px) 18px;flex-direction:column;align-items:stretch;gap:2px}
.nav .links a{padding:13px 10px;border-radius:10px;border-bottom:0;font-size:16px}
.nav .links a[aria-current="page"]{background:var(--ui-tint)}
.nav .links a.cta{margin-top:8px;min-height:48px}
.nav .links.open{display:flex}
.burger{display:inline-flex}
}
/* footer, the same on every page */
.foot{border-top:1px solid var(--ui-line);color:var(--ui-ink);margin-top:var(--sec,64px)}
.foot .wrap{padding-block:48px 32px}
.foot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:32px}
.foot-brand{display:flex;flex-direction:column;gap:12px;max-width:34ch}
.foot-brand .brand{align-self:flex-start}.foot-brand .word{font-size:16px}
.foot-brand p{color:var(--ui-ash);font-size:14px;margin:0}
.foot-col{display:flex;flex-direction:column;gap:10px;font-size:15px}
.foot-col .eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ui-ash);margin-bottom:4px}
.foot-col a{color:var(--ui-ink-2);text-decoration:none;display:inline-flex;align-items:center;gap:6px;align-self:flex-start}
.foot-col a:hover{color:var(--ui-hot);text-decoration:none}
.foot-base{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px 24px;margin-top:36px;padding-top:20px;border-top:1px solid var(--ui-line);font-size:13px;color:var(--ui-ash)}
.foot-base span{text-wrap:balance}.foot-base .mono{font-family:var(--f-mono)}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
</style>
<!-- head:end -->
<style>
:root{
--ground:#F4F1EC; --surface:#FFFFFF; --surface-2:#ECE8E0; --line:#DAD5CB;
--ink:#0C0C0E; --ink-2:#3D3B37; --quiet:#6E6B65;
--ember:#D9430F; --ember-ink:#FFFFFF; --molten:#B9741C; --tint:#FBE9E0;
--code:#16161A; --code-ink:#E6E2DA;
/* the shared nav and footer follow the paper's scheme: light here, the dark defaults below */
--ui-bg:rgba(244,241,236,.86); --ui-menu:#F4F1EC; --ui-ink:#0C0C0E; --ui-ink-2:#3D3B37; --ui-ash:#6E6B65; --ui-line:#DAD5CB; --ui-line-2:#C9C3B8;
--ui-accent:#D9430F; --ui-accent-ink:#FFFFFF; --ui-hot:#B9741C; --ui-hover:#F2541B; --ui-tint:#FBE9E0;
/* one system for every page: container, gutter, section rhythm, card and tile boxes, heading scale (same tokens as the homepage) */
--max:1200px;--gutter:clamp(16px,4vw,32px);--sec:clamp(56px,8vw,96px);--head:clamp(40px,6vw,64px);
--card-pad:clamp(18px,3vw,28px);--card-r:18px;--tile-pad:18px 20px;--tile-r:14px;--gap:24px;--gap-tile:12px;
--fs-h1:clamp(32px,5.5vw,56px);--fs-h2:clamp(28px,4.2vw,44px);--fs-h3:clamp(18px,2vw,22px);--fs-tile:clamp(20px,2.2vw,26px);
--lp-off:84px;
}
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]){
@ -46,6 +116,8 @@
--ink:#F4F1EC; --ink-2:#C9C7C2; --quiet:#9A9A9E;
--ember:#F2541B; --ember-ink:#0C0C0E; --molten:#FFB35C; --tint:#2A1A12;
--code:#0C0C0E; --code-ink:#C9C7C2;
--ui-bg:rgba(12,12,14,.84); --ui-menu:#0C0C0E; --ui-ink:#F4F1EC; --ui-ink-2:#C9C7C2; --ui-ash:#9A9A9E; --ui-line:#2A2A30; --ui-line-2:#3A3A42;
--ui-accent:#F2541B; --ui-accent-ink:#0C0C0E; --ui-hot:#FFB35C; --ui-hover:#FF6A2B; --ui-tint:rgba(242,84,27,.12);
color-scheme:dark;
}
}
@ -54,99 +126,130 @@
--ink:#F4F1EC; --ink-2:#C9C7C2; --quiet:#9A9A9E;
--ember:#F2541B; --ember-ink:#0C0C0E; --molten:#FFB35C; --tint:#2A1A12;
--code:#0C0C0E; --code-ink:#C9C7C2;
--ui-bg:rgba(12,12,14,.84); --ui-menu:#0C0C0E; --ui-ink:#F4F1EC; --ui-ink-2:#C9C7C2; --ui-ash:#9A9A9E; --ui-line:#2A2A30; --ui-line-2:#3A3A42;
--ui-accent:#F2541B; --ui-accent-ink:#0C0C0E; --ui-hot:#FFB35C; --ui-hover:#FF6A2B; --ui-tint:rgba(242,84,27,.12);
color-scheme:dark;
}
*{box-sizing:border-box}
body{margin:0;background:var(--ground);color:var(--ink);font-family:'IBM Plex Sans',system-ui,-apple-system,sans-serif;font-size:17px;line-height:1.6;padding:0}
body{margin:0;background:var(--ground);color:var(--ink);font-family:var(--f-sans);font-size:17px;line-height:1.6;padding:0;-webkit-font-smoothing:antialiased}
a{color:var(--ember);text-decoration:none}
a:hover{text-decoration:underline}
a:focus-visible,button:focus-visible{outline:2px solid var(--ember);outline-offset:3px}
/* every id lands under the sticky bar (and the sticky contents row on a phone); --lp-off is measured by the script */
[id]{scroll-margin-top:var(--lp-off)}
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gutter)}
.cover{padding-block:var(--head) 40px;border-bottom:1px solid var(--line);display:flex;flex-wrap:wrap;gap:32px;align-items:flex-end;justify-content:space-between}
.brand{display:flex;align-items:center;gap:14px}
.brand .word{font-family:'Unbounded',sans-serif;font-weight:900;font-size:26px;letter-spacing:.06em}
.eyebrow{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--quiet)}
.cover h1{margin:12px 0 10px;font-family:'Unbounded',sans-serif;font-weight:900;font-size:var(--fs-h1);line-height:1.05;letter-spacing:-.01em;text-wrap:balance}
.eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--quiet)}
.cover h1{margin:12px 0 10px;font-family:var(--f-display);font-weight:900;font-size:var(--fs-h1);line-height:1.05;letter-spacing:-.01em;text-wrap:balance}
.cover .tag{font-size:20px;color:var(--ink-2);max-width:40ch}
.meta{display:flex;flex-direction:column;gap:6px;font-family:'IBM Plex Mono',monospace;font-size:13px;color:var(--quiet);text-align:right}
.meta{display:flex;flex-direction:column;gap:6px;font-family:var(--f-mono);font-size:13px;color:var(--quiet);text-align:right}
.meta b{color:var(--ink);font-weight:500}
.layout{display:grid;grid-template-columns:minmax(0,1fr);gap:32px;padding-block:40px var(--sec)}
@media (min-width:960px){.layout{grid-template-columns:240px minmax(0,1fr);gap:56px}}
.toc{align-self:start}
@media (min-width:960px){.toc{position:sticky;top:calc(env(safe-area-inset-top,0px) + 24px)}}
@media (min-width:960px){.toc{position:sticky;top:calc(var(--nav-h) + 24px)}}
.toc ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px;counter-reset:s}
.toc li a{display:flex;gap:10px;padding:7px 10px;border-radius:8px;color:var(--ink-2);font-size:14px;counter-increment:s}
.toc li a::before{content:counter(s,decimal-leading-zero);font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--quiet);min-width:22px;padding-top:2px}
.toc li a{display:flex;gap:10px;padding:7px 10px;border-radius:8px;color:var(--ink-2);font-size:14px;counter-increment:s;line-height:1.35}
.toc li a::before{content:counter(s,decimal-leading-zero);font-family:var(--f-mono);font-size:12px;color:var(--quiet);min-width:22px;padding-top:2px}
.toc li a:hover{background:var(--surface-2);text-decoration:none;color:var(--ink)}
.toc .dl{margin-top:18px;padding-top:18px;border-top:1px solid var(--line);font-size:13px;color:var(--quiet)}
article{max-width:72ch}
section{padding-block:40px;border-top:1px solid var(--line)}
section:first-of-type{border-top:0;padding-top:0}
h2{margin:0 0 18px;font-family:'Unbounded',sans-serif;font-weight:700;font-size:var(--fs-h2);line-height:1.1;text-wrap:balance}
h3{margin:28px 0 8px;font-family:'Unbounded',sans-serif;font-weight:500;font-size:var(--fs-h3);line-height:1.3}
h2{margin:0 0 18px;font-family:var(--f-display);font-weight:700;font-size:var(--fs-h2);line-height:1.1;text-wrap:balance}
h3{margin:28px 0 8px;font-family:var(--f-display);font-weight:500;font-size:var(--fs-h3);line-height:1.3}
p{margin:0 0 16px}
.lead{font-size:20px;line-height:1.5;color:var(--ink-2)}
ul,ol{margin:0 0 16px;padding-left:22px}
li{margin-bottom:8px}
strong{font-weight:600}
.pull{margin:24px 0;padding:20px var(--card-pad);border-left:4px solid var(--ember);background:var(--tint);border-radius:0 var(--tile-r) var(--tile-r) 0;font-family:'Unbounded',sans-serif;font-weight:500;font-size:19px;line-height:1.4}
.pull{margin:24px 0;padding:20px var(--card-pad);border-left:4px solid var(--ember);background:var(--tint);border-radius:0 var(--tile-r) var(--tile-r) 0;font-family:var(--f-display);font-weight:500;font-size:19px;line-height:1.4}
.tbl{overflow-x:auto;margin:18px 0 24px;border:1px solid var(--line);border-radius:var(--card-r);background:var(--surface)}
table{border-collapse:collapse;width:100%;min-width:560px;font-size:15px}
th,td{padding:12px 14px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
th{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--quiet);font-weight:500;background:var(--surface-2)}
th{font-family:var(--f-mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--quiet);font-weight:500;background:var(--surface-2)}
tr:last-child td{border-bottom:0}
td.num{font-family:'IBM Plex Mono',monospace;font-variant-numeric:tabular-nums;white-space:nowrap}
td.num{font-family:var(--f-mono);font-variant-numeric:tabular-nums;white-space:nowrap}
.figure{margin:24px 0;padding:var(--card-pad);background:var(--surface);border:1px solid var(--line);border-radius:var(--card-r);overflow-x:auto}
.figure svg{display:block;width:100%;height:auto;max-width:100%}
.figure .cap{margin-top:12px;font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--quiet)}
.figure .cap{margin-top:12px;font-family:var(--f-mono);font-size:12px;color:var(--quiet)}
.stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--gap-tile);margin:8px 0 24px}
@media (min-width:700px){.stats{grid-template-columns:repeat(4,minmax(0,1fr))}}
.stat{padding:var(--tile-pad);background:var(--surface);border:1px solid var(--line);border-radius:var(--tile-r);min-width:0}
.stat .v{font-family:'Unbounded',sans-serif;font-weight:700;font-size:var(--fs-tile);color:var(--ember);line-height:1.1}
.stat .v{font-family:var(--f-display);font-weight:700;font-size:var(--fs-tile);color:var(--ember);line-height:1.1}
.stat .k{margin-top:6px;font-size:14px;color:var(--quiet);line-height:1.35;text-wrap:balance}
pre{margin:0 0 16px;padding:16px 18px;background:var(--code);color:var(--code-ink);border-radius:var(--card-r);font-family:'IBM Plex Mono',monospace;font-size:13px;line-height:1.6;overflow-x:auto}
.foot{padding-block:32px 48px;border-top:1px solid var(--line);display:flex;flex-wrap:wrap;gap:16px 32px;justify-content:space-between;font-size:14px;color:var(--quiet)}
.mark{flex:0 0 auto}
pre{margin:0 0 16px;padding:16px 18px;background:var(--code);color:var(--code-ink);border-radius:var(--card-r);font-family:var(--f-mono);font-size:13px;line-height:1.6;overflow-x:auto}
.foot{margin-top:0}
article section{display:none;border-top:0;padding-top:0}
article section.active{display:block}
body.all article section{display:block;border-top:1px solid var(--line);padding-top:40px}
body.all article section:first-of-type{border-top:0;padding-top:0}
article h2:focus,article h3:focus{outline:none}
article h2:focus-visible,article h3:focus-visible{outline:2px solid var(--ember);outline-offset:6px;border-radius:4px}
.toc li a.active{background:var(--tint);color:var(--ink);font-weight:600}
.toc li a.active::before{color:var(--ember)}
.toc .mode{margin-top:14px;display:flex;gap:8px}
.toc .mode{margin-top:14px;display:flex;flex-direction:column;gap:8px}
@media (max-width:959px){.toc .mode{flex-direction:row}}
.toc .mode button{flex:1;min-height:40px;border-radius:8px;border:1px solid var(--line);background:var(--surface);color:var(--ink-2);font:inherit;font-size:13px;cursor:pointer}
.toc .mode button.on{background:var(--ink);color:var(--ground);border-color:var(--ink)}
.toc .mode button:hover:not(.on){border-color:var(--quiet)}
.pager{display:flex;justify-content:space-between;gap:12px;margin-top:36px;padding-top:22px;border-top:1px solid var(--line)}
.pager a{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:10px 16px;border:1px solid var(--line);border-radius:10px;color:var(--ink);font-size:14px;max-width:48%}
.pager a:hover{text-decoration:none;border-color:var(--ember)}
.pager a span{color:var(--quiet);font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.12em;text-transform:uppercase}
.pager a span{color:var(--quiet);font-family:var(--f-mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase}
.pager a.next{margin-left:auto;text-align:right}
body.all .pager{display:none}
@media (max-width:600px){.pager{flex-direction:column}.pager a{max-width:none;justify-content:space-between}.pager a.next{margin-left:0}}
@media (max-width:959px){
.toc{position:sticky;top:0;z-index:5;background:var(--ground);margin-inline:calc(-1 * var(--gutter));padding:10px var(--gutter);border-bottom:1px solid var(--line)}
.toc ol{flex-direction:row;overflow-x:auto;gap:6px;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding-bottom:2px}
.toc{position:sticky;top:var(--nav-h);z-index:5;background:var(--ground);margin-inline:calc(-1 * var(--gutter));padding:8px var(--gutter);border-bottom:1px solid var(--line)}
.toc ol{flex-direction:row;overflow-x:auto;gap:6px;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding-bottom:2px;scroll-padding-inline:var(--gutter)}
.toc ol::-webkit-scrollbar{display:none}
.toc li a{white-space:nowrap;border:1px solid var(--line);border-radius:999px;padding:8px 12px;font-size:13px;gap:6px}
.toc li a{white-space:nowrap;border:1px solid var(--line);border-radius:999px;padding:7px 12px;font-size:13px;gap:6px}
.toc li a::before{min-width:0}
.toc .dl{display:none}
.toc .mode{margin-top:8px}
.toc .mode{margin-top:6px}
.toc .mode button{min-height:32px;font-size:12px}
}
@media (prefers-reduced-motion:no-preference){.pull{transition:transform .2s}}
</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="36" height="36" aria-hidden="true"><rect width="1024" height="1024" 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>
<button class="burger" id="nav-burger" type="button" aria-expanded="false" aria-controls="nav-links" aria-label="Menu"><svg class="bars" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"></path></svg><svg class="x" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"></path></svg></button>
<div class="links" id="nav-links">
<a href="/litepaper" data-nav="litepaper" aria-current="page">Litepaper</a>
<a href="/live" data-nav="live">Live devnet</a>
<a href="/bench" data-nav="bench">Engineering log</a>
<a href="/evidence" data-nav="evidence">Evidence</a>
<a href="https://github.com/igneum-network/spec" rel="noopener">GitHub</a>
<a href="/#mine" class="cta">Get the miner</a>
</div>
</div>
</nav>
<script>
(function(){
// the menu: open on the button, closed by any link, a tap outside, Escape (focus back on the button) or a resize past 900 px
var b=document.getElementById('nav-burger'),l=document.getElementById('nav-links');if(!b||!l)return;
function set(o){l.classList.toggle('open',o);b.setAttribute('aria-expanded',o?'true':'false');}
b.addEventListener('click',function(){set(!l.classList.contains('open'));});
l.addEventListener('click',function(e){if(e.target.closest('a'))set(false);});
document.addEventListener('click',function(e){if(l.classList.contains('open')&&!l.contains(e.target)&&!b.contains(e.target))set(false);});
document.addEventListener('keydown',function(e){if(e.key==='Escape'&&l.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 -->
<div class="wrap">
<main id="main" class="wrap">
<header class="cover">
<div>
<div class="brand">
<svg class="mark" viewBox="0 0 100 100" width="40" height="40" role="img" aria-label="Igneum mark"><polygon points="50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34" fill="var(--ember)"></polygon><polygon points="50,42 59,58 50,82 41,58" fill="var(--ground)"></polygon></svg>
<span class="word">IGNEUM</span>
</div>
<div style="margin-top:10px;display:flex;gap:18px;flex-wrap:wrap"><a href="/" style="font-size:14px">← igneum.network</a><a href="/live" style="font-size:14px">Live devnet →</a></div>
<div class="eyebrow" style="margin-top:26px">Litepaper · version 0.1</div>
<div class="eyebrow">Litepaper · version 0.1</div>
<h1>Mined by GPUs.<br>Proven by fire.</h1>
<div class="tag">A proof-of-work chain whose miners also prove every block, run Ethereum's apps, and built so no chip can ever take your place.</div>
</div>
@ -179,7 +282,7 @@ body.all .pager{display:none}
<li><a href="#shoulders">Built on the shoulders</a></li>
<li><a href="#limits">What Igneum does not claim</a></li>
</ol>
<div class="mode" role="group" aria-label="Reading mode"><button type="button" id="m-tabs" class="on">One section at a time</button><button type="button" id="m-all">Whole paper</button></div>
<div class="mode" role="group" aria-label="Reading mode"><button type="button" id="m-tabs" class="on" aria-pressed="true">One section at a time</button><button type="button" id="m-all" aria-pressed="false">Whole paper</button></div>
<div class="dl">Latin igneum: fiery. A cupel is the vessel in which metal is proven by fire.</div>
</nav>
@ -516,38 +619,95 @@ body.all .pager{display:none}
</section>
</article>
</div>
</main>
<footer class="foot">
<div class="brand"><svg viewBox="0 0 100 100" width="22" height="22" aria-hidden="true"><polygon points="50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34" fill="var(--ember)"></polygon><polygon points="50,42 59,58 50,82 41,58" fill="var(--ground)"></polygon></svg><span style="font-family:'Unbounded',sans-serif;font-weight:700;font-size:14px;letter-spacing:.06em;color:var(--ink)">IGNEUM</span></div>
<div>Litepaper v0.1 · 3 October 2026 · Mined by GPUs. Proven by fire.</div>
</footer>
</div>
<!-- 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="30" height="30" aria-hidden="true"><rect width="1024" height="1024" 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>
</nav>
<nav class="foot-col" aria-label="Follow">
<div class="eyebrow">Follow</div>
<a href="/live">Live devnet</a>
<a href="/#journey">Journey</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="/#mine">Get the miner</a>
</nav>
</div>
<div class="foot-base">
<span>© 2026 Igneum. Nothing on this page is an offer to sell anything.</span>
<span class="mono">igneum.network</span>
</div>
</div>
</footer>
<!-- footer:end -->
<script>
(function(){
// Section router. The URL hash names a section (or any heading inside one) in both reading modes. In-page links are
// routed here instead of the browser's own fragment jump: that jump cannot land on a hidden section, and in whole-paper
// mode it used to land and then be dragged back to the top of the article by a second scroll. Back and forward replay
// through popstate, every scroll clears the sticky bar (and the contents row on a phone), and focus moves to the
// heading so the keyboard and a screen reader continue from the section, not from the contents list.
var secs=Array.prototype.slice.call(document.querySelectorAll('article section'));
var links=Array.prototype.slice.call(document.querySelectorAll('.toc ol a'));
var ids=secs.map(function(s){return s.id;});
var toc=document.querySelector('.toc'),links=Array.prototype.slice.call(document.querySelectorAll('.toc ol a'));
var mAll=document.getElementById('m-all'),mTabs=document.getElementById('m-tabs');
var reduce=window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var all=false;try{all=localStorage.getItem('lp-mode')==='all';}catch(e){}
// every subsection heading gets an id from its text, so each one is reachable by URL
var used={};secs.forEach(function(s){used[s.id]=1;});
secs.forEach(function(s){Array.prototype.slice.call(s.querySelectorAll('h3')).forEach(function(h){if(h.id)return;
var base=h.textContent.toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'').slice(0,60).replace(/-$/,''),id=base,n=2;
while(used[id])id=base+'-'+(n++);used[id]=1;h.id=id;});});
secs.forEach(function(s,i){
var pager=document.createElement('div');pager.className='pager';
if(i>0){var a=document.createElement('a');a.href='#'+ids[i-1];a.innerHTML='<span>previous</span> '+secs[i-1].querySelector('h2').textContent;pager.appendChild(a);}
if(i<secs.length-1){var b=document.createElement('a');b.href='#'+ids[i+1];b.className='next';b.innerHTML=secs[i+1].querySelector('h2').textContent+' <span>next</span>';pager.appendChild(b);}
if(i>0){var a=document.createElement('a');a.href='#'+secs[i-1].id;a.innerHTML='<span>previous</span> '+secs[i-1].querySelector('h2').textContent;pager.appendChild(a);}
if(i<secs.length-1){var b=document.createElement('a');b.href='#'+secs[i+1].id;b.className='next';b.innerHTML=secs[i+1].querySelector('h2').textContent+' <span>next</span>';pager.appendChild(b);}
s.appendChild(pager);
});
function show(id,scroll){
if(ids.indexOf(id)<0)id=ids[0];
secs.forEach(function(s){s.classList.toggle('active',s.id===id);});
links.forEach(function(l){var on=l.getAttribute('href')==='#'+id;l.classList.toggle('active',on);if(on&&l.scrollIntoView&&window.innerWidth<960){try{l.scrollIntoView({block:'nearest',inline:'center'});}catch(e){}}});
if(scroll){var top=document.querySelector('article').getBoundingClientRect().top+window.scrollY-(window.innerWidth<960?70:24);window.scrollTo({top:Math.max(0,top),behavior:'smooth'});}
function target(hash){var id=(hash||'').replace(/^#/,'');if(!id)return null;var el=document.getElementById(id);if(!el)return null;var s=el.closest('article section');return s?{sec:s,el:el===s?null:el}:null;}
function offset(){var nav=parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--nav-h'))||68;return nav+(window.innerWidth<960&&toc?toc.offsetHeight:0)+12;}
function measure(){document.documentElement.style.setProperty('--lp-off',offset()+'px');}
function go(hash,o){o=o||{};var t=target(hash)||{sec:secs[0],el:null};
secs.forEach(function(s){s.classList.toggle('active',s===t.sec);});
links.forEach(function(l){var on=l.getAttribute('href')==='#'+t.sec.id;l.classList.toggle('active',on);if(on)l.setAttribute('aria-current','true');else l.removeAttribute('aria-current');
if(on&&window.innerWidth<960&&l.scrollIntoView){try{l.scrollIntoView({block:'nearest',inline:'center'});}catch(e){}}});
if(o.scroll!==false){var el=t.el||t.sec,top=el.getBoundingClientRect().top+window.pageYOffset-offset();window.scrollTo({top:Math.max(0,top),behavior:(o.instant||reduce)?'auto':'smooth'});}
if(o.focus!==false){var f=t.el||t.sec.querySelector('h2');if(f){if(!f.hasAttribute('tabindex'))f.setAttribute('tabindex','-1');try{f.focus({preventScroll:true});}catch(e){f.focus();}}}
}
function setMode(a){all=a;document.body.classList.toggle('all',all);mAll.classList.toggle('on',all);mTabs.classList.toggle('on',!all);try{localStorage.setItem('lp-mode',all?'all':'tabs');}catch(e){}}
mAll.addEventListener('click',function(){setMode(true);});
mTabs.addEventListener('click',function(){setMode(false);show(location.hash.slice(1),false);});
window.addEventListener('hashchange',function(){show(location.hash.slice(1),true);});
setMode(all);
show(location.hash.slice(1),false);
document.addEventListener('click',function(e){
if(e.defaultPrevented||e.button||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;
var a=e.target.closest('a[href^="#"]');if(!a)return;var h=a.getAttribute('href');if(h.length<2||!target(h))return;
e.preventDefault();if(location.hash!==h)history.pushState(null,'',h);go(h,{});
});
window.addEventListener('popstate',function(){go(location.hash,{});});
function setMode(a){all=a;document.body.classList.toggle('all',all);mAll.classList.toggle('on',all);mTabs.classList.toggle('on',!all);mAll.setAttribute('aria-pressed',all?'true':'false');mTabs.setAttribute('aria-pressed',all?'false':'true');try{localStorage.setItem('lp-mode',all?'all':'tabs');}catch(e){}}
mAll.addEventListener('click',function(){setMode(true);measure();go(location.hash,{instant:true,focus:false});});
mTabs.addEventListener('click',function(){setMode(false);measure();go(location.hash,{instant:true,focus:false});});
window.addEventListener('resize',measure);
measure();setMode(all);
// A face can arrive after a scroll was aimed (a section shown for the first time loads its heading face), and the
// layout above the target then moves a few pixels. Until the reader moves, the last navigation is re-aimed after each
// font batch, so the heading sits exactly under the bar.
var aimed=null,moved=false;
['wheel','touchstart','keydown','pointerdown'].forEach(function(ev){window.addEventListener(ev,function(){moved=true;},{passive:true});});
var go0=go;go=function(hash,o){go0(hash,o);aimed={hash:location.hash,at:performance.now(),instant:!!(o&&o.instant)};moved=false;};
function reaim(){measure();if(aimed&&!moved&&location.hash&&location.hash===aimed.hash&&performance.now()-aimed.at<4000)go(location.hash,{instant:aimed.instant,focus:false});}
window.addEventListener('load',reaim);
if(document.fonts){document.fonts.ready.then(function(){setTimeout(reaim,0);});document.fonts.addEventListener('loadingdone',function(){setTimeout(reaim,0);});}
if(location.hash)go(location.hash,{instant:true,focus:false});else go0('',{scroll:false,focus:false});
})();
</script>
</body>

View file

@ -28,9 +28,72 @@
<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">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Unbounded:wght@500;700;900&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap">
<!-- 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>
<style>
/* Shared by every page. Source: site/partials/head.html, injected by site/build.mjs 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. */
@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%}
:root{--f-sans:'IBM Plex Sans','Plex Sans Fallback',system-ui,-apple-system,sans-serif;--f-display:'Unbounded','Unbounded Fallback',sans-serif;--f-mono:'IBM Plex Mono','Plex Mono Fallback',ui-monospace,Menlo,monospace;
/* site chrome tokens (nav, footer, skip link). Dark by default; the litepaper sets light values and resets these in dark mode */
--nav-h:68px;--ui-bg:rgba(12,12,14,.84);--ui-menu:#0C0C0E;--ui-ink:#F4F1EC;--ui-ink-2:#C9C7C2;--ui-ash:#9A9A9E;--ui-line:#2A2A30;--ui-line-2:#3A3A42;--ui-accent:#F2541B;--ui-accent-ink:#0C0C0E;--ui-hot:#FFB35C;--ui-hover:#FF6A2B;--ui-tint:rgba(242,84,27,.12)}
html{-webkit-text-size-adjust:100%}
h1,h2,h3{text-wrap:balance}
p,li,dd,figcaption{text-wrap:pretty}
a:focus-visible,button:focus-visible,summary:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--ui-accent);outline-offset:3px;border-radius:6px}
.skip{position:absolute;left:12px;top:-80px;z-index:50;background:var(--ui-accent);color:var(--ui-accent-ink);padding:10px 14px;border-radius:10px;font:600 15px/1.2 var(--f-sans);text-decoration:none}
.skip:focus{top:12px}
/* nav: one bar on every page, the mark in its black square, five links and the miner button, a menu under 901 px */
.nav{position:sticky;top:0;z-index:20;background:var(--ui-bg);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid var(--ui-line);color:var(--ui-ink)}
.nav .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:var(--nav-h)}
.nav a{color:inherit;text-decoration:none}
.brand{display:inline-flex;align-items:center;gap:10px;color:var(--ui-ink);text-decoration:none;flex:0 0 auto}
.brand .mark{display:block;flex:0 0 auto}
.brand .word{font-family:var(--f-display);font-weight:900;font-size:20px;letter-spacing:.06em;line-height:1}
.nav .links{display:flex;align-items:center;gap:clamp(14px,2vw,26px);font-size:15px;font-weight:500}
.nav .links a{color:var(--ui-ink-2);padding:4px 0;border-bottom:2px solid transparent;transition:color .15s ease,border-color .15s ease}
.nav .links a:hover,.nav .brand:hover{color:var(--ui-hot);text-decoration:none}
.nav .brand:hover{color:var(--ui-ink)}
.nav .links a[aria-current="page"]{color:var(--ui-ink);border-bottom-color:var(--ui-accent)}
.nav .links a.cta{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:8px 16px;border-radius:10px;font-weight:600;background:var(--ui-accent);color:var(--ui-accent-ink);border:1px solid var(--ui-accent);transition:background .15s ease,transform .15s ease}
.nav .links a.cta:hover{background:var(--ui-hover);border-color:var(--ui-hover);color:var(--ui-accent-ink);transform:translateY(-1px)}
.burger{display:none;background:none;border:1px solid var(--ui-line-2);color:var(--ui-ink);border-radius:10px;width:44px;height:44px;align-items:center;justify-content:center;cursor:pointer;padding:0;flex:0 0 auto}
.burger .x{display:none}.burger[aria-expanded="true"] .x{display:block}.burger[aria-expanded="true"] .bars{display:none}
@media (max-width:900px){
.nav .links{display:none;position:absolute;left:0;right:0;top:100%;background:var(--ui-menu);border-bottom:1px solid var(--ui-line);box-shadow:0 24px 40px rgba(0,0,0,.35);padding:10px var(--gutter,16px) 18px;flex-direction:column;align-items:stretch;gap:2px}
.nav .links a{padding:13px 10px;border-radius:10px;border-bottom:0;font-size:16px}
.nav .links a[aria-current="page"]{background:var(--ui-tint)}
.nav .links a.cta{margin-top:8px;min-height:48px}
.nav .links.open{display:flex}
.burger{display:inline-flex}
}
/* footer, the same on every page */
.foot{border-top:1px solid var(--ui-line);color:var(--ui-ink);margin-top:var(--sec,64px)}
.foot .wrap{padding-block:48px 32px}
.foot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:32px}
.foot-brand{display:flex;flex-direction:column;gap:12px;max-width:34ch}
.foot-brand .brand{align-self:flex-start}.foot-brand .word{font-size:16px}
.foot-brand p{color:var(--ui-ash);font-size:14px;margin:0}
.foot-col{display:flex;flex-direction:column;gap:10px;font-size:15px}
.foot-col .eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ui-ash);margin-bottom:4px}
.foot-col a{color:var(--ui-ink-2);text-decoration:none;display:inline-flex;align-items:center;gap:6px;align-self:flex-start}
.foot-col a:hover{color:var(--ui-hot);text-decoration:none}
.foot-base{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px 24px;margin-top:36px;padding-top:20px;border-top:1px solid var(--ui-line);font-size:13px;color:var(--ui-ash)}
.foot-base span{text-wrap:balance}.foot-base .mono{font-family:var(--f-mono)}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
</style>
<!-- head:end -->
<style>
:root{--obsidian:#0C0C0E;--graphite:#16161A;--line:#2A2A30;--line-2:#3A3A42;--ember:#F2541B;--molten:#FFB35C;--bone:#F4F1EC;--ash:#9A9A9E;--ink-2:#C9C7C2;--ember-ink:#0C0C0E;
/* one system for every page: container, gutter, section rhythm, card and tile boxes, heading scale (same tokens as the homepage) */
@ -39,15 +102,15 @@
--fs-hero:clamp(40px,7vw,76px);--fs-h1:clamp(32px,5.5vw,56px);--fs-h2:clamp(28px,4.2vw,44px);--fs-h3:clamp(18px,2vw,22px);--fs-tile:clamp(20px,2.2vw,26px)}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--obsidian);color:var(--bone);font-family:'IBM Plex Sans',system-ui,-apple-system,sans-serif;font-size:17px;line-height:1.55;-webkit-font-smoothing:antialiased;overflow-x:hidden}
body{margin:0;background:var(--obsidian);color:var(--bone);font-family:var(--f-sans);font-size:17px;line-height:1.55;-webkit-font-smoothing:antialiased;overflow-x:hidden}
a{color:inherit;text-decoration:none}
a:hover{color:var(--molten)}
a:focus-visible,button:focus-visible{outline:2px solid var(--ember);outline-offset:3px;border-radius:6px}
img,svg,canvas{max-width:100%}
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gutter)}
.mono{font-family:'IBM Plex Mono',monospace}
.eyebrow{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ash)}
h1,h2,h3{font-family:'Unbounded',sans-serif;margin:0;line-height:1.08;text-wrap:balance}
.mono{font-family:var(--f-mono)}
.eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ash)}
h1,h2,h3{font-family:var(--f-display);margin:0;line-height:1.08;text-wrap:balance}
h1{font-weight:900;font-size:var(--fs-h1);letter-spacing:-.01em}
h2{font-weight:700;font-size:var(--fs-h3)}
p{margin:0}
@ -56,22 +119,7 @@ p{margin:0}
.btn.primary:hover{background:#FF6A2B;border-color:#FF6A2B;color:var(--ember-ink)}
.card{background:var(--graphite);border:1px solid var(--line);border-radius:var(--card-r);padding:var(--card-pad);min-width:0}
/* nav, same as the homepage */
.nav{position:sticky;top:0;z-index:20;background:rgba(12,12,14,.82);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-bottom:1px solid rgba(42,42,48,.6)}
.nav .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:68px}
.brand{display:flex;align-items:center;gap:10px}
.brand .word{font-family:'Unbounded',sans-serif;font-weight:900;font-size:20px;letter-spacing:.06em}
.links{display:flex;align-items:center;gap:26px;font-size:15px;font-weight:500}
.links .btn{min-height:42px;padding:10px 16px;font-size:15px}
.links a.here{color:var(--molten)}
.burger{display:none;background:none;border:1px solid var(--line-2);color:var(--bone);border-radius:10px;width:44px;height:44px;align-items:center;justify-content:center;cursor:pointer}
@media (max-width:900px){
.links{display:none;position:absolute;left:0;right:0;top:68px;background:var(--obsidian);border-bottom:1px solid var(--line);padding:16px var(--gutter) 24px;flex-direction:column;align-items:stretch;gap:6px}
.links a{padding:12px 6px;border-radius:8px}
.links .btn{width:100%;margin-top:6px}
.links.open{display:flex}
.burger{display:inline-flex}
}
/* nav and footer: shared, see site/partials */
/* page */
.head{padding-block:var(--head) var(--gap);display:flex;flex-direction:column;gap:14px}
@ -79,10 +127,12 @@ p{margin:0}
.strip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--gap-tile);margin-bottom:var(--gap)}
@media (max-width:700px){.strip{grid-template-columns:repeat(2,minmax(0,1fr))}}
.cell{background:var(--graphite);border:1px solid var(--line);border-radius:var(--tile-r);padding:var(--tile-pad);display:flex;flex-direction:column;gap:6px;min-width:0}
.cell .k{font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash)}
.cell .v{font-family:'Unbounded',sans-serif;font-weight:700;font-size:var(--fs-tile);line-height:1.1;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cell .v.name{font-family:'IBM Plex Mono',monospace;font-size:15px;font-weight:500}
.cell .s{font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--ash);text-wrap:balance}
.cell .k{font-family:var(--f-mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash)}
.cell .v{font-family:var(--f-display);font-weight:700;font-size:var(--fs-tile);line-height:1.1;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cell .v small{font-family:var(--f-mono);font-weight:500;font-size:13px;color:var(--ash);margin-left:4px;letter-spacing:.04em}
@media (max-width:700px){.cell .v{font-size:19px}}
.cell .v.name{font-family:var(--f-mono);font-size:15px;font-weight:500}
.cell .s{font-family:var(--f-mono);font-size:12px;color:var(--ash);text-wrap:balance}
.cell.status .v{display:flex;align-items:center;gap:10px}
.dot{width:10px;height:10px;border-radius:50%;background:var(--molten);display:inline-block;flex:0 0 10px;animation:pulse 2s ease-in-out infinite}
.off .dot{background:var(--ash);animation:none}
@ -98,8 +148,9 @@ p{margin:0}
@media (max-width:640px){#dag{height:calc(clamp(240px,38vw,380px) + 18px + 50px)}}
.legend{display:flex;flex-direction:column;gap:8px;margin-top:16px;font-size:13px;color:var(--ink-2)}
.legend div{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
.legend .lk{font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);min-width:64px}
.legend .lk{font-family:var(--f-mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);min-width:64px}
.legend span{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.legend span.txt{white-space:normal;display:inline;color:var(--ash)}
.sw{width:14px;height:14px;border-radius:4px;display:inline-block}
.two{display:grid;gap:var(--gap);grid-template-columns:1fr;margin-top:var(--gap)}
@ -107,13 +158,13 @@ p{margin:0}
.tbl{overflow-x:auto;margin-top:12px;-webkit-overflow-scrolling:touch}
table{border-collapse:collapse;width:100%;font-size:14px}
th,td{padding:10px 10px;text-align:left;border-bottom:1px solid var(--line);white-space:nowrap}
th{font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);font-weight:500}
th{font-family:var(--f-mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ash);font-weight:500}
td.n{font-variant-numeric:tabular-nums;text-align:right}th.n{text-align:right}
tr:last-child td{border-bottom:0}
.id{font-family:'IBM Plex Mono',monospace;color:var(--molten)}
.id{font-family:var(--f-mono);color:var(--molten)}
.bar{height:6px;border-radius:3px;background:var(--line);overflow:hidden;min-width:60px}
.bar i{display:block;height:100%;background:var(--ember)}
.feed{display:flex;flex-direction:column;margin-top:12px;font-family:'IBM Plex Mono',monospace;font-size:13px;color:var(--ink-2)}
.feed{display:flex;flex-direction:column;margin-top:12px;font-family:var(--f-mono);font-size:13px;color:var(--ink-2)}
.feed div{display:flex;justify-content:space-between;gap:12px;border-bottom:1px solid var(--line);padding:9px 0;align-items:baseline}
.feed div:last-child{border-bottom:0}
.feed .t{color:var(--ash);flex:0 0 auto;font-size:12px}
@ -122,44 +173,45 @@ tr:last-child td{border-bottom:0}
#spark{display:block;width:100%;height:120px;border-radius:12px;background:var(--obsidian);margin-top:12px}
.note{font-size:13px;color:var(--ash);margin-top:14px}
main{padding-bottom:var(--sec)}
/* footer, same as the homepage */
footer{border-top:1px solid var(--line);padding-block:48px 32px}
.foot-grid{display:grid;gap:32px;grid-template-columns:1fr;margin-bottom:32px}
@media (min-width:720px){.foot-grid{grid-template-columns:1.4fr 1fr 1fr}}
.foot-brand p{color:var(--ash);font-size:15px;margin-top:12px;max-width:40ch}
.foot-col{display:flex;flex-direction:column;gap:10px;font-size:15px}
.foot-col .eyebrow{margin-bottom:6px}
.foot-col a{color:var(--ink-2)}
.foot-base{display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;border-top:1px solid var(--line);padding-top:24px;font-size:13px;color:var(--ash)}
.foot-base span{text-wrap:balance}
.foot{margin-top:0}
</style>
</head>
<body class="off">
<!-- 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 viewBox="0 0 100 100" width="30" height="30" aria-hidden="true"><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></svg>
<svg class="mark" viewBox="0 0 1024 1024" width="36" height="36" aria-hidden="true"><rect width="1024" height="1024" 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>
<button class="burger" id="burger" aria-expanded="false" aria-controls="links" aria-label="Menu"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"></path></svg></button>
<div class="links" id="links">
<a href="/#mine">Mine</a>
<a href="/#prove">Prove</a>
<a href="/#build">Build</a>
<a href="/#randomx">vs RandomX</a>
<a href="/#journey">Journey</a>
<a href="/#economics">Economics</a>
<a href="/litepaper">Litepaper</a>
<a href="/bench">Log</a>
<a href="/live" class="here" aria-current="page">Live</a>
<a href="/#mine" class="btn primary">Get the miner</a>
<button class="burger" id="nav-burger" type="button" aria-expanded="false" aria-controls="nav-links" aria-label="Menu"><svg class="bars" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"></path></svg><svg class="x" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"></path></svg></button>
<div class="links" id="nav-links">
<a href="/litepaper" data-nav="litepaper">Litepaper</a>
<a href="/live" data-nav="live" aria-current="page">Live devnet</a>
<a href="/bench" data-nav="bench">Engineering log</a>
<a href="/evidence" data-nav="evidence">Evidence</a>
<a href="https://github.com/igneum-network/spec" rel="noopener">GitHub</a>
<a href="/#mine" class="cta">Get the miner</a>
</div>
</div>
</nav>
<script>
(function(){
// the menu: open on the button, closed by any link, a tap outside, Escape (focus back on the button) or a resize past 900 px
var b=document.getElementById('nav-burger'),l=document.getElementById('nav-links');if(!b||!l)return;
function set(o){l.classList.toggle('open',o);b.setAttribute('aria-expanded',o?'true':'false');}
b.addEventListener('click',function(){set(!l.classList.contains('open'));});
l.addEventListener('click',function(e){if(e.target.closest('a'))set(false);});
document.addEventListener('click',function(e){if(l.classList.contains('open')&&!l.contains(e.target)&&!b.contains(e.target))set(false);});
document.addEventListener('keydown',function(e){if(e.key==='Escape'&&l.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 class="wrap">
<main id="main" class="wrap">
<div class="head">
<div class="eyebrow">devnet v0</div>
<h1>Live devnet</h1>
@ -184,9 +236,9 @@ footer{border-top:1px solid var(--line);padding-block:48px 32px}
</div>
<canvas id="dag" aria-hidden="true"></canvas>
<div class="legend">
<div><span class="lk">blocks</span><span><i class="sw" style="background:var(--ember);border:1.5px solid #5CB8FF"></i>chain</span><span><i class="sw" style="background:rgba(92,184,255,.7);border:1.5px solid #5CB8FF"></i>included, paid</span><span><i class="sw" style="border:1.5px solid var(--ash)"></i>pending</span><span><i class="sw" style="border:1.5px solid rgba(154,154,158,.6);background:linear-gradient(45deg,transparent 44%,var(--ash) 44%,var(--ash) 56%,transparent 56%) center/8px 8px no-repeat"></i>excluded</span><span><i class="sw" style="border:2px solid var(--molten);box-shadow:0 0 8px rgba(255,179,92,.7)"></i>just arrived</span><span><i class="sw" style="width:22px;height:0;border-top:2px solid var(--ember)"></i>selected chain</span><span>one lane per miner, colour from its id; hover or tap a block</span></div>
<div><span class="lk">finality</span><span><i class="sw" style="width:22px;height:10px;background:rgba(242,84,27,.22);border-radius:2px"></i>final</span><span><i class="sw" style="width:3px;height:12px;background:var(--molten);border-radius:1px"></i>locked checkpoint</span><span><i class="sw" style="width:22px;height:10px;background:rgba(154,154,158,.10);border:1px solid rgba(154,154,158,.3);border-radius:2px"></i>proposed</span><span>reads "paused" whenever under two thirds of the weight is signing</span></div>
<div><span class="lk">proving</span><span><i class="sw" style="width:12px;height:9px;border:1px solid rgba(154,154,158,.55);border-radius:2px"></i>shard planned</span><span><i class="sw" style="width:12px;height:9px;border:1px solid var(--molten);background:rgba(255,179,92,.25);border-radius:2px"></i>proving</span><span><i class="sw" style="width:12px;height:9px;background:#3FD39A;border-radius:2px"></i>verified, prover colour</span><span><i class="sw" style="width:12px;height:9px;background:#3FD39A;border-radius:2px;position:relative"><i style="position:absolute;left:3px;top:1px;width:3px;height:5px;border:solid #0C0C0E;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)"></i></i>paid</span><span><i class="sw" style="width:0;height:12px;border-left:1px dashed var(--molten)"></i>where proofs land behind the tip</span><span>hover or tap a cell</span></div>
<div><span class="lk">blocks</span><span><i class="sw" style="background:var(--ember);border:1.5px solid #5CB8FF"></i>chain</span><span><i class="sw" style="background:rgba(92,184,255,.7);border:1.5px solid #5CB8FF"></i>included, paid</span><span><i class="sw" style="border:1.5px solid var(--ash)"></i>pending</span><span><i class="sw" style="border:1.5px solid rgba(154,154,158,.6);background:linear-gradient(45deg,transparent 44%,var(--ash) 44%,var(--ash) 56%,transparent 56%) center/8px 8px no-repeat"></i>excluded</span><span><i class="sw" style="border:2px solid var(--molten);box-shadow:0 0 8px rgba(255,179,92,.7)"></i>just arrived</span><span><i class="sw" style="width:22px;height:0;border-top:2px solid var(--ember)"></i>selected chain</span><span class="txt">one lane per miner, colour from its id; hover or tap a block</span></div>
<div><span class="lk">finality</span><span><i class="sw" style="width:22px;height:10px;background:rgba(242,84,27,.22);border-radius:2px"></i>final</span><span><i class="sw" style="width:3px;height:12px;background:var(--molten);border-radius:1px"></i>locked checkpoint</span><span><i class="sw" style="width:22px;height:10px;background:rgba(154,154,158,.10);border:1px solid rgba(154,154,158,.3);border-radius:2px"></i>proposed</span><span class="txt">reads "paused" whenever under two thirds of the weight is signing</span></div>
<div><span class="lk">proving</span><span><i class="sw" style="width:12px;height:9px;border:1px solid rgba(154,154,158,.55);border-radius:2px"></i>shard planned</span><span><i class="sw" style="width:12px;height:9px;border:1px solid var(--molten);background:rgba(255,179,92,.25);border-radius:2px"></i>proving</span><span><i class="sw" style="width:12px;height:9px;background:#3FD39A;border-radius:2px"></i>verified, prover colour</span><span><i class="sw" style="width:12px;height:9px;background:#3FD39A;border-radius:2px;position:relative"><i style="position:absolute;left:3px;top:1px;width:3px;height:5px;border:solid #0C0C0E;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)"></i></i>paid</span><span><i class="sw" style="width:0;height:12px;border-left:1px dashed var(--molten)"></i>where proofs land behind the tip</span><span class="txt">hover or tap a cell</span></div>
</div>
</div>
@ -214,11 +266,12 @@ footer{border-top:1px solid var(--line);padding-block:48px 32px}
</div>
</main>
<footer>
<!-- footer:start -->
<footer class="foot">
<div class="wrap">
<div class="foot-grid">
<div class="foot-brand">
<div class="brand"><svg viewBox="0 0 100 100" width="26" height="26" aria-hidden="true"><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></svg><span class="word" style="font-size:16px;color:var(--bone)">IGNEUM</span></div>
<a href="/" class="brand" aria-label="Igneum home"><svg class="mark" viewBox="0 0 1024 1024" width="30" height="30" aria-hidden="true"><rect width="1024" height="1024" 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">
@ -226,13 +279,15 @@ footer{border-top:1px solid var(--line);padding-block:48px 32px}
<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>
</nav>
<nav class="foot-col" aria-label="Follow">
<div class="eyebrow">Follow</div>
<a href="/#journey">Journey</a>
<a href="/live">Live devnet</a>
<a href="https://github.com/igneum-network/spec" rel="noopener" style="display:inline-flex;align-items:center;gap:6px"><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"/></svg>GitHub</a>
<a href="/#journey">Journey</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="/#mine">Get the miner</a>
</nav>
</div>
@ -242,16 +297,14 @@ footer{border-top:1px solid var(--line);padding-block:48px 32px}
</div>
</div>
</footer>
<!-- footer:end -->
<script>
(function(){
var reduce=window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var dpr=Math.min(2,window.devicePixelRatio||1);
// nav
var burger=document.getElementById('burger'),navLinks=document.getElementById('links');
burger.addEventListener('click',function(){var open=navLinks.classList.toggle('open');burger.setAttribute('aria-expanded',open?'true':'false');});
document.addEventListener('click',function(e){if(navLinks.classList.contains('open')&&!navLinks.contains(e.target)&&!burger.contains(e.target)){navLinks.classList.remove('open');burger.setAttribute('aria-expanded','false');}});
// the DAG canvas is redrawn every frame, so its backing store is capped at 1.5x: text stays crisp on a phone and the fill
// cost on a 2x laptop display drops by 44%
var dpr=Math.min(1.5,window.devicePixelRatio||1);
// formatting
function $(id){return document.getElementById(id);}
@ -436,7 +489,10 @@ footer{border-top:1px solid var(--line);padding-block:48px 32px}
x.font='500 10px IBM Plex Mono, monospace';x.textAlign='left';x.textBaseline='middle';
if(!provOn()){var ptxt=!prov||!prov.supported?'Proving layer: '+(prov&&prov.reason?prov.reason:'node without proving'):'Proving layer: not yet activated on this devnet; activation '+(prov.activation_daa!==null&&prov.activation_daa!==undefined?'at DAA '+prov.activation_daa.toLocaleString('en-GB')+(prov.tip_daa?' (tip '+prov.tip_daa.toLocaleString('en-GB')+')':''):'not set');
if(narrow)ptxt=ptxt.replace('Proving layer: ','').replace(' on this devnet','').replace(/ \(tip [^)]*\)/,'');
x.fillStyle='rgba(154,154,158,0.9)';x.fillText(ptxt,G+8,y1+PROV_H/2);}
x.fillStyle='rgba(154,154,158,0.9)';
// a line wider than the strip breaks at its semicolon into two lines, so the phone never clips the activation height
if(x.measureText(ptxt).width>W-G-16&&ptxt.indexOf('; ')>0){var parts=ptxt.split('; ');x.fillText(parts[0]+';',G+8,y1+PROV_H/2-7);x.fillText(parts.slice(1).join('; '),G+8,y1+PROV_H/2+7);}
else x.fillText(ptxt,G+8,y1+PROV_H/2);}
else{
// the lag line: proofs land about median_proof_lag_s behind the tip
var lag=prov.median_proof_lag_s;
@ -476,7 +532,12 @@ footer{border-top:1px solid var(--line);padding-block:48px 32px}
if(!n){x.fillStyle='rgba(154,154,158,0.9)';x.font='500 13px IBM Plex Mono, monospace';x.textAlign='center';x.fillText(lagNote?'no block has reached the observer for '+lagNote.replace('observer ','').replace(' behind',''):(live?'waiting for the first block':'no observer data'),G+(W-G)/2,BH/2);}
if(note){x.fillStyle='rgba(12,12,14,0.72)';x.fillRect(0,BH/2-22,W,44);x.fillStyle='#F4F1EC';x.font='500 13px IBM Plex Mono, monospace';x.textAlign='center';x.fillText(note,W/2,BH/2+5);}
}
function frame(now){if(!running)return;draw(now);requestAnimationFrame(frame);}
// Idle, the scene moves at 14 to 40 px/s, so 30 frames a second is enough; a pointer or a pinned block gets every frame.
// ?perf=1 exposes window.__igneumPerf = {frames, drawMs, since} so the draw cost can be read from the console.
var PERF=/[?&]perf=1/.test(location.search)?(window.__igneumPerf={frames:0,drawMs:0,since:performance.now()}):null,lastDraw=0;
function frame(now){if(!running)return;
if(ptrX>=0||pin||now-lastDraw>=31){lastDraw=now;var t0=PERF?performance.now():0;draw(now);if(PERF){PERF.frames++;PERF.drawMs+=performance.now()-t0;}}
requestAnimationFrame(frame);}
function start(){if(running||reduce)return;if(document.hidden||!inView)return;running=true;requestAnimationFrame(frame);}
function stop(){running=false;}
function kick(){if(!running)requestAnimationFrame(function(now){draw(now);});}
@ -512,7 +573,8 @@ footer{border-top:1px solid var(--line);padding-block:48px 32px}
$('st-network').textContent=s.network||'igneum-devnet';$('st-node').textContent=s.node_version?'node '+s.node_version:'node';
$('st-bps').textContent=(s.blocks_per_second_60s||0).toFixed(2);
$('st-blue').textContent=compact(s.blue_score);$('st-count').textContent=compact(s.block_count)+' blocks';
$('st-diff').textContent=compact(s.difficulty);$('st-hps').textContent=hashrate(s.hashes_per_second_estimate);
$('st-diff').textContent=compact(s.difficulty);
var hr=hashrate(s.hashes_per_second_estimate).split(' ');$('st-hps').innerHTML=hr.length>1?esc(hr[0])+'<small>'+esc(hr[1])+'</small>':esc(hr[0]);
$('st-miners').textContent=s.miners_10m;$('st-peers').textContent=s.peers===null?'0':s.peers;$('st-mempool').textContent='mempool '+(s.mempool||0);
var now=new Date(d.now).getTime();
if(d.miners.length){minersEl.innerHTML=d.miners.map(function(m){return '<tr><td><span class="id">'+esc(m.id)+'</span></td><td class="n">'+m.blocks+'</td><td><div style="display:flex;align-items:center;gap:8px"><div class="bar" style="width:70px"><i style="width:'+m.share+'%"></i></div><span class="mono" style="font-size:12px">'+m.share+'%</span></div></td><td>'+rel(now-new Date(m.last_seen).getTime())+'</td><td>'+(m.engine?esc(m.engine):'<span style="color:var(--ash)">not reported</span>')+'</td></tr>';}).join('');}

30
site/partials/footer.html Normal file
View file

@ -0,0 +1,30 @@
<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="30" height="30" aria-hidden="true"><rect width="1024" height="1024" 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>
</nav>
<nav class="foot-col" aria-label="Follow">
<div class="eyebrow">Follow</div>
<a href="/live">Live devnet</a>
<a href="/#journey">Journey</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="/#mine">Get the miner</a>
</nav>
</div>
<div class="foot-base">
<span>© 2026 Igneum. Nothing on this page is an offer to sell anything.</span>
<span class="mono">igneum.network</span>
</div>
</div>
</footer>

64
site/partials/head.html Normal file
View file

@ -0,0 +1,64 @@
<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>
<style>
/* Shared by every page. Source: site/partials/head.html, injected by site/build.mjs 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. */
@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%}
:root{--f-sans:'IBM Plex Sans','Plex Sans Fallback',system-ui,-apple-system,sans-serif;--f-display:'Unbounded','Unbounded Fallback',sans-serif;--f-mono:'IBM Plex Mono','Plex Mono Fallback',ui-monospace,Menlo,monospace;
/* site chrome tokens (nav, footer, skip link). Dark by default; the litepaper sets light values and resets these in dark mode */
--nav-h:68px;--ui-bg:rgba(12,12,14,.84);--ui-menu:#0C0C0E;--ui-ink:#F4F1EC;--ui-ink-2:#C9C7C2;--ui-ash:#9A9A9E;--ui-line:#2A2A30;--ui-line-2:#3A3A42;--ui-accent:#F2541B;--ui-accent-ink:#0C0C0E;--ui-hot:#FFB35C;--ui-hover:#FF6A2B;--ui-tint:rgba(242,84,27,.12)}
html{-webkit-text-size-adjust:100%}
h1,h2,h3{text-wrap:balance}
p,li,dd,figcaption{text-wrap:pretty}
a:focus-visible,button:focus-visible,summary:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--ui-accent);outline-offset:3px;border-radius:6px}
.skip{position:absolute;left:12px;top:-80px;z-index:50;background:var(--ui-accent);color:var(--ui-accent-ink);padding:10px 14px;border-radius:10px;font:600 15px/1.2 var(--f-sans);text-decoration:none}
.skip:focus{top:12px}
/* nav: one bar on every page, the mark in its black square, five links and the miner button, a menu under 901 px */
.nav{position:sticky;top:0;z-index:20;background:var(--ui-bg);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid var(--ui-line);color:var(--ui-ink)}
.nav .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:var(--nav-h)}
.nav a{color:inherit;text-decoration:none}
.brand{display:inline-flex;align-items:center;gap:10px;color:var(--ui-ink);text-decoration:none;flex:0 0 auto}
.brand .mark{display:block;flex:0 0 auto}
.brand .word{font-family:var(--f-display);font-weight:900;font-size:20px;letter-spacing:.06em;line-height:1}
.nav .links{display:flex;align-items:center;gap:clamp(14px,2vw,26px);font-size:15px;font-weight:500}
.nav .links a{color:var(--ui-ink-2);padding:4px 0;border-bottom:2px solid transparent;transition:color .15s ease,border-color .15s ease}
.nav .links a:hover,.nav .brand:hover{color:var(--ui-hot);text-decoration:none}
.nav .brand:hover{color:var(--ui-ink)}
.nav .links a[aria-current="page"]{color:var(--ui-ink);border-bottom-color:var(--ui-accent)}
.nav .links a.cta{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:8px 16px;border-radius:10px;font-weight:600;background:var(--ui-accent);color:var(--ui-accent-ink);border:1px solid var(--ui-accent);transition:background .15s ease,transform .15s ease}
.nav .links a.cta:hover{background:var(--ui-hover);border-color:var(--ui-hover);color:var(--ui-accent-ink);transform:translateY(-1px)}
.burger{display:none;background:none;border:1px solid var(--ui-line-2);color:var(--ui-ink);border-radius:10px;width:44px;height:44px;align-items:center;justify-content:center;cursor:pointer;padding:0;flex:0 0 auto}
.burger .x{display:none}.burger[aria-expanded="true"] .x{display:block}.burger[aria-expanded="true"] .bars{display:none}
@media (max-width:900px){
.nav .links{display:none;position:absolute;left:0;right:0;top:100%;background:var(--ui-menu);border-bottom:1px solid var(--ui-line);box-shadow:0 24px 40px rgba(0,0,0,.35);padding:10px var(--gutter,16px) 18px;flex-direction:column;align-items:stretch;gap:2px}
.nav .links a{padding:13px 10px;border-radius:10px;border-bottom:0;font-size:16px}
.nav .links a[aria-current="page"]{background:var(--ui-tint)}
.nav .links a.cta{margin-top:8px;min-height:48px}
.nav .links.open{display:flex}
.burger{display:inline-flex}
}
/* footer, the same on every page */
.foot{border-top:1px solid var(--ui-line);color:var(--ui-ink);margin-top:var(--sec,64px)}
.foot .wrap{padding-block:48px 32px}
.foot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:32px}
.foot-brand{display:flex;flex-direction:column;gap:12px;max-width:34ch}
.foot-brand .brand{align-self:flex-start}.foot-brand .word{font-size:16px}
.foot-brand p{color:var(--ui-ash);font-size:14px;margin:0}
.foot-col{display:flex;flex-direction:column;gap:10px;font-size:15px}
.foot-col .eyebrow{font-family:var(--f-mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--ui-ash);margin-bottom:4px}
.foot-col a{color:var(--ui-ink-2);text-decoration:none;display:inline-flex;align-items:center;gap:6px;align-self:flex-start}
.foot-col a:hover{color:var(--ui-hot);text-decoration:none}
.foot-base{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px 24px;margin-top:36px;padding-top:20px;border-top:1px solid var(--ui-line);font-size:13px;color:var(--ui-ash)}
.foot-base span{text-wrap:balance}.foot-base .mono{font-family:var(--f-mono)}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
</style>

30
site/partials/nav.html Normal file
View file

@ -0,0 +1,30 @@
<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="36" height="36" aria-hidden="true"><rect width="1024" height="1024" 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>
<button class="burger" id="nav-burger" type="button" aria-expanded="false" aria-controls="nav-links" aria-label="Menu"><svg class="bars" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"></path></svg><svg class="x" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"></path></svg></button>
<div class="links" id="nav-links">
<a href="/litepaper" data-nav="litepaper">Litepaper</a>
<a href="/live" data-nav="live">Live devnet</a>
<a href="/bench" data-nav="bench">Engineering log</a>
<a href="/evidence" data-nav="evidence">Evidence</a>
<a href="https://github.com/igneum-network/spec" rel="noopener">GitHub</a>
<a href="/#mine" class="cta">Get the miner</a>
</div>
</div>
</nav>
<script>
(function(){
// the menu: open on the button, closed by any link, a tap outside, Escape (focus back on the button) or a resize past 900 px
var b=document.getElementById('nav-burger'),l=document.getElementById('nav-links');if(!b||!l)return;
function set(o){l.classList.toggle('open',o);b.setAttribute('aria-expanded',o?'true':'false');}
b.addEventListener('click',function(){set(!l.classList.contains('open'));});
l.addEventListener('click',function(e){if(e.target.closest('a'))set(false);});
document.addEventListener('click',function(e){if(l.classList.contains('open')&&!l.contains(e.target)&&!b.contains(e.target))set(false);});
document.addEventListener('keydown',function(e){if(e.key==='Escape'&&l.classList.contains('open')){set(false);b.focus();}});
var mq=window.matchMedia('(min-width:901px)');if(mq.addEventListener)mq.addEventListener('change',function(){set(false);});
})();
</script>

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>https://igneum.network/</loc><lastmod>2026-10-03</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
<url><loc>https://igneum.network/litepaper</loc><lastmod>2026-10-03</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url>
<url><loc>https://igneum.network/live</loc><lastmod>2026-10-03</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://igneum.network/bench</loc><lastmod>2026-10-03</lastmod><changefreq>weekly</changefreq><priority>0.6</priority></url>
<url><loc>https://igneum.network/</loc><lastmod>2026-10-04</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
<url><loc>https://igneum.network/litepaper</loc><lastmod>2026-10-04</lastmod><changefreq>monthly</changefreq><priority>0.9</priority></url>
<url><loc>https://igneum.network/live</loc><lastmod>2026-10-04</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
<url><loc>https://igneum.network/bench</loc><lastmod>2026-10-04</lastmod><changefreq>weekly</changefreq><priority>0.6</priority></url>
<url><loc>https://igneum.network/evidence</loc><lastmod>2026-10-04</lastmod><changefreq>weekly</changefreq><priority>0.6</priority></url>
</urlset>

View file

@ -9,6 +9,9 @@
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" }
] },
{ "source": "/fonts/(.*)", "headers": [ { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" } ] },
{ "source": "/(.*)\\.(png|ico)", "headers": [ { "key": "Cache-Control", "value": "public, max-age=86400, stale-while-revalidate=604800" } ] },
{ "source": "/site.webmanifest", "headers": [ { "key": "Cache-Control", "value": "public, max-age=86400, stale-while-revalidate=604800" } ] },
{ "source": "/journey.json", "headers": [ { "key": "Cache-Control", "value": "public, max-age=300" } ] },
{ "source": "/api/live", "headers": [ { "key": "Cache-Control", "value": "public, max-age=1" } ] }
]