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:
parent
d917798090
commit
81af69bf53
7 changed files with 890 additions and 0 deletions
92
docs/Website/app.js
Normal file
92
docs/Website/app.js
Normal 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); });
|
||||
})();
|
||||
Loading…
Reference in a new issue