site: a lit hero, new slogans, the wallpapers, and a better reader

Home:
- The hero stands on a light from the upper left and a pool of the
  accent, mixed from Niveus tokens so it follows the theme. The mark sits
  in an .nv-tile key under a slogan: "Every layer its own -- from the
  first instruction to the last pixel."
- New section headings: "A teaching kernel that outgrew its lessons",
  "Measured, not marketed", "One ISO. One stick. Your disks untouched."
- A Wallpapers section with the four new ones, each downloadable as a
  4K JPEG or as SVG. The four-card grids are two across, so none is left
  alone on its row.

Docs reader:
- An index filter, a breadcrumb with reading time and source path,
  code blocks framed with a language strip and a Copy key, previous and
  next keys at the foot, a reading-progress hairline, and the contents
  entry lit for the section on screen.
- The index lists the documents it was missing: scheduler, FAT, audio,
  LDLS, debugging and the hardware report.
- On a phone the page is no longer wider than the screen (a pre block
  was sizing the grid's auto column), and the index folds away.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-23 15:56:43 +02:00
commit 7af579a20d
4 changed files with 421 additions and 19 deletions

View file

@ -55,6 +55,28 @@
/* --- Hero ------------------------------------------------------------------ */ /* --- Hero ------------------------------------------------------------------ */
/* The band behind the hero, lit the way the Graphite wallpaper is: a light
from the upper left, and a pool of the accent on the surface the window
stands on. Mixed from the system's own tokens rather than from the picture,
so it follows the brand and the appearance instead of fighting the copy. */
.heroband {
background:
radial-gradient(ellipse 45% 38% at 68% 62%,
color-mix(in oklab, var(--nv-color-accent) 45%, transparent), transparent 72%),
radial-gradient(ellipse 60% 70% at 18% 0%,
color-mix(in oklab, var(--nv-color-text-primary) 7%, transparent), transparent 70%),
var(--nv-color-background);
padding-block-end: var(--nv-space-12);
}
.hero__tile {
flex: none;
}
.hero__slogan {
max-inline-size: 22ch;
}
.hero { .hero {
display: grid; display: grid;
gap: var(--nv-space-12); gap: var(--nv-space-12);
@ -88,6 +110,41 @@
block-size: 1.15em; block-size: 1.15em;
} }
/* --- Wallpapers ----------------------------------------------------------- */
/* Two across, not auto-fit: four of anything at three per row leaves one
alone on the last, which reads as an afterthought. */
.walls,
#docs .nv-card-grid {
display: grid;
gap: var(--nv-space-5);
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 48rem) {
.walls,
#docs .nv-card-grid { grid-template-columns: 1fr; }
}
.wall {
margin: 0;
overflow: hidden;
}
.wall__img {
inline-size: 100%;
block-size: auto;
aspect-ratio: 16 / 9;
object-fit: cover;
}
.wall__caption {
display: flex;
flex-direction: column;
gap: var(--nv-space-2);
padding: var(--nv-space-4) var(--nv-space-5) var(--nv-space-5);
}
/* --- The console ----------------------------------------------------------- */ /* --- The console ----------------------------------------------------------- */
/* /*
A terminal is a window into the machine, so it is drawn as one: a solid A terminal is a window into the machine, so it is drawn as one: a solid
@ -367,11 +424,18 @@
*/ */
.docshell { .docshell {
max-inline-size: var(--nv-layout-max-width); /* Wider than the rest of the site: the document column carries tables and
diagrams that the prose measure would squeeze, and both side panels have
to fit beside it. */
max-inline-size: calc(var(--nv-layout-max-width) + 16rem);
margin-inline: auto; margin-inline: auto;
padding-inline: var(--nv-layout-gutter); padding-inline: var(--nv-layout-gutter);
padding-block: var(--nv-space-8) var(--nv-space-16); padding-block: var(--nv-space-8) var(--nv-space-16);
display: grid; display: grid;
/* minmax(0, ...) even with one column: a code block is white-space: pre,
and an auto column grows to its longest line -- which on a phone made
the whole page wider than the screen. */
grid-template-columns: minmax(0, 1fr);
gap: var(--nv-space-8); gap: var(--nv-space-8);
align-items: start; align-items: start;
} }
@ -385,6 +449,13 @@
@media (max-width: 64rem) { @media (max-width: 64rem) {
.docshell__rail { display: none; } .docshell__rail { display: none; }
/* One column: the index stops following the reader and folds away, so
the document is the first thing on the screen rather than the fortieth. */
.docshell__aside {
position: static;
max-block-size: none;
}
} }
/* Both panels follow the reader down the page, under the bar rather than /* Both panels follow the reader down the page, under the bar rather than
@ -457,6 +528,36 @@
border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle); border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle);
} }
/* A code block is a small window: a raised strip naming the language, with
the copy key on it, over the recess the code sits in. */
.codeframe {
margin: 0;
border-radius: var(--nv-radius-md);
overflow: hidden;
background: var(--nv-color-surface-elevated);
box-shadow: var(--nv-elevation-1);
}
.codeframe__bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--nv-space-1) var(--nv-space-1) var(--nv-space-1) var(--nv-space-4);
border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle);
}
.codeframe__lang {
font-family: var(--nv-font-family-mono);
font-size: var(--nv-font-size-xs);
letter-spacing: var(--nv-letter-spacing-wide);
text-transform: uppercase;
color: var(--nv-color-text-tertiary);
}
.codeframe .doc__pre {
border-radius: 0;
}
.doc__pre { .doc__pre {
margin: 0; margin: 0;
padding: var(--nv-space-4); padding: var(--nv-space-4);
@ -496,3 +597,94 @@
.features { .features {
--nv-scroller-item: 21rem; --nv-scroller-item: 21rem;
} }
/* --- The reader's furniture ----------------------------------------------- */
/* Where this document sits, and how long it is. */
.dochead {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: var(--nv-space-2) var(--nv-space-4);
padding-block-end: var(--nv-space-4);
border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle);
}
.doc > .dochead + * {
margin-block-start: var(--nv-space-6);
}
/* Previous and next, as two keys. */
.docpager {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--nv-space-4);
margin-block-start: var(--nv-space-12);
}
.docpager__key {
display: flex;
flex-direction: column;
gap: var(--nv-space-1);
padding: var(--nv-space-4) var(--nv-space-5);
text-decoration: none;
color: inherit;
}
.docpager__key--next {
text-align: end;
align-items: flex-end;
grid-column: 2;
}
@media (max-width: 40rem) {
.docpager { grid-template-columns: 1fr; }
.docpager__key--next { grid-column: auto; }
}
/* The filter well above the index. */
.docfind {
margin-block-end: var(--nv-space-5);
}
.docfind .nv-input {
inline-size: 100%;
}
/* Reading progress: a hairline of accent under the bar, growing from the
left. Transform rather than width, so it costs a composite and no layout. */
.readbar {
position: sticky;
inset-block-start: 0;
z-index: 10;
block-size: var(--nv-border-width-strong);
margin-block-end: calc(var(--nv-border-width-strong) * -1);
}
.readbar span {
display: block;
block-size: 100%;
background: var(--nv-color-accent);
box-shadow: 0 0 var(--nv-space-2) var(--nv-color-accent);
transform: scaleX(0);
transform-origin: left;
}
/* The contents entry for the section being read. */
#toc .nv-nav__item[aria-current="location"] {
color: var(--nv-color-accent-text);
}
/* The index's fold. Open on a wide screen, where it is a column; closed on a
narrow one (docs.js), where it would push the document out of view. */
.docindex > summary {
display: none;
}
@media (max-width: 64rem) {
.docindex > summary {
display: flex;
margin-block-end: var(--nv-space-3);
}
}

