/* substandard brand theme: paper, ink, and a red pen that disagrees. Everything sits a degree or two off level on purpose — tilts are static (they are the design, not motion), only the hover corrections animate. */ :root { --bg: #f4f3ee; --card: #fdfcf9; --fg: #26282b; --muted: #6d6a62; --line: #dedcd3; --red: #d9482b; --gold: #e8b52a; --gold-hl: rgba(232, 181, 42, 0.35); --shadow: #dedcd3; } @media (prefers-color-scheme: dark) { :root { --bg: #1c1d20; --card: #26272b; --fg: #e9e7e0; --muted: #96938a; --line: #3a3b40; --red: #e2593a; --gold: #d9a826; --gold-hl: rgba(217, 168, 38, 0.28); --shadow: #131417; } } * { box-sizing: border-box; } body { margin: 0; font-family: system-ui, -apple-system, "Segoe UI", sans-serif; line-height: 1.6; background: var(--bg); color: var(--fg); } ::selection { background: var(--gold-hl); } a { color: var(--fg); text-decoration: underline; text-decoration-style: wavy; text-decoration-color: var(--red); text-decoration-thickness: 1.5px; text-underline-offset: 3px; } .hero { max-width: 44rem; margin: 0 auto; padding: 4rem 1.5rem 3rem; text-align: center; } /* The lockup follows the og card: Subby on the left, wordmark to his right. Subby arrives pre-tilted, same 2° as his sticker frame; hovering straightens him out, and he leans right back when you let go. */ .hero-mark { display: flex; align-items: center; justify-content: center; gap: 1.25rem; } .hero-icon { width: 5.5rem; height: 5.5rem; transform: rotate(2deg); transition: transform 0.25s ease; } .hero-icon:hover { transform: rotate(0deg); } /* The wordmark is inlined so the theme can retake its baked-in colors: ink follows the foreground, the squiggle keeps the red pen. */ .hero-wordmark { flex: 0 1 17rem; min-width: 0; } .hero-wordmark svg { display: block; width: 100%; height: auto; } .hero-wordmark text { fill: var(--fg); } .hero-wordmark path { stroke: var(--red); } .hero h1 { margin: 1.25rem 0 0.75rem; font-size: 3rem; line-height: 1.15; letter-spacing: -0.01em; transform: rotate(-1deg); text-decoration: underline; text-decoration-style: wavy; text-decoration-color: var(--red); text-decoration-thickness: 3px; text-underline-offset: 10px; } /* The signup button is a gold sticker somebody slapped on almost straight. Its drop shadow is a solid misprint offset, not a blur. */ .blurb { display: block; max-width: 36rem; margin: 1.75rem auto 0; padding: 1.1rem 1.5rem; border: 3px solid var(--fg); border-radius: 0.9rem; background: var(--gold); color: #26282b; text-decoration: none; font-size: 1.15rem; font-weight: 650; transform: rotate(-0.8deg); box-shadow: 4px 5px 0 var(--shadow); transition: transform 0.15s ease, box-shadow 0.15s ease; } .blurb:hover { transform: rotate(-0.8deg) translate(2px, 3px); box-shadow: 1px 1px 0 var(--shadow); } main { max-width: 44rem; margin: 0 auto; padding: 0 1.5rem 3rem; } /* Cards were laid out by eye: each one tilts its own way, and none of the shadows agree on where the light is. */ main section { background: var(--card); border: 2px solid var(--line); border-radius: 0.75rem; padding: 1.5rem; margin-bottom: 1.75rem; } main section:nth-of-type(odd) { transform: rotate(-0.6deg); box-shadow: 5px 4px 0 var(--shadow); } main section:nth-of-type(even) { transform: rotate(0.45deg); box-shadow: -4px 5px 0 var(--shadow); } /* Headings get a slightly overshooting marker highlight. */ main h2 { display: inline-block; margin: 0 0 0.5rem; font-size: 1.5rem; line-height: 1.3; padding: 0 0.35rem; background: linear-gradient( 100deg, transparent 0.5%, var(--gold-hl) 3%, var(--gold-hl) 98%, transparent 99.5% ); transform: rotate(-0.4deg); } main p { margin: 0.5rem 0 0; color: var(--muted); } main ul { margin: 0.5rem 0 0; padding-left: 1.5rem; color: var(--muted); } main li::marker { color: var(--red); } /* The screenshot gallery: the popup captures the store listing is composed from (scripts/shots.mjs), taped to the page by somebody in a hurry. Each frame leans the other way from the one before it and none of the shadows agree; hovering one straightens it out. The frames live here rather than in the images so they follow the theme and stay sharp at any width. */ /* Wrapping flex rather than a grid: with an odd number of shots a grid leaves a hole in the last row, and a centered short row looks handmade where a hole just looks broken. The cap keeps a lone last shot the same size as the pair above it instead of stretching across the card. */ .shots { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 1.75rem 1.5rem; margin: 1.25rem 0 0.25rem; padding: 0; } .shot { flex: 1 1 15rem; max-width: 20rem; margin: 0; } .shot img { display: block; width: 100%; height: auto; border: 2px solid var(--fg); border-radius: 0.4rem; background: var(--card); box-shadow: 5px 5px 0 var(--shadow); transform: rotate(-1.1deg); transition: transform 0.25s ease; } .shot:nth-child(3n + 2) img { box-shadow: -4px 6px 0 var(--shadow); transform: rotate(0.9deg); } .shot:nth-child(3n) img { box-shadow: 6px 4px 0 var(--shadow); transform: rotate(1.5deg); } /* Last, so it beats the per-position tilts at equal specificity. */ .shot img:hover { transform: rotate(0deg); } .shot-caption { margin: 0.9rem 0 0; font-size: 0.85rem; transform: rotate(-0.3deg); } /* Updates: the homepage preview list, the /posts backlog, and the posts themselves. Posts reuse the tilted section cards; these are trimmings. */ .hero-sub { margin: 0.75rem 0 0; color: var(--muted); } /* A post page has no hero above it, so the first card needs its own air. */ .post-page { padding-top: 3rem; } /* The homepage's updates feed is a little changelog note. In the narrow flow it sits at the bottom of the column; once the viewport has room it is pinned off to the side instead — a sticky note beside the page proper, dashed border and a harder lean to set it apart from the real cards. */ .changelog { background: var(--card); border: 2px dashed var(--line); border-radius: 0.75rem; padding: 1rem 1.25rem; margin-bottom: 1.75rem; font-size: 0.9rem; transform: rotate(0.9deg); box-shadow: 4px 4px 0 var(--shadow); } .changelog h2 { font-size: 1.05rem; } /* 84rem, not the 80rem the raw geometry suggests: the note leans and casts a shadow past its own box, and the scrollbar eats into the viewport — pinning it any earlier puts a horizontal scrollbar on the whole page. */ @media (min-width: 84rem) { main { position: relative; } .changelog { position: absolute; top: 0; left: calc(100% + 2rem); width: 16rem; margin-bottom: 0; transform: rotate(1.2deg); } } .update-list { list-style: none; margin: 0.5rem 0 0.75rem; padding-left: 0; } .update-list li { margin: 0.6rem 0 0; } /* Date above title, changelog style. */ .update-list .post-meta { display: block; } .post-card h2 { display: block; background: none; transform: none; } .post-card h2 a { padding: 0 0.35rem; background: linear-gradient( 100deg, transparent 0.5%, var(--gold-hl) 3%, var(--gold-hl) 98%, transparent 99.5% ); } .post-meta { color: var(--muted); font-size: 0.9rem; } .post-meta > * + * { margin-left: 0.6rem; } .post-tag, .post-draft { padding: 0 0.35rem; border: 1px solid var(--line); border-radius: 0.4rem; } .post-draft { color: var(--red); border-color: var(--red); } .post-back { color: var(--muted); } /* The architecture diagram (/architecture). Mermaid's own stylesheet is stripped at render time — `style-src 'self'` covers inline SVG, so a