Files
libretro/website/src/styles/retrobios.css
T
Abdessamad Derraz fda6845289 refactor: show diagrams as themed SVG images
An inline SVG put every label of both layouts, its title and its desc
into the page text, next to the prose that already says the steps: a
text dump of the Steam Deck tab read the steps three times, glued.
Each drawing is now one SVG file per layout and theme under
assets/diagrams, shown through <picture> with alt="". The figure says
its words once, in one screen-reader line and its caption.
2026-11-10 14:11:47 +01:00

1063 lines
41 KiB
CSS

/* RetroBIOS on top of Starlight.
Starlight's dark theme is :root and its light theme
:root[data-theme='light']. Colour pairs are the ones measured for WCAG AA
on the previous site, in both themes.
Classes the generator and the wiki pages use:
.rb-lead first paragraph under a page title
.rb-level-* level label (start, setup, explore, reference, contribute)
.rb-cards, .rb-card card grid
.rb-steps ordered list drawn as numbered steps
.rb-button a link drawn as a button (.rb-button-primary: filled)
.rb-terminal wraps a code block that shows terminal output
.rb-cmd wraps a command that must wrap instead of scrolling
code.rb-path a folder path shown as a chip
.rb-figure a generated diagram (scripts/sitediagrams.py)
.rb-bar inline coverage bar, width from --v
.rb-details-* collapsible block, neutral unless caution or danger
dl.rb-facts the facts of a file card, label and value side by side
.rb-install-all the list of every command in a system's install box
.rb-copy the copy button site.ts adds after a hash
.rb-install-setup the setup list of a system's install box
abbr.rb-term a glossary term, its definition on hover or tap
*/
:root {
--sl-font: system-ui, -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif;
--sl-font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
--sl-color-accent-low: #1f2147;
--sl-color-accent: #aebcff;
--sl-color-accent-high: #c9d2ff;
--sl-color-text-accent: var(--sl-color-accent);
--sl-text-h1: 2.25rem;
--sl-text-h2: 1.5rem;
--sl-text-h3: 1.2rem;
--sl-text-h4: 1rem;
/* The width the page grid is placed from: the file card column. */
--rb-grid-width: 54rem;
--rb-link: #aebcff;
--rb-link-strong: #c9d2ff;
--rb-surface: #252838;
--rb-border: #3a3d52;
--rb-border-strong: #5a5e7a;
--rb-text-secondary: #a6adc8;
--rb-ok-fg: #a5d6a7;
--rb-ok-bg: #1b3a1f;
--rb-warn-fg: #ffcc80;
--rb-warn-bg: #7a2e00;
--rb-err-fg: #ef9a9a;
--rb-err-bg: #7f1414;
--rb-info-fg: #90caf9;
--rb-info-bg: #0d2a55;
--rb-muted-fg: #cfd8dc;
--rb-muted-bg: #37474f;
--rb-level-start: #a5d6a7;
--rb-level-setup: #90caf9;
--rb-level-explore: #ce93d8;
--rb-level-reference: #cfd8dc;
--rb-level-contribute: #ffcc80;
--rb-terminal-bg: #12131c;
--rb-terminal-fg: #e6e6f0;
--rb-terminal-label: #9aa0c3;
--rb-diagram-fill: #252838;
--rb-diagram-stroke: #7c82a3;
--rb-diagram-accent: #aebcff;
--rb-select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23a6adc8' stroke-width='1.6'/%3E%3C/svg%3E");
}
:root[data-theme='light'] {
--sl-color-accent-low: #e3e5f6;
--sl-color-accent: #273c8f;
--sl-color-accent-high: #1d2f73;
--sl-color-text-accent: var(--sl-color-accent);
--rb-link: #273c8f;
--rb-link-strong: #1d2f73;
--rb-surface: #f5f6fa;
--rb-border: #e0e3eb;
--rb-border-strong: #b8bdcc;
--rb-text-secondary: #546e7a;
--rb-ok-fg: #1b5e20;
--rb-ok-bg: #e8f5e9;
--rb-warn-fg: #a33f00;
--rb-warn-bg: #fff3e0;
--rb-err-fg: #b71c1c;
--rb-err-bg: #ffebee;
--rb-info-fg: #0d47a1;
--rb-info-bg: #e3f2fd;
--rb-muted-fg: #455a64;
--rb-muted-bg: #eceff1;
--rb-level-start: #1b5e20;
--rb-level-setup: #0d47a1;
--rb-level-explore: #6a1b9a;
--rb-level-reference: #455a64;
--rb-level-contribute: #a33f00;
--rb-terminal-bg: #1b1d2e;
--rb-diagram-fill: #f5f6fa;
--rb-diagram-stroke: #8c92ac;
--rb-diagram-accent: #3b3f7a;
--rb-select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23546e7a' stroke-width='1.6'/%3E%3C/svg%3E");
}
/* Links and focus */
.sl-markdown-content a:not(.rb-button):not(.rb-badge):not(.rb-permalink):not(.rb-download) {
color: var(--rb-link);
text-decoration-thickness: 0.08em;
text-underline-offset: 0.14em;
}
.sl-markdown-content a:not(.rb-button):hover { text-decoration-thickness: 0.14em; }
.sl-markdown-content a code { color: var(--rb-link); }
/* The ring is the link colour: red is kept for what is wrong. The offset
puts it on the page background, never on the fill it surrounds. */
:where(a, button, input, select, textarea, summary, abbr, [tabindex]):focus-visible {
outline: 2px solid var(--rb-link);
outline-offset: 2px;
}
/* Type scale: h2 two thirds of the h1, so a page of short blocks keeps
one title and its sections, not a column of headlines. */
.sl-markdown-content h2 { font-weight: 600; letter-spacing: -0.01em; }
.sl-markdown-content h3 { font-weight: 600; }
.sl-markdown-content :not(h1, h2, h3, h4, h5, h6, .sl-heading-wrapper) + :is(.sl-heading-wrapper.level-h2, h2) { margin-top: 2.75rem; }
.sl-markdown-content :not(h1, h2, h3, h4, h5, h6, .sl-heading-wrapper) + :is(.sl-heading-wrapper.level-h3, h3:not(.rb-file-title)) { margin-top: 1.75rem; }
/* A row of buttons right under a heading does not touch it. */
.sl-markdown-content .sl-heading-wrapper:has(+ .rb-button) { margin-bottom: 0.5rem; }
.sl-markdown-content .rb-lead { font-size: 1.05em; line-height: 1.55; max-width: 44em; }
/* Breadcrumbs above the title */
.rb-breadcrumbs ol {
display: flex;
flex-wrap: wrap;
gap: 0.15rem 0;
margin: 0 0 0.4rem;
padding: 0;
list-style: none;
font-size: var(--sl-text-sm);
color: var(--rb-text-secondary);
}
/* The separator stays with the crumb after it: a long label wraps inside
its own box, never leaving the "/" alone at a line end. */
.rb-breadcrumbs li { white-space: nowrap; }
.rb-breadcrumbs li > :is(a, span) { white-space: normal; }
.rb-breadcrumbs li + li::before { content: '/'; padding: 0 0.45rem; color: var(--rb-border-strong); }
.rb-breadcrumbs a {
display: inline-block;
min-height: 24px;
line-height: 24px;
color: var(--rb-text-secondary);
text-decoration: none;
}
.rb-breadcrumbs a:hover { color: var(--rb-link); text-decoration: underline; }
/* Level label above a title */
.rb-level {
display: inline-block;
margin: 0 0 0.5rem;
padding: 0.05rem 0.45rem;
border: 1px solid currentColor;
border-radius: 2px;
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.01em;
line-height: 1.6;
color: var(--rb-level-reference);
}
.rb-level-start { color: var(--rb-level-start); }
.rb-level-setup { color: var(--rb-level-setup); }
.rb-level-explore { color: var(--rb-level-explore); }
.rb-level-reference { color: var(--rb-level-reference); }
.rb-level-contribute { color: var(--rb-level-contribute); }
/* Buttons */
.sl-markdown-content .rb-button {
display: inline-flex;
align-items: center;
min-height: 44px;
padding: 0.5rem 1.1rem;
margin: 0.25rem 0.4rem 0.25rem 0;
border: 2px solid var(--rb-link);
border-radius: 4px;
color: var(--rb-link);
font-weight: 600;
text-decoration: none;
}
.sl-markdown-content .rb-button-primary { background: var(--rb-link); color: var(--sl-color-black); }
.sl-markdown-content .rb-button:hover { background: var(--sl-color-accent-low); }
.sl-markdown-content .rb-button-primary:hover {
background: var(--rb-link-strong);
border-color: var(--rb-link-strong);
}
.sl-markdown-content table .rb-button { font-size: 0.8rem; padding: 0.4rem 0.8rem; }
/* Starlight spaces blocks only after a block: the line under a button sat
4 px below it. */
.sl-markdown-content :is(.rb-button, p:has(> .rb-button)) + p { margin-top: 1rem; }
/* A search keyword marker between two blocks is inline and empty: the block
after it kept no gap ("iPhone and iPad" touched its first line). */
.sl-markdown-content span[data-pagefind-meta]:empty + :is(p, ul, ol, table, div) { margin-top: var(--sl-content-gap-y); }
/* Badges */
.rb-badge {
display: inline-block;
padding: 0 0.4em;
border-radius: 2px;
font-size: 0.75rem;
font-weight: 600;
line-height: 1.6;
white-space: nowrap;
}
.rb-badge-success { background: var(--rb-ok-bg); color: var(--rb-ok-fg); }
.rb-badge-warning { background: var(--rb-warn-bg); color: var(--rb-warn-fg); }
.rb-badge-danger { background: var(--rb-err-bg); color: var(--rb-err-fg); }
.rb-badge-info { background: var(--rb-info-bg); color: var(--rb-info-fg); }
.rb-badge-muted { background: var(--rb-muted-bg); color: var(--rb-muted-fg); }
.sl-markdown-content .rb-badge a,
.sl-markdown-content a.rb-badge { color: inherit; }
/* A badge link sits in a dense list: it keeps a 24 px target (WCAG 2.5.8). */
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) li:has(.rb-badge a) { min-height: 24px; line-height: 24px; }
.sl-markdown-content .rb-badge a { display: inline-block; min-width: 24px; line-height: 24px; text-align: center; }
/* Headline figures */
.rb-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
gap: 0.6rem 1rem;
margin: 1rem 0 1.5rem;
padding: 0.8rem 1rem;
border: 1px solid var(--rb-border);
border-radius: 4px;
background: var(--rb-surface);
}
.sl-markdown-content .rb-stats > *,
.sl-markdown-content .rb-stat > * { margin: 0; }
.rb-stat-value { display: block; font-size: 1.25rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.rb-stat-label { display: block; font-size: 0.75rem; color: var(--rb-text-secondary); }
.sl-markdown-content img[src*='assets/logos/'] { padding: 2px; border-radius: 2px; background: #fff; }
/* A system icon beside a console heading holds its box before it loads:
it pushed every card below it down once it arrived. */
.sl-markdown-content :is(h2, h3) img {
display: inline;
width: 24px;
height: 24px;
object-fit: contain;
vertical-align: middle;
margin: 0 0.4rem 0 0;
}
/* Card grids */
.rb-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
gap: 0.8rem;
margin: 1rem 0 1.5rem;
}
.sl-markdown-content .rb-cards > .rb-card {
display: flex;
flex-direction: column;
gap: 0.35rem;
margin: 0;
padding: 0.8rem;
border: 1px solid var(--rb-border);
border-radius: 4px;
background: var(--sl-color-bg);
}
.rb-card:is(:hover, :focus-within) { border-color: var(--rb-border-strong); }
.sl-markdown-content .rb-card > * { margin: 0; }
.sl-markdown-content .rb-card .rb-button { margin-top: auto; align-self: flex-start; }
.sl-markdown-content .rb-card-logo {
width: 40px;
height: 40px;
object-fit: contain;
padding: 4px;
border: 1px solid var(--rb-border);
border-radius: 4px;
background: #fff;
vertical-align: middle;
}
/* Device tiles: the whole tile is the link. Logo on the left, name over
what it runs on, so a phone shows a short row per setup. */
.sl-markdown-content .rb-tiles { grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.6rem; }
.sl-markdown-content .rb-cards > a.rb-tile {
display: grid;
grid-template-columns: 40px 1fr;
grid-template-rows: auto auto;
column-gap: 0.75rem;
row-gap: 0.1rem;
align-items: center;
align-content: center;
padding: 0.6rem 0.75rem;
color: var(--sl-color-white);
text-decoration: none;
}
.sl-markdown-content a.rb-tile .rb-card-logo { grid-row: 1 / span 2; }
.sl-markdown-content a.rb-tile .rb-tile-name { color: var(--sl-color-text-accent); font-weight: 600; line-height: 1.3; }
.sl-markdown-content a.rb-tile .rb-tile-runs { color: var(--sl-color-gray-3); font-size: var(--sl-text-sm); line-height: 1.35; }
.sl-markdown-content a.rb-tile:hover .rb-tile-name { text-decoration: underline; }
/* Numbered steps */
.sl-markdown-content .rb-steps > ol {
counter-reset: rb-step;
list-style: none;
padding-left: 0;
}
.sl-markdown-content .rb-steps > ol > li {
counter-increment: rb-step;
position: relative;
margin: 0 0 1.2rem;
padding-left: 2.6rem;
min-height: 1.8rem;
}
.sl-markdown-content .rb-steps > ol > li::before {
content: counter(rb-step);
position: absolute;
top: 0;
left: 0;
width: 1.8rem;
height: 1.8rem;
border-radius: 4px;
background: var(--rb-link);
color: var(--sl-color-black);
font-weight: 700;
line-height: 1.8rem;
text-align: center;
}
/* Path chip */
.sl-markdown-content code.rb-path {
padding: 0.15rem 0.45rem;
border: 1px solid var(--rb-border);
border-radius: 2px;
font-size: 0.8em;
overflow-wrap: anywhere;
}
/* Inline coverage bar beside a number */
.rb-bar {
display: inline-block;
width: 5rem;
height: 0.4rem;
margin-right: 0.4rem;
border-radius: 2px;
background: var(--rb-border);
vertical-align: middle;
}
.rb-bar > span { display: block; width: var(--v, 0%); height: 100%; border-radius: 2px; background: var(--rb-ok-fg); }
/* Tables */
.sl-markdown-content table { font-variant-numeric: tabular-nums; }
.sl-markdown-content table th { font-weight: 600; }
.sl-markdown-content table[role='region']:focus-visible { outline: 2px solid var(--rb-link); outline-offset: 2px; }
/* A long path in a cell breaks to fit its column, at a separator where it
can: the installer's detection tables and Cemu's file list pushed their
last column past the page at 1440 px. A last column of such paths keeps
room to read. */
.sl-markdown-content table td code:not(.rb-short) { overflow-wrap: anywhere; }
@media (min-width: 50rem) {
.sl-markdown-content table:not([data-rb-stack='kv']) td:last-child:not(:first-child):has(code:not(.rb-short)) { min-width: 9rem; }
}
/* A hash in a table cell is its first 12 characters, the full value in the
title: one line, dotted to say there is more on hover. */
.sl-markdown-content td code[title] {
white-space: nowrap;
text-decoration: underline dotted;
text-underline-offset: 0.2em;
cursor: help;
}
@media (min-width: 50rem) {
/* The reason a file is listed reads as a sentence, not a word per line. */
.sl-markdown-content :is(td.rb-reason, td[data-label='Reason'], td:has(> .rb-reason)) { min-width: 12rem; }
/* Get your files: every group table shares one set of columns. */
.sl-markdown-content table:has(td[data-label='Runs on']):has(td[data-label='ZIP']) {
display: table;
table-layout: fixed;
width: 100%;
}
.sl-markdown-content table:has(td[data-label='Runs on']):has(td[data-label='ZIP']) th:nth-child(1) { width: 18%; }
.sl-markdown-content table:has(td[data-label='Runs on']):has(td[data-label='ZIP']) th:nth-child(2) { width: 20%; }
.sl-markdown-content table:has(td[data-label='Runs on']):has(td[data-label='ZIP']) th:nth-child(3) { width: 40%; }
.sl-markdown-content table:has(td[data-label='Runs on']):has(td[data-label='ZIP']) th:nth-child(4) { width: 22%; }
.sl-markdown-content table:has(td[data-label='Runs on']):has(td[data-label='ZIP']) td { overflow-wrap: break-word; }
}
/* A ZIP part link or button never breaks across two lines. */
.sl-markdown-content table:has(td[data-label='Runs on']):has(td[data-label='ZIP']) td:last-child :is(a, .rb-button) { white-space: nowrap; }
/* Key and value cards: the empty header row is not drawn */
.rb-meta-card thead,
.sl-markdown-content table thead:not(:has(th:not(:empty))) { display: none; }
/* Fixed layout: the label column keeps its share and a value wraps between
words. Only code and long addresses break inside a word. */
.sl-markdown-content .rb-meta-card table { display: table; table-layout: fixed; width: 100%; }
.rb-meta-card td { overflow-wrap: break-word; }
.rb-meta-card td code { overflow-wrap: anywhere; }
.rb-meta-card td a { word-break: normal; }
.rb-meta-card td:first-child { font-weight: 600; color: var(--rb-text-secondary); width: 11rem; }
/* Cross-reference by upstream, the last table of its page: the address
column wraps instead of pushing the cores and platforms off screen. */
.sl-markdown-content .sl-heading-wrapper:has(> #by-upstream-emulator) ~ section td:has(a[href^='http']) {
max-width: 22rem;
overflow-wrap: anywhere;
}
/* Beside the column, the five columns share its width: at 1440 px the
Platforms column sat 100 px past the edge. */
@media (min-width: 50rem) {
.sl-markdown-content .sl-heading-wrapper:has(> #by-upstream-emulator) ~ section table {
display: table;
table-layout: fixed;
width: 100%;
}
.sl-markdown-content .sl-heading-wrapper:has(> #by-upstream-emulator) ~ section td {
overflow-wrap: anywhere;
}
.sl-markdown-content .sl-heading-wrapper:has(> #by-upstream-emulator) ~ section th:nth-child(1) { width: 25%; }
.sl-markdown-content .sl-heading-wrapper:has(> #by-upstream-emulator) ~ section th:nth-child(2) { width: 26%; }
.sl-markdown-content .sl-heading-wrapper:has(> #by-upstream-emulator) ~ section th:nth-child(3) { width: 15%; }
.sl-markdown-content .sl-heading-wrapper:has(> #by-upstream-emulator) ~ section th:nth-child(4) { width: 20%; }
.sl-markdown-content .sl-heading-wrapper:has(> #by-upstream-emulator) ~ section th:nth-child(5) { width: 14%; }
}
/* The id a platform writes for a system, beside the name in its heading:
smaller and quieter than the name, set as code. */
.sl-markdown-content :is(h2, h3) small {
margin-left: 0.4em;
font-family: var(--sl-font-mono);
font-size: 0.65em;
font-weight: 400;
color: var(--rb-text-secondary);
overflow-wrap: anywhere;
}
.rb-timestamp {
font-size: 0.8rem;
color: var(--rb-text-secondary);
margin-top: 2rem;
padding-top: 1rem;
border-top: 1px solid var(--rb-border);
}
/* File cards on system and emulator pages. A page holds hundreds: those
off screen are laid out when they come near, and the column is wide
enough for a sha256 on one line. */
body:has(.rb-sys-file, .rb-file-entry) { --sl-content-width: var(--rb-grid-width); }
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) {
border-top: 1px solid var(--rb-border);
padding: 0.75rem 0 0.25rem;
content-visibility: auto;
contain-intrinsic-size: auto 320px;
}
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) > :first-child { margin-top: 0; }
.sl-markdown-content .rb-file-title {
margin: 0 0 0.3rem;
font-size: 1rem;
font-weight: 400;
letter-spacing: normal;
scroll-margin-top: 5rem;
}
.sl-markdown-content .rb-file-title code { font-weight: 700; }
.sl-markdown-content .rb-search-skip > ul { margin-top: 0.1rem; }
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) ul {
margin: 0.3rem 0 0;
padding-left: 1.2rem;
font-size: 0.85rem;
}
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) li { margin: 0.1rem 0; }
.rb-hash {
font-family: var(--sl-font-mono);
font-size: 0.8125rem;
color: var(--rb-text-secondary);
overflow-wrap: anywhere;
}
.rb-hash code { background: none; padding: 0; overflow-wrap: anywhere; }
.rb-permalink {
display: inline-flex;
align-items: center;
min-height: 24px;
margin-left: 0.4rem;
font-size: 0.75rem;
color: var(--rb-text-secondary);
text-decoration: none;
opacity: 0;
}
:is(.rb-sys-file, .rb-file-entry):hover .rb-permalink,
.rb-permalink:focus { opacity: 1; }
/* No hover on a touch screen: the link is always shown there. */
@media (hover: none) {
.rb-permalink { opacity: 1; }
}
.rb-download {
display: inline-flex;
align-items: center;
min-height: 32px;
margin-left: 0.5rem;
padding: 0.15rem 0.7rem;
border: 1px solid var(--rb-link);
border-radius: 4px;
font-size: 0.8rem;
font-weight: 600;
color: var(--rb-link);
text-decoration: none;
vertical-align: middle;
}
.rb-download:hover { background: var(--sl-color-accent-low); }
/* The download beside a "Start with" file (site.ts startDownloads): the
card's button, at the size of the line it sits in. */
.sl-markdown-content a.rb-start-download {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 0.6rem;
border: 1px solid var(--rb-link);
border-radius: 4px;
font-size: 0.8em;
font-weight: 600;
color: var(--rb-link);
text-decoration: none;
}
.sl-markdown-content a.rb-start-download:hover { background: var(--sl-color-accent-low); }
/* The facts of a file card: label column, value column, one column on a phone. */
.sl-markdown-content dl.rb-facts {
display: grid;
grid-template-columns: 11rem minmax(0, 1fr);
gap: 0.2rem 1rem;
margin: 0.4rem 0 0;
font-size: 0.85rem;
}
.sl-markdown-content .rb-facts :is(dt, dd) { margin: 0; padding: 0; }
.sl-markdown-content .rb-facts dt { font-size: 0.8rem; font-weight: 400; color: var(--rb-text-secondary); }
.sl-markdown-content .rb-facts dd { min-width: 0; min-height: 24px; overflow-wrap: break-word; line-height: 24px; }
/* A lone link in a card value is a 24 px target too (WCAG 2.5.8). */
.sl-markdown-content .rb-facts dd > a { display: inline-block; min-height: 24px; }
/* A badge link in a card keeps a 24 px target, rows 4 px apart (WCAG 2.5.8). */
.sl-markdown-content .rb-facts :is(.rb-badge:has(> a), a.rb-badge) {
display: inline-flex;
align-items: center;
min-height: 24px;
margin-block: 2px;
vertical-align: middle;
}
.sl-markdown-content .rb-facts code { overflow-wrap: anywhere; }
@media (max-width: 30rem) {
.sl-markdown-content dl.rb-facts { grid-template-columns: minmax(0, 1fr); gap: 0; }
.sl-markdown-content .rb-facts dd + dt { margin-top: 0.4rem; }
}
:is(.rb-sys-file, .rb-file-entry):has(> .rb-file-title:target) { background: var(--rb-surface); }
/* Entries as table rows (scripts/siteentries.py): the name takes the room
and its card opens under it. On a phone the row stacks like any table
with a hash column, the name on the full width. */
body:has(table.rb-entries) { --sl-content-width: var(--rb-grid-width); }
/* A row the filter leaves out stays out on a phone, where a stacked row is
a block: `display: block` outweighed the hidden attribute, and every
stacked table showed all its rows under "11 of 1,037 rows". */
.sl-markdown-content table[data-rb-stack] tr[hidden] { display: none; }
@media (min-width: 50rem) {
.sl-markdown-content table.rb-wanted td.rb-hash { min-width: 10rem; }
}
.sl-markdown-content .rb-entries-wrap { container-type: inline-size; }
.sl-markdown-content table.rb-entries { width: 100%; }
@media (min-width: 50rem) {
.sl-markdown-content table.rb-entries { display: table; }
.sl-markdown-content table.rb-entries td:first-child { width: 100%; }
/* An open card takes the table's width, not its column's: the other
cells of its row keep to one line, so the room under them is free. */
.sl-markdown-content table.rb-entries tr:has(> td > details[open]) > td:not(:first-child) { white-space: nowrap; }
.sl-markdown-content details.rb-entry[open] { contain: inline-size; }
.sl-markdown-content details.rb-entry[open] > :not(summary) { width: 100cqi; }
}
.sl-markdown-content details.rb-entry { border: 0; padding: 0; }
.sl-markdown-content details.rb-entry > summary { min-height: 24px; font-weight: 400; }
.sl-markdown-content details.rb-entry > summary > .rb-file-title { display: inline; margin: 0; }
.sl-markdown-content details.rb-entry[open] > summary { margin-bottom: 0.4rem; }
.sl-markdown-content details.rb-entry ul { margin: 0.3rem 0 0; padding-left: 1.2rem; font-size: 0.85rem; }
.sl-markdown-content details.rb-entry li { margin: 0.1rem 0; }
.sl-markdown-content details.rb-entry:has(.rb-file-title:target) { background: var(--rb-surface); }
@media (max-width: 50rem) {
.sl-markdown-content table.rb-entries td:first-child { padding-left: 0.6rem; font-size: 1rem; }
.sl-markdown-content table.rb-entries td:first-child::before { content: none; }
/* "required for Data East DECO Cassette System" ran 12 px past a phone
beside its label: a long badge wraps in its cell. */
.sl-markdown-content table.rb-entries .rb-badge { white-space: normal; }
.sl-markdown-content details.rb-entry ul { font-size: 0.75rem; }
}
/* A fold of a file card (Hashes, the rest): no frame, a small summary in
the muted colour, a 24 px target (WCAG 2.5.8). */
.sl-markdown-content :is(:is(.rb-sys-file, .rb-file-entry) details, details.rb-install-all) { margin: 0.3rem 0 0; padding: 0; border: 0; font-size: 0.85rem; }
.sl-markdown-content :is(:is(.rb-sys-file, .rb-file-entry) details, details.rb-install-all) > summary {
min-height: 24px;
line-height: 24px;
font-size: 0.8rem;
color: var(--rb-text-secondary);
cursor: pointer;
}
.sl-markdown-content :is(:is(.rb-sys-file, .rb-file-entry) details, details.rb-install-all) > summary::before { background-color: var(--rb-text-secondary); }
.sl-markdown-content :is(:is(.rb-sys-file, .rb-file-entry) details, details.rb-install-all) > summary:hover { color: var(--sl-color-white); }
.sl-markdown-content :is(:is(.rb-sys-file, .rb-file-entry) details, details.rb-install-all) > :not(summary) { margin-top: 0.2rem; }
/* The copy button after a hash (site.ts): the Download button's frame,
smaller, a 24 px target that stays inside a 24 px line, so it never
covers the fold below it (WCAG 2.5.8). */
.rb-copy {
display: inline-flex;
align-items: center;
box-sizing: border-box;
height: 24px;
margin-left: 0.4rem;
padding: 0 0.5rem;
border: 1px solid var(--rb-border-strong);
border-radius: 4px;
background: transparent;
font: inherit;
font-family: var(--sl-font);
font-size: 0.75rem;
line-height: 1;
color: var(--rb-link);
vertical-align: top;
cursor: pointer;
}
.rb-copy:hover { background: var(--sl-color-accent-low); }
/* A system's install box: the setup list above the OS tabs, and the list
of every command, which wraps anywhere rather than scroll a phone. */
.sl-markdown-content .rb-install-all code { overflow-wrap: anywhere; }
.sl-markdown-content .rb-install-setup { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; font-size: 0.9rem; }
/* Its select is styled as every other choice list on the site (the
arrow of --rb-select-arrow, below): a rule of its own hid the arrow. */
/* Collapsible blocks are quiet: a closed block must not outweigh the
command it explains. Colour is kept for caution and danger. */
.sl-markdown-content details.rb-details {
border: 1px solid var(--rb-border);
border-radius: 4px;
background: transparent;
padding: 0.6rem 1rem;
}
.sl-markdown-content details.rb-details:not(.rb-details-caution, .rb-details-danger):has(> summary:hover) { border-color: var(--rb-border-strong); }
.sl-markdown-content details.rb-details-caution { border-color: var(--sl-color-orange); background: var(--sl-color-orange-low); }
.sl-markdown-content details.rb-details-danger { border-color: var(--sl-color-red); background: var(--sl-color-red-low); }
.sl-markdown-content details.rb-details > summary {
min-height: 24px;
font-size: 0.95rem;
font-weight: 600;
cursor: pointer;
}
/* Starlight's chevron, which turns when the block opens, in the muted colour. */
.sl-markdown-content details.rb-details > summary::before { background-color: var(--rb-text-secondary); }
.sl-markdown-content details.rb-details[open] > summary { margin-bottom: 0.6rem; }
/* A platform's file list (generate_site._platform_file_list): each row
a details whose summary is the
row (name, folder, status), its body the evidence across the whole
list. The short hash sits on its copy button (site.ts) beside the
summary, since a summary is itself a control. The details reaches under
the button column, so the row rule and an opened body run full width. */
.sl-markdown-content .rb-files {
--rb-hash-column: 6.75rem;
display: grid;
grid-template-columns: minmax(0, 1fr) var(--rb-hash-column);
margin-top: 0.75rem;
border-top: 1px solid var(--rb-border-strong);
}
.sl-markdown-content .rb-files > * { margin: 0; }
.sl-markdown-content .rb-files > details.rb-file {
grid-column: 1;
margin-right: calc(-1 * var(--rb-hash-column));
padding: 0 0 0 1.75rem;
border: 0;
border-bottom: 1px solid var(--rb-border);
font-size: 0.8125rem;
line-height: 1.5;
overflow-wrap: anywhere;
}
.sl-markdown-content .rb-files > details.rb-file[open] { padding-bottom: 0.6rem; background: var(--rb-surface); }
.sl-markdown-content .rb-files > details.rb-file > summary {
display: grid;
grid-template-columns: 1.25rem minmax(0, 1fr) 9rem 6rem;
gap: 0.5rem;
align-items: center;
min-height: 2.25rem;
margin-left: -1.75rem;
padding: 0.3rem calc(var(--rb-hash-column) + 0.5rem) 0.3rem 0;
font: 0.8125rem/1.4 var(--sl-font-mono);
cursor: pointer;
}
.sl-markdown-content .rb-files:not(.rb-files-path) > details.rb-file > summary { grid-template-columns: 1.25rem minmax(0, 1fr) 6rem; }
.sl-markdown-content .rb-files > details.rb-file > summary:hover { background: var(--rb-surface); }
.sl-markdown-content .rb-files > details.rb-file > summary::before { margin: 0; background-color: var(--rb-text-secondary); }
.sl-markdown-content .rb-files > details.rb-file > summary > code { grid-column: 3; padding: 0; background: none; color: var(--rb-text-secondary); }
.sl-markdown-content .rb-files > details.rb-file > summary > .rb-badge { grid-column: -2; justify-self: start; font-family: var(--sl-font); }
.sl-markdown-content .rb-files > button.rb-copy {
position: relative;
grid-column: 2;
align-self: start;
justify-self: start;
margin-top: 0.4rem;
}
.sl-markdown-content .rb-files > [hidden] { display: none; }
.sl-markdown-content .rb-files button.rb-copy {
display: inline-flex;
align-items: center;
gap: 0.3em;
min-height: 24px;
padding: 0 0.35em;
border: 1px solid var(--rb-border-strong);
border-radius: 3px;
background: var(--sl-color-bg);
color: var(--sl-color-white);
font: 0.8125rem/1.4 var(--sl-font-mono);
cursor: pointer;
white-space: nowrap;
}
.sl-markdown-content .rb-files button.rb-copy::after {
content: '';
width: 0.9em;
height: 0.9em;
background: var(--rb-text-secondary);
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5 1h8a2 2 0 0 1 2 2v8h-2V3H5zM3 5h7a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2zm0 2v7h7V7z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.sl-markdown-content .rb-files button.rb-copy[data-copied]::after {
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 11.2 2.8 8 1.4 9.4 6 14l8.6-8.6-1.4-1.4z'/%3E%3C/svg%3E");
background: var(--rb-ok-fg);
}
.sl-markdown-content .rb-files button.rb-copy:hover { border-color: var(--rb-link); }
@media (max-width: 50rem) {
/* On a phone the folder goes under the name, the status stays on the
first line. A row with no folder prints nothing for it. */
.sl-markdown-content .rb-files > details.rb-file > summary,
.sl-markdown-content .rb-files:not(.rb-files-path) > details.rb-file > summary {
grid-template-columns: 1.25rem minmax(0, 1fr) auto;
row-gap: 0.1rem;
}
.sl-markdown-content .rb-files > details.rb-file > summary::before { grid-row: 1; }
.sl-markdown-content .rb-files > details.rb-file > summary > code { grid-column: 2; grid-row: 2; }
.sl-markdown-content .rb-files > details.rb-file > summary > .rb-badge { grid-column: 3; grid-row: 1; }
}
/* Asides: a neutral box for notes and tips, no side stripe, no icon.
Caution and danger keep their colour, as a 1 px border all round. */
.sl-markdown-content .starlight-aside {
border: 1px solid var(--sl-color-asides-border);
border-radius: 4px;
}
.sl-markdown-content .starlight-aside:is(.starlight-aside--note, .starlight-aside--tip) {
--sl-color-asides-border: var(--rb-border);
--sl-color-asides-text-accent: var(--sl-color-white);
background: var(--rb-surface);
}
.sl-markdown-content .starlight-aside:is(.starlight-aside--note, .starlight-aside--tip) .starlight-aside__icon { display: none; }
/* Terminal output: what the screen shows, not something to type */
.sl-markdown-content .rb-terminal .expressive-code pre { background: var(--rb-terminal-bg); color: var(--rb-terminal-fg); }
/* Diagrams written by scripts/sitediagrams.py follow the theme: each is an
image per theme (its colours written in the file, sitediagrams.THEMES),
and the one of the other theme is not shown, so not fetched either.
Starlight's dark theme is the one without data-theme='light'. */
.sl-markdown-content .rb-figure { margin: 1.2rem 0 1.6rem; }
.sl-markdown-content .rb-figure .rb-diagram { display: block; max-width: 52rem; }
.sl-markdown-content .rb-figure .rb-diagram img { display: block; width: 100%; height: auto; }
.sl-markdown-content .rb-figure .rb-diagram-light { display: none; }
:root[data-theme='light'] .sl-markdown-content .rb-figure .rb-diagram-light { display: block; }
:root[data-theme='light'] .sl-markdown-content .rb-figure .rb-diagram-dark { display: none; }
.sl-markdown-content .rb-figure :is(figcaption, .rb-figure-caption) {
display: block;
max-width: 44em;
margin-top: 0.4rem;
font-size: 0.8rem;
color: var(--rb-text-secondary);
}
/* Glossary terms */
abbr.rb-term {
position: relative;
text-decoration: underline dotted;
text-underline-offset: 0.2em;
cursor: help;
}
abbr.rb-term[data-open]::after {
content: attr(data-definition);
position: absolute;
z-index: 10;
top: calc(100% + 0.3rem);
left: 0;
width: max-content;
max-width: min(20rem, 80vw);
padding: 0.4rem 0.6rem;
border: 1px solid var(--rb-border-strong);
border-radius: 4px;
background: var(--sl-color-bg);
color: var(--sl-color-text);
font-size: 0.85rem;
font-weight: 400;
line-height: 1.4;
white-space: normal;
}
/* Inline code: a flag or a name of 30 characters or fewer (marked rb-short
at build time) never splits, longer code wraps at its spaces and keeps them. */
.sl-markdown-content :not(pre) > code { white-space: break-spaces; }
.sl-markdown-content :not(pre) > code.rb-short { white-space: pre; }
.sl-markdown-content table.rb-options td:first-child { white-space: nowrap; }
/* Forms: lookup, picker, table filters */
.rb-file-lookup,
.rb-picker fieldset {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
}
.sl-markdown-content :is(.rb-file-lookup, .rb-picker) :is(input, select, button) {
min-height: 44px;
padding: 0 0.6rem;
border: 1px solid var(--rb-border-strong);
border-radius: 4px;
background: var(--sl-color-bg);
color: var(--sl-color-text);
font: inherit;
}
.sl-markdown-content .rb-file-lookup input { flex: 1 1 20rem; font-family: var(--sl-font-mono); }
/* A choice list reads as the filter boxes do: their border, radius and
padding, and an arrow in the quiet text colour instead of the browser's. */
.sl-markdown-content :is(.rb-file-lookup, .rb-picker) select,
.sl-markdown-content select {
appearance: none;
min-width: min(100%, 16rem);
min-height: 44px;
padding: 0.55rem 2.25rem 0.55rem 0.75rem;
border: 1px solid var(--rb-text-secondary);
border-radius: 2px;
background: var(--sl-color-bg) var(--rb-select-arrow) no-repeat right 0.75rem center / 0.75rem;
color: var(--sl-color-text);
font: inherit;
cursor: pointer;
}
/* Both lookup labels, the hash and the file chooser, share one weight. */
.sl-markdown-content .rb-file-lookup label { font-weight: 600; }
.sl-markdown-content :is(.rb-file-lookup, .rb-picker) button {
background: var(--rb-link);
color: var(--sl-color-black);
font-weight: 600;
border: 0;
}
.rb-visually-hidden {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
border: 0 !important;
}
.rb-table-filter {
display: grid;
grid-template-columns: minmax(14rem, 28rem) auto;
gap: 0.35rem 0.8rem;
align-items: end;
margin: 1rem 0 0.45rem;
}
.sl-markdown-content .rb-table-filter > * { margin: 0; }
.rb-table-filter label { grid-column: 1 / -1; color: var(--rb-text-secondary); font-size: 0.78rem; font-weight: 700; }
.rb-table-filter input {
width: 100%;
min-height: 44px;
border: 1px solid var(--rb-text-secondary);
border-radius: 2px;
background: var(--sl-color-bg);
color: var(--sl-color-text);
padding: 0.55rem 0.75rem;
font: inherit;
}
.rb-table-filter-count { align-self: center; color: var(--rb-text-secondary); font-size: 0.8rem; white-space: nowrap; }
/* 404 */
.sl-markdown-content .rb-notfound-search {
display: inline-flex;
align-items: center;
min-height: 44px;
padding: 0.55em 1.2em;
border: 2px solid var(--rb-link);
border-radius: 4px;
background: none;
color: var(--rb-link);
font: inherit;
font-weight: 700;
cursor: pointer;
}
/* Search: a system page's file names rank it (its `files` meta field) but
are not printed under the result. */
site-search .pagefind-ui__result-tags { display: none; }
/* The site name keeps its size: Starlight sizes it from the h4 step. */
.site-title { font-size: var(--sl-text-xl); }
@media (min-width: 50rem) {
.site-title { font-size: var(--sl-text-2xl); }
}
/* Pagination and the phone menu button sit flat on the page. */
.pagination-links a { box-shadow: none; border-color: var(--rb-border); }
.pagination-links a:hover { border-color: var(--rb-border-strong); }
.pagination-links .link-title { font-size: 1.05rem; font-weight: 600; }
.sl-menu-button {
box-shadow: none;
border: 1px solid var(--rb-border);
background: transparent;
color: var(--sl-color-white);
}
.sl-menu-button:has(~ :popover-open) { box-shadow: none; background: var(--sl-color-accent-low); }
/* Sidebar: small grey group labels above 14 px links, top-level links as
large as the children, the current page on a tinted background with no
bar or rule beside it. */
#starlight__sidebar .top-level summary .large {
font-size: var(--sl-text-xs);
font-weight: 600;
color: var(--rb-text-secondary);
}
#starlight__sidebar .top-level a { font-size: var(--sl-text-sm); font-weight: 400; }
#starlight__sidebar .top-level a[aria-current='page'] {
background: var(--sl-color-accent-low);
color: var(--sl-color-accent-high);
font-weight: 600;
}
/* OS tabs wrap to a second row on a narrow phone: every tab stays on screen. */
starlight-tabs [role='tablist'] { flex-wrap: wrap; overflow-x: visible; row-gap: 0.25rem; }
starlight-tabs [role='tab'] { white-space: nowrap; }
/* One grid on every page. Starlight places the search box, the column and
"On this page" from --sl-content-width, which the file card pages widen:
crossing from a guide to a console moved all three by 12 px. They are
placed from one width instead, the widest column's. Every column starts
on the same edge, and a narrower one leaves the room on its right.
A page without "On this page" keeps the same places. */
:root[data-has-sidebar]:not([data-has-toc]) { --__toc-width: initial; }
@media (min-width: 50rem) {
:root[data-has-sidebar] header.header { --sl-content-width: var(--rb-grid-width); }
}
@media (min-width: 72rem) {
:root[data-has-sidebar] .right-sidebar-container {
width: max(
var(--sl-sidebar-width),
calc(var(--sl-sidebar-width) + (100% - var(--rb-grid-width) - var(--sl-sidebar-width)) / 2)
);
}
:root[data-has-sidebar] .main-pane {
--sl-content-margin-inline: max(0rem, 100% - var(--rb-grid-width)) auto;
order: 1;
width: min(
calc(100% - var(--sl-sidebar-width)),
calc(var(--rb-grid-width) + (100% - var(--rb-grid-width) - var(--sl-sidebar-width)) / 2)
);
}
}
/* Licence line under every page */
.rb-copyright { margin: 1.5rem 0 0; font-size: var(--sl-text-xs); color: var(--sl-color-gray-3); }
@media (max-width: 50rem) {
/* Tables with an action column become one block per row, so the button
is never behind a horizontal scroll (site.ts marks them). */
.sl-markdown-content table[data-rb-stack] { display: block; width: 100%; overflow: visible; }
.sl-markdown-content table[data-rb-stack] thead {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
}
.sl-markdown-content table[data-rb-stack] :is(tbody, tr) { display: block; }
.sl-markdown-content table[data-rb-stack] tr { padding: 0.3rem 0; border-top: 1px solid var(--rb-border); }
/* A cell holds its label as a float in its left padding: a label on two
lines pushes the row down instead of running into the next one. No
sibling margin between cells. Values start 7.1rem in, the column of
the shortest labels. A longer label takes what it needs up to 9rem and
its value starts after it on that line only. One line per cell at
0.875rem: a row of four short cells is 87 px, not 136. */
.sl-markdown-content table[data-rb-stack] td {
display: flow-root;
margin-top: 0;
padding: 0 0.6rem 0 7.1rem;
border: 0;
font-size: 0.875rem;
line-height: 1.35;
text-align: left !important;
overflow-wrap: anywhere;
}
.sl-markdown-content table[data-rb-stack] td::before {
content: attr(data-label);
position: static;
float: left;
width: max-content;
min-width: 6.5rem;
max-width: 9rem;
margin: 0 0.6rem 0 -7.1rem;
font-size: 0.8125rem;
font-weight: 600;
color: var(--rb-text-secondary);
}
.sl-markdown-content table[data-rb-stack] td:empty { display: none; }
/* A two-column table of labels and values: the label above, the value
on the full width under it. */
.sl-markdown-content table[data-rb-stack='kv'] td { padding: 0 0.6rem; font-size: 1rem; line-height: 1.5; }
.sl-markdown-content table[data-rb-stack='kv'] td::before { content: none; }
.sl-markdown-content table[data-rb-stack='kv'] td:first-child {
padding-bottom: 0.15rem;
font-size: 0.85rem;
font-weight: 600;
color: var(--rb-text-secondary);
}
/* A stacked value column is about 14rem wide: short code moves to the
next line whole, and splits only when it is wider than the column. */
.sl-markdown-content table[data-rb-stack] td code.rb-short {
display: inline-block;
max-width: 100%;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
/* On a phone every command wraps: the end of a one-liner is never
off-screen. A word is cut only when it cannot fit on a line. */
.sl-markdown-content .expressive-code pre > code { white-space: pre-wrap; }
.sl-markdown-content :is(.rb-sys-file, .rb-file-entry) ul { font-size: 0.75rem; }
}
@media (max-width: 50rem) {
:root { --sl-text-h1: 1.875rem; }
.rb-meta-card td:first-child { width: 40%; }
}
@media (max-width: 600px) {
.rb-table-filter { grid-template-columns: 1fr; }
.rb-table-filter label { grid-column: auto; }
.rb-stats { grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr)); }
.rb-stat-value { font-size: 1.1rem; }
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
}
}
/* Starlight sizes the header logo from --sl-nav-height, which also holds the
tab row from 50rem up. Size it from the top bar alone. */
@media (min-width: 50rem) {
header .site-title img { height: calc(4rem - 2 * var(--sl-nav-pad-y)); width: auto; }
}