diff --git a/.gitignore b/.gitignore index e844850..323afe9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,8 @@ __pycache__/ dist/ *.egg-info/ node_modules/ + +# Kernel release binaries — 32 MB. These are published as Gitea release assets, +# not committed. Rebuild them with kernel/build.sh; verify with SHA256SUMS. +kernel/release/*.img.gz +kernel/release/*.tar.gz diff --git a/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-400.woff2 b/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-400.woff2 new file mode 100644 index 0000000..2e43c90 Binary files /dev/null and b/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-400.woff2 differ diff --git a/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-700.woff2 b/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-700.woff2 new file mode 100644 index 0000000..bc31903 Binary files /dev/null and b/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-700.woff2 differ diff --git a/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-mono-400.woff2 b/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-mono-400.woff2 new file mode 100644 index 0000000..f5c1081 Binary files /dev/null and b/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-mono-400.woff2 differ diff --git a/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-mono-600.woff2 b/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-mono-600.woff2 new file mode 100644 index 0000000..f5c1081 Binary files /dev/null and b/dashboard/src/gpsntp_dashboard/static/fonts/atkinson-mono-600.woff2 differ diff --git a/dashboard/src/gpsntp_dashboard/static/fonts/baskerville-400.woff2 b/dashboard/src/gpsntp_dashboard/static/fonts/baskerville-400.woff2 new file mode 100644 index 0000000..2d44bee Binary files /dev/null and b/dashboard/src/gpsntp_dashboard/static/fonts/baskerville-400.woff2 differ diff --git a/dashboard/src/gpsntp_dashboard/static/fonts/baskerville-700.woff2 b/dashboard/src/gpsntp_dashboard/static/fonts/baskerville-700.woff2 new file mode 100644 index 0000000..2d44bee Binary files /dev/null and b/dashboard/src/gpsntp_dashboard/static/fonts/baskerville-700.woff2 differ diff --git a/dashboard/src/gpsntp_dashboard/static/fonts/fonts.css b/dashboard/src/gpsntp_dashboard/static/fonts/fonts.css new file mode 100644 index 0000000..75a4dc2 --- /dev/null +++ b/dashboard/src/gpsntp_dashboard/static/fonts/fonts.css @@ -0,0 +1,57 @@ +/* Self-hosted: this dashboard runs on a LAN and must work with no internet. + * Latin subset only — the latin-ext/greek/vietnamese blocks Google serves + * would triple the payload for glyphs a status page will never render. + * + * Atkinson Hyperlegible is the Braille Institute's legibility face. It is + * here for a functional reason, not a brand one: it disambiguates 0/O, 1/l/I + * and rn/m, which is exactly what you need when reading `+66 ns` or + * `2607:f740:e::d3` at a glance from across a room. + */ + +@font-face { + font-family: "Atkinson Hyperlegible"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("/static/fonts/atkinson-400.woff2") format("woff2"); +} + +@font-face { + font-family: "Atkinson Hyperlegible"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url("/static/fonts/atkinson-700.woff2") format("woff2"); +} + +@font-face { + font-family: "Atkinson Hyperlegible Mono"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("/static/fonts/atkinson-mono-400.woff2") format("woff2"); +} + +@font-face { + font-family: "Atkinson Hyperlegible Mono"; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url("/static/fonts/atkinson-mono-600.woff2") format("woff2"); +} + +@font-face { + font-family: "Libre Baskerville"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("/static/fonts/baskerville-400.woff2") format("woff2"); +} + +@font-face { + font-family: "Libre Baskerville"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url("/static/fonts/baskerville-700.woff2") format("woff2"); +} diff --git a/dashboard/src/gpsntp_dashboard/static/index.html b/dashboard/src/gpsntp_dashboard/static/index.html index 60508f5..0d8ef86 100644 --- a/dashboard/src/gpsntp_dashboard/static/index.html +++ b/dashboard/src/gpsntp_dashboard/static/index.html @@ -171,6 +171,13 @@
diff --git a/dashboard/src/gpsntp_dashboard/static/style.css b/dashboard/src/gpsntp_dashboard/static/style.css index db2eef2..b7b918c 100644 --- a/dashboard/src/gpsntp_dashboard/static/style.css +++ b/dashboard/src/gpsntp_dashboard/static/style.css @@ -1,13 +1,34 @@ +@import url("/static/fonts/fonts.css"); + +/* Supported Systems house style, applied as WARM SHELL / COOL DATA. + * + * The chrome — background, panels, type, brand accent — comes from + * supported.systems: warm near-black, cream text, Libre Baskerville display, + * Atkinson Hyperlegible body, brass accent. + * + * The INSTRUMENTS do not. Cyan, green, amber and red stay exactly as they were, + * because on this page those colors carry information: which constellation a + * satellite belongs to, whether a source is selected, whether the clock is + * healthy. Recoloring them to brass would trade meaning for brand, which on a + * status page is a bad trade at any exchange rate. + * + * So: --brand is for chrome, --accent is for live data. They are different + * variables on purpose. Don't merge them. + */ :root { - --bg: #0a0e13; - --bg-2: #0e141c; - --panel: #121a23; - --panel-2: #16212d; - --border: #21303f; - --border-soft: #1a2632; - --text: #e7eef5; - --muted: #8a99a8; - --faint: #57687a; + /* shell — warm (supported.systems) */ + --bg: #171717; + --bg-2: #1b1a18; + --panel: #232120; + --panel-2: #2b2825; + --border: #3d382f; + --border-soft: #322e28; + --text: #eeece8; + --muted: #a8a196; + --faint: #6f6a61; + --brand: #d9a441; /* brass. chrome, links, brand marks. NOT data. */ + + /* instruments — cool (semantic; do not rebrand) */ --accent: #22d3ee; --good: #34d399; --warn: #f5a524; @@ -20,8 +41,15 @@ --c-sbas: #a3e635; --c-qzss: #2dd4bf; --c-other: #94a3b8; + --shadow: 0 1px 0 rgba(255, 255, 255, 0.03), 0 12px 30px -18px rgba(0, 0, 0, 0.9); - --mono: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Menlo, monospace; + + /* Atkinson Hyperlegible: the Braille Institute's legibility face. Chosen for + * function before brand — it disambiguates 0/O, 1/l/I, rn/m, which is exactly + * what a glanceable status page needs. */ + --sans: "Atkinson Hyperlegible", system-ui, -apple-system, sans-serif; + --serif: "Libre Baskerville", Georgia, serif; + --mono: "Atkinson Hyperlegible Mono", ui-monospace, "SF Mono", Menlo, monospace; } * { box-sizing: border-box; } @@ -29,11 +57,13 @@ body { margin: 0; background: - radial-gradient(1200px 600px at 80% -10%, rgba(34, 211, 238, 0.06), transparent 60%), - radial-gradient(900px 500px at 0% 0%, rgba(52, 211, 153, 0.05), transparent 55%), + /* the warm bench light from supported.systems */ + radial-gradient(1100px 620px at 50% -8%, rgba(217, 164, 65, 0.07), transparent 62%), + /* one cool wash, bottom-left, so the instruments feel like instruments */ + radial-gradient(900px 500px at 0% 100%, rgba(34, 211, 238, 0.04), transparent 58%), var(--bg); color: var(--text); - font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + font: 15px/1.5 var(--sans); -webkit-font-smoothing: antialiased; min-height: 100vh; } @@ -47,12 +77,16 @@ svg { width: 1.15em; height: 1.15em; fill: none; stroke: currentColor; stroke-wi gap: 16px; padding: 16px 20px; border-bottom: 1px solid var(--border-soft); position: sticky; top: 0; z-index: 5; - background: linear-gradient(var(--bg), rgba(10, 14, 19, 0.86)); + background: linear-gradient(var(--bg), rgba(23, 23, 23, 0.86)); backdrop-filter: blur(8px); } .brand { display: flex; align-items: center; gap: 13px; } -.brand-icon { width: 30px; height: 30px; color: var(--accent); } -.brand h1 { font-size: 19px; margin: 0; letter-spacing: 0.3px; font-family: var(--mono); } +/* The dish is brand chrome, not a reading — brass, not cyan. */ +.brand-icon { width: 30px; height: 30px; color: var(--brand); } +/* Libre Baskerville, as on supported.systems. The wordmark is the one place a + serif belongs on this page; everything that reports a NUMBER stays mono. */ +.brand h1 { font-size: 20px; margin: 0; letter-spacing: 0.2px; font-family: var(--serif); + font-weight: 700; } .brand-sub { margin: 0; color: var(--muted); font-size: 12.5px; } .conn { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); @@ -75,7 +109,7 @@ main { max-width: 1180px; margin: 0 auto; padding: 20px; display: grid; gap: 18p .panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; } .panel-head h2 { font-size: 14px; margin: 0; color: var(--muted); font-weight: 600; display: flex; align-items: center; gap: 8px; text-transform: uppercase; letter-spacing: 0.6px; } -.panel-head h2 svg { color: var(--accent); } +.panel-head h2 svg { color: var(--brand); } /* ---------- hero ---------- */ .hero { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; } @@ -104,7 +138,7 @@ main { max-width: 1180px; margin: 0 auto; padding: 20px; display: grid; gap: 18p .card { background: var(--panel); border: 1px solid var(--border-soft); border-radius: 14px; padding: 14px 15px; } .card-head { display: flex; align-items: center; gap: 7px; color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; } -.card-head svg { width: 15px; height: 15px; color: var(--accent); } +.card-head svg { width: 15px; height: 15px; color: var(--brand); } .card-value { font-family: var(--mono); font-size: 25px; font-weight: 650; margin: 7px 0 3px; letter-spacing: 0.3px; } .card-value.good { color: var(--good); } .card-value.warn { color: var(--warn); } @@ -179,8 +213,13 @@ main { max-width: 1180px; margin: 0 auto; padding: 20px; display: grid; gap: 18p /* ---------- footer ---------- */ .foot { max-width: 1180px; margin: 0 auto; padding: 14px 20px 30px; } -.foot-meta { display: flex; justify-content: space-between; margin-top: 14px; - color: var(--faint); font-size: 12px; font-family: var(--mono); } +.foot-meta { display: flex; justify-content: space-between; align-items: center; gap: 12px; + margin-top: 14px; color: var(--faint); font-size: 12px; font-family: var(--mono); } +.foot-docs { display: inline-flex; align-items: center; gap: 5px; color: var(--faint); + text-decoration: none; transition: color .2s; } +.foot-docs:hover { color: var(--brand); } +.foot-docs svg { width: 13px; height: 13px; stroke-width: 1.5; transition: transform .2s; } +.foot-docs:hover svg { transform: translateX(2px); } /* ---------- the maker's plate ---------- * Clockmakers signed the backplate — the brass face only a repairer sees once @@ -199,7 +238,7 @@ main { max-width: 1180px; margin: 0 auto; padding: 20px; display: grid; gap: 18p var(--panel); transition: color .2s, border-color .2s; } -.ss-plate__link:hover { color: var(--text); border-color: var(--accent); } +.ss-plate__link:hover { color: var(--text); border-color: var(--brand); } .ss-plate__logo { flex: 0 0 auto; width: 46px; height: auto; opacity: .85; transition: opacity .2s; } @@ -209,9 +248,9 @@ main { max-width: 1180px; margin: 0 auto; padding: 20px; display: grid; gap: 18p font-family: var(--mono); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .14em; } .ss-plate__body { display: block; font-size: 13px; line-height: 1.55; max-width: 62ch; } -.ss-plate__name { color: var(--accent); } +.ss-plate__name { color: var(--brand); } .ss-plate__cta { display: inline-flex; align-items: center; gap: 5px; margin-top: 8px; - font-size: 12px; color: var(--accent); } + font-size: 12px; color: var(--brand); } .ss-plate__cta svg { width: 14px; height: 14px; transition: transform .2s; } .ss-plate__link:hover .ss-plate__cta svg { transform: translateX(2px); } diff --git a/docs-site/Makefile b/docs-site/Makefile index 1d77058..fbc9515 100644 --- a/docs-site/Makefile +++ b/docs-site/Makefile @@ -56,4 +56,4 @@ deploy: ## Pull main + rebuild the docs container on the prod host @echo "==> deploying $(DEPLOY_HOST):$(DEPLOY_PATH)" ssh -A $(DEPLOY_HOST) "cd $(DEPLOY_PATH) && git fetch origin main && git reset --hard origin/main && cd docs-site && make prod" @echo "==> sanity check" - @curl -s -o /dev/null -w " HTTP %{http_code} %{url_effective}\n" "https://cuckoo.warehack.ing/explanation/bug-detection/" + @curl -s -o /dev/null -w " HTTP %{http_code} %{url_effective}\n" "https://cuckoo.warehack.ing/explanation/preempt-rt-made-it-worse/" diff --git a/docs-site/src/content/docs/reference/downloads.md b/docs-site/src/content/docs/reference/downloads.md index fb4a24a..2e105aa 100644 --- a/docs-site/src/content/docs/reference/downloads.md +++ b/docs-site/src/content/docs/reference/downloads.md @@ -1,6 +1,6 @@ --- title: Downloads — prebuilt RT kernel -description: A patched PREEMPT_RT kernel for the Raspberry Pi 4, so you don't need a cross-compile toolchain. +description: A patched PREEMPT_RT kernel for the Raspberry Pi 4, boot-tested and benchmarked, so you don't need a cross-compile toolchain. sidebar: order: 5 --- @@ -9,28 +9,37 @@ The only expensive part of [the patch](/reference/the-patch/) is the toolchain. Building natively on a Pi 4 takes hours; cross-compiling needs an x86 box and a setup session. So here's the artifact. +**Current release: `6.18.38-rt-cuckoo+`** — Raspberry Pi's `rpi-6.18.y`, +`bcm2711_defconfig`, `PREEMPT_RT`, plus the `IRQF_NO_THREAD` patch. + :::danger[Read this before you download] -- **Raspberry Pi 4 / arm64 only.** `bcm2711_defconfig`. It will not boot a Pi 5 or - a Pi 3. -- **Unsigned, community-built.** We built this on a workstation. There is no chain - of trust here beyond "we published the exact recipe and the checksums." If that - isn't good enough for your environment — and for some environments it correctly - isn't — [build it yourself](/how-to/cross-compile-rt-kernel/). It's forty - minutes. -- **Verify the checksums.** They're in `SHA256SUMS`. +- **Raspberry Pi 4 / arm64 only.** The installer refuses to run on anything else, + because a `bcm2711` kernel on a Pi 5 doesn't boot — and a black screen on a + headless box is exactly the outcome we're trying to prevent. +- **Unsigned, community-built.** There is no chain of trust here beyond published + checksums and a reproducible recipe. For some environments that is correctly + not good enough. [Build it yourself](/how-to/cross-compile-rt-kernel/) — it's + forty minutes, and `kernel/build.sh` in the repo does the whole thing. +- **Verify the checksums.** The installer does it for you if `SHA256SUMS` is + present. Don't skip it. ::: ## Artifacts -Published on the [releases page](https://git.supported.systems/warehack.ing/cuckoo-escapement/releases): +On the [releases page](https://git.supported.systems/warehack.ing/cuckoo-escapement/releases): -| File | What | +| File | | |---|---| -| `kernel-rt-