/* The default stylesheet.
 *
 * The eleven colour variables and the four typography variables below are the
 * *contract*: `appearance::ColorPalette` and `appearance::TypographySettings`
 * write exactly these names, and `html::css` appends what they write after this
 * file. Every rule here therefore reads a variable rather than a literal, and
 * the dark values live in a bare `@media (prefers-color-scheme: dark) { :root }`
 * so a caller's override — which has the same shape and comes later — wins.
 *
 * Names that begin `--_` are this file's own, derived from the contract with
 * `color-mix` so that a caller who supplies only an accent still gets tints,
 * rules and focus rings in their own colour.
 */

:root {
    /* ── Contract: colour ── */
    --bg: #fafaf9;
    --text: #14181f;
    --text-muted: #5b6674;
    /* blue-600 rather than blue-500: 5.2:1 on the page background, so link text
       clears WCAG AA where the lighter blue did not. */
    --accent: #2563eb;
    --accent-hover: #1d4ed8;
    --border: #e3e5e9;
    --code-bg: #f2f3f5;
    --surface-bg: rgba(255, 255, 255, 0.95);
    --surface-border: rgba(15, 23, 42, 0.08);
    --surface-shadow: 0 1px 3px rgba(15, 23, 42, 0.08), 0 8px 24px rgba(15, 23, 42, 0.06);
    --divider-color: rgba(15, 23, 42, 0.1);

    /* ── Contract: typography ── */
    --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    --font-size: 16px;
    --line-height: 1.7;
    /* ~72 characters in the default stack: the top of the comfortable range for
       running prose, and wide enough that a fenced code line rarely scrolls. */
    --content-max-width: 44rem;

    /* ── Local ── */
    --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Consolas, monospace;
    --line-height-tight: 1.25;
    --sidebar-width: 16rem;
    /* How far down anything under the fixed mobile bar has to start. The bar
       is a little under 3.5rem tall, so this clears it with room to spare. The
       drawer and the page both read it, because the bar sits over both and a
       change to its size must move both. Only consulted below the nav
       breakpoint, where the bar is shown. */
    --nav-toggle-clear: 4.5rem;
    --page-pad-x: 1.5rem;
    --radius: 0.5rem;
    --radius-sm: 0.3rem;
    --_accent-tint: color-mix(in oklab, var(--accent) 10%, transparent);
    --_accent-tint-strong: color-mix(in oklab, var(--accent) 22%, transparent);
    --_accent-rule: color-mix(in oklab, var(--accent) 45%, transparent);
    /* An underline that reads as one without competing with the text over it. */
    --_faint-underline: color-mix(in oklab, currentColor 35%, transparent);

    /* Syntax highlighting. Literals rather than mixes of `--accent`: a palette
       derived from one hue is a palette whose colours are hard to tell apart,
       which is the one thing highlighting exists to do. Chosen against
       `--code-bg` rather than `--bg`, since that is what they are read on, and
       kept above 4.5:1 on it so a comment is still text and not decoration.
       File-local like every other `--_` name, and overridable by a caller's
       sheet on the same terms. */
    --_syn-comment: #6a7580;
    --_syn-string: #0a7040;
    --_syn-keyword: #9526a0;
    --_syn-entity: #2b62d9;
    --_syn-constant: #98590a;
    --_syn-support: #016a99;
    --_syn-invalid: #c02617;

    /* Let the user agent paint scrollbars, checkboxes and text fields to match
       the mode. Without it a dark page keeps light scrollbars and a light
       task-list checkbox, which is what the two palettes here are for.
       It follows the *preference*, not the palette — so a caller who overrides
       `--bg` and friends for one mode only, pinning a light page in a browser
       set to dark, should pin `color-scheme` alongside it. */
    color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
    :root {
        /* Not pure black against near-white: the softened pair cuts the halation
           that makes long reading on an OLED display tiring. */
        --bg: #0e1015;
        --text: #e6eaf0;
        --text-muted: #9aa5b4;
        --accent: #7cb0fb;
        --accent-hover: #a9cbfd;
        --border: #2b3341;
        --code-bg: #171b23;
        --surface-bg: rgba(23, 27, 35, 0.95);
        --surface-border: rgba(255, 255, 255, 0.1);
        --surface-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), 0 12px 32px rgba(0, 0, 0, 0.4);
        --divider-color: rgba(255, 255, 255, 0.1);

        --_syn-comment: #7f8b99;
        --_syn-string: #9ece6a;
        --_syn-keyword: #c678dd;
        --_syn-entity: #7aa2f7;
        --_syn-constant: #e0af68;
        --_syn-support: #56b6c2;
        --_syn-invalid: #f7768e;
    }
}

* { box-sizing: border-box; }

html {
    scroll-behavior: smooth;
}

body {
    font-family: var(--font-family);
    font-size: var(--font-size);
    line-height: var(--line-height);
    color: var(--text);
    background: var(--bg);
    max-width: var(--content-max-width);
    margin: 0 auto;
    padding: 2.5rem var(--page-pad-x) 5rem;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* A long URL, a long identifier or a wide inline code span must not push
       the page sideways; only the elements that scroll on purpose do. */
    overflow-wrap: break-word;
}

