*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
    --bg: #f7f8fa;
    --surface: #ffffff;
    --text: #1b1f27;
    --text-soft: #454c59;
    --muted: #6b7280;
    --line: #e3e6ec;
    --accent: #0e9488;
    --accent-strong: #0b7e73;
    --max-width: 42rem;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0e1116;
        --surface: #151a22;
        --text: #e8edf5;
        --text-soft: #c4ccda;
        --muted: #8b96a8;
        --line: #262e3a;
        --accent: #2dd4bf;
        --accent-strong: #5eead4;
    }
}

html { -webkit-text-size-adjust: 100%; }

body {
    background: var(--bg);
    color: var(--text);
    font: 1.0625rem/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    text-rendering: optimizeLegibility;
}

a { color: var(--accent-strong); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover, a:focus { color: var(--accent); }

/* Visually hidden, but read by screen readers and shown by text browsers
   that ignore CSS. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Keyboard users get the same visible ring on every theme: themes recolour
   --accent, they never have to restate this rule. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Painted in --text on --surface rather than on --accent: themes recolour the
   accent freely, and a fixed ink colour on top of it went unreadable on three
   of the four. The accent stays as the border, which needs only 3:1. */
.skip-link {
    position: absolute;
    left: -999px;
    top: 0;
    background: var(--surface);
    color: var(--text);
    border: 2px solid var(--accent);
    padding: .6rem 1rem;
    border-radius: 0 0 .4rem 0;
    z-index: 10;
}
.skip-link:focus { left: 0; }

.site-header {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 2rem 1.25rem 1rem;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: .75rem;
    border-bottom: 1px solid var(--line);
}
.site-brand a { color: var(--text); text-decoration: none; font-size: 1.375rem; font-weight: 700; }
.site-nav a { color: var(--muted); text-decoration: none; margin-left: 1rem; }
.site-nav a:first-child { margin-left: 0; }
.site-nav a:hover, .site-nav a:focus { color: var(--accent-strong); }

main {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 2rem 1.25rem 3rem;
}

.site-description { color: var(--text-soft); margin-bottom: 2rem; }

.post-list { list-style: none; }
.post-summary {
    padding: 1.5rem 0;
    border-bottom: 1px solid var(--line);
}
.post-summary:first-child { padding-top: 0; }
.post-summary h2 { font-size: 1.25rem; line-height: 1.4; margin-bottom: .35rem; }
.post-summary h2 a { text-decoration: none; color: var(--text); }
.post-summary h2 a:hover, .post-summary h2 a:focus { color: var(--accent-strong); }

.post-meta { color: var(--muted); font-size: .875rem; margin-bottom: .5rem; }
.post-meta a { color: var(--muted); }
.post-meta a:hover, .post-meta a:focus { color: var(--accent-strong); }

.post-excerpt { color: var(--text-soft); }
.empty { color: var(--muted); }

article h1 { font-size: 1.75rem; line-height: 1.3; margin-bottom: .5rem; }

.post-body { margin-top: 1.5rem; }
.post-body p { margin: 0 0 1.1rem; }
.post-body a { word-break: break-word; }
.post-body img { max-width: 100%; height: auto; border-radius: .4rem; }

/* The reset above zeroes every margin, so each block the post body can
   contain has to ask for its own spacing back. Post HTML comes from the
   fediverse and can hold anything, so this covers the whole set rather than
   the tags a given post happens to use. */
.post-body h2, .post-body h3, .post-body h4 { margin: 1.75rem 0 .6rem; line-height: 1.3; }
.post-body > :first-child { margin-top: 0; }
.post-body ul, .post-body ol { margin: 0 0 1.1rem; padding-left: 1.5rem; }
.post-body li { margin-bottom: .3rem; }
.post-body hr { margin: 1.75rem 0; border: 0; border-top: 1px solid var(--line); }
.post-body pre {
    overflow-x: auto;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: .4rem;
    padding: .9rem;
    margin: 0 0 1.1rem;
}
.post-body blockquote {
    margin: 0 0 1.1rem;
    padding-left: 1rem;
    border-left: 3px solid var(--line);
    color: var(--text-soft);
}

.post-media {
    display: grid;
    /* auto-fit, not auto-fill: empty tracks collapse, so a post with one
       attachment gets one full-measure figure instead of a 14rem thumbnail
       stranded at the left edge. */
    grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
    gap: 1rem;
    margin-top: 1.5rem;
}
.post-media-item { border-radius: .4rem; overflow: hidden; background: var(--surface); }
.post-media-item img,
.post-media-item video { display: block; width: 100%; height: auto; border-radius: .4rem; }
.post-media-item audio { width: 100%; }
.post-media-item figcaption {
    padding: .5rem .1rem 0;
    color: var(--muted);
    font-size: .8125rem;
}
.post-media-cw {
    margin-top: 1.5rem;
    border: 1px solid var(--line);
    border-radius: .4rem;
    padding: .75rem 1rem;
}
.post-media-cw summary { cursor: pointer; font-weight: 600; color: var(--text-soft); }
.post-media-cw .post-media { margin-top: 1rem; }

.fediverse-thread-link { margin-top: 1.5rem; font-size: .9375rem; }

.post-replies { margin-top: 2.5rem; border-top: 1px solid var(--line); padding-top: 1rem; }
.reply-list { padding-left: 1.5rem; }
.blog-reply { margin: 1rem 0; }
.blog-reply header { color: var(--muted); font-size: .9rem; }

.post-pager {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--line);
    font-size: .9375rem;
}
.post-pager a { text-decoration: none; }

