Guru and SchCotie are gone. Shift is the only mark, and the crash screen draws it where the face used to be. Guru was an icon -- a pictogram with a face, denoting one state -- that lived on the crash screen and nowhere else. Its argument was identity: `:(` is recognisably Microsoft's, and a crash screen is the single screenshot most likely to leave the machine, so it is the worst place to be wearing somebody else's face. That part holds, and it is kept in the branding README because it is the argument against any second mark. What does not follow is that the answer is a *new* mark. Shift already signs the system, it is already what the machine drew on the splash it started with, and a reader who has seen it twice before the crash recognises it faster than a face they have never seen. SchCotie was a mascot, and never existed: the file said so itself under "what this does not cover". A brief for a character nobody is about to draw is not worth carrying. So `draw_guru()` and its SVG-space geometry leave panic.c, the two `guru.svg` files are deleted, and PSOGM calls gfx_draw_logo() -- the same include/logo.h mask the loader splash and the boot console composite. At its native 128 px: there is no resampler in the crash path, and the face was scalable in a place that only ever drew it at one size. The name stays. "Purple Screen of Guru Meditation" is the Amiga nod, which panic.c's own header already called out as a separate thing from the mark. **And taking the screenshot to check it caught a regression from the TTF console work.** `gfx_draw_char()` -- the pixel-positioned path, which only PSOGM uses -- still walked `font_data[c][row]` for `row < CHAR_HEIGHT`. font_data has exactly 16 rows per glyph; CHAR_HEIGHT is the *TrueType* cell height now, about 21. So every line of the crash report drew five rows of the next character's bitmap underneath itself, and it looked like each line had been printed twice. The grid path had been updated when the cell size stopped being a constant; this one had not, because nothing routine draws text in pixel coordinates. Both go through one draw_glyph_px() now, and the bitmap's own geometry is spelled BITMAP_W/BITMAP_H so it cannot be mistaken for a cell size again. Two stale claims corrected while in there, in panic.c's header and in graphics.md: PSOGM has not dimmed-and-floated over the old screen for a while -- it clears to full purple, and the file's own code comment says why -- and there is no longer "a face that is obviously a cartoon". The website's crash section shows the mark in flat white rather than its own violets, which is what the kernel actually draws: PSOGM composites a coverage mask in one colour, and those violets sit close enough to #4B1D9A to half-disappear against it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
701 lines
21 KiB
CSS
701 lines
21 KiB
CSS
/* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* The palette is not chosen here. It is include/theme.h, transcribed, because
|
|
* a site that describes an operating system should look like the operating
|
|
* system. That includes the rule theme.h enforces:
|
|
*
|
|
* normal states are calm and dark; only failure is loud.
|
|
*
|
|
* PSOGM purple (--psogm) therefore appears exactly once on this page, in the
|
|
* crash-screen section. If it ever appears anywhere else, delete it there.
|
|
*/
|
|
|
|
:root {
|
|
/* include/theme.h */
|
|
--bg: #0C0E13; /* SCH_BG */
|
|
--fg: #E6E8EC; /* SCH_FG */
|
|
--dim: #707784; /* SCH_DIM */
|
|
--accent: #7C5CFF; /* SCH_ACCENT */
|
|
--accent-dim: #2A2440; /* SCH_ACCENT_DIM */
|
|
--ok: #4ADE80; /* SCH_OK */
|
|
--warn: #FBBF24; /* SCH_WARN */
|
|
--psogm: #4B1D9A; /* PSOGM_BG — failure, and nothing else */
|
|
|
|
/* Surfaces lifted off the ground, keeping its blue bias rather than
|
|
sliding toward neutral grey. */
|
|
--surface: #12151C;
|
|
--surface-2: #171B24;
|
|
--line: #212632;
|
|
|
|
--sans: "Roboto", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "Cascadia Code",
|
|
Menlo, Consolas, monospace;
|
|
|
|
--measure: 66ch;
|
|
--gap: clamp(1rem, 2.5vw, 1.75rem);
|
|
--section: clamp(4rem, 10vw, 7.5rem);
|
|
}
|
|
|
|
*, *::before, *::after { box-sizing: border-box; }
|
|
|
|
html { scroll-behavior: smooth; }
|
|
@media (prefers-reduced-motion: reduce) {
|
|
html { scroll-behavior: auto; }
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--fg);
|
|
font-family: var(--sans);
|
|
font-size: clamp(1rem, 0.95rem + 0.2vw, 1.0625rem);
|
|
line-height: 1.65;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
/* ---- shared shells ------------------------------------------------- */
|
|
|
|
.wrap {
|
|
width: min(100% - 2.5rem, 68rem);
|
|
margin-inline: auto;
|
|
}
|
|
|
|
section { padding-block: var(--section); }
|
|
|
|
.eyebrow {
|
|
font-family: var(--mono);
|
|
font-size: 0.75rem;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--accent);
|
|
margin: 0 0 0.75rem;
|
|
}
|
|
|
|
h1, h2, h3 { text-wrap: balance; line-height: 1.15; margin: 0; }
|
|
|
|
h2 {
|
|
font-size: clamp(1.75rem, 1.3rem + 2vw, 2.75rem);
|
|
font-weight: 700;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
.lede {
|
|
max-width: var(--measure);
|
|
color: var(--dim);
|
|
font-size: clamp(1.05rem, 1rem + 0.35vw, 1.2rem);
|
|
margin: 1.25rem 0 0;
|
|
}
|
|
|
|
p { max-width: var(--measure); }
|
|
|
|
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
|
|
a:hover { color: var(--fg); }
|
|
a:focus-visible,
|
|
button:focus-visible {
|
|
outline: 2px solid var(--accent);
|
|
outline-offset: 3px;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
code, .mono { font-family: var(--mono); font-size: 0.9em; }
|
|
code { color: var(--fg); background: var(--surface-2); padding: 0.1em 0.4em; border-radius: 3px; }
|
|
|
|
/* ---- header -------------------------------------------------------- */
|
|
|
|
header.top {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 10;
|
|
background: color-mix(in srgb, var(--bg) 88%, transparent);
|
|
backdrop-filter: blur(8px);
|
|
border-bottom: 1px solid var(--line);
|
|
}
|
|
.top .wrap {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1.5rem;
|
|
padding-block: 0.85rem;
|
|
}
|
|
.brand {
|
|
display: flex; align-items: center; gap: 0.6rem;
|
|
font-weight: 700; letter-spacing: -0.01em;
|
|
color: inherit; text-decoration: none;
|
|
}
|
|
.brand img { width: 26px; height: 26px; display: block; }
|
|
.top nav { margin-left: auto; display: flex; gap: 1.5rem; font-size: 0.9rem; }
|
|
.top nav a { color: var(--dim); text-decoration: none; }
|
|
.top nav a:hover { color: var(--fg); }
|
|
@media (max-width: 46rem) { .top nav { display: none; } }
|
|
|
|
/* ---- hero ---------------------------------------------------------- */
|
|
|
|
.hero { padding-block: clamp(3.5rem, 9vw, 6.5rem) var(--section); }
|
|
.hero .wrap {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
|
|
gap: clamp(2rem, 5vw, 4rem);
|
|
align-items: center;
|
|
}
|
|
@media (max-width: 56rem) {
|
|
.hero .wrap { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
.hero h1 {
|
|
font-size: clamp(2.75rem, 1.8rem + 4.2vw, 4.75rem);
|
|
font-weight: 700;
|
|
letter-spacing: -0.035em;
|
|
}
|
|
.hero h1 .mark {
|
|
display: inline-block;
|
|
width: 0.95em;
|
|
height: 0.95em;
|
|
vertical-align: -0.08em;
|
|
margin-right: 0.22em;
|
|
}
|
|
.hero p { color: var(--dim); font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem); margin-top: 1.25rem; }
|
|
.hero .cta { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 2rem; }
|
|
|
|
.btn {
|
|
display: inline-block;
|
|
padding: 0.65rem 1.25rem;
|
|
border-radius: 4px;
|
|
font-size: 0.925rem;
|
|
font-weight: 500;
|
|
text-decoration: none;
|
|
border: 1px solid var(--line);
|
|
color: var(--fg);
|
|
background: var(--surface);
|
|
}
|
|
.btn:hover { border-color: var(--accent); color: var(--fg); }
|
|
.btn.primary { background: var(--accent); border-color: var(--accent); color: #0B0714; font-weight: 700; }
|
|
.btn.primary:hover { background: #8F73FF; border-color: #8F73FF; color: #0B0714; }
|
|
|
|
/* ---- console ------------------------------------------------------- */
|
|
|
|
.console {
|
|
background: #090B0F;
|
|
border: 1px solid var(--line);
|
|
border-radius: 6px;
|
|
overflow: hidden;
|
|
box-shadow: 0 24px 60px -30px #000;
|
|
}
|
|
.console-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.55rem 0.85rem;
|
|
border-bottom: 1px solid var(--line);
|
|
background: var(--surface);
|
|
font-family: var(--mono);
|
|
font-size: 0.72rem;
|
|
color: var(--dim);
|
|
letter-spacing: 0.06em;
|
|
}
|
|
.console-bar .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
|
|
.console-bar .dot.live { background: var(--ok); }
|
|
.console-bar span { margin-left: auto; }
|
|
|
|
.console pre {
|
|
margin: 0;
|
|
padding: 1rem 1.1rem 1.4rem;
|
|
font-family: var(--mono);
|
|
font-size: clamp(0.72rem, 0.62rem + 0.35vw, 0.82rem);
|
|
line-height: 1.85;
|
|
color: var(--fg);
|
|
overflow-x: auto;
|
|
}
|
|
/* The hero's console reserves its height so the typing animation does not
|
|
push the page around as it fills. A static transcript sizes to its own
|
|
content instead, which is why this is not on .console pre. */
|
|
.hero .console pre { min-height: 16.5rem; }
|
|
.console.transcript { margin-top: 3rem; }
|
|
.console .t { color: var(--dim); }
|
|
.console .k { color: var(--accent); }
|
|
.console .g { color: var(--ok); }
|
|
.console .cursor {
|
|
display: inline-block;
|
|
width: 0.55em;
|
|
height: 1.05em;
|
|
background: var(--accent);
|
|
vertical-align: -0.18em;
|
|
animation: blink 1.1s step-end infinite;
|
|
}
|
|
@keyframes blink { 50% { opacity: 0; } }
|
|
@media (prefers-reduced-motion: reduce) { .console .cursor { animation: none; } }
|
|
|
|
/* ---- origin timeline ----------------------------------------------- */
|
|
|
|
.origin-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
|
gap: var(--gap);
|
|
margin-top: 3rem;
|
|
}
|
|
.step {
|
|
border-left: 2px solid var(--accent-dim);
|
|
padding-left: 1.1rem;
|
|
}
|
|
.step h3 { font-size: 1.05rem; font-weight: 700; margin-bottom: 0.4rem; }
|
|
.step .when { font-family: var(--mono); font-size: 0.72rem; color: var(--accent); letter-spacing: 0.08em; text-transform: uppercase; display: block; margin-bottom: 0.5rem; }
|
|
.step p { color: var(--dim); font-size: 0.925rem; margin: 0; }
|
|
|
|
/* ---- the stack ----------------------------------------------------- */
|
|
|
|
.stack { display: flex; flex-direction: column; gap: 3px; margin-top: 3rem; }
|
|
.layer {
|
|
display: grid;
|
|
grid-template-columns: 10.5rem 1fr;
|
|
gap: 1.25rem;
|
|
align-items: baseline;
|
|
padding: 0.95rem 1.15rem;
|
|
background: var(--surface);
|
|
border: 1px solid transparent;
|
|
border-radius: 3px;
|
|
}
|
|
.layer:hover { border-color: var(--accent-dim); background: var(--surface-2); }
|
|
.layer .name { font-family: var(--mono); font-size: 0.8rem; color: var(--accent); letter-spacing: 0.04em; }
|
|
.layer .what { color: var(--dim); font-size: 0.9rem; }
|
|
.layer.seam { background: var(--accent-dim); }
|
|
.layer.seam .name { color: var(--fg); }
|
|
.layer.seam .what { color: #C9BEEC; }
|
|
@media (max-width: 42rem) {
|
|
.layer { grid-template-columns: 1fr; gap: 0.3rem; }
|
|
}
|
|
.seam-note { margin-top: 1.5rem; color: var(--dim); font-size: 0.9rem; }
|
|
|
|
/* ---- features ------------------------------------------------------ */
|
|
|
|
.cards {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
|
|
gap: var(--gap);
|
|
margin-top: 3rem;
|
|
}
|
|
.card {
|
|
background: var(--surface);
|
|
border: 1px solid var(--line);
|
|
border-radius: 5px;
|
|
padding: 1.4rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.6rem;
|
|
}
|
|
.card h3 { font-size: 1.05rem; font-weight: 700; }
|
|
.card p { color: var(--dim); font-size: 0.925rem; margin: 0; max-width: none; }
|
|
.tag {
|
|
align-self: flex-start;
|
|
font-family: var(--mono);
|
|
font-size: 0.68rem;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
padding: 0.2rem 0.5rem;
|
|
border-radius: 3px;
|
|
border: 1px solid var(--line);
|
|
color: var(--dim);
|
|
}
|
|
.tag.runs { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, transparent); }
|
|
.tag.partial{ color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
|
|
.tag.planned{ color: var(--dim); }
|
|
|
|
/* ---- numbers ------------------------------------------------------- */
|
|
|
|
.figures {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
|
|
gap: var(--gap);
|
|
margin-top: 3rem;
|
|
}
|
|
.figure { border-top: 1px solid var(--line); padding-top: 1rem; }
|
|
.figure b {
|
|
display: block;
|
|
font-family: var(--mono);
|
|
font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.25rem);
|
|
font-weight: 700;
|
|
font-variant-numeric: tabular-nums;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
.figure span { color: var(--dim); font-size: 0.85rem; }
|
|
|
|
/* ---- the crash screen: the one loud thing --------------------------- */
|
|
|
|
.crash { background: var(--psogm); color: #fff; }
|
|
.crash .wrap {
|
|
display: grid;
|
|
grid-template-columns: 8rem minmax(0, 1fr);
|
|
gap: clamp(1.5rem, 4vw, 3rem);
|
|
align-items: start;
|
|
}
|
|
@media (max-width: 44rem) { .crash .wrap { grid-template-columns: 1fr; } }
|
|
/* Flat white, not the logo's own violets. This is what the kernel actually
|
|
draws: PSOGM composites the coverage mask in one colour, so a full-colour
|
|
mark here would show something the crash screen never shows -- and those
|
|
violets are close enough to this purple to half-disappear against it. */
|
|
.crash img {
|
|
width: 100%;
|
|
max-width: 8rem;
|
|
height: auto;
|
|
filter: brightness(0) invert(1);
|
|
}
|
|
.crash .eyebrow { color: #C3AEEC; }
|
|
.crash h2 { color: #fff; }
|
|
.crash p { color: #DBCEF5; }
|
|
.crash code { background: rgba(0, 0, 0, 0.28); color: #fff; }
|
|
|
|
/* ---- closing links -------------------------------------------------- */
|
|
|
|
.links { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: var(--gap); margin-top: 2.5rem; }
|
|
.link-card {
|
|
display: block;
|
|
padding: 1.2rem;
|
|
border: 1px solid var(--line);
|
|
border-radius: 5px;
|
|
text-decoration: none;
|
|
color: var(--fg);
|
|
background: var(--surface);
|
|
}
|
|
.link-card:hover { border-color: var(--accent); color: var(--fg); }
|
|
.link-card b { display: block; margin-bottom: 0.3rem; }
|
|
.link-card span { color: var(--dim); font-size: 0.875rem; }
|
|
|
|
footer {
|
|
border-top: 1px solid var(--line);
|
|
padding-block: 2.5rem 3.5rem;
|
|
color: var(--dim);
|
|
font-size: 0.85rem;
|
|
}
|
|
footer .wrap { display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center; }
|
|
footer .mono { font-size: 0.78rem; }
|
|
|
|
/* ---- reveal on scroll ---------------------------------------------- */
|
|
|
|
.reveal { opacity: 0; transform: translateY(12px); transition: opacity .5s ease, transform .5s ease; }
|
|
.reveal.in { opacity: 1; transform: none; }
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.reveal { opacity: 1; transform: none; transition: none; }
|
|
}
|
|
|
|
/* The SchFS mark, set beside its own card heading. Baseline-aligned rather
|
|
than centred: it sits next to a word, so it follows the word. */
|
|
.card h3 .cardmark {
|
|
width: 1.15em;
|
|
height: 1.15em;
|
|
vertical-align: -0.22em;
|
|
margin-right: 0.4em;
|
|
}
|
|
|
|
/* =====================================================================
|
|
The pride mark
|
|
---------------------------------------------------------------------
|
|
Small, and permanent. It is in the top bar in November the same way it
|
|
is in June, which is the only version of this that means anything --
|
|
support with an end date is marketing.
|
|
|
|
Deliberately not bigger than this. The site is about an operating
|
|
system; the flag is a statement, not a subject.
|
|
===================================================================== */
|
|
|
|
.pride {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
line-height: 0;
|
|
border-radius: 2px;
|
|
text-decoration: none;
|
|
}
|
|
.pride img {
|
|
width: 26px;
|
|
height: auto;
|
|
display: block;
|
|
border-radius: 2px;
|
|
/* Sits down slightly against the dark ground so it reads as part of the
|
|
bar rather than as a sticker on top of it; full colour on hover. */
|
|
opacity: 0.85;
|
|
transition: opacity .18s ease, transform .18s ease;
|
|
}
|
|
.pride:hover img { opacity: 1; transform: translateY(-1px); }
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.pride img { transition: none; }
|
|
.pride:hover img { transform: none; }
|
|
}
|
|
|
|
.pride-note {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.6rem;
|
|
flex-basis: 100%;
|
|
color: var(--dim);
|
|
font-size: 0.82rem;
|
|
}
|
|
.pride-note img { width: 20px; height: auto; border-radius: 2px; flex: none; }
|
|
|
|
/* =====================================================================
|
|
The documentation reader
|
|
===================================================================== */
|
|
|
|
body.reading { display: flex; flex-direction: column; min-height: 100vh; }
|
|
body.reading footer { margin-top: auto; }
|
|
|
|
.docshell {
|
|
width: min(100% - 2.5rem, 84rem);
|
|
margin-inline: auto;
|
|
display: grid;
|
|
grid-template-columns: 15rem minmax(0, 1fr) 13rem;
|
|
gap: clamp(1.5rem, 3vw, 3rem);
|
|
align-items: start;
|
|
padding-block: 2.5rem 4rem;
|
|
}
|
|
@media (max-width: 72rem) { .docshell { grid-template-columns: 14rem minmax(0, 1fr); } .rail { display: none; } }
|
|
@media (max-width: 54rem) { .docshell { grid-template-columns: 1fr; } .sidebar .sticky { position: static; max-height: none; } }
|
|
|
|
.sticky {
|
|
position: sticky;
|
|
top: 4.5rem;
|
|
max-height: calc(100vh - 6rem);
|
|
overflow-y: auto;
|
|
scrollbar-width: thin;
|
|
}
|
|
|
|
.navgroup {
|
|
font-family: var(--mono);
|
|
font-size: 0.68rem;
|
|
letter-spacing: 0.13em;
|
|
text-transform: uppercase;
|
|
color: var(--dim);
|
|
margin: 1.6rem 0 0.5rem;
|
|
}
|
|
.navgroup:first-child { margin-top: 0; }
|
|
|
|
#docnav ul, #toc ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
|
|
#docnav a, #toc a {
|
|
display: block;
|
|
padding: 0.28rem 0.6rem;
|
|
margin-left: -0.6rem;
|
|
border-radius: 3px;
|
|
color: var(--dim);
|
|
text-decoration: none;
|
|
font-size: 0.875rem;
|
|
line-height: 1.45;
|
|
}
|
|
#docnav a:hover, #toc a:hover { color: var(--fg); background: var(--surface); }
|
|
#docnav a.on {
|
|
color: var(--fg);
|
|
background: var(--accent-dim);
|
|
box-shadow: inset 2px 0 0 var(--accent);
|
|
}
|
|
#toc .lvl3 a { padding-left: 1.5rem; font-size: 0.8rem; }
|
|
|
|
/* ---- prose ---------------------------------------------------------- */
|
|
|
|
.prose { max-width: 46rem; }
|
|
.prose .loading { color: var(--dim); font-family: var(--mono); font-size: 0.85rem; }
|
|
|
|
.prose h1 {
|
|
font-size: clamp(1.9rem, 1.4rem + 2.2vw, 2.6rem);
|
|
font-weight: 700;
|
|
letter-spacing: -0.025em;
|
|
margin: 0 0 1.25rem;
|
|
}
|
|
.prose h2 {
|
|
font-size: clamp(1.3rem, 1.1rem + 1vw, 1.65rem);
|
|
font-weight: 700;
|
|
letter-spacing: -0.015em;
|
|
margin: 2.75rem 0 0.9rem;
|
|
padding-top: 1.6rem;
|
|
border-top: 1px solid var(--line);
|
|
}
|
|
.prose h3 { font-size: 1.1rem; font-weight: 700; margin: 2rem 0 0.6rem; }
|
|
.prose h4, .prose h5, .prose h6 { font-size: 0.95rem; font-weight: 700; margin: 1.5rem 0 0.5rem; color: var(--dim); }
|
|
|
|
.prose p, .prose li { color: #C6CAD3; }
|
|
.prose p { margin: 0 0 1.1rem; max-width: none; }
|
|
.prose strong { color: var(--fg); }
|
|
.prose a { color: var(--accent); }
|
|
|
|
.prose ul, .prose ol { margin: 0 0 1.2rem; padding-left: 1.35rem; display: flex; flex-direction: column; gap: 0.4rem; }
|
|
.prose li { line-height: 1.6; }
|
|
.prose li::marker { color: var(--accent); }
|
|
|
|
.prose hr { border: 0; border-top: 1px solid var(--line); margin: 2.25rem 0; }
|
|
|
|
.prose blockquote {
|
|
margin: 1.4rem 0;
|
|
padding: 0.2rem 0 0.2rem 1.1rem;
|
|
border-left: 2px solid var(--accent);
|
|
color: var(--dim);
|
|
}
|
|
.prose blockquote p:last-child { margin-bottom: 0; }
|
|
|
|
.prose pre.code {
|
|
background: #090B0F;
|
|
border: 1px solid var(--line);
|
|
border-radius: 5px;
|
|
padding: 0.95rem 1.1rem;
|
|
overflow-x: auto;
|
|
margin: 0 0 1.3rem;
|
|
position: relative;
|
|
}
|
|
.prose pre.code code {
|
|
font-family: var(--mono);
|
|
font-size: 0.815rem;
|
|
line-height: 1.7;
|
|
color: #CBD1DC;
|
|
background: none;
|
|
padding: 0;
|
|
white-space: pre;
|
|
}
|
|
.prose pre.code[data-lang]::after {
|
|
content: attr(data-lang);
|
|
position: absolute;
|
|
top: 0.5rem;
|
|
right: 0.7rem;
|
|
font-family: var(--mono);
|
|
font-size: 0.62rem;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--dim);
|
|
}
|
|
|
|
.prose :not(pre) > code {
|
|
font-family: var(--mono);
|
|
font-size: 0.85em;
|
|
background: var(--surface-2);
|
|
border: 1px solid var(--line);
|
|
color: #D8DCE4;
|
|
padding: 0.08em 0.36em;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.tablewrap { overflow-x: auto; margin: 0 0 1.4rem; }
|
|
.prose table { border-collapse: collapse; width: 100%; font-size: 0.9rem; }
|
|
.prose th, .prose td {
|
|
text-align: left;
|
|
padding: 0.55rem 0.85rem;
|
|
border-bottom: 1px solid var(--line);
|
|
vertical-align: top;
|
|
}
|
|
.prose th {
|
|
font-family: var(--mono);
|
|
font-size: 0.72rem;
|
|
letter-spacing: 0.07em;
|
|
text-transform: uppercase;
|
|
color: var(--accent);
|
|
border-bottom-color: var(--accent-dim);
|
|
white-space: nowrap;
|
|
}
|
|
.prose td { color: #C6CAD3; }
|
|
.prose tbody tr:hover td { background: var(--surface); }
|
|
|
|
.prose img { max-width: 100%; height: auto; }
|
|
|
|
.top nav a.on { color: var(--fg); }
|
|
|
|
.readerlink { margin-top: 2rem; }
|
|
|
|
/* A footer note that is a paragraph rather than a credit line. Same width
|
|
discipline as body text: these are read, not scanned. */
|
|
footer .note {
|
|
flex-basis: 100%;
|
|
max-width: 54rem;
|
|
color: var(--dim);
|
|
font-size: 0.82rem;
|
|
line-height: 1.7;
|
|
}
|
|
footer .note b { color: var(--fg); font-weight: 700; }
|
|
footer .note a { color: var(--accent); }
|
|
|
|
/* The two notes sit below the identity line, not beside it. */
|
|
footer .wrap { row-gap: 1.5rem; }
|
|
|
|
|
|
/* ---- the download page --------------------------------------------- */
|
|
/*
|
|
* Same components as the front page, arranged for a page with one job. The
|
|
* hero here is a two-column split rather than a pitch: the action on the left,
|
|
* and immediately beside it the thing a download page usually buries, which is
|
|
* what this has actually been run on.
|
|
*/
|
|
|
|
.getit .wrap { align-items: start; }
|
|
.getit h1 { font-size: clamp(2rem, 1.5rem + 2.4vw, 3.1rem); }
|
|
.getit p { color: var(--dim); }
|
|
|
|
h2.small {
|
|
font-size: clamp(1.15rem, 1rem + 0.6vw, 1.4rem);
|
|
letter-spacing: -0.01em;
|
|
margin: 0;
|
|
}
|
|
|
|
.getpanel {
|
|
background: var(--surface);
|
|
border: 1px solid var(--line);
|
|
border-radius: 6px;
|
|
padding: clamp(1.25rem, 3vw, 1.75rem);
|
|
}
|
|
.getpanel p { font-size: 0.92rem; margin: 0.85rem 0 0; }
|
|
|
|
/* Not a data table -- a two-column list of claims, where the claim on the
|
|
right is the whole content and should line up down the page. */
|
|
.support {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 1.25rem;
|
|
font-size: 0.9rem;
|
|
}
|
|
.support td { padding: 0.55rem 0; border-top: 1px solid var(--line); }
|
|
.support tr:first-child td { border-top: 0; }
|
|
.support td:last-child { text-align: right; white-space: nowrap; }
|
|
.dimtext { color: var(--dim); }
|
|
|
|
.getit .filemeta {
|
|
margin-top: 1.25rem;
|
|
font-family: var(--mono);
|
|
font-size: 0.78rem;
|
|
color: var(--dim);
|
|
}
|
|
.fineprint, .getpanel .fineprint, .card .fineprint {
|
|
color: var(--dim);
|
|
font-size: 0.82rem;
|
|
line-height: 1.65;
|
|
}
|
|
|
|
/* Two columns rather than as-many-as-fit: these two are a pair to be compared,
|
|
and a three-up row would put the destructive one somewhere it reads as an
|
|
equal option. */
|
|
.cards.two { grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr)); }
|
|
|
|
/* A command you are meant to type, as opposed to output you are meant to read
|
|
-- which is what .console is for. The prompt is dim because it is not part
|
|
of what you type, and the part to substitute is the accent, because that is
|
|
the only decision in the line. */
|
|
.cmd {
|
|
margin: 1.1rem 0 0;
|
|
padding: 0.8rem 0.9rem;
|
|
background: #090B0F;
|
|
border: 1px solid var(--line);
|
|
border-radius: 4px;
|
|
font-family: var(--mono);
|
|
font-size: 0.78rem;
|
|
line-height: 1.8;
|
|
color: var(--fg);
|
|
overflow-x: auto;
|
|
}
|
|
.cmd.block { margin-top: 2.5rem; font-size: 0.82rem; padding: 1.1rem 1.2rem; }
|
|
.cmd .p { color: var(--dim); user-select: none; }
|
|
.cmd .v { color: var(--accent); }
|
|
.cmd .c { color: var(--dim); }
|
|
|
|
/* The closing band on the front page. Same two-column shape as the crash
|
|
section, so the page ends the way it turns: a mark on the left, the thing to
|
|
do on the right. */
|
|
.getband { border-top: 1px solid var(--line); }
|
|
.getband .wrap {
|
|
display: grid;
|
|
grid-template-columns: clamp(5rem, 10vw, 8rem) minmax(0, 1fr);
|
|
gap: clamp(1.5rem, 4vw, 3rem);
|
|
align-items: center;
|
|
}
|
|
.getband img { width: 100%; height: auto; display: block; }
|
|
.getband .readerlink { display: flex; flex-wrap: wrap; gap: 0.75rem; }
|
|
@media (max-width: 40rem) {
|
|
.getband .wrap { grid-template-columns: 1fr; }
|
|
.getband img { width: 5rem; }
|
|
}
|