docs: a website, in three files

index.html, style.css, app.js and the three marks. No build step, no
dependencies, no framework -- it opens from a file:// URL.

The palette is not a design decision: it is include/theme.h transcribed,
including the rule that header enforces. PSOGM purple appears exactly once,
on the crash-screen section, because branding/README.md says a colour used
everywhere means nothing. The typefaces are Roboto and JetBrains Mono, both
already in ports/ and both requested from the system rather than downloaded --
a font file would outweigh the rest of the site.

The boot log in the hero is real lines from a real boot. The script is
decoration and the page is complete without it; it does nothing at all under
prefers-reduced-motion.

The feature tags (runs / in progress / designed) are a promise, and the
README says so: anything marked `runs` is in the tree and works today.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
This commit is contained in:
Nexoniarz 2026-09-12 21:38:47 +02:00
commit 81af69bf53
7 changed files with 890 additions and 0 deletions

92
docs/Website/app.js Normal file
View file

@ -0,0 +1,92 @@
/* SPDX-License-Identifier: Apache-2.0
*
* Two behaviours, no framework:
* 1. the hero console types a real boot log
* 2. sections fade in once, as they arrive
*
* Both are decoration. If this file fails to load the page is still complete
* and still readable, which is the test any script on a documentation site
* should have to pass.
*/
(function () {
"use strict";
var reduced = window.matchMedia &&
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ---- 1. the boot log ------------------------------------------------
* These are real lines from a real boot, not invented ones. The timer
* calibration line in particular is there because of what it cost: the
* clock ran seven times slow until a graphics driver was made to
* acknowledge its own interrupt. See docs/history/kernel.md.
*/
var LINES = [
{ t: "[ 0.000]", k: "SchIFT", s: " 64-bit, 2 cpus" },
{ t: "[ 0.004]", k: "cpu0", s: ": lapic timer 999949260 Hz, tsc 3792 MHz" },
{ t: "[ 0.061]", k: "virtio-gpu", s: ": 1280x800, 4000 KB framebuffer, irq 11" },
{ t: "[ 0.088]", k: "e1000", s: ": 52:54:00:12:34:56, link up, irq 11" },
{ t: "[ 0.143]", k: "schfs0", s: ": mounted, generation 41" },
{ t: "[ 0.169]", k: "net", s: ": eth0 10.0.2.15/255.255.255.0" },
{ t: "[ 0.204]", k: "schinit", s: ": 4 jobs", g: true },
{ t: "", k: "", s: "# " }
];
var out = document.getElementById("bootlog");
function span(cls, text) {
var e = document.createElement("span");
if (cls) e.className = cls;
e.textContent = text;
return e;
}
function emit(line) {
if (line.t) {
out.appendChild(span("t", line.t + " "));
out.appendChild(span("k", line.k));
}
out.appendChild(span(line.g ? "g" : "", line.s));
out.appendChild(document.createTextNode("\n"));
}
function cursor() {
var c = document.createElement("i");
c.className = "cursor";
out.appendChild(c);
}
if (!out) {
/* nothing to do */
} else if (reduced) {
LINES.forEach(emit); // the whole log at once, no animation
cursor();
} else {
var i = 0;
(function step() {
if (i >= LINES.length) { cursor(); return; }
emit(LINES[i++]);
/* Uneven on purpose: a boot that ticks out at a metronome's pace reads
as a progress bar rather than as a machine doing different work. */
setTimeout(step, 180 + Math.random() * 220);
})();
}
/* ---- 2. reveal on scroll ------------------------------------------ */
var targets = document.querySelectorAll(".reveal");
if (reduced || !("IntersectionObserver" in window)) {
Array.prototype.forEach.call(targets, function (el) { el.classList.add("in"); });
return;
}
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (!entry.isIntersecting) return;
entry.target.classList.add("in");
io.unobserve(entry.target); // once, not on every scroll past
});
}, { rootMargin: "0px 0px -12% 0px", threshold: 0.05 });
Array.prototype.forEach.call(targets, function (el) { io.observe(el); });
})();