::selection {
    background: var(--_accent-tint-strong);
    color: var(--text);
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Anchor jumps land clear of the top of the window rather than flush against
   it, and clear of the fixed nav button on a narrow screen. */
:target,
.content :is(h1, h2, h3, h4, h5, h6) {
    scroll-margin-top: 2rem;
}

/* ── Content typography ── */

a {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 0.15em;
    text-decoration-thickness: from-font;
}

a:hover {
    color: var(--accent-hover);
}

/* A link whose target isn't published for this audience — a page the gate
   refused, or a file whose sidecar says it is for someone else, in the place
   its picture or player would have been: kept as text so the page reads
   naturally, but visibly inert (muted, dotted underline). */
.unpublished-link {
    color: var(--text-muted);
    text-decoration: underline dotted;
    text-underline-offset: 2px;
    cursor: not-allowed;
}

.content h1, .content h2, .content h3, .content h4, .content h5, .content h6 {
    margin-top: 2.5rem;
    margin-bottom: 0.5rem;
    line-height: var(--line-height-tight);
    letter-spacing: -0.011em;
    font-weight: 650;
    text-wrap: balance;
}

/* A whole scale, so that h4–h6 stay headings. Left to the user agent, h5 and h6
   come out *smaller* than the body text they introduce. */
.content h1 { font-size: 2.1rem; letter-spacing: -0.02em; }
.content h2 { font-size: 1.55rem; }
.content h3 { font-size: 1.25rem; }
.content h4 { font-size: 1.08rem; }
.content h5 { font-size: 1rem; }
.content h6 {
    font-size: 0.85rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* Whatever opens the body opens it: no leading gap above the first element,
   whichever element that turns out to be. */
.content > :first-child {
    margin-top: 0;
}

/* The link every heading carries to itself (`plates_render::headings`).
   Invisible until the heading is hovered or the link itself focused, so a
   page reads as prose and a reader who wants the anchor can still find it
   with a mouse or by tabbing. */
.heading-anchor {
    margin-left: 0.35em;
    font-weight: 400;
    text-decoration: none;
    color: var(--text-muted);
    opacity: 0;
    transition: opacity 0.15s;
}

.content :is(h1, h2, h3, h4, h5, h6):hover > .heading-anchor,
.heading-anchor:focus-visible {
    opacity: 1;
}

.heading-anchor:hover {
    color: var(--accent);
}

.content p {
    margin: 1rem 0;
    text-wrap: pretty;
}

.content ul, .content ol {
    margin: 1rem 0;
    padding-left: 1.6rem;
}

.content li {
    margin: 0.3rem 0;
}

.content li > ul, .content li > ol {
    margin: 0.3rem 0;
}

.content dl {
    margin: 1rem 0;
}

.content dt {
    font-weight: 650;
    margin-top: 1rem;
}

.content dd {
    margin: 0.25rem 0 0 1.6rem;
    color: var(--text-muted);
}

.content pre {
    background: var(--code-bg);
    border: 1px solid var(--border);
    padding: 0.9rem 1rem;
    border-radius: var(--radius);
    overflow-x: auto;
    line-height: 1.55;
    font-size: 0.875em;
    tab-size: 4;
}

.content code {
    background: var(--code-bg);
    /* Tight horizontally: a wider inset reads as a space before the comma or
       colon that so often follows an inline `code` span. */
    padding: 0.15em 0.3em;
    border-radius: var(--radius-sm);
    font-size: 0.875em;
    font-family: var(--font-mono);
}

.content pre code {
    background: none;
    padding: 0;
    font-size: inherit;
}

/* ── Syntax highlighting ──
 *
 * `plates_render::syntax` emits a class per atom of the Sublime scope it
 * matched, each prefixed `plates-`: `keyword.control.rust` arrives as
 * `plates-keyword plates-control plates-rust`. So these select the *first*
 * atom, which is the one that names what a token is.
 *
 * Two things decide the order of the rules below, and both are load-bearing:
 *
 * 1. Every selector here is one class, so they all have the same specificity
 *    and the last matching rule wins. A scope's atoms overlap — the `"` opening
 *    a string is `punctuation.definition.string.begin`, carrying *both*
 *    `plates-punctuation` and `plates-string` — so the rule that should win
 *    goes later. Punctuation is therefore first: a quote inside a string reads
 *    as string, a `//` inside a comment reads as comment, and neither is left
 *    a different colour from the token it belongs to.
 *
 * 2. `plates-meta` is deliberately absent. `meta.function` wraps a whole
 *    function, signature and body together, so colouring it would flood
 *    everything nested inside with one colour and undo the rest of this block.
 *
 * Scoped to `.plates-highlighted` — the class the pass adds only to blocks it
 * actually coloured — so a fence in a language no grammar covers keeps the
 * plain `<pre>` treatment above rather than half of this one.
 */
.content pre code.plates-highlighted .plates-punctuation { color: var(--_syn-comment); }
.content pre code.plates-highlighted .plates-keyword,
.content pre code.plates-highlighted .plates-storage { color: var(--_syn-keyword); }
.content pre code.plates-highlighted .plates-entity,
.content pre code.plates-highlighted .plates-variable { color: var(--_syn-entity); }
.content pre code.plates-highlighted .plates-support { color: var(--_syn-support); }
.content pre code.plates-highlighted .plates-constant { color: var(--_syn-constant); }
.content pre code.plates-highlighted .plates-string { color: var(--_syn-string); }
.content pre code.plates-highlighted .plates-comment { color: var(--_syn-comment); font-style: italic; }
.content pre code.plates-highlighted .plates-invalid { color: var(--_syn-invalid); }

.content kbd {
    font-family: var(--font-mono);
    font-size: 0.8em;
    padding: 0.15em 0.4em;
    border: 1px solid var(--border);
    border-bottom-width: 2px;
    border-radius: var(--radius-sm);
    background: var(--code-bg);
}

/* Not italic: a pull quote is often several sentences, and a run of italic that
   long is harder to read than the text around it. The rule and the tint mark it
   instead. */
.content blockquote {
    border-left: 3px solid var(--_accent-rule);
    margin: 1.5rem 0;
    padding: 0.25rem 0 0.25rem 1.25rem;
    color: var(--text-muted);
}

.content blockquote > :first-child { margin-top: 0; }
.content blockquote > :last-child { margin-bottom: 0; }

/* `width: max-content` with `max-width: 100%` is what makes a table that does
   not fit scroll *inside itself* rather than widening the page. It costs the
   full-bleed look for a table that would have fitted, which is the cheaper of
   the two — a clipped table is unreadable, a narrow one is not. */
.content table {
    display: block;
    width: max-content;
    max-width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    margin: 1.5rem 0;
    font-size: 0.94em;
    line-height: 1.5;
}

.content th, .content td {
    border: none;
    border-bottom: 1px solid var(--border);
    padding: 0.55rem 0.9rem;
    text-align: left;
    vertical-align: top;
}

.content th {
    background: none;
    font-weight: 650;
    border-bottom: 2px solid var(--border);
    white-space: nowrap;
}

.content tbody tr:last-child td {
    border-bottom: none;
}

.content th:first-child, .content td:first-child { padding-left: 0; }
.content th:last-child, .content td:last-child { padding-right: 0; }

.content img {
    max-width: 100%;
    height: auto;
    border-radius: var(--radius);
}

.content figure {
    margin: 1.5rem 0;
}

.content figcaption {
    margin-top: 0.5rem;
    font-size: 0.875rem;
    color: var(--text-muted);
    text-align: center;
}

.content details {
    margin: 1rem 0;
    padding: 0.75rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.content summary {
    cursor: pointer;
    font-weight: 600;
}

.content details[open] > summary {
    margin-bottom: 0.5rem;
}

/* ── The outline ──
 *
 * Two things wear `nav.toc`: the single-file render's table of contents, with
 * an `<h2>` and a flat list, and a site page's "On this page" block, a
 * `<details>` over a nested list of the page's own headings. Below the rail
 * breakpoint the page's outline is a box above the content, closed by the
 * built-in script so a long outline does not push the prose down; at width it
 * moves out to the right-hand margin and stays put while the page scrolls.
 */

nav.toc {
    border: 1px solid var(--border);
    padding: 1rem 1.25rem;
    border-radius: var(--radius);
    margin-bottom: 2.5rem;
    font-size: 0.875rem;
    line-height: 1.5;
}

nav.toc h2,
nav.toc summary {
    margin: 0 0 0.5rem;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

nav.toc summary {
    cursor: pointer;
    list-style: none;
}

nav.toc summary::-webkit-details-marker {
    display: none;
}

nav.toc details:not([open]) > summary {
    margin-bottom: 0;
}

nav.toc ul {
    margin: 0;
    padding-left: 1.1rem;
}

nav.toc li {
    margin: 0.3rem 0;
}

nav.toc a {
    color: var(--text-muted);
    text-decoration: none;
}

nav.toc a:hover {
    color: var(--accent);
    text-decoration: underline;
}

/* At width the outline is a rail in the right-hand margin, fixed so it stays
   beside the reader as the page scrolls. 88rem is where a 12rem rail fits
   beside a 44rem measure and a 16rem sidebar with the margins the layout
   already leaves; a narrower window keeps the box above the content. */
@media (min-width: 88rem) {
    .site-content nav.toc {
        position: fixed;
        top: 2.5rem;
        right: 1.25rem;
        width: 12rem;
        max-height: calc(100dvh - 5rem);
        overflow-y: auto;
        margin: 0;
        padding: 0;
        border: none;
        border-left: 1px solid var(--divider-color);
        border-radius: 0;
        padding-left: 1rem;
    }

    .site-content nav.toc summary {
        pointer-events: none;
    }

    .site-content nav.toc ul {
        padding-left: 0;
        list-style: none;
    }

    .site-content nav.toc ul ul {
        padding-left: 0.75rem;
    }
}

/* ── Layout misc ── */

hr,
.content hr {
    border: none;
    border-top: 1px solid var(--divider-color);
    margin: 3rem 0;
}

section {
    margin-bottom: 2rem;
}

footer {
    margin-top: 4rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--divider-color);
    color: var(--text-muted);
    font-size: 0.875rem;
}

footer p {
    margin: 0.5rem 0;
}

/* The site's own header and footer documents, and the attribution line. An
   empty element is one the site declared nothing for, and it costs no space. */
.site-header:empty,
.site-footer:empty {
    display: none;
}

.site-header {
    margin-bottom: 2rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--divider-color);
    color: var(--text-muted);
    font-size: 0.9rem;
}

.site-header > :first-child,
.site-footer > :first-child {
    margin-top: 0;
}

.site-header > :last-child,
.site-footer > :last-child {
    margin-bottom: 0;
}

/* A list in the header is a row of links, which is what a header's list is. */
.site-header ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.25rem;
}

.site-footer ul {
    padding-left: 1.25rem;
}

.site-footer .generator {
    margin-top: 1rem;
    font-size: 0.8rem;
}

footer a {
    color: var(--text-muted);
    text-decoration-color: var(--_faint-underline);
}

footer a:hover {
    color: var(--accent);
    text-decoration-color: currentColor;
}

/* ── Skip link ──
 *
 * The first thing in the body: off-screen until focused, so a keyboard reader
 * can step past the sidebar to `#content` in one tab.
 */

.skip-link {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    z-index: 1020;
    padding: 0.5rem 0.75rem;
    background: var(--bg);
    color: var(--accent);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    transform: translateY(-200%);
}

.skip-link:focus {
    transform: none;
}

/* ── Site navigation sidebar ── */

/* The mobile bar: the menu button and the masthead, shown only below the nav
   breakpoint, where it is the spelling of the sidebar's own masthead. */
.site-bar {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1010;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem var(--page-pad-x);
    background: var(--surface-bg);
    border-bottom: 1px solid var(--surface-border);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
}

/* The drawer's state is a checkbox ahead of the bar and the nav, so opening
   is `:checked ~` and needs no script — a page inside a frame that runs none
   still has a menu. Hidden by clipping rather than `display: none`, which
   would take it out of the tab order and the label's reach. */
.nav-toggle-state {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.nav-toggle {
    background: none;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 0.35rem 0.7rem;
    font: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    color: var(--text);
    line-height: 1.2;
    user-select: none;
    -webkit-user-select: none;
}

.nav-toggle-state:checked ~ .site-bar .nav-toggle {
    background: var(--_accent-tint);
    border-color: var(--_accent-rule);
    color: var(--accent);
}

.nav-toggle-state:focus-visible ~ .site-bar .nav-toggle {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* The site's name, linking home. In the sidebar it heads the tree; in the
   mobile bar it sits beside the button. */
.site-masthead {
    display: block;
    font-weight: 650;
    font-size: 1rem;
    letter-spacing: -0.011em;
    color: var(--text);
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.site-masthead:hover {
    color: var(--accent);
}

.site-nav > .site-masthead {
    margin: 0 0.55rem 1rem;
}

.site-masthead[aria-current] {
    color: var(--accent);
}

.site-nav {
    position: fixed;
    top: 0;
    left: 0;
    width: var(--sidebar-width);
    height: 100dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
    padding: 2.5rem 0.75rem 3rem;
    border-right: 1px solid var(--divider-color);
    background: var(--bg);
    z-index: 1000;
    font-size: 0.9rem;
    line-height: 1.45;
}

/* The sidebar is fixed, so the page it sits beside is offset by *padding on the
   body*: that holds whatever the shell puts inside it, including a template's
   own markup, rather than depending on one wrapper element existing.
   `body.has-site-nav`, not `.has-site-nav body` — the class is on the body, and
   an element is not its own descendant. */
body.has-site-nav {
    max-width: none;
    padding-left: calc(var(--sidebar-width) + var(--page-pad-x));
}

/* …and the measure moves down to the column, which centres in what is left. */
.has-site-nav .site-content {
    max-width: var(--content-max-width);
    margin-inline: auto;
}

.nav-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* A guide line down each nested level: at three levels deep the indent alone
   stops being legible. */
.nav-list .nav-list {
    margin-left: 0.75rem;
    padding-left: 0.5rem;
    border-left: 1px solid var(--divider-color);
}

.nav-list li {
    margin: 0.05rem 0;
}

.nav-list a {
    display: block;
    padding: 0.3rem 0.55rem;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    text-decoration: none;
    transition: background 0.15s, color 0.15s;
}

.nav-list a:hover {
    background: var(--code-bg);
    color: var(--text);
}

.nav-current > a,
.nav-current > details > summary > a {
    background: var(--_accent-tint);
    color: var(--accent);
    font-weight: 600;
}

.nav-ancestor > a,
.nav-ancestor > details > summary > a {
    color: var(--text);
    font-weight: 500;
}

/* A section is a disclosure: the link is the summary's content and the
   chevron beside it is the summary itself, so the title navigates and the
   chevron opens. The user-agent marker is replaced because it sits before the
   text and reads as a bullet. */
.nav-section > details > summary {
    display: flex;
    align-items: center;
    list-style: none;
    cursor: pointer;
}

.nav-section > details > summary::-webkit-details-marker {
    display: none;
}

.nav-section > details > summary > a {
    flex: 1 1 auto;
    min-width: 0;
}

.nav-section > details > summary::after {
    content: "";
    flex: 0 0 auto;
    width: 0.45em;
    height: 0.45em;
    margin: 0 0.6rem 0 0.4rem;
    border-right: 1.5px solid var(--text-muted);
    border-bottom: 1.5px solid var(--text-muted);
    transform: rotate(-45deg);
    transition: transform 0.15s;
    opacity: 0.7;
}

.nav-section > details[open] > summary::after {
    transform: rotate(45deg);
}

.nav-section > details > summary:hover::after {
    opacity: 1;
    border-color: var(--text);
}

/* ── Pager ── */

.pager {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 3rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--divider-color);
    font-size: 0.9rem;
}

.pager a {
    display: block;
    max-width: 48%;
    text-decoration: none;
    font-weight: 550;
}

.pager a:hover {
    text-decoration: underline;
}

.pager a span {
    display: block;
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.pager-next {
    margin-left: auto;
    text-align: right;
}

/* ── Breadcrumbs (single parent link, and the full trail) ── */

.breadcrumb,
.breadcrumbs {
    margin-bottom: 0.75rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.breadcrumb a,
.breadcrumbs a {
    color: var(--text-muted);
    text-decoration: none;
}

.breadcrumb a:hover,
.breadcrumbs a:hover {
    color: var(--accent);
    text-decoration: underline;
}

.breadcrumb-sep {
    margin: 0 0.4rem;
    color: var(--text-muted);
    opacity: 0.5;
}

/* ── Attachments ── */

/* A sidecar's page: the payload, shown as what it is. The frame a document
   sits in takes the column's width and a tall, bounded height; a picture is
   a figure like any the prose would carry. */
.attachment {
    margin: 0 0 1.25rem;
}

.attachment img,
.attachment video {
    display: block;
    max-width: 100%;
    height: auto;
    border-radius: var(--radius-sm);
}

.attachment audio {
    display: block;
    width: 100%;
}

.attachment iframe {
    display: block;
    width: 100%;
    height: min(80vh, 60rem);
    border: 1px solid var(--surface-border);
    border-radius: var(--radius-sm);
    background: var(--surface-bg);
}

.attachment-download {
    font-size: 0.9rem;
}

/* ── Responsive ── */

@media (max-width: 60rem) {
    .site-bar {
        display: flex;
    }

    /* The drawer slides out *underneath* the bar, so its own first item
       needs the same clearance the page gets; and the bar already names the
       site, so the drawer's own masthead is redundant there. */
    .site-nav {
        padding-top: var(--nav-toggle-clear);
        transform: translateX(-100%);
        transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
        box-shadow: none;
    }

    .site-nav > .site-masthead {
        display: none;
    }

    .nav-toggle-state:checked ~ .site-nav {
        transform: translateX(0);
        box-shadow: 4px 0 16px rgba(0, 0, 0, 0.1);
    }

    /* Clear the fixed bar, which would otherwise sit on top of the first
       heading. */
    body.has-site-nav {
        padding-left: var(--page-pad-x);
        padding-top: var(--nav-toggle-clear);
    }
}

/* Only the frame tightens on a phone. The body size is deliberately left alone:
   the old rule set `font-size: 15px` on the body, which threw away whatever a
   caller had put in `--font-size` — and 16px is the size at which iOS stops
   zooming a focused field anyway. */
@media (max-width: 600px) {
    :root {
        --page-pad-x: 1.1rem;
    }

    body {
        padding-top: 1.5rem;
    }

    .content h1 { font-size: 1.75rem; }
    .content h2 { font-size: 1.35rem; }
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

@media print {
    :root {
        --bg: #fff;
        --text: #000;
        --text-muted: #444;
    }

    .site-nav, .site-bar, .skip-link, .pager, nav.toc { display: none; }

    .heading-anchor { display: none; }

    body.has-site-nav {
        padding-left: 0;
        padding-top: 0;
    }

    body {
        max-width: none;
        font-size: 11pt;
    }

    .content pre, .content table, .content blockquote, .content img {
        break-inside: avoid;
    }

    .content :is(h1, h2, h3) {
        break-after: avoid;
    }
}

/* ── Colored highlights ── */

.highlight-mark {
    background: none;
    padding: 0.1em 0.2em;
    border-radius: 0.2em;
    /* The user agent forces `color: MarkText` — near-black — on `<mark>`, which
       is unreadable on the dark-mode swatches below. */
    color: inherit;
}

.highlight-red { background: oklch(0.92 0.12 25); }
.highlight-orange { background: oklch(0.93 0.1 60); }
.highlight-yellow { background: oklch(0.95 0.12 95); }
.highlight-green { background: oklch(0.92 0.08 145); }
.highlight-cyan { background: oklch(0.92 0.08 195); }
.highlight-blue { background: oklch(0.88 0.1 250); }
.highlight-violet { background: oklch(0.9 0.1 300); }
.highlight-pink { background: oklch(0.93 0.1 350); }
.highlight-brown { background: oklch(0.88 0.06 60); }
.highlight-grey { background: oklch(0.9 0 0); }

@media (prefers-color-scheme: dark) {
    .highlight-red { background: oklch(0.35 0.12 25); }
    .highlight-orange { background: oklch(0.38 0.1 60); }
    .highlight-yellow { background: oklch(0.42 0.12 95); }
    .highlight-green { background: oklch(0.38 0.08 145); }
    .highlight-cyan { background: oklch(0.38 0.08 195); }
    .highlight-blue { background: oklch(0.35 0.1 250); }
    .highlight-violet { background: oklch(0.38 0.1 300); }
    .highlight-pink { background: oklch(0.4 0.1 350); }
    .highlight-brown { background: oklch(0.38 0.06 60); }
    .highlight-grey { background: oklch(0.4 0 0); }
}

/* ── Spoilers ── */

.spoiler-mark {
    cursor: pointer;
    border-radius: 0.2em;
    padding: 0.1em 0.3em;
    transition: background 0.2s, color 0.2s;
}

.spoiler-hidden {
    background: var(--text);
    color: transparent;
    user-select: none;
}

.spoiler-revealed {
    background: var(--code-bg);
    color: var(--text);
}

/* ── Footnotes ──
 *
 * Two spellings, because two engines have rendered these pages. comrak used
 * `.footnotes` / `.footnote-ref`; twig, which replaced it so Djot and HTML
 * could be published at all, uses the DPUB-ARIA roles (`doc-endnotes`,
 * `doc-noteref`, `doc-backlink`). Both are styled so a site published before
 * that change and one published after look the same — the CSS is served fresh
 * on every publish, but the pages in a namespace are not all re-rendered.
 */

.footnotes,
[role="doc-endnotes"] {
    margin-top: 3rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--divider-color);
    font-size: 0.875rem;
    color: var(--text-muted);
}

/* twig opens its endnotes section with its own rule; the section's border-top
   above is already the separator, so a second one reads as a double line. */
[role="doc-endnotes"] > hr {
    display: none;
}

.footnotes ol,
[role="doc-endnotes"] ol {
    padding-left: 1.5rem;
}

.footnotes li,
[role="doc-endnotes"] li {
    margin: 0.5rem 0;
}

/* Jumping to a note is a jump to a one-line target in a page of small grey
   text; without this the reader has to find it again by eye. */
.footnotes li:target,
[role="doc-endnotes"] li:target {
    background: var(--_accent-tint);
    border-radius: var(--radius-sm);
    box-shadow: 0 0 0 0.4rem var(--_accent-tint);
}

.footnote-ref a, .footnotes a,
a[role="doc-noteref"], [role="doc-endnotes"] a {
    color: var(--accent);
    text-decoration: none;
    font-weight: 500;
}

.footnote-ref a:hover, .footnotes a:hover,
a[role="doc-noteref"]:hover, [role="doc-endnotes"] a:hover {
    text-decoration: underline;
}

sup.footnote-ref,
a[role="doc-noteref"] sup {
    font-size: 0.75em;
    line-height: 0;
    vertical-align: super;
}

/* The return arrow sits immediately after the note's last word otherwise. */
a[role="doc-backlink"],
.footnotes .footnote-backref {
    margin-left: 0.4em;
    text-decoration: none;
}

/* ── Generated index ──
 *
 * The markup `site::synthesize_index` writes for a site with no authored front
 * page: a `<ul>` of entries, optionally inside a `<section>` per group.
 */

.entry-group {
    margin-bottom: 2.5rem;
}

.entry-group h2 {
    font-size: 0.85rem;
    margin-bottom: 0.75rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid var(--divider-color);
    color: var(--text-muted);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* Qualified with `.content` throughout, so that these outweigh the `.content
   ul` / `.content li` / `.content pre` rules above — which are more specific
   than a bare class and would otherwise put the list indent and the code-block
   border back. */
.content .entry-list,
.entry-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.content .entry-list li,
.entry-list li {
    margin: 0.75rem 0;
    padding-left: 0;
}

.entry-list a {
    text-decoration: none;
    font-weight: 550;
}

.entry-list a:hover {
    text-decoration: underline;
}

.entry-description {
    display: block;
    color: var(--text-muted);
    font-size: 0.9rem;
    line-height: 1.5;
}

/* ── Task lists ──
 *
 * twig marks the list rather than each item (`<ul class="task-list">`), so the
 * bullet has to be removed on the list and the indent given back by hand. The
 * selector is qualified with `.content` so that it outweighs `.content ul`,
 * which would otherwise keep the ordinary list indent it sets.
 */

.content .task-list,
.task-list {
    list-style: none;
    padding-left: 0.15rem;
}

.content .task-list li,
.task-list li {
    padding-left: 0;
}

.task-list input[type="checkbox"] {
    margin-right: 0.5rem;
    accent-color: var(--accent);
    vertical-align: baseline;
}

/* ── Embedded islands ──
 *
 * An HTML attachment embedded with `![alt](page.html)`. The `min-height` and
 * the final height both come from the tag — authored via `{height=…}`, then
 * measured by the resize bridge — so nothing here may set a height.
 */

.diaryx-island {
    display: block;
    width: 100%;
    margin: 1.5rem 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    color-scheme: light dark;
}

/* ── Unrendered bodies ──
 *
 * A body the parser refused, shown as escaped source rather than dropped. It is
 * a failure the reader can see, so it is marked as one instead of passing for
 * an ordinary code block.
 */

.content .diaryx-unrendered,
.diaryx-unrendered {
    background: var(--code-bg);
    border: none;
    border-left: 3px solid var(--text-muted);
    padding: 1rem;
    border-radius: var(--radius-sm);
    overflow-x: auto;
    white-space: pre-wrap;
    font-family: var(--font-mono);
    font-size: 0.9em;
    line-height: 1.5;
}

/* ── Library theme ── */
/* ── The library theme ──────────────────────────────────────────────────────
 *
 * Appended to the base stylesheet, and read only by pages wearing the library
 * shell (`library_shell.html`), whose <body> says `class="library …"`. Every
 * rule is scoped under `.library` so a page in any other shell is untouched.
 *
 * A page's colour is a name — `tone-green` on the body, on a cover, on a sheet
 * — and the nine names are the Diaryx app's cover papers, value for value:
 * face (the board), spine (a step darker) and ink (the text printed on it).
 * A page with no colour, or one this sheet does not know, is grey.
 *
 * No script: a sealed site renders every page in a sandboxed frame that runs
 * none, so the contents drawer and the margin are checkboxes (`#lib-contents`,
 * `#lib-margin`) and `:has()` decides which columns exist.
 */

:root {
    --lib-serif: "Iowan Old Style", "New York", Charter, "Source Serif Pro", Georgia, serif;
    --lib-remark: #2F6F6B;
    --lib-pages: #FAF7F0;
    --lib-rule: color-mix(in oklab, var(--text) 9%, transparent);
    --lib-panel: color-mix(in oklab, var(--bg) 70%, #f3f1ec);
    --lib-contents-width: 18rem;
    --lib-margin-width: 20rem;
    --lib-measure: 36rem;
    --lib-wide: 74rem;
}

.library {
    --face: #D5D5D2; --spine: #ABABA6; --ink: #2E2E2C;
}
.library .tone-red,    .library.tone-red    { --face: #F0D3CE; --spine: #D9A49D; --ink: #5C3230; }
.library .tone-orange, .library.tone-orange { --face: #F1DDC4; --spine: #DBB68C; --ink: #5A4128; }
.library .tone-yellow, .library.tone-yellow { --face: #F0E6B9; --spine: #D6C77A; --ink: #524818; }
.library .tone-green,  .library.tone-green  { --face: #D3E6CB; --spine: #A2C798; --ink: #2F4A2A; }
.library .tone-blue,   .library.tone-blue   { --face: #7FE1F5; --spine: #49C6DF; --ink: #1F4A54; }
.library .tone-purple, .library.tone-purple { --face: #E2D5EE; --spine: #BCA4D6; --ink: #44305C; }
.library .tone-white,  .library.tone-white  { --face: #F7F6F2; --spine: #D9D7D0; --ink: #3A3A36; }
.library .tone-grey,   .library.tone-grey   { --face: #D5D5D2; --spine: #ABABA6; --ink: #2E2E2C; }
.library .tone-black,  .library.tone-black  { --face: #3B3B3A; --spine: #232322; --ink: #EDEDE8; }

@media (prefers-color-scheme: dark) {
    :root {
        --lib-remark: #7FD1CB;
        --lib-pages: #8E8C86;
        --lib-panel: color-mix(in oklab, var(--bg) 85%, #ffffff);
    }
    .library { --face: #5A5A57; --spine: #3F3F3D; --ink: #ECECE8; }
    .library .tone-red,    .library.tone-red    { --face: #622C28; --spine: #86413C; --ink: #F0D3CE; }
    .library .tone-orange, .library.tone-orange { --face: #624528; --spine: #86623C; --ink: #F1DDC4; }
    .library .tone-yellow, .library.tone-yellow { --face: #625728; --spine: #867B3C; --ink: #F0E6B9; }
    .library .tone-green,  .library.tone-green  { --face: #34582D; --spine: #4A7B42; --ink: #D3E6CB; }
    .library .tone-blue,   .library.tone-blue   { --face: #1F5C6B; --spine: #307F91; --ink: #7FE1F5; }
    .library .tone-purple, .library.tone-purple { --face: #442862; --spine: #5A3C86; --ink: #E2D5EE; }
    .library .tone-white,  .library.tone-white  { --face: #E8E6E0; --spine: #C8C6BF; --ink: #3A3A36; }
    .library .tone-grey,   .library.tone-grey   { --face: #5A5A57; --spine: #3F3F3D; --ink: #ECECE8; }
    .library .tone-black,  .library.tone-black  { --face: #262625; --spine: #121211; --ink: #D8D8D3; }
}

/* ── The frame ── */

body.library {
    max-width: none;
    margin: 0;
    padding: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.library .lib-state {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.library .lib-bar {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    height: 3.5rem;
    padding: 0 1.25rem;
    background: var(--surface-bg);
    border-bottom: 1px solid var(--lib-rule);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
}

.library .lib-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
    color: var(--text);
    font-weight: 600;
    font-size: 0.95rem;
    text-decoration: none;
}

.library .lib-brand-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.library .lib-brand-mark {
    flex: none;
    width: 1.1rem;
    height: 1.35rem;
    border-radius: 2px 4px 4px 2px;
    background: var(--face);
    box-shadow: inset 3px 0 0 var(--spine), 0 1px 2px rgba(0, 0, 0, 0.2);
}

.library.kind-page .lib-brand-mark { background: var(--lib-pages); box-shadow: inset 3px 0 0 var(--border), 0 1px 2px rgba(0, 0, 0, 0.2); }

.library .lib-bar-space { flex: 1; }

.library .lib-toggle {
    display: none;
    align-items: center;
    height: 2rem;
    padding: 0 0.8rem;
    border-radius: 1rem;
    border: 1px solid var(--border);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
}

.library .lib-toggle:hover { background: color-mix(in oklab, var(--face) 25%, transparent); }

/* A toggle a reader's annotation layer adds to the bar from outside the page
   — the sealed reader's Margin button — which shows whenever it is there and
   says whether its panel is open. */
.library .lib-bar button.lib-toggle {
    display: inline-flex;
    background: none;
    color: inherit;
    font: inherit;
    font-size: 0.85rem;
    font-weight: 500;
}

.library .lib-bar button.lib-toggle[aria-pressed="true"] {
    background: color-mix(in oklab, var(--face) 40%, var(--bg));
    border-color: color-mix(in oklab, var(--spine) 70%, transparent);
    color: var(--ink);
}

.library.kind-page:has(.lib-contents:not(:empty)) .lib-toggle-contents,
.library:has(.lib-margin:not(:empty)) .lib-toggle-margin {
    display: inline-flex;
}

.library #lib-contents:focus-visible ~ .lib-bar .lib-toggle-contents,
.library #lib-margin:focus-visible ~ .lib-bar .lib-toggle-margin {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.library .site-header:empty { display: none; }

.library .lib-room {
    flex: 1;
    display: grid;
    grid-template-columns: var(--lib-left, 0) minmax(0, 1fr) var(--lib-right, 0);
}

.library .lib-contents,
.library .lib-margin {
    display: none;
    min-width: 0;
}

.library .lib-main {
    grid-column: 2;
    min-width: 0;
    padding-bottom: 4rem;
}

/* ── Panels, wide ── */

@media (min-width: 64rem) {
    .library.kind-page:has(.lib-contents:not(:empty)):not(:has(#lib-contents:checked)) {
        --lib-left: var(--lib-contents-width);
    }
    .library.kind-page:has(.lib-contents:not(:empty)):not(:has(#lib-contents:checked)) .lib-contents {
        display: block;
    }
    .library:has(.lib-margin:not(:empty)):not(:has(#lib-margin:checked)) {
        --lib-right: var(--lib-margin-width);
    }
    .library:has(.lib-margin:not(:empty)):not(:has(#lib-margin:checked)) .lib-margin {
        display: block;
    }
    .library:not(:has(#lib-contents:checked)) .lib-toggle-contents,
    .library:not(:has(#lib-margin:checked)) .lib-toggle-margin {
        background: color-mix(in oklab, var(--face) 40%, var(--bg));
        border-color: color-mix(in oklab, var(--spine) 70%, transparent);
        color: var(--ink);
    }
    .library .lib-contents,
    .library .lib-margin {
        position: sticky;
        top: 3.5rem;
        height: calc(100vh - 3.5rem);
        overflow-y: auto;
        background: var(--lib-panel);
    }
    .library .lib-contents { grid-column: 1; border-right: 1px solid var(--lib-rule); }
    .library .lib-margin { grid-column: 3; border-left: 1px solid var(--lib-rule); }
}

/* ── Panels, narrow: a drawer from the left, a sheet from below ── */

@media (max-width: 63.99rem) {
    .library:has(#lib-contents:checked) .lib-contents {
        display: block;
        position: fixed;
        z-index: 40;
        top: 3.5rem;
        bottom: 0;
        left: 0;
        width: min(22rem, 88vw);
        overflow-y: auto;
        background: var(--bg);
        box-shadow: var(--surface-shadow);
    }
    .library:has(#lib-margin:checked) .lib-margin {
        display: block;
        position: fixed;
        z-index: 40;
        left: 0;
        right: 0;
        bottom: 0;
        max-height: 70vh;
        overflow-y: auto;
        background: var(--bg);
        border-radius: 1rem 1rem 0 0;
        box-shadow: var(--surface-shadow);
    }
    .library:has(#lib-contents:checked) .lib-toggle-contents,
    .library:has(#lib-margin:checked) .lib-toggle-margin {
        background: color-mix(in oklab, var(--face) 40%, var(--bg));
        color: var(--ink);
    }
}

/* ── The band ── */

.library .page-head-front,
.library .page-head-book {
    display: flex;
    gap: 2rem;
    align-items: flex-start;
    padding: 2.25rem var(--lib-gutter) 2rem;
    background: linear-gradient(180deg,
        color-mix(in oklab, var(--face) 70%, var(--bg)) 0%,
        color-mix(in oklab, var(--face) 22%, var(--bg)) 70%,
        var(--bg) 100%);
}

.library .page-head .cover {
    flex: none;
    width: 9.5rem;
    cursor: default;
}

.library .page-head .cover:hover { transform: none; }

.library .page-head-text { min-width: 0; padding-top: 0.25rem; }

.library .page-head .page-title {
    margin: 0 0 0.5rem;
    font-family: var(--lib-serif);
    font-size: clamp(1.9rem, 4vw, 2.5rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.01em;
    color: var(--ink);
}

.library .page-head .page-description {
    margin: 0 0 0.75rem;
    max-width: 40rem;
    font-family: var(--lib-serif);
    font-size: 1.15rem;
    line-height: 1.45;
    color: color-mix(in oklab, var(--ink) 80%, var(--bg));
}

.library .page-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    margin: 0 0 1rem;
    font-size: 0.85rem;
    color: color-mix(in oklab, var(--ink) 70%, var(--bg));
}

.library .page-meta b { font-weight: 600; }

.library .page-actions { margin: 0; }

.library .start-with {
    display: inline-flex;
    align-items: center;
    height: 2.3rem;
    padding: 0 1rem;
    border-radius: 0.55rem;
    background: var(--ink);
    color: var(--face);
    font-weight: 600;
    font-size: 0.9rem;
    text-decoration: none;
}

.library .start-with:hover { text-decoration: none; filter: brightness(1.12); }

/* A page being read: its book above its title, centred over the column. */
.library .page-head-reading {
    max-width: var(--lib-measure);
    margin: 0 auto;
    padding: 3rem 1.5rem 1.5rem;
    text-align: center;
}

.library .page-eyebrow {
    margin: 0 0 0.6rem;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: color-mix(in oklab, var(--ink) 75%, var(--bg));
}

.library .page-eyebrow a { color: inherit; text-decoration: none; }
.library .page-eyebrow a:hover { text-decoration: underline; }
.library .page-chapter::before { content: "·"; margin: 0 0.5em; }

.library .page-head-reading .page-title {
    margin: 0;
    font-family: var(--lib-serif);
    font-size: clamp(1.8rem, 4vw, 2.3rem);
    font-weight: 600;
    line-height: 1.15;
}

.library .page-head-reading .page-description {
    margin: 0.5rem 0 0;
    font-family: var(--lib-serif);
    font-style: italic;
    font-size: 1.05rem;
    color: var(--text-muted);
}

/* ── The text ── */

.library .lib-article {
    max-width: var(--lib-measure);
    margin: 0 auto;
    padding: 0 1.5rem;
}

.library .lib-article .content:empty { display: none; }

/* On a front page or a book the text sits under the band's title, and the
   shelf and footer under its cover: one gutter, the band's, for all three. */
.library {
    --lib-gutter: max(2.75rem, calc((100% - var(--lib-wide)) / 2));
}

.library.kind-front .lib-article,
.library.kind-book .lib-article {
    max-width: none;
    margin: 0;
    padding: 0 var(--lib-gutter) 0 calc(var(--lib-gutter) + 11.5rem);
}

.library.kind-front .lib-article .content,
.library.kind-book .lib-article .content {
    max-width: 40rem;
}

.library .content {
    font-family: var(--lib-serif);
    font-size: 1.15rem;
    line-height: 1.7;
}

.library.kind-page .content { font-size: 1.2rem; line-height: 1.72; }

.library .content :is(h1, h2, h3, h4) { font-family: var(--lib-serif); }

.library .content blockquote {
    border-left: 2px solid var(--spine);
    font-style: italic;
}

.library .content a { text-decoration-color: color-mix(in oklab, currentColor 40%, transparent); }

/* ── The shelf ── */

.library .shelf {
    margin: 2rem 0 0;
    padding: 0 var(--lib-gutter);
}

.library .shelf-heading {
    margin: 0 0 1.25rem;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.library .shelf-count { margin-left: 0.6em; opacity: 0.7; font-weight: 500; }

.library .shelf-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
    gap: 2rem 1.9rem;
}

.library .shelf-grid li { margin: 0; min-width: 0; }

.library .cover {
    position: relative;
    display: block;
    aspect-ratio: 5 / 6;
    overflow: hidden;
    border-radius: 3px 9px 9px 3px;
    color: var(--ink);
    text-decoration: none;
    background: linear-gradient(140deg,
        color-mix(in oklab, var(--face) 80%, white) 0%,
        var(--face) 55%,
        color-mix(in oklab, var(--face) 88%, black) 100%);
    box-shadow:
        5px 6px 0 -1px var(--lib-pages),
        5px 6px 0 0 rgba(0, 0, 0, 0.1),
        0 12px 24px -6px rgba(0, 0, 0, 0.22);
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.library a.cover:hover {
    transform: translateY(-3px);
    text-decoration: none;
    box-shadow:
        5px 6px 0 -1px var(--lib-pages),
        5px 6px 0 0 rgba(0, 0, 0, 0.1),
        0 18px 30px -6px rgba(0, 0, 0, 0.26);
}

.library .cover::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 11px;
    background: linear-gradient(90deg,
        color-mix(in oklab, var(--spine) 85%, black),
        var(--spine) 60%,
        color-mix(in oklab, var(--spine) 70%, white));
}

.library .cover-title {
    display: block;
    padding: 1.2rem 1rem 0 1.75rem;
    font-family: var(--lib-serif);
    font-size: 1.25rem;
    font-weight: 600;
    line-height: 1.2;
    overflow-wrap: anywhere;
}

.library .cover-title::after {
    content: "";
    display: block;
    width: 1.9rem;
    height: 2px;
    margin-top: 0.75rem;
    background: var(--spine);
}

.library .cover-count {
    position: absolute;
    left: 1.75rem;
    bottom: 1rem;
    font-size: 0.78rem;
    opacity: 0.75;
}

.library .page-head .cover-title { font-size: 1.05rem; padding: 1rem 0.75rem 0 1.4rem; }
.library .page-head .cover-count { left: 1.4rem; }

.library .cover-label {
    display: block;
    margin-top: 0.8rem;
    font-size: 0.92rem;
    line-height: 1.35;
    text-align: center;
}

/* A sheet: a page that opens to text, with its corner turned down. */
.library .sheet {
    position: relative;
    display: block;
    aspect-ratio: 5 / 6;
    padding: 1.1rem 1.1rem 0;
    overflow: hidden;
    color: var(--ink);
    text-decoration: none;
    background: color-mix(in oklab, var(--face) 38%, var(--lib-pages));
    clip-path: polygon(0 0, calc(100% - 1.6rem) 0, 100% 1.6rem, 100% 100%, 0 100%);
    filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.12)) drop-shadow(0 1px 1px rgba(0, 0, 0, 0.08));
    transition: transform 0.18s ease;
}

.library .sheet::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: 1.6rem;
    height: 1.6rem;
    background: linear-gradient(225deg, transparent 50%, color-mix(in oklab, var(--spine) 70%, var(--lib-pages)) 50%);
}

.library a.sheet:hover { transform: translateY(-3px); text-decoration: none; }

/* A chapter with parts is a place: its own paper, pages behind it, no fold. */
.library .sheet-room {
    clip-path: none;
    border-radius: 2px;
    background: color-mix(in oklab, var(--face) 70%, var(--lib-pages));
    box-shadow:
        4px 4px 0 -1px var(--lib-pages), 4px 4px 0 0 rgba(0, 0, 0, 0.08),
        8px 8px 0 -1px var(--lib-pages), 8px 8px 0 0 rgba(0, 0, 0, 0.07);
    filter: none;
    overflow: visible;
}

.library .sheet-room::after { display: none; }

.library .sheet-number {
    display: block;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    opacity: 0.55;
}

.library .sheet-title {
    display: block;
    margin-top: 0.35rem;
    font-family: var(--lib-serif);
    font-size: 1.1rem;
    font-weight: 600;
    line-height: 1.25;
    overflow-wrap: anywhere;
}

.library .sheet-description {
    display: -webkit-box;
    margin-top: 0.6rem;
    font-family: var(--lib-serif);
    font-size: 0.85rem;
    line-height: 1.45;
    opacity: 0.72;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* A sheet that is a picture: the photograph fills the page below its title. */
.library .sheet-pictured {
    display: flex;
    flex-direction: column;
    padding-bottom: 1.1rem;
}

.library .sheet-picture {
    display: block;
    flex: 1;
    min-height: 0;
    margin-top: 0.6rem;
    border-radius: 2px;
    overflow: hidden;
    background: color-mix(in oklab, var(--ink) 6%, transparent);
}

.library .sheet-picture img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ── A book's contents, beside a page being read ── */

.library .book-nav { font-size: 0.9rem; }

.library .book-nav-up {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    height: 3rem;
    padding: 0 1rem;
    color: var(--text);
    font-weight: 500;
    text-decoration: none;
    border-bottom: 1px solid var(--lib-rule);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.library .book-nav-up::before { content: "‹"; font-size: 1.3rem; line-height: 1; margin-top: -0.1rem; }

.library .book-nav-book {
    display: block;
    padding: 1rem 1rem 1rem 3.2rem;
    position: relative;
    color: var(--ink);
    text-decoration: none;
    background: linear-gradient(180deg,
        color-mix(in oklab, var(--face) 55%, var(--bg)),
        color-mix(in oklab, var(--face) 18%, var(--bg)));
}

.library .book-nav-book::before {
    content: "";
    position: absolute;
    left: 1rem;
    top: 50%;
    width: 1.6rem;
    height: 2rem;
    transform: translateY(-50%);
    border-radius: 2px 4px 4px 2px;
    background: var(--face);
    box-shadow: inset 4px 0 0 var(--spine), 2px 2px 0 -1px var(--lib-pages), 0 2px 4px rgba(0, 0, 0, 0.18);
}

.library .book-nav-title { display: block; font-family: var(--lib-serif); font-size: 1.05rem; font-weight: 600; line-height: 1.2; }
.library .book-nav-count { display: block; font-size: 0.78rem; opacity: 0.7; }

.library .book-nav-list,
.library .book-nav-parts {
    list-style: none;
    margin: 0;
    padding: 0.4rem 0;
}

.library .book-nav-parts { padding: 0; }

.library .book-nav li { margin: 0; }

.library .book-nav li a {
    position: relative;
    display: flex;
    gap: 0.6rem;
    padding: 0.55rem 1.1rem;
    color: var(--text);
    line-height: 1.35;
    text-decoration: none;
}

.library .book-nav .book-nav-parts li a { padding-left: 2.7rem; font-size: 0.85rem; }

.library .book-nav li a:hover { background: color-mix(in oklab, var(--text) 5%, transparent); }

.library .book-nav-number {
    flex: none;
    width: 1rem;
    padding-top: 0.1rem;
    font-size: 0.75rem;
    color: var(--text-muted);
    text-align: right;
}

.library .book-nav a[aria-current] {
    background: color-mix(in oklab, var(--face) 38%, var(--bg));
    color: var(--ink);
    font-weight: 600;
}

.library .book-nav a[aria-current]::after {
    content: "";
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--spine);
}

/* ── Pager and footer ── */

.library .pager {
    max-width: var(--lib-measure);
    margin: 3rem auto 0;
    padding: 1.25rem 1.5rem 0;
    border-top: 1px solid var(--lib-rule);
}

.library .pager a { font-family: var(--lib-serif); font-size: 1.05rem; color: var(--ink); }
.library.kind-front .pager,
.library.kind-book .pager { display: none; }

.library .site-footer {
    margin: 4rem var(--lib-gutter) 0;
    padding: 1.25rem 0 0;
}

.library.kind-page .site-footer { max-width: var(--lib-measure); margin-inline: auto; padding-inline: 1.5rem; }

/* ── Narrow ── */

@media (max-width: 40rem) {
    .library .page-head-front,
    .library .page-head-book {
        padding: 1.5rem 1.25rem 1.25rem;
    }
    .library .page-head-front .cover,
    .library .page-head-book .cover { display: none; }
    .library { --lib-gutter: 1.25rem; }
    .library.kind-front .lib-article,
    .library.kind-book .lib-article { padding: 0 var(--lib-gutter); }
    .library .shelf-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem 1.1rem; }
    .library .cover-title { font-size: 1rem; padding: 0.9rem 0.6rem 0 1.3rem; }
    .library .cover-count { left: 1.3rem; bottom: 0.7rem; }
    .library .sheet-title { font-size: 0.98rem; }
}

@media print {
    .library .lib-bar, .library .lib-contents, .library .lib-margin, .library .pager { display: none !important; }
    .library .lib-room { display: block; }
}