View file

@ -52,13 +52,23 @@
</div> </div>
</nav> </nav>
<div class="readbar" aria-hidden="true"><span id="readbar"></span></div>
<!-- Index, document, contents. Three columns that become one on a narrow <!-- Index, document, contents. Three columns that become one on a narrow
screen, in that order, because that is their order of importance when screen, in that order, because that is their order of importance when
there is only room for the middle one. --> there is only room for the middle one. -->
<div class="docshell"> <div class="docshell">
<aside class="docshell__aside" aria-label="Documentation index"> <aside class="docshell__aside" aria-label="Documentation index">
<nav class="nv-nav nv-nav--vertical nv-nav--static docnav" id="docnav" <details class="nv-disclosure nv-disclosure--plain docindex" id="docindex" open>
style="--nv-selection-name: nv-docs-index"></nav> <summary class="nv-button nv-button--sm nv-disclosure__summary">All documents</summary>
<div class="docfind">
<label class="nv-visually-hidden" for="docfilter">Filter documents</label>
<input class="nv-input nv-input--sm" id="docfilter" type="search"
placeholder="Filter documents…" autocomplete="off">
</div>
<nav class="nv-nav nv-nav--vertical nv-nav--static docnav" id="docnav"
style="--nv-selection-name: nv-docs-index"></nav>
</details>
</aside> </aside>
<main class="docshell__main"> <main class="docshell__main">

