Public Access
/dev/ has Debug Builds and the Debug Console (builds and the token, the console and its protocol, files and screenshots, driving the UI, crashes and Safe Mode, the command reference), Build, test and release (including how an update works), the architecture decisions and the milestone plans. Generated from the repository by site/tools/gen_dev_docs.py: the ADRs, the milestones, the README's sections, and the command reference, read from the firmware's own `help` text. The pages are committed (Zola cannot read outside its folder); the Site workflow checks they are current, and now also runs when src/main.cpp changes. M0, M1 and CONTEXT.md are not published. README: the gnss commands that the table lacked. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
257 lines
16 KiB
CSS
257 lines
16 KiB
CSS
/* roro9stack.net: the tokens and shapes of the design (docs/milestones/W1.md). Every colour is on the
|
|
device's RGB332 grid. Dark is the default; a visitor who prefers light gets light, and the switch
|
|
in the header overrides both. */
|
|
|
|
@font-face { font-family: "DM Mono"; src: url(/fonts/DMMono-Regular.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
|
|
@font-face { font-family: "DM Mono"; src: url(/fonts/DMMono-Medium.woff2) format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
|
|
@font-face { font-family: "Hanken Grotesk"; src: url(/fonts/HankenGrotesk.woff2) format("woff2"); font-weight: 100 900; font-style: normal; font-display: swap; }
|
|
|
|
:root {
|
|
--mono: "DM Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
|
|
--sans: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
|
|
color-scheme: dark;
|
|
--s1: #494955; --s2: #000000; --s3: #6d6d55; --line: #6d6d55; --ls: #b6b6aa;
|
|
--ink: #ffffff; --muted: #b6dbff;
|
|
--cyan: #00dbff; --onfill: #000055; --cyandeep: #00dbff; --cyantext: #00dbff;
|
|
--mag: #ff00ff; --magtext: #ff92ff; --orange: #ff9200; --orangetext: #ffb655;
|
|
--icons: url(/img/icons-dark.svg);
|
|
--logo-dark: block; --logo-light: none;
|
|
}
|
|
@media (prefers-color-scheme: light) {
|
|
:root:not([data-theme="dark"]) {
|
|
color-scheme: light;
|
|
--s1: #ffffff; --s2: #dbffff; --s3: #b6dbff; --line: #92b6ff; --ls: #6d6daa;
|
|
--ink: #000055; --muted: #4949aa;
|
|
--cyandeep: #0092aa; --cyantext: #006daa; --magtext: #b600aa; --orangetext: #b64900;
|
|
--icons: url(/img/icons-light.svg);
|
|
--logo-dark: none; --logo-light: block;
|
|
}
|
|
}
|
|
:root[data-theme="light"] {
|
|
color-scheme: light;
|
|
--s1: #ffffff; --s2: #dbffff; --s3: #b6dbff; --line: #92b6ff; --ls: #6d6daa;
|
|
--ink: #000055; --muted: #4949aa;
|
|
--cyandeep: #0092aa; --cyantext: #006daa; --magtext: #b600aa; --orangetext: #b64900;
|
|
--icons: url(/img/icons-light.svg);
|
|
--logo-dark: none; --logo-light: block;
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
|
|
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
|
|
body { margin: 0; background: var(--s1); color: var(--ink); font: 400 16px/24px var(--sans); }
|
|
a { color: inherit; text-decoration: none; }
|
|
a:hover { text-decoration: underline; text-underline-offset: 4px; }
|
|
img { max-width: 100%; height: auto; }
|
|
h1, h2, h3, p, ul, ol, figure, dl, dd { margin: 0; }
|
|
ul, ol { padding: 0; list-style: none; }
|
|
|
|
/* A focus ring must show. clip-path clips an outline along with everything else outside the shape,
|
|
so a focused notched control drops its notches and shows square corners and its ring. */
|
|
:focus-visible { outline: 2px solid var(--cyandeep); outline-offset: 2px; }
|
|
.n-sm:focus-visible, .n-md:focus-visible, .n-lg:focus-visible { clip-path: none; }
|
|
|
|
.skip { position: absolute; left: 8px; top: -60px; z-index: 10; background: var(--cyan); color: var(--onfill); padding: 12px 16px; font: 500 14px/20px var(--mono); }
|
|
.skip:focus { top: 8px; }
|
|
|
|
/* Notched corners: whole steps on a 4px grid (the device draws no curves). */
|
|
.n-sm { clip-path: polygon(0 4px,4px 4px,4px 0,calc(100% - 4px) 0,calc(100% - 4px) 4px,100% 4px,100% calc(100% - 4px),calc(100% - 4px) calc(100% - 4px),calc(100% - 4px) 100%,4px 100%,4px calc(100% - 4px),0 calc(100% - 4px)); }
|
|
.n-md { clip-path: polygon(0 8px,4px 8px,4px 4px,8px 4px,8px 0,calc(100% - 8px) 0,calc(100% - 8px) 4px,calc(100% - 4px) 4px,calc(100% - 4px) 8px,100% 8px,100% calc(100% - 8px),calc(100% - 4px) calc(100% - 8px),calc(100% - 4px) calc(100% - 4px),calc(100% - 8px) calc(100% - 4px),calc(100% - 8px) 100%,8px 100%,8px calc(100% - 4px),4px calc(100% - 4px),4px calc(100% - 8px),0 calc(100% - 8px)); }
|
|
.n-lg { clip-path: polygon(0 16px,8px 16px,8px 8px,16px 8px,16px 0,calc(100% - 16px) 0,calc(100% - 16px) 8px,calc(100% - 8px) 8px,calc(100% - 8px) 16px,100% 16px,100% calc(100% - 16px),calc(100% - 8px) calc(100% - 16px),calc(100% - 8px) calc(100% - 8px),calc(100% - 16px) calc(100% - 8px),calc(100% - 16px) 100%,16px 100%,16px calc(100% - 8px),8px calc(100% - 8px),8px calc(100% - 16px),0 calc(100% - 16px)); }
|
|
|
|
.wrap { width: 100%; max-width: 1200px; margin: 0 auto; padding-left: 32px; padding-right: 32px; }
|
|
.mono { font-family: var(--mono); }
|
|
|
|
/* Header */
|
|
.bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; padding-top: 24px; padding-bottom: 24px; }
|
|
.brand { display: flex; align-items: center; min-height: 44px; }
|
|
.logo { height: 28px; width: auto; }
|
|
.logo-dark { display: var(--logo-dark); }
|
|
.logo-light { display: var(--logo-light); }
|
|
.bar nav { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
.bar nav a, .link-btn { display: inline-flex; align-items: center; min-height: 44px; padding: 0 12px; font: 400 14px/20px var(--mono); }
|
|
.link-btn { background: none; border: 0; color: inherit; cursor: pointer; }
|
|
.link-btn:hover { text-decoration: underline; text-underline-offset: 4px; }
|
|
.js-only { display: none; }
|
|
.js .js-only { display: inline-flex; }
|
|
|
|
/* Buttons */
|
|
.btn { display: inline-flex; align-items: center; justify-content: center; min-height: 48px; padding: 0 24px; font: 500 14px/20px var(--mono); border: 0; cursor: pointer; }
|
|
.btn:hover { text-decoration: none; filter: brightness(1.08); }
|
|
.btn-primary { background: var(--cyan); color: var(--onfill); }
|
|
.btn-secondary { background: var(--s2); color: var(--ink); }
|
|
.bar nav a.btn { min-height: 44px; padding: 0 20px; }
|
|
.bar nav a.btn:hover { text-decoration: none; }
|
|
|
|
/* Type */
|
|
.eyebrow { font: 500 12px/16px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--cyantext); }
|
|
.eyebrow-row { display: flex; align-items: center; gap: 8px; }
|
|
.eyebrow .v { text-transform: none; }
|
|
.dot { width: 8px; height: 8px; background: var(--cyan); flex: none; }
|
|
h1, h2 { font-family: var(--mono); font-weight: 500; }
|
|
h1 { font-size: 64px; line-height: 64px; letter-spacing: -.02em; }
|
|
h2 { font-size: 40px; line-height: 44px; letter-spacing: -.01em; }
|
|
h3 { font-size: 24px; line-height: 30px; font-weight: 600; }
|
|
.accent { color: var(--cyantext); }
|
|
.lead { font-size: 18px; line-height: 28px; max-width: 520px; }
|
|
.muted { color: var(--muted); }
|
|
.small { font-size: 14px; line-height: 20px; }
|
|
.caption { font: 400 12px/16px var(--mono); color: var(--muted); }
|
|
code, .code { font-family: var(--mono); font-size: .9em; }
|
|
|
|
section { padding-top: 64px; padding-bottom: 64px; }
|
|
.section-head { display: flex; flex-direction: column; gap: 12px; max-width: 680px; }
|
|
.stack { display: flex; flex-direction: column; gap: 24px; }
|
|
|
|
/* Hero */
|
|
.hero { padding-top: 48px; padding-bottom: 32px; display: flex; flex-direction: column; gap: 48px; }
|
|
.hero-grid { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 32px 56px; }
|
|
.hero-grid > div { flex: 1 1 360px; min-width: 0; display: flex; flex-direction: column; gap: 24px; }
|
|
.hero-grid > div:first-child { flex-basis: 480px; }
|
|
.actions { display: flex; flex-wrap: wrap; gap: 16px; }
|
|
.facts { display: flex; flex-wrap: wrap; gap: 8px 24px; }
|
|
.facts li { display: flex; align-items: center; gap: 8px; font: 400 14px/20px var(--mono); color: var(--muted); }
|
|
.facts li::before { content: ""; width: 8px; height: 8px; background: var(--mag); display: block; }
|
|
.slab { background: var(--cyan); padding: 40px; display: flex; flex-wrap: wrap; gap: 32px; }
|
|
.slab .device { flex: 1 1 440px; min-width: 0; }
|
|
.illustration { display: block; width: 100%; height: auto; }
|
|
.illustration .mono { font-family: var(--mono); }
|
|
.hero .caption { margin-top: -36px; }
|
|
|
|
/* Panels */
|
|
.panel { background: var(--s2); padding: 32px; }
|
|
.status-box { background: var(--s2); padding: 24px 32px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 24px; }
|
|
.status-box .eyebrow { color: var(--orangetext); }
|
|
.status-box p { flex: 1 1 420px; min-width: 0; }
|
|
.status-box a, .prose a, .steps a, .need a { color: var(--cyantext); text-decoration: underline; text-underline-offset: 4px; }
|
|
|
|
.need { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 24px; margin-top: 32px; }
|
|
.need li { display: flex; flex-direction: column; gap: 4px; padding-left: 16px; border-left: 4px solid var(--cyan); }
|
|
.need strong { font-weight: 600; }
|
|
.need span { color: var(--muted); }
|
|
|
|
/* App cards */
|
|
.cards { display: flex; flex-wrap: wrap; gap: 24px; margin-top: 40px; }
|
|
.card { flex: 1 1 320px; min-width: 0; background: var(--s2); padding: 32px; display: flex; flex-direction: column; gap: 16px; }
|
|
.card-top { display: flex; justify-content: space-between; align-items: center; }
|
|
.card .tag { font: 500 12px/16px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--cyantext); }
|
|
.card .num { font: 500 12px/16px var(--mono); letter-spacing: .08em; color: var(--muted); }
|
|
.card p { color: var(--muted); }
|
|
.card .fact { margin-top: auto; padding-top: 8px; display: flex; align-items: center; gap: 8px; font: 500 12px/16px var(--mono); letter-spacing: .04em; }
|
|
.card .fact::before { content: ""; width: 8px; height: 8px; background: var(--cyan); flex: none; }
|
|
.card.planned .tag { color: var(--orangetext); }
|
|
.card.planned .fact::before { background: var(--orange); }
|
|
.ic { width: 48px; height: 48px; flex: none; background-image: var(--icons); background-repeat: no-repeat; background-size: 144px 192px; image-rendering: pixelated; }
|
|
.i0 { background-position: 0 0; } .i1 { background-position: -48px 0; } .i2 { background-position: -96px 0; }
|
|
.i3 { background-position: 0 -48px; } .i4 { background-position: -48px -48px; } .i5 { background-position: -96px -48px; }
|
|
.i6 { background-position: 0 -96px; } .i7 { background-position: -48px -96px; } .i8 { background-position: -96px -96px; }
|
|
.i9 { background-position: 0 -144px; }
|
|
.cards-note { margin-top: 24px; font-size: 14px; line-height: 20px; color: var(--muted); }
|
|
|
|
/* Real screenshots */
|
|
.shots { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 24px; margin-top: 40px; }
|
|
.shot { background: var(--s2); padding: 16px; display: flex; flex-direction: column; gap: 12px; }
|
|
.shot img { display: block; width: 100%; height: auto; } /* shown at about half size: smoothed, not pixel-doubled */
|
|
.shot figcaption { font: 500 12px/16px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
|
|
|
|
/* Updates */
|
|
.split { display: flex; flex-wrap: wrap; gap: 48px; }
|
|
.split > div { flex: 1 1 380px; min-width: 0; display: flex; flex-direction: column; gap: 24px; }
|
|
.split > .aside { flex-basis: 420px; justify-content: center; gap: 32px; }
|
|
.updates { background: var(--s2); padding: 48px; }
|
|
.terminal { background: var(--s1); padding: 16px 20px; font: 400 14px/20px var(--mono); overflow-x: auto; white-space: pre; }
|
|
.terminal .p { color: var(--cyantext); }
|
|
.terminal .c { color: var(--muted); }
|
|
.num-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 24px; }
|
|
.num-row .big { flex: none; min-width: 160px; font: 500 64px/64px var(--mono); letter-spacing: -.02em; }
|
|
.num-row p { flex: 1 1 200px; min-width: 0; color: var(--muted); }
|
|
.big.c1 { color: var(--cyantext); } .big.c2 { color: var(--magtext); }
|
|
.split > .blocks { display: flex; flex-direction: column; gap: 4px; background: var(--s2); padding: 32px; font: 400 14px/20px var(--mono); overflow-x: auto; white-space: pre; }
|
|
.split > .blocks .gap { height: 16px; }
|
|
.split > .blocks .c { color: var(--muted); }
|
|
.split > .blocks .p { color: var(--cyantext); }
|
|
|
|
/* Call to action */
|
|
.cta { background: var(--cyan); color: var(--onfill); padding: 48px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 40px; }
|
|
.cta > div:not(.nine) { flex: 1 1 360px; min-width: 0; display: flex; flex-direction: column; gap: 20px; }
|
|
.cta p { font-size: 18px; line-height: 28px; max-width: 480px; }
|
|
.cta .btn { background: #000055; color: #ffffff; }
|
|
.nine { display: grid; grid-template-columns: repeat(5, 24px); gap: 4px; }
|
|
.nine i { display: block; width: 24px; height: 24px; }
|
|
.nine i.on { background: var(--s1); }
|
|
|
|
/* Footer */
|
|
footer .wrap { padding-top: 32px; padding-bottom: 64px; display: flex; flex-direction: column; gap: 24px; }
|
|
.foot-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; }
|
|
.foot-row span, footer small { font: 400 14px/20px var(--mono); color: var(--muted); }
|
|
footer nav { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
footer nav a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 12px; font: 400 14px/20px var(--mono); }
|
|
footer small { display: block; max-width: 760px; }
|
|
|
|
/* Pages: Install, Downloads, 404 */
|
|
.page { padding-top: 32px; padding-bottom: 64px; display: flex; flex-direction: column; gap: 40px; }
|
|
.page h1 { font-size: 48px; line-height: 52px; }
|
|
.page h2 { font-size: 32px; line-height: 36px; }
|
|
.prose { max-width: 720px; display: flex; flex-direction: column; gap: 16px; }
|
|
.prose h2 { margin-top: 24px; }
|
|
.prose ul { list-style: disc; padding-left: 24px; display: flex; flex-direction: column; gap: 8px; }
|
|
.prose ol, .steps { list-style: decimal; padding-left: 24px; display: flex; flex-direction: column; gap: 12px; }
|
|
.prose pre { margin: 0; padding: 16px 20px; background: var(--s2); font: 400 14px/20px var(--mono); overflow-x: auto; clip-path: polygon(0 8px,4px 8px,4px 4px,8px 4px,8px 0,calc(100% - 8px) 0,calc(100% - 8px) 4px,calc(100% - 4px) 4px,calc(100% - 4px) 8px,100% 8px,100% calc(100% - 8px),calc(100% - 4px) calc(100% - 8px),calc(100% - 4px) calc(100% - 4px),calc(100% - 8px) calc(100% - 4px),calc(100% - 8px) 100%,8px 100%,8px calc(100% - 4px),4px calc(100% - 4px),4px calc(100% - 8px),0 calc(100% - 8px)); }
|
|
.prose pre code { font-size: 14px; }
|
|
.prose :not(pre) > code { background: var(--s2); padding: 0 6px; }
|
|
.prose table { border-collapse: collapse; width: 100%; }
|
|
.prose th, .prose td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
|
|
|
|
.flasher { background: var(--s2); padding: 32px; display: flex; flex-direction: column; gap: 20px; max-width: 720px; }
|
|
.flasher dl { display: grid; grid-template-columns: max-content 1fr; gap: 4px 20px; font: 400 14px/20px var(--mono); }
|
|
.flasher dt { color: var(--muted); }
|
|
.flasher dd { overflow-wrap: anywhere; }
|
|
.flasher [hidden] { display: none !important; }
|
|
.flasher .msg { color: var(--orangetext); }
|
|
.hash { word-break: break-all; }
|
|
|
|
.releases { display: flex; flex-direction: column; gap: 24px; }
|
|
.release { background: var(--s2); padding: 24px 32px; display: flex; flex-direction: column; gap: 12px; max-width: 880px; }
|
|
.release h2 { font-size: 28px; line-height: 32px; }
|
|
.release .meta { font: 400 14px/20px var(--mono); color: var(--muted); }
|
|
.release .files { display: flex; flex-wrap: wrap; gap: 8px 20px; font: 400 14px/20px var(--mono); }
|
|
.release .files a { color: var(--cyantext); text-decoration: underline; text-underline-offset: 4px; }
|
|
|
|
@media (max-width: 720px) {
|
|
h1 { font-size: 40px; line-height: 44px; }
|
|
h2 { font-size: 32px; line-height: 36px; }
|
|
.wrap { padding-left: 20px; padding-right: 20px; }
|
|
section { padding-top: 48px; padding-bottom: 48px; }
|
|
.slab, .updates, .cta { padding: 24px; }
|
|
.panel, .card { padding: 24px; }
|
|
.hero .caption { margin-top: -24px; }
|
|
.num-row .big { font-size: 48px; line-height: 48px; min-width: 120px; }
|
|
}
|
|
|
|
.accent-link { color: var(--cyantext); text-decoration: underline; text-underline-offset: 4px; }
|
|
.page > header { display: flex; flex-direction: column; gap: 12px; }
|
|
.page .lead { max-width: 720px; }
|
|
|
|
/* The user guide */
|
|
.pager { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
|
|
.card h2 { font-size: 24px; line-height: 28px; }
|
|
.card h2 a { color: inherit; text-decoration: none; }
|
|
.card h2 a:hover, .card h2 a:focus-visible { text-decoration: underline; text-underline-offset: 4px; }
|
|
.eyebrow a { color: inherit; }
|
|
.prose kbd { font: 500 13px/16px var(--mono); background: var(--s2); padding: 1px 6px; border: 1px solid var(--line); }
|
|
.prose .note { background: var(--s2); padding: 16px 20px; }
|
|
.prose h3 { margin-top: 12px; }
|
|
|
|
/* The developer docs: generated pages hold wide tables and long code lines */
|
|
.docs { max-width: 820px; }
|
|
.docs table { display: block; overflow-x: auto; }
|
|
.docs h2 { margin-top: 32px; }
|
|
.docs h3 { font-size: 22px; line-height: 28px; margin-top: 8px; }
|
|
.docs h4 { font: 500 12px/16px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
|
|
.docs code { overflow-wrap: anywhere; }
|
|
.docs pre code { overflow-wrap: normal; }
|
|
.source { max-width: 820px; font-size: 14px; line-height: 20px; }
|
|
.source code { background: var(--s2); padding: 0 6px; }
|
|
.card.featured { flex-basis: 100%; }
|