mirror of
https://github.com/libretro/virtualjaguar-libretro.git
synced 2026-11-07 04:36:00 -10:00
Replaces the 2x2 hero mosaic with a sideways-scrolling strip of gameplay
frames (six visible on desktop, three on tablets, two on phones; scroll
snap, beveled scrollbar, Prev/Next buttons from gallery.js). Every card
opens in the gallery lightbox with the same red hover as the app page.
Twelve new captures from core 5d2ea0b8 at 2x internal resolution, true
colour and the Accurate blitter: Doom, Wolfenstein 3D, Missile Command 3D,
Atari Karts, Iron Soldier, Cybermorph, Super Burnout and Checkered Flag
from the headless harness with scripted input, and Tempest 2000, Raiden,
Defender 2000 and Ultra Vortek through crt-lottes, crt-aperture,
crt-easymode and crt-royale in the desktop app (slang-shaders e1d75632).
The four mosaic frames (Alien vs Predator, Iron Soldier, Skyhammer, Hover
Strike) stay as cards. WebP: 480px thumbnails, 960px full size.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
1097 lines
38 KiB
CSS
1097 lines
38 KiB
CSS
/* Virtual Jaguar libretro -- site stylesheet.
|
|
* Self-contained: no external fonts, JS, images or trackers. The site
|
|
* ships zero JavaScript; everything below is borders and gradients.
|
|
*
|
|
* DESIGN: "distribution disk, 1994". The page is a desktop; each section
|
|
* is a WINDOW with a striped title bar, hard 2px bevels and a solid drop
|
|
* shadow -- Windows 3.1 / GEM chrome, drawn with modern CSS. There is no
|
|
* border-radius anywhere except the face of the one CRT, and no soft glow
|
|
* anywhere at all: 1994 UI had hard edges and solid shadows, and bloom is
|
|
* a 2015 signifier wearing a period costume.
|
|
*
|
|
* The Jaguar's identity is black and red. Red is STRUCTURAL here -- title
|
|
* bars, rules, bevels, hazard stripes -- and never a glow. Three reds do
|
|
* three measured jobs (see --red-* below) so every red/text pair clears
|
|
* WCAG AA with room, instead of one brand red squeaking past at 4.5:1.
|
|
*
|
|
* DARK is primary (the console was a black box). LIGHT is not a fallback:
|
|
* it is the same bevel system rendered as a period desktop -- system gray,
|
|
* white highlights, near-white client areas. One theme per render.
|
|
*
|
|
* Type: exactly one display "shout" per page (the h1, condensed caps, the
|
|
* register Jaguar box art used). All chrome -- nav, title bars, tables,
|
|
* badges, numbers, captions -- is monospace, the readme/NFO register.
|
|
* Body prose is the system UI stack, because mono at length is fatiguing.
|
|
*
|
|
* Texture: a 2px dither checker on the header/footer bands and title bars
|
|
* (EGA-era 50% fill), and scanlines ONLY on the hero CRT. Scanlines never
|
|
* cross body text, and never cross an A/B measurement figure -- those PNGs
|
|
* are evidence, and the design frames them, it does not filter them.
|
|
*/
|
|
|
|
/* ---------------------------------------------------------------- tokens */
|
|
|
|
:root {
|
|
/* Surfaces: page (desktop) / window client area / inset well. */
|
|
--bg: #0b0b0e;
|
|
--panel: #16161b;
|
|
--well: #08080a;
|
|
--code-bg: #1e1e25;
|
|
|
|
--fg: #dcdce2;
|
|
--fg-dim: #9c9ca6; /* 6.6:1 on --panel */
|
|
|
|
/* Three reds, three jobs. Ratios measured against the surface each one
|
|
* actually sits on; none of them is asked to do a second job it fails. */
|
|
--red-bar: #7a0f0d; /* title-bar field; white text = 11.0:1 */
|
|
--red-fill: #c81a17; /* buttons and filled badges; white = 5.8:1 */
|
|
--red-rule: #e52521; /* borders, rules, hazard stripes; never text */
|
|
--red-link: #ff4438; /* link and accent TEXT; 5.3:1 on --panel */
|
|
--red-wash: rgba(229, 37, 33, 0.10);
|
|
|
|
/* Bevels. Themed, not hardcoded white/black: a highlight that reads on
|
|
* a black chassis disappears on a gray desktop. */
|
|
--bevel-hi: rgba(255, 255, 255, 0.16);
|
|
--bevel-lo: rgba(0, 0, 0, 0.80);
|
|
--line: #2b2b34;
|
|
--shadow: rgba(0, 0, 0, 0.55);
|
|
--dither: rgba(255, 255, 255, 0.045);
|
|
|
|
--good: #4ac26b; --good-bg: rgba(74, 194, 107, 0.12);
|
|
--warn: #e3b341; --warn-bg: rgba(227, 179, 65, 0.12);
|
|
--bad: #ff7b72; --bad-bg: rgba(255, 123, 114, 0.12);
|
|
|
|
/* Window width, not prose width. The compatibility matrices are 4-column
|
|
* and the hi-res diffs are three panels wide, so the frame has to be
|
|
* generous; readability is protected separately by holding p/ul/ol to
|
|
* 46rem inside it. */
|
|
--measure: 72rem;
|
|
/* Impact leads on purpose. It is the one condensed-heavy face actually
|
|
* present on essentially every Mac and Windows machine, and it is the
|
|
* register Jaguar box art shouted in. Putting anything ahead of it means
|
|
* the h1 lands on whatever narrow-but-light face happens to be installed
|
|
* and the one shout on the page comes out a whisper -- which is what the
|
|
* first cut of this stack did.
|
|
*
|
|
* The tail is the Linux path. On a host with none of these the h1 lands
|
|
* on the default sans; `font-stretch: condensed` on h1 asks a variable or
|
|
* multi-width family to narrow, and where nothing obliges the headline
|
|
* simply renders wide and plain. That degrades gracefully and is not
|
|
* worth a webfont, which this site does not get to have anyway. */
|
|
--font-display: Impact, Haettenschweiler, "Franklin Gothic Demi Cond",
|
|
"Arial Narrow", "Liberation Sans Narrow", "Nimbus Sans Narrow",
|
|
"DejaVu Sans Condensed", sans-serif;
|
|
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
|
|
"DejaVu Sans Mono", "Liberation Mono", monospace;
|
|
--font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
"Helvetica Neue", Arial, sans-serif;
|
|
}
|
|
|
|
/* The period desktop. Same chrome, system-gray surfaces: the bevels that
|
|
* read as machined black plastic in dark mode read as 1992 GUI in light. */
|
|
@media (prefers-color-scheme: light) {
|
|
:root {
|
|
--bg: #b5b5ae;
|
|
--panel: #ecebe6;
|
|
--well: #dcdbd4;
|
|
--code-bg: #dcdbd4;
|
|
|
|
--fg: #16161a;
|
|
--fg-dim: #4e4e56; /* 6.9:1 on --panel */
|
|
|
|
--red-bar: #7a0f0d; /* title bars stay theme-invariant, like a */
|
|
--red-fill: #c81a17; /* real system chrome colour would */
|
|
--red-rule: #a81410;
|
|
--red-link: #a81410; /* 6.4:1 on --panel */
|
|
--red-wash: rgba(168, 20, 16, 0.09);
|
|
|
|
--bevel-hi: #ffffff;
|
|
--bevel-lo: #74746d;
|
|
--line: #9a9a94;
|
|
--shadow: rgba(0, 0, 0, 0.30);
|
|
--dither: rgba(0, 0, 0, 0.05);
|
|
|
|
--good: #14622b; --good-bg: rgba(20, 98, 43, 0.11);
|
|
--warn: #7a5100; --warn-bg: rgba(122, 81, 0, 0.11);
|
|
--bad: #b42318; --bad-bg: rgba(180, 35, 24, 0.10);
|
|
}
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
html { -webkit-text-size-adjust: 100%; }
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--fg);
|
|
font-family: var(--font-body);
|
|
font-size: 1rem;
|
|
line-height: 1.62;
|
|
}
|
|
|
|
/* ------------------------------------------------------- shared surfaces */
|
|
|
|
/* Raised and pressed, the whole system in two rules. Everything that is a
|
|
* control or a panel gets one of these; nothing gets a blur. */
|
|
.bevel-out {
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
}
|
|
.bevel-in {
|
|
border: 2px solid;
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
|
|
/* 2px checkerboard at 50% coverage -- the EGA/VGA way to make a tint out of
|
|
* two colours. Kept faint; it is texture, never contrast. */
|
|
.dither {
|
|
background-image:
|
|
repeating-conic-gradient(var(--dither) 0% 25%, transparent 0% 50%);
|
|
background-size: 4px 4px;
|
|
}
|
|
|
|
/* Diagonal hazard stripe. Used exactly twice per page, as bookends under
|
|
* the header and above the footer. */
|
|
.hazard {
|
|
height: 4px;
|
|
background-image: repeating-linear-gradient(135deg,
|
|
var(--red-rule) 0 6px, transparent 6px 12px);
|
|
background-color: var(--line);
|
|
}
|
|
|
|
a { color: var(--red-link); text-decoration: none; }
|
|
a:hover, a:focus-visible {
|
|
text-decoration: underline;
|
|
text-decoration-thickness: 2px;
|
|
text-underline-offset: 3px;
|
|
}
|
|
a:focus-visible { outline: 2px solid var(--red-rule); outline-offset: 2px; }
|
|
|
|
code, pre { font-family: var(--font-mono); font-size: 0.9em; }
|
|
code { background: var(--code-bg); padding: 0.05em 0.3em; }
|
|
pre {
|
|
background: var(--code-bg);
|
|
padding: 0.9rem 1.1rem;
|
|
overflow-x: auto;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
pre code { background: none; padding: 0; }
|
|
|
|
/* ---------------------------------------------------- header / nav / foot */
|
|
|
|
.site-header {
|
|
background: var(--panel);
|
|
background-image:
|
|
repeating-conic-gradient(var(--dither) 0% 25%, transparent 0% 50%);
|
|
background-size: 4px 4px;
|
|
border-bottom: 2px solid var(--bevel-lo);
|
|
box-shadow: inset 0 2px 0 var(--bevel-hi);
|
|
}
|
|
|
|
.site-header .inner {
|
|
max-width: var(--measure);
|
|
margin: 0 auto;
|
|
padding: 0.7rem 1.1rem;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 0.6rem 1.4rem;
|
|
}
|
|
|
|
.site-title {
|
|
font-family: var(--font-display);
|
|
font-weight: 400;
|
|
font-size: 1.3rem;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--fg);
|
|
line-height: 1.1;
|
|
}
|
|
.site-title .jag { color: var(--red-link); }
|
|
.site-title:hover, .site-title:focus-visible { text-decoration: none; }
|
|
|
|
/* Tabs, not links: raised by default, physically pressed when you are on
|
|
* that page. This is what a 1992 tab control did, and it means the active
|
|
* state is legible without relying on colour alone. */
|
|
.site-nav { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-left: auto; }
|
|
.site-nav a {
|
|
color: var(--fg-dim);
|
|
background: var(--panel);
|
|
font-family: var(--font-mono);
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.09em;
|
|
text-transform: uppercase;
|
|
padding: 0.28rem 0.6rem;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
}
|
|
.site-nav a:hover { color: var(--fg); text-decoration: none; }
|
|
.site-nav a.active {
|
|
color: var(--red-link);
|
|
background: var(--well);
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
|
|
.site-footer {
|
|
background: var(--panel);
|
|
background-image:
|
|
repeating-conic-gradient(var(--dither) 0% 25%, transparent 0% 50%);
|
|
background-size: 4px 4px;
|
|
border-top: 2px solid var(--bevel-hi);
|
|
color: var(--fg-dim);
|
|
font-family: var(--font-mono);
|
|
font-size: 0.78rem;
|
|
line-height: 1.7;
|
|
}
|
|
.site-footer .inner {
|
|
max-width: var(--measure);
|
|
margin: 0 auto;
|
|
padding: 1.1rem 1.1rem 2rem;
|
|
}
|
|
.site-footer p { margin: 0 0 0.7rem; }
|
|
.site-footer p:last-child { margin-bottom: 0; }
|
|
|
|
/* ---------------------------------------------------------------- layout */
|
|
|
|
main {
|
|
max-width: var(--measure);
|
|
margin: 0 auto;
|
|
padding: 1.6rem 1.1rem 3rem;
|
|
}
|
|
|
|
/* The one display shout per page. */
|
|
h1 {
|
|
font-family: var(--font-display);
|
|
font-weight: 400; /* Impact has one weight; 700 fakes an ugly bold */
|
|
font-stretch: condensed; /* the fallback path; see --font-display */
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.015em;
|
|
font-size: clamp(2.3rem, 7vw, 3.9rem);
|
|
line-height: 1.04;
|
|
margin: 0.2rem 0 0.6rem;
|
|
}
|
|
h1::after {
|
|
content: "";
|
|
display: block;
|
|
height: 4px;
|
|
margin-top: 0.55rem;
|
|
background-image: repeating-linear-gradient(135deg,
|
|
var(--red-rule) 0 6px, transparent 6px 12px);
|
|
background-color: var(--line);
|
|
}
|
|
|
|
.lede {
|
|
font-size: 1.1rem;
|
|
color: var(--fg-dim);
|
|
max-width: 44rem;
|
|
margin: 0.8rem 0 1.4rem;
|
|
}
|
|
|
|
p { margin: 0 0 0.9rem; max-width: 46rem; }
|
|
ul, ol { max-width: 46rem; }
|
|
li { margin-bottom: 0.4rem; }
|
|
|
|
/* ---------------------------------------------------------- the window */
|
|
|
|
/* Every content section is a window on the desktop: raised client area,
|
|
* striped title bar, solid drop shadow. The bar's right slot carries real
|
|
* metadata (a ship badge, a capture size) -- never a decorative glyph. */
|
|
.win {
|
|
background: var(--panel);
|
|
margin: 1.8rem 0;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
box-shadow: 3px 3px 0 var(--shadow);
|
|
}
|
|
|
|
.win > h2,
|
|
.win-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 0.5rem 0.8rem;
|
|
margin: 0;
|
|
padding: 0.34rem 0.6rem;
|
|
background-color: var(--red-bar);
|
|
/* GEM/TOS drew the active title as hairline stripes with the caption
|
|
* sitting in the field. 1px stripes at 3px pitch, inside one hue. */
|
|
background-image: repeating-linear-gradient(0deg,
|
|
rgba(0, 0, 0, 0.22) 0 1px, transparent 1px 3px);
|
|
border-bottom: 2px solid var(--red-rule);
|
|
color: #fff;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.78rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.win-body { padding: 1rem 1.1rem 1.1rem; }
|
|
.win-body > :last-child { margin-bottom: 0; }
|
|
|
|
/* Badges sitting in a title bar are window metadata, so they drop the
|
|
* semantic colour coding (which would fight the red field) and become a
|
|
* plain chip. White on bar+15% white is still ~9:1. */
|
|
.win > h2 .badge,
|
|
.win-bar .badge {
|
|
margin-left: auto;
|
|
background: rgba(255, 255, 255, 0.16);
|
|
color: #fff;
|
|
border: 0;
|
|
font-size: 0.7rem;
|
|
}
|
|
|
|
h3 {
|
|
font-family: var(--font-mono);
|
|
font-size: 0.92rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--fg);
|
|
margin: 1.7rem 0 0.6rem;
|
|
padding-bottom: 0.3rem;
|
|
border-bottom: 2px solid var(--line);
|
|
}
|
|
h3 .badge { margin-left: 0.4rem; }
|
|
|
|
/* Bare h2 outside a window (rare; a divider between window groups). */
|
|
main > h2 {
|
|
font-family: var(--font-mono);
|
|
font-size: 0.9rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
color: var(--fg-dim);
|
|
margin: 2.4rem 0 0.8rem;
|
|
padding-bottom: 0.35rem;
|
|
border-bottom: 2px solid var(--line);
|
|
}
|
|
|
|
/* --------------------------------------------------------- the manifest */
|
|
|
|
/* Packing list: mono key, prose value, evidence underneath. Replaces the
|
|
* card wall -- a 1994 readme listed what was on the disk, it did not put
|
|
* twelve identical boxes in a grid. */
|
|
.manifest {
|
|
margin: 0;
|
|
display: grid;
|
|
grid-template-columns: minmax(10rem, 14rem) 1fr;
|
|
}
|
|
.manifest > dt {
|
|
font-family: var(--font-mono);
|
|
font-size: 0.79rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--red-link);
|
|
padding: 0.85rem 1rem 0.85rem 0;
|
|
border-top: 1px solid var(--line);
|
|
}
|
|
.manifest > dd {
|
|
margin: 0;
|
|
padding: 0.85rem 0;
|
|
border-top: 1px solid var(--line);
|
|
color: var(--fg-dim);
|
|
font-size: 0.95rem;
|
|
}
|
|
.manifest > dt:first-of-type, .manifest > dd:first-of-type { border-top: 0; }
|
|
.manifest > dd p { margin: 0 0 0.4rem; max-width: 40rem; }
|
|
.manifest > dd p:last-child { margin-bottom: 0; }
|
|
|
|
@media (max-width: 34rem) {
|
|
.manifest { grid-template-columns: 1fr; }
|
|
.manifest > dt { padding-bottom: 0.15rem; }
|
|
.manifest > dd { padding-top: 0.15rem; border-top: 0; }
|
|
}
|
|
|
|
/* Evidence citations under a manifest entry or a figure. */
|
|
.src {
|
|
font-family: var(--font-mono);
|
|
font-size: 0.76rem;
|
|
letter-spacing: 0.02em;
|
|
color: var(--fg-dim);
|
|
margin: 0.35rem 0 0;
|
|
}
|
|
.src a { white-space: nowrap; }
|
|
|
|
/* ---------------------------------------------------------- the readout */
|
|
|
|
/* System-info panel: label left, value right, inset well, tabular figures.
|
|
* Replaces the glowing stat band. */
|
|
.readout {
|
|
margin: 0;
|
|
background: var(--well);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
font-family: var(--font-mono);
|
|
font-size: 0.83rem;
|
|
display: grid;
|
|
grid-template-columns: 1fr auto;
|
|
}
|
|
.readout > dt {
|
|
padding: 0.42rem 0.5rem 0.42rem 0.8rem;
|
|
color: var(--fg-dim);
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
font-size: 0.74rem;
|
|
border-top: 1px solid var(--line);
|
|
align-self: center;
|
|
}
|
|
.readout > dd {
|
|
margin: 0;
|
|
padding: 0.42rem 0.8rem 0.42rem 0.5rem;
|
|
text-align: right;
|
|
color: var(--fg);
|
|
font-weight: 700;
|
|
font-variant-numeric: tabular-nums;
|
|
border-top: 1px solid var(--line);
|
|
align-self: center;
|
|
white-space: nowrap;
|
|
}
|
|
.readout > dt:first-of-type, .readout > dd:first-of-type { border-top: 0; }
|
|
|
|
/* ---------------------------------------------------------- screenshots */
|
|
|
|
/* A captured frame gets window chrome and an inset well, so it reads as an
|
|
* image in a viewer rather than as page decoration. The pixels themselves
|
|
* are never filtered: these are measurements. */
|
|
figure { margin: 1.4rem 0; }
|
|
figure img {
|
|
display: block;
|
|
width: 100%;
|
|
height: auto;
|
|
image-rendering: pixelated;
|
|
}
|
|
figure.smooth img { image-rendering: auto; }
|
|
|
|
.shot {
|
|
background: var(--panel);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
box-shadow: 3px 3px 0 var(--shadow);
|
|
}
|
|
.shot > .win-bar { border-bottom-width: 2px; }
|
|
.shot .well {
|
|
padding: 6px;
|
|
background: var(--well);
|
|
overflow-x: auto;
|
|
}
|
|
.shot figcaption {
|
|
padding: 0.6rem 0.8rem 0.75rem;
|
|
font-size: 0.86rem;
|
|
color: var(--fg-dim);
|
|
border-top: 1px solid var(--line);
|
|
}
|
|
.shot figcaption strong { color: var(--fg); }
|
|
|
|
/* Wide three-panel diffs are up to 1816px of measured evidence, and they
|
|
* live INSIDE a window. So they cancel the window body's padding to reach
|
|
* its full width -- never past its frame, which would look like a broken
|
|
* layout rather than a deliberate break-out. The page measure carries the
|
|
* rest of the job: --measure is wide, and prose is held to 46rem inside it.
|
|
*
|
|
* On a phone the well SCROLLS at a legible size instead of shrinking three
|
|
* panels to 110px each, which would destroy the thing being evidenced. */
|
|
.shot.wide { margin-left: -1.1rem; margin-right: -1.1rem; }
|
|
.shot.wide .well img { min-width: 42rem; }
|
|
|
|
/* That scroll needs an affordance, because iOS Safari hides overflow
|
|
* scrollbars until they are touched: a phone reader would see panel one of
|
|
* three and no reason to believe the other two exist. A chunky beveled
|
|
* always-visible scrollbar is the honest fix AND the period-correct one --
|
|
* 1994 scroll bars were exactly this, a raised thumb in a sunken track.
|
|
* This is an affordance on a real scroll region, not a decorative cue. */
|
|
.shot.wide .well {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: var(--red-fill) var(--code-bg);
|
|
}
|
|
.shot.wide .well::-webkit-scrollbar {
|
|
height: 14px;
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
}
|
|
.shot.wide .well::-webkit-scrollbar-track {
|
|
background: var(--code-bg);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
.shot.wide .well::-webkit-scrollbar-thumb {
|
|
background: var(--red-fill);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
}
|
|
|
|
figcaption {
|
|
font-size: 0.86rem;
|
|
color: var(--fg-dim);
|
|
margin-top: 0.45rem;
|
|
}
|
|
|
|
/* The one CRT. A tube face is round even though the bezel is square, so
|
|
* this is the single place a radius is honest -- and the only place
|
|
* scanlines are drawn. */
|
|
.crt-frame { margin: 1.5rem 0; }
|
|
.crt-bezel {
|
|
padding: 12px;
|
|
background: var(--panel);
|
|
background-image:
|
|
repeating-conic-gradient(var(--dither) 0% 25%, transparent 0% 50%);
|
|
background-size: 4px 4px;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
box-shadow: 3px 3px 0 var(--shadow);
|
|
}
|
|
.crt-screen {
|
|
position: relative;
|
|
background: #06060a;
|
|
border-radius: 7px / 9px;
|
|
overflow: hidden;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
.crt-screen::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
background:
|
|
radial-gradient(ellipse 130% 130% at 50% 50%,
|
|
transparent 62%, rgba(0, 0, 0, 0.42)),
|
|
repeating-linear-gradient(0deg,
|
|
rgba(0, 0, 0, 0.22) 0 1px, transparent 1px 3px);
|
|
}
|
|
|
|
.crt-frame figcaption {
|
|
font-family: var(--font-mono);
|
|
font-size: 0.74rem;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
/* Side-by-side A/B captures. */
|
|
.ab-pair {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
|
gap: 1rem;
|
|
align-items: start;
|
|
margin: 1.3rem 0;
|
|
}
|
|
.ab-pair .shot { margin: 0; }
|
|
|
|
/* ------------------------------------------------------------ badges */
|
|
|
|
.badge {
|
|
display: inline-block;
|
|
padding: 0.1em 0.5em;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.7rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
white-space: nowrap;
|
|
border: 1px solid currentColor;
|
|
vertical-align: 0.08em;
|
|
}
|
|
.badge.good { color: var(--good); background: var(--good-bg); }
|
|
.badge.warn { color: var(--warn); background: var(--warn-bg); }
|
|
.badge.bad { color: var(--bad); background: var(--bad-bg); }
|
|
.badge.plain { color: var(--fg-dim); background: var(--code-bg); }
|
|
|
|
/* -------------------------------------------------------------- tables */
|
|
|
|
/* Terminal readouts. The wrapper is an inset well so a table reads as
|
|
* data printed into the window, not as another raised panel. */
|
|
.table-wrap {
|
|
overflow-x: auto;
|
|
margin: 1.1rem 0;
|
|
background: var(--well);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
.win-body > .table-wrap:last-child { margin-bottom: 0; }
|
|
|
|
/* Collapsible long tables (the generated boot matrices). */
|
|
details.fold { margin: 1rem 0 0; }
|
|
details.fold > summary {
|
|
cursor: pointer;
|
|
display: inline-block;
|
|
padding: 0.3rem 0.8rem;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.78rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--fg);
|
|
background: var(--code-bg);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
}
|
|
details.fold > summary:hover { color: var(--red-link); }
|
|
details.fold > summary:focus-visible {
|
|
outline: 2px solid var(--red-link);
|
|
outline-offset: 2px;
|
|
}
|
|
details.fold[open] > summary { margin-bottom: 0.4rem; }
|
|
|
|
table {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
font-size: 0.88rem;
|
|
}
|
|
th, td {
|
|
text-align: left;
|
|
padding: 0.5rem 0.75rem;
|
|
border-bottom: 1px solid var(--line);
|
|
vertical-align: top;
|
|
}
|
|
th {
|
|
position: sticky;
|
|
top: 0;
|
|
background: var(--code-bg);
|
|
border-bottom: 2px solid var(--red-rule);
|
|
font-family: var(--font-mono);
|
|
font-size: 0.71rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.09em;
|
|
text-transform: uppercase;
|
|
color: var(--fg);
|
|
white-space: nowrap;
|
|
}
|
|
td { font-variant-numeric: tabular-nums; }
|
|
td code { font-size: 0.85em; }
|
|
tr:last-child td { border-bottom: none; }
|
|
tbody tr:hover td, table tr:hover td { background: var(--red-wash); }
|
|
table tr:hover th { background: var(--code-bg); }
|
|
|
|
/* download page */
|
|
|
|
/* Generic platform and architecture glyphs (inline <symbol> sprite on the
|
|
* page). Stroke-only, currentColor: they follow the text colour in both
|
|
* themes. Always printed next to the platform name, so aria-hidden. */
|
|
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
|
|
svg.ico {
|
|
width: 1.05em; height: 1.05em;
|
|
flex: none;
|
|
vertical-align: -0.17em;
|
|
fill: none;
|
|
stroke: currentColor;
|
|
stroke-width: 1.4;
|
|
stroke-linecap: round;
|
|
stroke-linejoin: round;
|
|
}
|
|
.sr-only {
|
|
position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
|
|
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
|
|
}
|
|
|
|
.dl .win-body { padding-top: 0.8rem; }
|
|
.dl-nojs { margin: 0 0 0.8rem; font-size: 0.9rem; }
|
|
|
|
/* Release picker: two quick buttons and a select for older tags. */
|
|
.dl-picker {
|
|
display: flex; flex-wrap: wrap; align-items: center;
|
|
gap: 0.5rem 0.7rem;
|
|
margin: 0 0 0.9rem;
|
|
}
|
|
.dl-picker[hidden] { display: none; }
|
|
.dl-label {
|
|
font-family: var(--font-mono); font-size: 0.74rem; font-weight: 700;
|
|
letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-dim);
|
|
}
|
|
.dl-seg { display: inline-flex; flex-wrap: wrap; gap: 0.4rem; }
|
|
.dl-btn, .dl-older select {
|
|
font: inherit;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.8rem;
|
|
font-weight: 700;
|
|
color: var(--fg);
|
|
background: var(--code-bg);
|
|
padding: 0.32rem 0.8rem;
|
|
min-height: 2.2rem;
|
|
cursor: pointer;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
border-radius: 0;
|
|
}
|
|
.dl-btn code { background: none; padding: 0; font-size: inherit; }
|
|
.dl-btn:hover, .dl-older select:hover { color: var(--red-link); }
|
|
.dl-btn[aria-pressed="true"], .dl-older select.on {
|
|
color: #fff;
|
|
background: var(--red-fill);
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
.dl-btn[aria-pressed="true"]:hover { color: #fff; }
|
|
.dl-btn:focus-visible, .dl-older select:focus-visible,
|
|
.inst-tabs [role="tab"]:focus-visible, details.plat > summary:focus-visible {
|
|
outline: 2px solid var(--red-link);
|
|
outline-offset: 2px;
|
|
}
|
|
.dl-older select { max-width: 100%; padding-right: 0.4rem; }
|
|
|
|
/* One release. */
|
|
.dl-meta {
|
|
margin: 0 0 0.6rem; max-width: none;
|
|
font-family: var(--font-mono); font-size: 0.8rem; color: var(--fg-dim);
|
|
}
|
|
.dl-meta strong { color: var(--fg); }
|
|
.dl-note { margin: 0 0 0.6rem; font-size: 0.86rem; color: var(--fg-dim); max-width: none; }
|
|
.dl-h {
|
|
display: flex; align-items: baseline; gap: 0.6rem;
|
|
margin: 1.1rem 0 0.45rem;
|
|
padding-bottom: 0.2rem;
|
|
border-bottom: 2px solid var(--red-rule);
|
|
font-family: var(--font-mono); font-size: 0.78rem; font-weight: 700;
|
|
letter-spacing: 0.1em; text-transform: uppercase;
|
|
}
|
|
.dl-h small { font-weight: 400; letter-spacing: 0.04em; color: var(--fg-dim); text-transform: none; }
|
|
.dl-empty { margin: 0.4rem 0; font-size: 0.9rem; color: var(--fg-dim); max-width: none; }
|
|
.dl-hint { margin: 0.1rem 0 0.5rem; font-size: 0.84rem; color: var(--fg-dim); max-width: none; }
|
|
|
|
.plat-name { display: inline-flex; align-items: center; gap: 0.45rem; white-space: nowrap; }
|
|
.arch { display: inline-flex; align-items: center; gap: 0.35rem; font-family: var(--font-mono); font-size: 0.82rem; white-space: nowrap; }
|
|
|
|
table.dl-table { font-size: 0.86rem; }
|
|
.dl-table th, .dl-table td { padding: 0.38rem 0.7rem; vertical-align: middle; }
|
|
.dl-table tbody th[scope="rowgroup"] {
|
|
position: static; background: none; border-bottom: 1px solid var(--line);
|
|
text-transform: none; letter-spacing: 0; font-size: 0.86rem;
|
|
vertical-align: middle;
|
|
}
|
|
.dl-table tbody:not(:last-child) tr:last-child > * { border-bottom: 1px solid var(--line); }
|
|
.dl-table td.files { white-space: normal; }
|
|
.file { display: inline-block; margin: 0.1rem 1rem 0.1rem 0; white-space: nowrap; }
|
|
.file small, .chip small { margin-left: 0.4rem; color: var(--fg-dim); font-family: var(--font-mono); font-size: 0.72rem; }
|
|
|
|
/* Platform groups: the long core list collapses to one line per platform. */
|
|
details.plat { border-bottom: 1px solid var(--line); }
|
|
details.plat > summary {
|
|
display: flex; flex-wrap: wrap; align-items: center; gap: 0.2rem 0.8rem;
|
|
padding: 0.4rem 0.2rem;
|
|
cursor: pointer;
|
|
list-style: none;
|
|
font-size: 0.9rem; font-weight: 600;
|
|
}
|
|
details.plat > summary::-webkit-details-marker { display: none; }
|
|
details.plat > summary::before {
|
|
content: "+"; flex: none; width: 1.1rem; text-align: center;
|
|
font-family: var(--font-mono); font-weight: 700; color: var(--red-link);
|
|
}
|
|
details.plat[open] > summary::before { content: "-"; }
|
|
details.plat > summary:hover { background: var(--red-wash); }
|
|
.count { font-family: var(--font-mono); font-size: 0.74rem; font-weight: 400; color: var(--fg-dim); }
|
|
ul.chips {
|
|
list-style: none; margin: 0.1rem 0 0.7rem; padding: 0;
|
|
display: grid; gap: 0.35rem;
|
|
grid-template-columns: repeat(auto-fill, minmax(min(100%, 14.5rem), 1fr));
|
|
}
|
|
ul.chips li { margin: 0; }
|
|
a.chip {
|
|
display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.1rem;
|
|
height: 100%;
|
|
padding: 0.3rem 0.55rem;
|
|
background: var(--well);
|
|
border: 1px solid var(--line);
|
|
color: var(--fg);
|
|
font-size: 0.84rem;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
a.chip svg.ico { align-self: center; margin-right: 0.4rem; color: var(--fg-dim); }
|
|
a.chip .t { font-family: var(--font-mono); font-size: 0.82rem; }
|
|
a.chip:hover, a.chip:focus-visible { background: var(--red-wash); color: var(--red-link); text-decoration: none; }
|
|
a.chip:focus-visible { outline: 2px solid var(--red-link); outline-offset: 1px; }
|
|
details.tools > .table-wrap { margin-top: 0.3rem; }
|
|
.dl .footnote#verify { margin-top: 0.9rem; }
|
|
|
|
/* Installer: a compact widget, tabs when scripts run. */
|
|
details.inst { margin: 0 0 0.6rem; border: 1px solid var(--line); background: var(--well); }
|
|
details.inst > summary { padding: 0.45rem 0.7rem; }
|
|
details.inst[open] > summary { border-bottom: 1px solid var(--line); }
|
|
details.inst > :not(summary) { margin-left: 0.7rem; margin-right: 0.7rem; }
|
|
details.inst .inst-label { margin: 0.6rem 0 0.2rem; max-width: none; font-size: 0.86rem; }
|
|
details.inst pre { margin: 0 0 0.5rem; }
|
|
details.inst .footnote { margin: 0.4rem 0.7rem 0.6rem; max-width: none; }
|
|
.inst-tabs { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.6rem; margin-bottom: 0.5rem; }
|
|
.inst-tabs[hidden] { display: none; }
|
|
.inst-tabs [role="tab"] {
|
|
font: inherit; font-family: var(--font-mono); font-size: 0.78rem; font-weight: 700;
|
|
color: var(--fg); background: var(--code-bg);
|
|
padding: 0.28rem 0.7rem; min-height: 2rem; cursor: pointer;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
border-radius: 0;
|
|
}
|
|
.inst-tabs [role="tab"][aria-selected="true"] {
|
|
color: #fff; background: var(--red-fill);
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
.inst-tabs:not([hidden]) ~ .inst-panel .inst-label { display: none; }
|
|
.inst-panel[hidden] { display: none; }
|
|
|
|
@media (max-width: 34rem) {
|
|
.dl .win-body { padding-left: 0.7rem; padding-right: 0.7rem; }
|
|
.dl-picker { gap: 0.4rem; }
|
|
.dl-label { flex-basis: 100%; }
|
|
.dl-older { flex: 1 1 100%; }
|
|
.dl-older select { width: 100%; }
|
|
.dl-seg { flex: 1 1 100%; }
|
|
.dl-seg .dl-btn { flex: 1 1 0; }
|
|
.dl-table th, .dl-table td { padding: 0.35rem 0.5rem; }
|
|
/* The app table becomes platform headers over arch + files lines. */
|
|
.dl-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
|
|
.dl-table tbody { display: block; }
|
|
.dl-table tbody tr { display: grid; grid-template-columns: 6.6rem 1fr; align-items: baseline; }
|
|
.dl-table tbody tr th[rowspan] { grid-column: 1 / -1; padding-bottom: 0.1rem; border-bottom: 0; }
|
|
.dl-table tbody tr td { border-bottom: 0; padding-top: 0.1rem; padding-bottom: 0.1rem; }
|
|
.dl-table tbody tr:last-child td { padding-bottom: 0.4rem; }
|
|
.dl-table tbody:not(:last-child) { border-bottom: 1px solid var(--line); }
|
|
.dl-table tbody:not(:last-child) tr:last-child > * { border-bottom: 0; }
|
|
.file { margin-right: 0.8rem; }
|
|
}
|
|
|
|
/* ---------------------------------------------------- notes / evidence */
|
|
|
|
/* Two callouts, one shape: a thick coloured spine on an inset field. The
|
|
* spine colour is the only difference, so they never compete. */
|
|
.note, .evidence {
|
|
margin: 1.2rem 0;
|
|
padding: 0.7rem 0.95rem;
|
|
font-size: 0.9rem;
|
|
background: var(--well);
|
|
border: 1px solid var(--line);
|
|
border-left: 5px solid var(--warn);
|
|
max-width: none;
|
|
}
|
|
.evidence { border-left-color: var(--red-rule); }
|
|
.note > :last-child, .evidence > :last-child { margin-bottom: 0; }
|
|
.note p, .evidence p { max-width: none; }
|
|
|
|
.footnote {
|
|
font-family: var(--font-mono);
|
|
font-size: 0.78rem;
|
|
line-height: 1.65;
|
|
color: var(--fg-dim);
|
|
max-width: 48rem;
|
|
}
|
|
|
|
/* -------------------------------------------------------------- buttons */
|
|
|
|
/* Raised control that physically depresses. The whole motion budget of
|
|
* this site is 1px of travel on :active -- feedback, nothing else. */
|
|
.actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 1.4rem 0 0.4rem; }
|
|
|
|
.btn {
|
|
display: inline-block;
|
|
background: var(--red-fill);
|
|
color: #fff; /* 5.8:1 on --red-fill */
|
|
font-family: var(--font-mono);
|
|
font-weight: 700;
|
|
font-size: 0.82rem;
|
|
letter-spacing: 0.09em;
|
|
text-transform: uppercase;
|
|
padding: 0.52rem 1.1rem;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
box-shadow: 2px 2px 0 var(--shadow);
|
|
}
|
|
.btn:hover, .btn:focus-visible { text-decoration: none; filter: brightness(1.12); }
|
|
.btn:active {
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
box-shadow: none;
|
|
transform: translate(2px, 2px);
|
|
}
|
|
.btn.secondary { background: var(--panel); color: var(--red-link); }
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.btn:active { transform: none; }
|
|
}
|
|
|
|
/* ------------------------------------------------------------- gallery */
|
|
|
|
/* A responsive grid of screenshot cards; each thumbnail is a link to the
|
|
* full picture, and assets/js/gallery.js upgrades it to a lightbox. */
|
|
.gallery {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(min(100%, 15.5rem), 1fr));
|
|
gap: 1rem;
|
|
margin: 1.1rem 0 1.8rem;
|
|
}
|
|
.gal-card {
|
|
margin: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: var(--panel);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
box-shadow: 3px 3px 0 var(--shadow);
|
|
}
|
|
.gal-link {
|
|
display: block;
|
|
padding: 6px;
|
|
background: var(--well);
|
|
line-height: 0;
|
|
}
|
|
.gal-link:hover, .gal-link:focus-visible {
|
|
outline: 2px solid var(--red-link);
|
|
outline-offset: -2px;
|
|
}
|
|
.gal-card img { display: block; width: 100%; height: auto; image-rendering: auto; }
|
|
/* Captured frames (figure.shot) open in the same lightbox and take the same
|
|
* red hover. The well already supplies the inset, so the link adds none;
|
|
* a wide (scrolling) frame's link is as wide as its picture, so the outline
|
|
* spans what scrolls. */
|
|
.shot .well > .gal-link { padding: 0; background: none; outline-offset: 0; }
|
|
.shot.wide .well > .gal-link { min-width: 42rem; }
|
|
.gal-card figcaption {
|
|
margin: 0;
|
|
padding: 0.5rem 0.65rem 0.65rem;
|
|
font-size: 0.82rem;
|
|
line-height: 1.45;
|
|
color: var(--fg-dim);
|
|
border-top: 1px solid var(--line);
|
|
}
|
|
.gal-card figcaption strong { display: block; color: var(--fg); font-size: 0.86rem; }
|
|
.win-body > h3 { margin-top: 1.8rem; }
|
|
|
|
dialog.lightbox {
|
|
width: min(96vw, 80rem);
|
|
max-width: 96vw;
|
|
max-height: 96vh;
|
|
padding: 0;
|
|
color: var(--fg);
|
|
background: var(--panel);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
box-shadow: 4px 4px 0 var(--shadow);
|
|
}
|
|
dialog.lightbox::backdrop { background: rgba(0, 0, 0, 0.78); }
|
|
.lb-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 0.4rem;
|
|
padding: 0.3rem 0.5rem;
|
|
background: var(--red-bar);
|
|
color: #fff;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.78rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
}
|
|
.lb-title { margin-right: auto; }
|
|
.lb-btn {
|
|
font: inherit;
|
|
letter-spacing: inherit;
|
|
text-transform: inherit;
|
|
color: var(--red-link);
|
|
background: var(--panel);
|
|
padding: 0.2rem 0.7rem;
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
cursor: pointer;
|
|
}
|
|
.lb-btn:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
|
|
.lb-well { background: var(--well); padding: 6px; line-height: 0; overflow: auto; max-height: calc(96vh - 7rem); }
|
|
.lb-img { display: block; width: 100%; height: auto; max-height: calc(96vh - 8rem); object-fit: contain; }
|
|
.lb-cap { margin: 0; padding: 0.5rem 0.8rem 0.7rem; font-size: 0.86rem; color: var(--fg-dim); min-height: 1.2em; }
|
|
|
|
/* --------------------------------------------------------------- print */
|
|
|
|
@media print {
|
|
body { background: #fff; color: #000; }
|
|
.site-header, .site-footer, .hazard { display: none; }
|
|
.win, .shot, .crt-bezel { box-shadow: none; border: 1px solid #000; }
|
|
.win > h2, .win-bar { background: #000; color: #fff; }
|
|
.crt-screen::after { display: none; }
|
|
a { color: #000; text-decoration: underline; }
|
|
main { max-width: none; }
|
|
}
|
|
|
|
/* app page */
|
|
/* The screenshot galleries (only app.html uses .gallery): always 4 columns, 2 on
|
|
* narrower screens, never 3 -- every gallery holds an even number of cards, so
|
|
* the last row is never ragged. Tighter gaps and captions mean less scrolling. */
|
|
.gallery {
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
gap: 0.7rem;
|
|
margin: 0.8rem 0 1.2rem;
|
|
}
|
|
.gal-link { padding: 4px; }
|
|
.gal-card figcaption { padding: 0.35rem 0.5rem 0.45rem; font-size: 0.78rem; line-height: 1.35; }
|
|
.gal-card figcaption strong { font-size: 0.82rem; }
|
|
#gallery > .win-body > h3 { margin-top: 1.3rem; }
|
|
/* The short bullet intros above each gallery run in two columns on wide screens. */
|
|
#gallery .win-body > ul { max-width: none; columns: 2; column-gap: 2rem; margin-bottom: 0.7rem; }
|
|
#gallery .win-body > ul > li { break-inside: avoid; }
|
|
@media (max-width: 60rem) {
|
|
.gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
#gallery .win-body > ul { columns: 1; max-width: 46rem; }
|
|
}
|
|
@media (max-width: 34rem) {
|
|
.gallery { grid-template-columns: minmax(0, 1fr); }
|
|
}
|
|
|
|
/* home page */
|
|
/* The screenshot strip: six frames across, the rest a sideways scroll away
|
|
* (snap per frame, the beveled scrollbar from .shot.wide, and Prev/Next
|
|
* buttons once gallery.js runs). Three across on tablets, two on phones;
|
|
* the scroll stays inside the strip, never the page. */
|
|
.strip-wrap { margin: 1.4rem 0 0.4rem; }
|
|
.strip {
|
|
--strip-cols: 6;
|
|
--strip-gap: 0.6rem;
|
|
display: grid;
|
|
grid-auto-flow: column;
|
|
grid-auto-columns: calc((100% - (var(--strip-cols) - 1) * var(--strip-gap)) / var(--strip-cols));
|
|
gap: var(--strip-gap);
|
|
max-width: none;
|
|
margin: 0;
|
|
padding: 0 0 0.6rem;
|
|
list-style: none;
|
|
overflow-x: auto;
|
|
overscroll-behavior-x: contain;
|
|
scroll-snap-type: x mandatory;
|
|
scrollbar-width: thin;
|
|
scrollbar-color: var(--red-fill) var(--code-bg);
|
|
}
|
|
.strip > li { margin: 0; scroll-snap-align: start; min-width: 0; }
|
|
.strip .gal-card { position: relative; height: 100%; }
|
|
.strip .gal-link { padding: 3px; }
|
|
.strip .gal-card img { aspect-ratio: 4 / 3; object-fit: cover; }
|
|
.strip .gal-card figcaption { padding: 0.3rem 0.45rem 0.4rem; font-size: 0.74rem; line-height: 1.3; }
|
|
.strip .gal-card figcaption strong { font-size: 0.78rem; }
|
|
/* In the strip a card shows the title (and the shader, when there is one);
|
|
* the full caption stays in the markup for the lightbox and screen readers. */
|
|
.strip .gal-cap {
|
|
position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
|
|
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
|
|
}
|
|
.strip .gal-card figcaption .badge { margin-top: 0.2rem; font-size: 0.62rem; }
|
|
.strip::-webkit-scrollbar { height: 14px; -webkit-appearance: none; appearance: none; }
|
|
.strip::-webkit-scrollbar-track {
|
|
background: var(--code-bg);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-lo) var(--bevel-hi) var(--bevel-hi) var(--bevel-lo);
|
|
}
|
|
.strip::-webkit-scrollbar-thumb {
|
|
background: var(--red-fill);
|
|
border: 2px solid;
|
|
border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
|
|
}
|
|
.strip-bar { display: flex; align-items: center; gap: 0.4rem; margin: 0 0 0.5rem; }
|
|
.strip-bar[hidden] { display: none; }
|
|
.strip-bar .dl-label { margin-right: auto; }
|
|
.strip-bar .dl-btn { min-height: 2rem; padding: 0.2rem 0.7rem; }
|
|
.strip-bar .dl-btn:disabled { opacity: 0.45; cursor: default; color: var(--fg-dim); }
|
|
.strip-note { margin: 0.2rem 0 0; font-size: 0.8rem; color: var(--fg-dim); max-width: none; }
|
|
@media (max-width: 60rem) { .strip { --strip-cols: 3; } }
|
|
@media (max-width: 34rem) { .strip { --strip-cols: 2; } }
|
|
|
|
/* release log */
|
|
table.release-log td:first-child, table.release-log td:last-child { white-space: nowrap; }
|