View file

@ -26,21 +26,27 @@
["architecture/README.md", "The system, layer by layer"], ["architecture/README.md", "The system, layer by layer"],
["architecture/boot.md", "Boot"], ["architecture/boot.md", "Boot"],
["architecture/kernel.md", "Kernel"], ["architecture/kernel.md", "Kernel"],
["architecture/scheduler.md", "Scheduler"],
["architecture/syscalls.md", "Syscalls"], ["architecture/syscalls.md", "Syscalls"],
["architecture/filesystem.md", "The VFS"], ["architecture/filesystem.md", "The VFS"],
["architecture/schfs.md", "SchFS"], ["architecture/schfs.md", "SchFS"],
["architecture/fat.md", "FAT"],
["architecture/terminals.md", "Virtual terminals"], ["architecture/terminals.md", "Virtual terminals"],
["architecture/devices.md", "Device model"], ["architecture/devices.md", "Device model"],
["architecture/usb.md", "USB"], ["architecture/usb.md", "USB"],
["architecture/graphics.md", "Graphics"], ["architecture/graphics.md", "Graphics"],
["architecture/audio.md", "Audio"],
["architecture/networking.md", "Networking"], ["architecture/networking.md", "Networking"],
["architecture/init.md", "init"] ["architecture/init.md", "init"],
["architecture/ldls.md", "Linux drivers (LDLS)"],
["architecture/debugging.md", "Debugging"]
]}, ]},
{ group: "Guides", items: [ { group: "Guides", items: [
["guides/building.md", "Building"], ["guides/building.md", "Building"],
["guides/testing.md", "Testing"], ["guides/testing.md", "Testing"],
["guides/layout.md", "Tree layout"], ["guides/layout.md", "Tree layout"],
["guides/adding-a-driver.md", "Adding a driver"] ["guides/adding-a-driver.md", "Adding a driver"],
["guides/hardware-report.md", "Reporting hardware"]
]}, ]},
{ group: "Plan", items: [ { group: "Plan", items: [
["plan/README.md", "What plan/ is for"], ["plan/README.md", "What plan/ is for"],
@ -57,7 +63,7 @@
["history/moving-to-linux.md", "Moving to Linux"] ["history/moving-to-linux.md", "Moving to Linux"]
]}, ]},
{ group: "Branding", items: [ { group: "Branding", items: [
["branding/README.md", "The three marks"] ["branding/README.md", "Shift, and the wallpapers"]
]} ]}
]; ];
@ -178,9 +184,17 @@
i++; i++;
while (i < L.length && !/^\s*```/.test(L[i])) buf.push(L[i++]); while (i < L.length && !/^\s*```/.test(L[i])) buf.push(L[i++]);
i++; i++;
out.push('<pre class="nv-code doc__pre"' + /* A frame rather than a bare block: a title strip naming the language,
and a button that copies it, because the thing a reader most often
wants from a code block in these docs is to paste it somewhere. */
out.push('<figure class="codeframe">' +
'<figcaption class="codeframe__bar">' +
'<span class="codeframe__lang">' + esc(lang || "text") + "</span>" +
'<button class="nv-button nv-button--ghost nv-button--sm" type="button" data-copy>Copy</button>' +
"</figcaption>" +
'<pre class="nv-code doc__pre"' +
(lang ? ' data-lang="' + esc(lang) + '"' : "") + (lang ? ' data-lang="' + esc(lang) + '"' : "") +
"><code>" + esc(buf.join("\n")) + "</code></pre>"); "><code>" + esc(buf.join("\n")) + "</code></pre></figure>");
continue; continue;
} }
@ -307,6 +321,77 @@
tocEl.appendChild(ul); tocEl.appendChild(ul);
} }
/* Every document in index order, with the group it belongs to. */
var FLAT = [];
DOCS.forEach(function (g) {
g.items.forEach(function (it) { FLAT.push({ path: it[0], title: it[1], group: g.group }); });
});
function indexOf(path) {
for (var k = 0; k < FLAT.length; k++) if (FLAT[k].path === path) return k;
return -1;
}
/* Where the reader is, how long it will take, and where the file lives --
above the document, because a page arrived at from a search has no other
way to say which part of the docs it belongs to. */
function header(path, text) {
var at = FLAT[indexOf(path)] || { group: "Docs", title: path };
var words = text.split(/\s+/).length;
var mins = Math.max(1, Math.round(words / 230));
return '<header class="dochead">' +
'<ol class="nv-breadcrumbs">' +
'<li><a href="?doc=README.md">Docs</a></li>' +
"<li>" + esc(at.group) + "</li>" +
'<li aria-current="page">' + esc(at.title) + "</li>" +
"</ol>" +
'<span class="dochead__meta nv-caption nv-text-tertiary">' +
mins + " min read · " +
'<a href="../' + esc(path) + '">' + esc(path) + "</a>" +
"</span>" +
"</header>";
}
/* The next and previous document, as two keys at the foot of the page. A
reader who reaches the end of one has nearly always come to read the
section, not the file. */
function pager(path) {
var k = indexOf(path), html = '<nav class="docpager" aria-label="More documents">';
function key(d, dir) {
return '<a class="nv-card nv-card--interactive docpager__key docpager__key--' + dir +
'" href="' + docHref(d.path) + '">' +
'<span class="nv-overline nv-text-tertiary">' + (dir === "prev" ? "← Previous" : "Next →") + "</span>" +
'<span class="nv-title">' + esc(d.title) + "</span>" +
'<span class="nv-caption nv-text-tertiary">' + esc(d.group) + "</span></a>";
}
if (k > 0) html += key(FLAT[k - 1], "prev");
else html += "<span></span>";
if (k >= 0 && k < FLAT.length - 1) html += key(FLAT[k + 1], "next");
return html + "</nav>";
}
/* Light the contents entry for the section being read. */
var spy;
function watchHeadings() {
if (spy) spy.disconnect();
if (!("IntersectionObserver" in window)) return;
var links = {};
Array.prototype.forEach.call(tocEl.querySelectorAll("a"), function (a) {
links[a.getAttribute("href").slice(1)] = a;
});
spy = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (!e.isIntersecting || !links[e.target.id]) return;
Array.prototype.forEach.call(tocEl.querySelectorAll("a"), function (a) {
a.removeAttribute("aria-current");
});
links[e.target.id].setAttribute("aria-current", "location");
});
}, { rootMargin: "0px 0px -70% 0px" });
Array.prototype.forEach.call(article.querySelectorAll("h2[id], h3[id]"), function (h) {
spy.observe(h);
});
}
function fail(title, body) { function fail(title, body) {
article.innerHTML = "<h1>" + title + "</h1>" + body; article.innerHTML = "<h1>" + title + "</h1>" + body;
tocEl.hidden = true; tocEl.hidden = true;
@ -322,8 +407,9 @@
return r.text(); return r.text();
}).then(function (text) { }).then(function (text) {
var headings = []; var headings = [];
article.innerHTML = render(text, path, headings); article.innerHTML = header(path, text) + render(text, path, headings) + pager(path);
buildToc(headings); buildToc(headings);
watchHeadings();
article.removeAttribute("aria-busy"); article.removeAttribute("aria-busy");
if (headings.length) document.title = headings[0].text + " — SchOS docs"; if (headings.length) document.title = headings[0].text + " — SchOS docs";
var hash = location.hash.slice(1); var hash = location.hash.slice(1);
@ -340,7 +426,7 @@
"<p>Browsers block <code>fetch()</code> on <code>file://</code> URLs, so the " + "<p>Browsers block <code>fetch()</code> on <code>file://</code> URLs, so the " +
"reader cannot load the Markdown. The rest of the site works from a file; " + "reader cannot load the Markdown. The rest of the site works from a file; " +
"this page does not. Serve the repository root:</p>" + "this page does not. Serve the repository root:</p>" +
'<pre class="nv-code doc__pre"><code>cd /home/nexoniarz/Dokumenty/Projects/SchOS\n' + '<pre class="nv-code doc__pre"><code>cd path/to/SchOS\n' +
"python3 -m http.server 8000</code></pre>" + "python3 -m http.server 8000</code></pre>" +
"<p>Then open <code>http://localhost:8000/docs/Website/docs.html</code>.</p>" + "<p>Then open <code>http://localhost:8000/docs/Website/docs.html</code>.</p>" +
'<p>Or read this one directly: <a href="../' + esc(path) + '">' + esc(path) + "</a></p>"); '<p>Or read this one directly: <a href="../' + esc(path) + '">' + esc(path) + "</a></p>");
@ -365,6 +451,54 @@
buildNav(); buildNav();
load(pathFromUrl()); load(pathFromUrl());
/* Fold the index on a narrow screen, and fold it again after picking a
document there -- the choice is made, and the document is what was asked
for. */
var fold = document.getElementById("docindex");
var narrow = window.matchMedia && window.matchMedia("(max-width: 64rem)");
if (fold && narrow && narrow.matches) fold.open = false;
nav.addEventListener("click", function () {
if (fold && narrow && narrow.matches) fold.open = false;
});
/* Filter the index as you type. Groups with nothing left in them go too,
so the heading of an empty section does not sit there implying a match. */
var filter = document.getElementById("docfilter");
if (filter) filter.addEventListener("input", function () {
var q = filter.value.trim().toLowerCase();
Array.prototype.forEach.call(nav.querySelectorAll(".nv-nav__list"), function (ul) {
var any = false;
Array.prototype.forEach.call(ul.querySelectorAll("li"), function (li) {
var hit = !q || li.textContent.toLowerCase().indexOf(q) >= 0;
li.hidden = !hit;
any = any || hit;
});
ul.hidden = !any;
if (ul.previousElementSibling) ul.previousElementSibling.hidden = !any;
});
});
/* Copy a code block. The label says what happened, then goes back. */
article.addEventListener("click", function (ev) {
var b = ev.target.closest ? ev.target.closest("[data-copy]") : null;
if (!b) return;
var code = b.closest(".codeframe").querySelector("code").textContent;
var done = function (ok) {
b.textContent = ok ? "Copied" : "Select and copy";
setTimeout(function () { b.textContent = "Copy"; }, 1600);
};
if (navigator.clipboard) navigator.clipboard.writeText(code).then(function () { done(true); }, function () { done(false); });
else done(false);
});
/* How far down the document the reader is: a hairline under the bar. */
var bar = document.getElementById("readbar");
if (bar) window.addEventListener("scroll", function () {
var h = document.documentElement;
var f = h.scrollHeight > h.clientHeight ? h.scrollTop / (h.scrollHeight - h.clientHeight) : 0;
bar.style.transform = "scaleX(" + Math.min(1, Math.max(0, f)) + ")";
}, { passive: true });
/* Intercept in-page navigation so the reader does not reload its own shell. */ /* Intercept in-page navigation so the reader does not reload its own shell. */
document.addEventListener("click", function (ev) { document.addEventListener("click", function (ev) {
var a = ev.target.closest ? ev.target.closest("a") : null; var a = ev.target.closest ? ev.target.closest("a") : null;

View file

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>SchOS — a 64-bit operating system written from scratch</title> <title>SchOS — every layer its own</title>
<meta name="description" content="SchOS is a from-scratch x86-64 operating system: the SchIFT kernel, the SchFS copy-on-write filesystem, a UEFI loader, and a userland that runs unmodified musl and toybox."> <meta name="description" content="SchOS is a from-scratch x86-64 operating system: the SchIFT kernel, the SchFS copy-on-write filesystem, a UEFI loader, and a userland that runs unmodified musl and toybox.">
<link rel="icon" href="Assets/shift.svg" type="image/svg+xml"> <link rel="icon" href="Assets/shift.svg" type="image/svg+xml">
@ -47,6 +47,7 @@
<li><a class="nv-nav__item" href="#what">What it has</a></li> <li><a class="nv-nav__item" href="#what">What it has</a></li>
<li><a class="nv-nav__item" href="#hybrid">Hybrid</a></li> <li><a class="nv-nav__item" href="#hybrid">Hybrid</a></li>
<li><a class="nv-nav__item" href="#numbers">Numbers</a></li> <li><a class="nv-nav__item" href="#numbers">Numbers</a></li>
<li><a class="nv-nav__item" href="#wallpapers">Wallpapers</a></li>
</ul> </ul>
<span class="nv-nav__spacer"></span> <span class="nv-nav__spacer"></span>
@ -69,7 +70,9 @@
<main id="top"> <main id="top">
<!-- ====================================================================== --> <!-- ====================================================================== -->
<header class="shell hero"> <!-- The one full-bleed band on the page, lit like the Graphite wallpaper. -->
<header class="heroband">
<div class="shell hero">
<div class="hero__copy"> <div class="hero__copy">
<span class="nv-badge nv-badge--accent"> <span class="nv-badge nv-badge--accent">
<span class="nv-badge__dot"></span> <span class="nv-badge__dot"></span>
@ -77,9 +80,11 @@
</span> </span>
<h1 class="nv-display hero__title"> <h1 class="nv-display hero__title">
<img class="hero__mark" src="Assets/shift.svg" alt="">SchOS <span class="nv-tile nv-tile--xl hero__tile"><img src="Assets/shift.svg" alt=""></span>SchOS
</h1> </h1>
<p class="nv-heading hero__slogan">Every layer its own — from the first instruction to the last pixel.</p>
<p class="nv-prose"> <p class="nv-prose">
A 64-bit operating system written from scratch — its own kernel, its own A 64-bit operating system written from scratch — its own kernel, its own
filesystem, its own bootloader. It boots on UEFI, drives real hardware, filesystem, its own bootloader. It boots on UEFI, drives real hardware,
@ -109,13 +114,14 @@
</div> </div>
<pre class="nv-window__body nv-code console__log" id="bootlog" aria-live="polite"></pre> <pre class="nv-window__body nv-code console__log" id="bootlog" aria-live="polite"></pre>
</div> </div>
</div>
</header> </header>
<!-- ====================================================================== --> <!-- ====================================================================== -->
<section id="origin" class="shell section" data-reveal> <section id="origin" class="shell section" data-reveal>
<div class="section__head"> <div class="section__head">
<p class="nv-overline nv-text-accent">Origin</p> <p class="nv-overline nv-text-accent">Origin</p>
<h2 class="nv-heading">It started as a teaching kernel and stopped being one</h2> <h2 class="nv-heading">A teaching kernel that outgrew its lessons</h2>
<p class="nv-prose nv-text-secondary"> <p class="nv-prose nv-text-secondary">
SchOS began as <a href="https://github.com/mit-pdos/xv6-public">xv6</a>, MIT's SchOS began as <a href="https://github.com/mit-pdos/xv6-public">xv6</a>, MIT's
teaching operating system: 32-bit, single core, one filesystem, a few dozen teaching operating system: 32-bit, single core, one filesystem, a few dozen
@ -195,7 +201,7 @@
<section id="stack" class="shell section" data-reveal> <section id="stack" class="shell section" data-reveal>
<div class="section__head"> <div class="section__head">
<p class="nv-overline nv-text-accent">Architecture</p> <p class="nv-overline nv-text-accent">Architecture</p>
<h2 class="nv-heading">Three seams hold the whole thing together</h2> <h2 class="nv-heading">Three seams, and everything else is arrangement</h2>
<p class="nv-prose nv-text-secondary"> <p class="nv-prose nv-text-secondary">
Above the syscall table, software is ordinary and portable. Below the device Above the syscall table, software is ordinary and portable. Below the device
model, a driver never names its consumer and a consumer never names a driver. model, a driver never names its consumer and a consumer never names a driver.
@ -261,7 +267,7 @@
<section id="what" class="shell section" data-reveal> <section id="what" class="shell section" data-reveal>
<div class="section__head"> <div class="section__head">
<p class="nv-overline nv-text-accent">What it has</p> <p class="nv-overline nv-text-accent">What it has</p>
<h2 class="nv-heading">Built and running, and honest about the rest</h2> <h2 class="nv-heading">Running today, and honest about the rest</h2>
<p class="nv-prose nv-text-secondary"> <p class="nv-prose nv-text-secondary">
Every card marked <b>runs</b> is in the tree and works today. The tags are Every card marked <b>runs</b> is in the tree and works today. The tags are
not aspirational; the things that are not finished say so. not aspirational; the things that are not finished say so.
@ -536,7 +542,7 @@
<section id="numbers" class="shell section" data-reveal> <section id="numbers" class="shell section" data-reveal>
<div class="section__head"> <div class="section__head">
<p class="nv-overline nv-text-accent">Numbers</p> <p class="nv-overline nv-text-accent">Numbers</p>
<h2 class="nv-heading">The size of it</h2> <h2 class="nv-heading">Measured, not marketed</h2>
</div> </div>
<dl class="nv-stat-group"> <dl class="nv-stat-group">
@ -583,6 +589,66 @@
</div> </div>
</section> </section>
<!-- ====================================================================== -->
<section id="wallpapers" class="shell section" data-reveal>
<div class="section__head">
<p class="nv-overline nv-text-accent">Wallpapers</p>
<h2 class="nv-heading">Four surfaces to sit on</h2>
<p class="nv-prose nv-text-secondary">
Every one is the Shift mark under a different light, generated from the
same geometry the loader draws — so they change when the mark does.
3840×2160, free to use under the same licence as the rest of the tree.
</p>
</div>
<div class="walls">
<figure class="nv-card wall">
<img class="wall__img" src="../branding/wallpapers/graphite.jpg" alt="Graphite: Shift on warm graphite, throwing a pool of violet on the surface. The default." loading="lazy" width="3840" height="2160">
<figcaption class="wall__caption">
<span class="nv-title">Graphite</span>
<span class="nv-body nv-text-secondary">Shift on warm graphite, throwing a pool of violet on the surface. The default.</span>
<span class="nv-cluster">
<a class="nv-button nv-button--sm" href="../branding/wallpapers/graphite.jpg" download>4K JPEG</a>
<a class="nv-button nv-button--ghost nv-button--sm" href="../branding/wallpapers/graphite.svg" download>SVG</a>
</span>
</figcaption>
</figure>
<figure class="nv-card wall">
<img class="wall__img" src="../branding/wallpapers/strata.jpg" alt="Strata: The slabs repeated into a cascade that recedes into indigo." loading="lazy" width="3840" height="2160">
<figcaption class="wall__caption">
<span class="nv-title">Strata</span>
<span class="nv-body nv-text-secondary">The slabs repeated into a cascade that recedes into indigo.</span>
<span class="nv-cluster">
<a class="nv-button nv-button--sm" href="../branding/wallpapers/strata.jpg" download>4K JPEG</a>
<a class="nv-button nv-button--ghost nv-button--sm" href="../branding/wallpapers/strata.svg" download>SVG</a>
</span>
</figcaption>
</figure>
<figure class="nv-card wall">
<img class="wall__img" src="../branding/wallpapers/porcelain.jpg" alt="Porcelain: The light one: glazed porcelain on paper, the top slab in the accent." loading="lazy" width="3840" height="2160">
<figcaption class="wall__caption">
<span class="nv-title">Porcelain</span>
<span class="nv-body nv-text-secondary">The light one: glazed porcelain on paper, the top slab in the accent.</span>
<span class="nv-cluster">
<a class="nv-button nv-button--sm" href="../branding/wallpapers/porcelain.jpg" download>4K JPEG</a>
<a class="nv-button nv-button--ghost nv-button--sm" href="../branding/wallpapers/porcelain.svg" download>SVG</a>
</span>
</figcaption>
</figure>
<figure class="nv-card wall">
<img class="wall__img" src="../branding/wallpapers/dial.jpg" alt="Dial: The SchFS uberblock ring as hardware — the newest slot and the root lit." loading="lazy" width="3840" height="2160">
<figcaption class="wall__caption">
<span class="nv-title">Dial</span>
<span class="nv-body nv-text-secondary">The SchFS uberblock ring as hardware — the newest slot and the root lit.</span>
<span class="nv-cluster">
<a class="nv-button nv-button--sm" href="../branding/wallpapers/dial.jpg" download>4K JPEG</a>
<a class="nv-button nv-button--ghost nv-button--sm" href="../branding/wallpapers/dial.svg" download>SVG</a>
</span>
</figcaption>
</figure>
</div>
</section>
<!-- ====================================================================== --> <!-- ====================================================================== -->
<section id="docs" class="shell section" data-reveal> <section id="docs" class="shell section" data-reveal>
<div class="section__head"> <div class="section__head">
@ -648,7 +714,7 @@
<img class="getband__mark" src="Assets/usb.svg" alt=""> <img class="getband__mark" src="Assets/usb.svg" alt="">
<div class="getband__copy"> <div class="getband__copy">
<p class="nv-overline nv-text-accent">Try it</p> <p class="nv-overline nv-text-accent">Try it</p>
<h2 class="nv-heading">One ISO, one stick, nothing written to your disks</h2> <h2 class="nv-heading">One ISO. One stick. Your disks untouched.</h2>
<p class="nv-prose nv-text-secondary"> <p class="nv-prose nv-text-secondary">
It runs from RAM and leaves the machine as it found it. Or skip the It runs from RAM and leaves the machine as it found it. Or skip the
stick entirely — <code class="nv-code">make qemu</code> is the same stick entirely — <code class="nv-code">make qemu</code> is the same
@ -667,7 +733,7 @@
<footer class="shell site-footer"> <footer class="shell site-footer">
<div class="nv-divider"></div> <div class="nv-divider"></div>
<div class="site-footer__row"> <div class="site-footer__row">
<span class="nv-body">SchOS — kernel <b>SchIFT</b>, filesystem <b>SchFS</b>.</span> <span class="nv-body">SchOS — built from the metal up. Kernel <b>SchIFT</b>, filesystem <b>SchFS</b>.</span>
<span class="nv-code nv-text-tertiary">GPL-2.0-or-later, with the xv6-derived core under MIT.</span> <span class="nv-code nv-text-tertiary">GPL-2.0-or-later, with the xv6-derived core under MIT.</span>
</div> </div>