.back-link { margin-top: 2rem; font-size: .9375rem; }

.site-footer {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 1.5rem 1.25rem 2.5rem;
    color: var(--muted);
    font-size: .8125rem;
}

.archive-year {
    font-size: 1.1rem;
    margin: 2rem 0 .5rem;
    padding-bottom: .35rem;
    border-bottom: 1px solid var(--line);
}
.archive-year:first-of-type { margin-top: 0; }
.archive-entry {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .6rem;
    padding: .6rem 0;
    border-bottom: none;
}
.archive-entry time { color: var(--muted); font-size: .8125rem; flex: 0 0 auto; }
.archive-entry a { text-decoration: none; color: var(--text); }
.archive-entry a:hover, .archive-entry a:focus { color: var(--accent-strong); }

.tag-list { list-style: none; }
.tag-list li {
    display: flex;
    justify-content: space-between;
    padding: .6rem 0;
    border-bottom: 1px solid var(--line);
}
.tag-list a { text-decoration: none; color: var(--text); }
.tag-list a:hover, .tag-list a:focus { color: var(--accent-strong); }
.tag-count { color: var(--muted); font-size: .875rem; }

@media (max-width: 30rem) {
    .site-header { padding-top: 1.5rem; }
    article h1 { font-size: 1.5rem; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* On paper the navigation leads nowhere, so it goes; link targets inside the
   post do not survive the trip either, so they are spelled out. */
@media print {
    body { background: #fff; color: #000; font-size: 11pt; }
    .skip-link, .site-nav, .post-pager, .back-link, .fediverse-thread-link { display: none; }
    a { color: #000; }
    .post-body a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; word-break: break-all; }
    .post-body pre, .post-media-item { break-inside: avoid; }
}


/* theme: press */
/* Press - the reading half of the web UI theme of the same name.
 *
 * Two flat inks on stock paper, printed slightly out of register. The web UI
 * gives every card a plate offset by a few pixels; a published page has fewer
 * boxes to do that to, so here the second ink goes where a reader's eye
 * already travels: under every link, along the colophon beneath each title,
 * and around the pictures and the code.
 *
 * The display face is served by the instance at /static/press-display.woff2,
 * the same file the web UI theme loads, so a reader who has been signed in
 * already has it cached. Every rule names a fallback.
 *
 * The font is addressed absolutely rather than copied into the
 * generated site, because the same binary serves both. A site rsynced to a
 * separate web server loses the display face and falls back to the system
 * stack, which every rule below is written to survive. Copy the file next to
 * style.css and change the URL here if that ever stops being true. */

@font-face {
    font-family: 'Press Display';
    src: url("/static/press-display.woff2") format("woff2");
    font-weight: 400 800;
    font-style: normal;
    font-display: swap;
}

:root {
    --bg: #e8eaee;
    --surface: #f7f8fa;
    --text: #14182b;
    --text-soft: #2c3247;
    --muted: #545b70;
    --line: #c8ccd6;
    --accent: #2438c8;
    --accent-strong: #1b2aa0;
    --max-width: 38rem;
    --font-display: 'Press Display', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    /* The second ink, and the distance the plate misses the first one by. */
    --second: #e11d63;
    --plate: #f0b3c9;
    --reg: 4px;
    --halftone: rgba(20, 24, 43, .09);
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0e0f14;
        --surface: #171923;
        --text: #eceef5;
        --text-soft: #c9cedd;
        --muted: #98a0b5;
        --line: #2a2f3e;
        --accent: #7c8cff;
        --accent-strong: #a3aeff;
        --second: #ff6e9c;
        --plate: rgba(255, 110, 156, .45);
        --halftone: rgba(236, 238, 245, .05);
    }
}

/* The halftone lattice, small enough to read as tone rather than as dots. */
body {
    background-image: radial-gradient(circle at 1px 1px, var(--halftone) 1px, transparent 0);
    background-size: 6px 6px;
}

/* Every link is printed twice: the word in the first ink, the rule under it in
   the second. */
a {
    text-decoration-color: var(--second);
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
}

/* ---------- Nameplate ---------- */
.site-header {
    padding-bottom: 1.1rem;
    border-bottom: 2px solid var(--text);
    box-shadow: 0 var(--reg) 0 var(--plate);
    margin-bottom: var(--reg);
}
.site-brand a {
    font-family: var(--font-display);
    font-size: 1.75rem;
    font-weight: 800;
    letter-spacing: -.035em;
    text-decoration: none;
}
.site-nav a {
    font-family: var(--font-display);
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    text-decoration: none;
}
.site-nav a:hover, .site-nav a:focus { text-decoration: underline; }

/* ---------- Titles and the colophon ---------- */
.post-summary h2,
article h1,
.archive-year,
.post-replies h2 {
    font-family: var(--font-display);
    letter-spacing: -.03em;
}
article h1 { font-size: 2.1rem; font-weight: 800; }
.post-summary h2 { font-size: 1.4rem; font-weight: 750; }
.post-summary h2 a { text-decoration: none; }

/* The colophon: the line a printer sets under a title to say when and where.
   Same ink as the links, same register as the labels in the web UI. */
.post-meta {
    font-family: var(--font-display);
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--accent-strong);
}
.post-meta a { color: var(--accent-strong); text-decoration-color: var(--plate); }

.site-description { font-size: 1.05rem; }
.post-summary { padding: 1.75rem 0; border-bottom: 1px solid var(--line); }
.post-summary:last-child { border-bottom: 0; }

/* ---------- Body ---------- */
.post-body { font-size: 1.0625rem; line-height: 1.72; }
.post-body h2, .post-body h3, .post-body h4 {
    font-family: var(--font-display);
    letter-spacing: -.02em;
}
.post-body blockquote {
    border-left: 3px solid var(--second);
    color: var(--text-soft);
}
/* Boxed things carry the plate, the way the cards do in the web UI. */
.post-body pre,
.post-media-item,
.post-media-cw {
    border-radius: 2px;
    box-shadow: var(--reg) var(--reg) 0 var(--plate);
}
.post-body pre { border-color: var(--line); }
.post-body img,
.post-media-item img,
.post-media-item video { border-radius: 0; }
.post-media-item { border: 1px solid var(--line); }
.post-media-item figcaption {
    padding: .55rem .65rem;
    font-style: italic;
}

/* ---------- Foot of the page ---------- */
.post-replies { border-top: 2px solid var(--text); }
.blog-reply header { font-family: var(--font-display); letter-spacing: .04em; }
.post-pager { border-top: 2px solid var(--line); }
.post-pager a,
.back-link a,
.fediverse-thread-link a {
    font-family: var(--font-display);
    font-size: .8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .055em;
}
.archive-year { border-bottom: 2px solid var(--line); }
.archive-entry time { font-variant-numeric: tabular-nums; }
.tag-count { font-variant-numeric: tabular-nums; }
.site-footer { border-top: 1px solid var(--line); margin-top: 2rem; padding-top: 1.25rem; }
.skip-link { border-radius: 0; }

@media print {
    body { background-image: none; }
    .site-header { box-shadow: none; }
    .post-body pre, .post-media-item, .post-media-cw { box-shadow: none; }
}
