sandyland / assets /themes.css
olaservo's picture
prod: promote curated content (2026-08-04 06:26)
58972cf
Raw
History Blame Contribute Delete
17.1 kB
/* ===========================================================================
themes.css — Retro theme layer for the research hub
---------------------------------------------------------------------------
Two opt-in themes that sit ON TOP of the Birch design system
(assets/styles.css) without fighting it. Each theme is scoped under a
`body.theme-*` class and works mostly by re-defining Birch's own design
tokens (the CSS custom properties Birch already consumes), plus a few
component accents for personality. Because Birch reads everything through
var(--...), a token swap re-skins the whole page with almost no specificity
conflicts.
Apply a theme by putting the class on <body>, e.g. <body class="theme-hypercard">.
The control in theme-switcher.js toggles between them at runtime.
Themes: theme-hypercard (default) · theme-craigshouse · theme-tufte
The HyperCard theme comes from everything-else/.inbox/hypercard-revival/.
Inspiration: Apple HyperCard (1987, Bill Atkinson), Craigslist
(1995, Craig Newmark) — https://www.craigslist.org/ — and Edward Tufte's
print style via Tufte CSS (Dave Liepmann, MIT) —
https://github.com/edwardtufte/tufte-css.
=========================================================================== */
/* All themes: fill the viewport so the themed background reaches the bottom.
(Birch's <html> keeps its own background: var(--bg); since the theme only
overrides --bg on <body>, a short page would otherwise show white below.) */
body.theme-hypercard,
body.theme-craigshouse,
body.theme-tufte {
min-height: 100vh;
/* Birch's type scale runs small; nudge it up a notch across all themes
so body copy, eyebrows and captions read comfortably. */
--text-xs: 13px;
--text-sm: 14px;
--text-md: 15px;
--text-base: 16px;
--text-lg: 19px;
}
/* ===========================================================================
THEME: HYPERCARD — classic 1-bit Macintosh stack (Apple HyperCard, 1987)
strictly black on white, "gray" only as a CSS dither, Chicago-style chunky
headings over Geneva-style body, the page framed as a white card with a hard
offset drop shadow on a dithered desktop, rounded-rect buttons that invert
when pressed. Fonts are system approximations — no bundled bitmaps.
Distilled from everything-else/.inbox/hypercard-revival/.
=========================================================================== */
body.theme-hypercard {
--bg: #ffffff;
--surface: #ffffff;
--surface-tint: #ffffff;
--surface-warm: #ffffff;
--text: #000000;
--text-soft: #000000;
--text-muted: #000000;
--muted: #000000;
--border-color: #000000;
--accent: #000000;
--accent-strong: #000000;
/* Geneva ≈ plain humanist system sans for body/fields */
--font-sans: Geneva, Verdana, "Segoe UI", Tahoma, sans-serif;
--font-serif: Geneva, Verdana, "Segoe UI", Tahoma, sans-serif;
/* sharp 1-bit rectangles everywhere; buttons get their round-rect back below */
--radius-xs: 0; --radius-sm: 0; --radius-md: 0; --radius-lg: 0; --radius-xl: 0;
/* the desktop itself is painted by body::before below, fixed to the
viewport — a scrolling 2px checkerboard strobes against the pixel grid.
body must stay transparent: <html> has its own background, so body's
background would otherwise paint over the negative-z-index layer. */
background: transparent;
}
/* dithered "gray" desktop — the classic 50% Mac checkerboard, in pure CSS.
Fixed to the viewport (like a real Mac desktop: the card scrolls, the
desktop doesn't), which kills the moiré flashing a moving dither causes. */
body.theme-hypercard::before {
content: "";
position: fixed;
inset: 0;
z-index: -1;
background-image: repeating-conic-gradient(#000 0 25%, #fff 0 50%);
background-size: 4px 4px;
pointer-events: none;
}
/* the page itself is a white CARD on the desktop, with a hard drop shadow */
body.theme-hypercard .page {
background: #ffffff;
border: 1px solid #000000;
box-shadow: 3px 3px 0 0 #000000;
padding-inline: var(--page-pad);
}
/* Chicago ≈ heavy, slightly condensed system sans for chrome/headings */
body.theme-hypercard header { text-align: center; }
body.theme-hypercard h1,
body.theme-hypercard h2,
body.theme-hypercard h3 {
font-family: "Helvetica Neue", "Arial Narrow", Arial, sans-serif;
font-weight: 700;
color: #000000;
letter-spacing: .01em;
/* crisp/blocky chrome — scoped to headings so body copy stays readable
(esp. on iOS Safari, where this also disables body-text antialiasing) */
-webkit-font-smoothing: none;
}
body.theme-hypercard .eyebrow {
font-family: "Helvetica Neue", "Arial Narrow", Arial, sans-serif;
color: #000000;
justify-content: center;
-webkit-font-smoothing: none;
}
body.theme-hypercard .lede { color: #000000; text-align: center; }
/* links: underlined, invert on hover like a selected HyperCard text-link */
body.theme-hypercard a { color: #000000; text-decoration: underline; text-decoration-color: #000000; }
body.theme-hypercard a:visited { color: #000000; }
body.theme-hypercard a:hover { color: #ffffff; background: #000000; }
/* cards + panels: white "fields" with a 1px black border and a hard shadow */
body.theme-hypercard .card,
body.theme-hypercard .panel {
background: #ffffff;
border: 1px solid #000000;
box-shadow: 2px 2px 0 0 #000000;
}
/* the signature rounded-rectangle button with a hard offset drop shadow */
body.theme-hypercard .button,
body.theme-hypercard .btn {
background: #ffffff;
color: #000000;
border: 1px solid #000000;
border-radius: 9px;
box-shadow: 2px 2px 0 0 #000000;
font-family: "Helvetica Neue", "Arial Narrow", Arial, sans-serif;
font-weight: 700;
}
/* pressed/hover: button inverts and sinks onto its shadow */
body.theme-hypercard .button:hover,
body.theme-hypercard .btn:hover {
background: #000000;
color: #ffffff;
filter: none;
}
body.theme-hypercard .button:active,
body.theme-hypercard .btn:active {
box-shadow: none;
transform: translate(2px, 2px);
}
/* the survey pages colour-code their A/B/C/D variant groups; that colour is the
only hue on an otherwise 1-bit page, so flatten it to black & white. The A/B/C/D
letter is on every badge/chip/cell, so the grouping survives without the hue. */
body.theme-hypercard .variants {
--variant-a: #000000; --variant-b: #000000; --variant-c: #000000; --variant-d: #000000;
}
body.theme-hypercard .variants .badge[data-variant] {
color: #ffffff;
background: #000000;
border-radius: 3px;
}
body.theme-hypercard .variants .chip[data-variant] {
color: #000000;
background: #ffffff;
border: 1px solid #000000;
border-radius: 3px;
}
body.theme-hypercard .variants .card[data-variant] {
border-color: #000000;
}
/* ===========================================================================
THEME: CRAIGSHOUSE — classic Craigslist (1995, Craig Newmark)
the anti-design: stark white page, plain Helvetica/Arial, dense layout, no
rounded corners and no shadows, hairline grey rules. Links are the classic
blue underlined / purple visited; headings wear the recognizable Craigslist
purple as a nod to the wordmark. Inspiration: https://www.craigslist.org/.
=========================================================================== */
body.theme-craigshouse {
--bg: #ffffff;
--surface: #ffffff;
--surface-tint: #ffffff;
--surface-warm: #ffffff;
--text: #000000;
--text-soft: #222222;
--text-muted: #555555;
--muted: #555555;
--border-color: #cccccc;
--accent: #0000ee; /* classic blue link */
--accent-strong: #551a8b; /* craigslist purple / visited */
--font-sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
--radius-xs: 0; --radius-sm: 0; --radius-md: 0; --radius-lg: 0; --radius-xl: 0;
/* Craigslist runs denser than the other themes — undo the shared type-scale
bump for a tighter feel, but keep it comfortably readable. */
--text-xs: 12px;
--text-sm: 13px;
--text-md: 14px;
--text-base: 14px;
--text-lg: 17px;
background: #ffffff;
}
/* no outer card: Craigslist is a borderless white sheet, not a framed page */
body.theme-craigshouse .page {
background: #ffffff;
border: 0;
box-shadow: none;
padding-inline: var(--page-pad);
}
/* headings: h1 wears the Craigslist purple wordmark; section heads are plain
bold black like the homepage category labels. Left-aligned, unfussy. */
body.theme-craigshouse header { text-align: left; }
body.theme-craigshouse h1 {
color: #551a8b;
font-weight: 700;
letter-spacing: 0;
}
body.theme-craigshouse h2,
body.theme-craigshouse h3 {
color: #000000;
font-weight: 700;
letter-spacing: 0;
}
body.theme-craigshouse .eyebrow { color: #555555; justify-content: flex-start; }
body.theme-craigshouse .lede { color: #000000; text-align: left; }
/* links: the signature Craigslist tell — plain blue, NO underline until hover;
purple once visited. */
body.theme-craigshouse a { color: #0000ee; text-decoration: none; }
body.theme-craigshouse a:visited { color: #551a8b; }
body.theme-craigshouse a:hover { color: #0000ee; text-decoration: underline; }
/* cards + panels: white, hairline border, no shadow */
body.theme-craigshouse .card,
body.theme-craigshouse .panel {
background: #ffffff;
border: 1px solid #cccccc;
box-shadow: none;
}
/* buttons: plain bordered grey/white box, square corners, no shadow */
body.theme-craigshouse .button,
body.theme-craigshouse .btn {
background: #f0f0f0;
color: #000000;
border: 1px solid #999999;
border-radius: 0;
box-shadow: none;
}
body.theme-craigshouse .button:hover,
body.theme-craigshouse .btn:hover { background: #e6e6e6; filter: none; }
/* ===========================================================================
THEME: TUFTE — Edward Tufte's print aesthetic (via Tufte CSS, Dave
Liepmann / Edward Tufte, MIT — https://github.com/edwardtufte/tufte-css),
prototyped in the mcp/tool-schemas findings-tufte layout experiment.
Off-white paper, warm near-black ink, serif throughout, italic unbolded
headings, hairline rules, no boxes and no shadows. This is typography +
palette only — a token re-skin, not the margin-note layout (that needs
structural markup; see the tufterising project).
=========================================================================== */
body.theme-tufte {
--bg: #fffff8; /* Tufte CSS paper */
--surface: #fffff8;
--surface-tint: #f6f4e8;
--surface-warm: #f6f4e8;
--text: #191919; /* warm near-black ink */
--text-soft: #464440;
--text-muted: #6b675f;
--muted: #6b675f;
--border-color: #d8d4c8; /* hairline rule */
--accent: #8f1d1d; /* restrained dark red, used sparingly */
--accent-strong: #6d1414;
--danger: #8f1d1d;
/* serif everywhere — Birch's body/headings read --font-sans, so both
tokens point at the book stack (ET Book if installed, else Palatino) */
--font-sans: "et-book", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
--font-serif: "et-book", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
/* print has no rounded corners */
--radius-xs: 0; --radius-sm: 0; --radius-md: 0; --radius-lg: 0; --radius-xl: 0;
/* Tufte runs bigger and airier than Birch — generous, nothing tiny */
--text-xs: 14px;
--text-sm: 15px;
--text-md: 16px;
--text-base: 17px;
--text-lg: 20px;
--leading-body: 1.55;
background: #fffff8;
}
/* no card frame: the page is the paper */
body.theme-tufte .page {
background: #fffff8;
border: 0;
box-shadow: none;
padding-inline: var(--page-pad);
}
/* headings: italic, unbolded, left-set — the Tufte CSS convention */
body.theme-tufte header { text-align: left; }
body.theme-tufte h1,
body.theme-tufte h2,
body.theme-tufte h3 {
font-weight: 400;
font-style: italic;
letter-spacing: 0;
color: var(--text);
}
body.theme-tufte h1 code,
body.theme-tufte h2 code,
body.theme-tufte h3 code { font-style: normal; }
body.theme-tufte .eyebrow {
justify-content: flex-start;
font-variant: small-caps;
letter-spacing: .08em;
color: var(--text-muted);
}
body.theme-tufte .lede { text-align: left; font-style: italic; color: var(--text); }
/* links: ink-colored with a quiet underline that darkens on hover —
Tufte reserves hue for data, not navigation */
body.theme-tufte a {
color: inherit;
text-decoration: underline;
text-decoration-color: var(--border-color);
text-decoration-thickness: 1px;
text-underline-offset: 2px;
}
body.theme-tufte a:visited { color: inherit; }
body.theme-tufte a:hover {
color: var(--accent);
background: transparent;
text-decoration-color: var(--accent);
}
/* cards + panels: same paper, hairline border, no shadow */
body.theme-tufte .card,
body.theme-tufte .panel {
background: #fffff8;
border: 1px solid var(--border-color);
box-shadow: none;
}
/* buttons: understated bordered text, square, no shadow */
body.theme-tufte .button,
body.theme-tufte .btn {
background: transparent;
color: var(--text);
border: 1px solid var(--text-muted);
border-radius: 0;
box-shadow: none;
font-weight: 400;
}
body.theme-tufte .button:hover,
body.theme-tufte .btn:hover {
background: #f0eee0;
color: var(--text);
filter: none;
}
/* ===========================================================================
SURVEY VARIANT PALETTES, per theme
---------------------------------------------------------------------------
The client/server surveys colour-code their A/B/C/D groups via --variant-a..d
(defaults defined in styles.css). Those defaults are tuned for plain Birch and
look out of place under the retro themes, so each theme re-tones the four hues
to its own palette — keeping the client = cool / server = warm split. (The
HyperCard theme flattens them to 1-bit, handled above.)
=========================================================================== */
/* Craigshouse — flat web blues for client, plain reds for server */
body.theme-craigshouse .variants-client {
--variant-a: #0000ee; /* link blue */
--variant-b: #006699; /* steel */
--variant-c: #551a8b; /* purple */
--variant-d: #007a3d; /* green */
}
body.theme-craigshouse .variants-server {
--variant-a: #b00000; /* red */
--variant-b: #993300; /* rust */
--variant-c: #996600; /* amber */
--variant-d: #993366; /* plum */
}
/* Tufte — muted, ink-adjacent hues; still cool client / warm server */
body.theme-tufte .variants-client {
--variant-a: #3f4c5a; /* slate */
--variant-b: #4f6a67; /* sea gray */
--variant-c: #5c5470; /* plum gray */
--variant-d: #59663f; /* olive */
}
body.theme-tufte .variants-server {
--variant-a: #8f1d1d; /* dark red */
--variant-b: #8a5a2e; /* umber */
--variant-c: #7a6a33; /* ochre */
--variant-d: #7d4a5e; /* mulberry */
}
/* A linked card title should wear its theme's heading color, not the link color
— it only reveals itself as a link on hover. Works across all themes. */
.card-title a { color: inherit; text-decoration: none; border-bottom: 0; }
.card-title a:hover { text-decoration: underline; }
/* ===========================================================================
Theme switcher control — neutral styling, independent of the active theme so
it stays legible everywhere. Injected by theme-switcher.js.
=========================================================================== */
.theme-switcher {
position: fixed;
top: 10px;
right: 10px;
z-index: 9999;
display: flex;
flex-direction: column; /* vertical list — scales past 3-4 themes */
align-items: stretch; /* buttons span the control's width */
gap: 4px;
padding: 6px 7px;
background: rgba(28,28,30,.86);
border: 1px solid rgba(255,255,255,.25);
border-radius: 8px;
backdrop-filter: blur(4px);
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
font-size: 11px;
color: #f2f2f2;
box-shadow: 0 2px 10px rgba(0,0,0,.3);
}
.theme-switcher__label {
opacity: .7;
margin: 0 2px 2px;
text-transform: uppercase;
letter-spacing: .06em;
}
.theme-switcher button {
appearance: none;
cursor: pointer;
padding: 4px 10px;
text-align: left;
border: 1px solid rgba(255,255,255,.2);
border-radius: 5px;
background: transparent;
color: #f2f2f2;
font: inherit;
}
.theme-switcher button:hover { background: rgba(255,255,255,.12); }
.theme-switcher button:focus-visible {
outline: 2px solid #fff;
outline-offset: 1px;
}
.theme-switcher button[aria-checked="true"] {
background: #f2f2f2;
color: #1c1c1e;
border-color: #f2f2f2;
font-weight: 700;
}
@media print { .theme-switcher { display: none; } }