

/* =========================== assets/stylesheet/stylesheet/01-layers.public.css ========================== */

@layer reset, links, headers, components;


/* =========================== assets/stylesheet/stylesheet/02-reset.public.css ========================== */

/* Resets styles to known defaults to work around weird user agents. */
/* Based on http://meyerweb.com/eric/tools/css/reset/ */

@layer reset {
    html,
    body,
    div,
    span,
    applet,
    object,
    iframe,
    h1,
    h2,
    h3,
    h4,
    h5,
    h6,
    p,
    blockquote,
    pre,
    a,
    abbr,
    acronym,
    address,
    big,
    cite,
    code,
    del,
    dfn,
    em,
    img,
    ins,
    kbd,
    q,
    s,
    samp,
    small,
    strike,
    strong,
    sub,
    sup,
    tt,
    var,
    b,
    u,
    i,
    center,
    dl,
    dt,
    dd,
    ol,
    ul,
    li,
    fieldset,
    form,
    label,
    legend,
    table,
    caption,
    tbody,
    tfoot,
    thead,
    tr,
    th,
    td,
    article,
    aside,
    canvas,
    details,
    embed,
    figure,
    figcaption,
    footer,
    header,
    hgroup,
    menu,
    nav,
    output,
    ruby,
    section,
    summary,
    time,
    mark,
    audio,
    video {
        margin: 0;
        padding: 0;
        border: 0;
        font-size: 100%;
        font: inherit;
        vertical-align: baseline;
    }

    article,
    aside,
    details,
    figcaption,
    figure,
    footer,
    header,
    hgroup,
    menu,
    nav,
    section {
        display: block;
    }

    body {
        line-height: 1;
    }

    ol,
    ul {
        list-style: none;
    }

    blockquote,
    q {
        quotes: none;
    }

    blockquote:before,
    blockquote:after,
    q:before,
    q:after {
        content: "";
        content: none;
    }

    table {
        border-collapse: collapse;
        border-spacing: 0;
    }

    *,
    *:before,
    *:after {
        -moz-box-sizing: border-box;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
    }
}


/* =========================== assets/stylesheet/stylesheet/03-colours.public.css ========================== */

:root {
    --accent-colour: #3c658d;
    --accent-alt-colour: #223950;
    --background-colour: #15151a;
    --background-alt-colour: #202026;
    --text-colour: #d4d4de;
    --text-highlight-colour: #efefff;
    --text-alt-colour: #90909a;
    --link-colour: #7099c4;
    --pen-ink-colour: #8fb3e6;
}


/* =========================== assets/stylesheet/stylesheet/03-dimens.public.css ========================== */

:root {
    --border-radius: 10px;

    --small-space: 0.5rem;
    --smedium-space: 1rem;
    --medium-space: 2.5rem;
    --large-space: 5rem;

    --page-gutter: clamp(16px, 4vw, 72px);
    --content-width: min(1900px, 100vw - 2 * var(--page-gutter));
    --content-margin: calc((100vw - var(--content-width)) / 2);

    @media (width <= 1200px) {
        --small-space: 0.5rem;
        --smedium-space: 1rem;
        --medium-space: 2rem;
        --large-space: 4rem;
    }

    @media (width <= 800px) {
        --small-space: 0.4rem;
        --smedium-space: 0.8rem;
        --medium-space: 1.5rem;
        --large-space: 2.5rem;
    }
}


/* =========================== assets/stylesheet/stylesheet/04-about.public.css ========================== */

@property --curl {
    syntax: "<length>";
    inherits: true;
    initial-value: 0px;
}

.about {
    container: about / inline-size;

    /* Centers the trading card when it's not beside the content */
    text-align: center;

    * {
        text-align: left;
    }

    & > :last-child {
        flex: 100%;
        margin-right: var(--small-space);
        padding-top: var(--small-space);

        @media (width <= 500px) {
            margin-right: 0;
        }

        p:first-child {
            margin-top: var(--small-space);
            margin-bottom: var(--small-space);
            font-size: var(--font-size-large);
            line-height: 1.8em;
        }

        .drop {
            font-family: "Chris Hand", sans-serif;
            color: var(--text-highlight-colour);
            font-weight: 800;
            font-size: var(--font-size-giant);
            margin-right: var(--small-space);
            vertical-align: baseline;
            line-height: 0;
        }
    }

    /* On wide screens, the content's children join the section's grid so
       the trading card can sit in a column beside the intro and notes. */
    @media (width > 1200px) {
        display: grid;
        column-gap: var(--large-space);
        align-items: start;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "hello card"
            "intro card"
            "list card"
            "latest latest"
            "posts posts";

        & > :last-child {
            display: contents;

            & > p:nth-of-type(1) { grid-area: hello; }
            & > p:nth-of-type(2) { grid-area: intro; }
            & > ul { grid-area: list; }
            & > p:nth-of-type(3) { grid-area: latest; }
            & > .recent-posts { grid-area: posts; }
        }
    }

    /* The slash pages are post-it notes stuck up in staggered rows: k notes,
       then k-1 sitting in the gaps below and overlapping them, and so on.
       Everything is derived from the note's index (--i) and the number of
       notes (--n), so it copes with any number of links (up to the 24 the
       tables below cover). Notes are as big as fits, up to 270px, in two
       rows when there's room and as few balanced rows as possible otherwise.
       The thresholds for how many fit across assume a note of at least
       170px, 6% apart. */
    ul {
        /* Width available to the board: the whole section, or (on wide
           screens, below) the section minus the trading card column. */
        --board: calc(100cqi - var(--small-space));
        --kfit: 2;
        --n: 1;
        /* Rows needed (at least two), then the fewest notes per long
           row that fit them all, so the rows come out balanced. */
        --rows-min: max(min(2, var(--n)), round(up, calc(var(--n) / (var(--kfit) - 0.5)), 1));
        --k: max(2, round(up, calc((var(--n) + round(down, calc(var(--rows-min) / 2), 1)) / var(--rows-min)), 1));
        --w: min(270px, calc(var(--board) / (1.06 * var(--k) - 0.06)));
        --m: calc(2 * var(--k) - 1);
        --full: round(down, calc(var(--n) / var(--m)), 1);
        --rem: calc(var(--n) - var(--full) * var(--m));
        --rows: calc(2 * var(--full) + min(1, var(--rem)) + clamp(0, var(--rem) - var(--k), 1));

        position: relative;
        list-style: none;
        padding: 0;
        height: calc((var(--rows) - 1) * 0.8 * var(--w) + var(--w) + 30px);
        margin: var(--medium-space) 0 var(--small-space);
    }

    @container about (width >= 538px) { ul { --kfit: 3; } }
    @container about (width >= 719px) { ul { --kfit: 4; } }
    @container about (width >= 899px) { ul { --kfit: 5; } }
    @container about (width >= 1079px) { ul { --kfit: 6; } }
    @container about (width >= 1259px) { ul { --kfit: 7; } }

    ul:has(> li:nth-child(1):last-child) { --n: 1; }
    ul:has(> li:nth-child(2):last-child) { --n: 2; }
    ul:has(> li:nth-child(3):last-child) { --n: 3; }
    ul:has(> li:nth-child(4):last-child) { --n: 4; }
    ul:has(> li:nth-child(5):last-child) { --n: 5; }
    ul:has(> li:nth-child(6):last-child) { --n: 6; }
    ul:has(> li:nth-child(7):last-child) { --n: 7; }
    ul:has(> li:nth-child(8):last-child) { --n: 8; }
    ul:has(> li:nth-child(9):last-child) { --n: 9; }
    ul:has(> li:nth-child(10):last-child) { --n: 10; }
    ul:has(> li:nth-child(11):last-child) { --n: 11; }
    ul:has(> li:nth-child(12):last-child) { --n: 12; }
    ul:has(> li:nth-child(13):last-child) { --n: 13; }
    ul:has(> li:nth-child(14):last-child) { --n: 14; }
    ul:has(> li:nth-child(15):last-child) { --n: 15; }
    ul:has(> li:nth-child(16):last-child) { --n: 16; }
    ul:has(> li:nth-child(17):last-child) { --n: 17; }
    ul:has(> li:nth-child(18):last-child) { --n: 18; }
    ul:has(> li:nth-child(19):last-child) { --n: 19; }
    ul:has(> li:nth-child(20):last-child) { --n: 20; }
    ul:has(> li:nth-child(21):last-child) { --n: 21; }
    ul:has(> li:nth-child(22):last-child) { --n: 22; }
    ul:has(> li:nth-child(23):last-child) { --n: 23; }
    ul:has(> li:nth-child(24):last-child) { --n: 24; }

    li:nth-child(1) { --i: 0; }
    li:nth-child(2) { --i: 1; }
    li:nth-child(3) { --i: 2; }
    li:nth-child(4) { --i: 3; }
    li:nth-child(5) { --i: 4; }
    li:nth-child(6) { --i: 5; }
    li:nth-child(7) { --i: 6; }
    li:nth-child(8) { --i: 7; }
    li:nth-child(9) { --i: 8; }
    li:nth-child(10) { --i: 9; }
    li:nth-child(11) { --i: 10; }
    li:nth-child(12) { --i: 11; }
    li:nth-child(13) { --i: 12; }
    li:nth-child(14) { --i: 13; }
    li:nth-child(15) { --i: 14; }
    li:nth-child(16) { --i: 15; }
    li:nth-child(17) { --i: 16; }
    li:nth-child(18) { --i: 17; }
    li:nth-child(19) { --i: 18; }
    li:nth-child(20) { --i: 19; }
    li:nth-child(21) { --i: 20; }
    li:nth-child(22) { --i: 21; }
    li:nth-child(23) { --i: 22; }
    li:nth-child(24) { --i: 23; }

    li {
        /* Position in the staggered rows. */
        --j: mod(var(--i), var(--m));
        --odd: clamp(0, var(--j) - var(--k) + 1, 1);
        --row: calc(2 * round(down, calc(var(--i) / var(--m)), 1) + var(--odd));
        --col: calc(var(--j) - var(--odd) * var(--k));
        --step: calc(1.06 * var(--w));
        --used: calc((var(--k) - 1) * var(--step) + var(--w));

        /* Numbers in [0, 1) for this note, from low-discrepancy
           sequences (multiples of irrational numbers) so that
           neighbouring notes always come out noticeably different. */
        --r1: mod(calc(var(--i) * 0.6180340 + 0.35), 1);
        --r2: mod(calc(var(--i) * 0.7548777 + 0.1), 1);
        --r3: mod(calc(var(--i) * 0.5698403 + 0.6), 1);
        --r4: mod(calc(var(--i) * 0.4142136 + 0.5), 1);
        --r5: mod(calc(var(--i) * 0.3819660 + 0.02), 1);

        --tilt: calc((var(--r1) - 0.5) * 10deg);
        --dx: calc((var(--r2) - 0.5) * 0.05 * var(--w));
        --dy: calc((var(--r3) - 0.5) * 0.08 * var(--w));

        position: absolute;
        left: calc((100% - var(--used)) / 2 + (var(--col) + var(--odd) * 0.5) * var(--step));
        top: calc(var(--row) * 0.8 * var(--w) + 10px);
        width: var(--w);
        height: var(--w);
        padding: calc(var(--w) * 0.11) calc(var(--w) * 0.15) 0 calc(var(--w) * 0.085);
        box-sizing: border-box;
        color: #26231c;
        font-family: "Chris Hand", sans-serif;
        font-size: calc(var(--w) * 0.083);
        line-height: 1.15;
        transform: translate(var(--dx), var(--dy)) rotate(var(--tilt));

        /* Colour from the row and column, which guarantees no two
           touching notes (beside, above or below) match. */
        --c: mod(calc(2 * var(--row) + var(--col)), 5);
        --c0: calc(1 - min(1, var(--c) * var(--c)));
        --c1: calc(1 - min(1, (var(--c) - 1) * (var(--c) - 1)));
        --c2: calc(1 - min(1, (var(--c) - 2) * (var(--c) - 2)));
        --c3: calc(1 - min(1, (var(--c) - 3) * (var(--c) - 3)));
        --note: color-mix(in srgb, #e8d65e calc(var(--c0) * 100%),
            color-mix(in srgb, #eba3bd calc(var(--c1) * 100%),
                color-mix(in srgb, #a6d99a calc(var(--c2) * 100%),
                    color-mix(in srgb, #9ccbe6 calc(var(--c3) * 100%), #f0b175))));

        /* The bottom edge: lifted at the right, lifted at the left, or
           flat. A lifted corner curves and casts a longer shadow. The
           drop-shadow follows the note's shape, so cut corners show the
           wall behind. */
        --lift: round(down, calc(var(--r4) * 3), 1);
        --lift-r: calc(1 - min(1, var(--lift)));
        --lift-l: calc(1 - min(1, (var(--lift) - 1) * (var(--lift) - 1)));
        border-bottom-right-radius: calc(var(--lift-r) * 60px) calc(var(--lift-r) * 6px);
        border-bottom-left-radius: calc(var(--lift-l) * 60px) calc(var(--lift-l) * 6px);
        filter: drop-shadow(0 1px 1px rgb(0 0 0 / 0.3))
            drop-shadow(calc((var(--lift-r) - var(--lift-l)) * 3px + 2px) calc((var(--lift-r) + var(--lift-l)) * 5px + 4px) calc((var(--lift-r) + var(--lift-l)) * 2px + 4px) rgb(0 0 0 / 0.5));

        /* A fold at a random corner (or none): 0 top-left, 1 top-right,
           2 bottom-right, 3 bottom-left. */
        --fold-at: round(down, calc(var(--r5) * 9), 1);
        --f0: calc(1 - min(1, var(--fold-at) * var(--fold-at)));
        --f1: calc(1 - min(1, (var(--fold-at) - 1) * (var(--fold-at) - 1)));
        --f2: calc(1 - min(1, (var(--fold-at) - 2) * (var(--fold-at) - 2)));
        --f3: calc(1 - min(1, (var(--fold-at) - 3) * (var(--fold-at) - 3)));
        --fold: calc(var(--w) * 0.09);

        /* Each corner's cut. The top-right one is also the hover peel. */
        --curl: 0px;
        --cut-tl: calc(var(--f0) * var(--fold));
        --cut-tr: max(calc(var(--f1) * var(--fold)), var(--curl));
        --cut-br: calc(var(--f2) * var(--fold));
        --cut-bl: calc(var(--f3) * var(--fold));
        transition: --curl 300ms ease-out;

        &:hover,
        &:focus-within {
            --curl: calc(var(--w) * 0.24);
        }

        /* The paper, in quarters so each can have its corner cut away. */
        --shade: color-mix(in srgb, var(--note), black 10%);
        background:
            linear-gradient(135deg, transparent calc(var(--cut-tl) * 0.7071), var(--shade) calc(var(--cut-tl) * 0.7071), var(--note) 30%) 0 0,
            linear-gradient(225deg, transparent calc(var(--cut-tr) * 0.7071), var(--shade) calc(var(--cut-tr) * 0.7071), var(--note) 30%) 100% 0,
            linear-gradient(315deg, transparent calc(var(--cut-br) * 0.7071), var(--shade) calc(var(--cut-br) * 0.7071), var(--note) 30%) 100% 100%,
            linear-gradient(45deg, transparent calc(var(--cut-bl) * 0.7071), var(--shade) calc(var(--cut-bl) * 0.7071), var(--note) 30%) 0 100%;
        background-size: calc(50% + 1px) calc(50% + 1px);
        background-repeat: no-repeat;

        /* The adhesive strip, cut to match the top corners. */
        &::before {
            content: "";
            position: absolute;
            inset: 0 0 auto;
            height: calc(var(--w) * 0.11);
            background: linear-gradient(to bottom, rgb(0 0 0 / 0.08), transparent);
            mask:
                linear-gradient(135deg, transparent calc(var(--cut-tl) * 0.7071), #000 0),
                linear-gradient(225deg, transparent calc(var(--cut-tr) * 0.7071), #000 0);
            mask-composite: intersect;
            pointer-events: none;
        }

        /* The flaps: the back of the paper folded over where each cut
           corner was. The top-right one peels on hover; the link's
           ::before is borrowed for a fold at any other corner. */
        &::after,
        a::before {
            content: "";
            position: absolute;
            filter: drop-shadow(0 0 2px rgb(0 0 0 / 0.25));
            pointer-events: none;
        }

        &::after {
            top: 0;
            right: 0;
            width: var(--cut-tr);
            height: var(--cut-tr);
            background: linear-gradient(to top right,
                color-mix(in srgb, var(--note), white 30%) 0,
                color-mix(in srgb, var(--note), black 6%) 50%,
                transparent 50%);
        }

        a::before {
            --size: calc((var(--f0) + var(--f2) + var(--f3)) * var(--fold));
            top: calc((var(--f2) + var(--f3)) * (100% - var(--size)));
            left: calc(var(--f2) * (100% - var(--size)));
            width: var(--size);
            height: var(--size);
            background: linear-gradient(calc(315deg + var(--fold-at) * 90deg),
                color-mix(in srgb, var(--note), white 30%) 0,
                color-mix(in srgb, var(--note), black 6%) 50%,
                transparent 50%);
        }

        a {
            display: block;
            background: none;
            text-decoration: none;
            margin-bottom: 0.3em;
            color: #1b2a44;
            font-size: 1.65em;
            font-weight: 800;
            line-height: 1;

            &::after {
                content: "";
                position: absolute;
                inset: 0;
            }

            &:focus-visible {
                outline: none;
            }
        }
    }

    /* Wide screens: the board shrinks to make room for the trading card. */
    @media (width > 1200px) {
        ul {
            --board: calc(100cqi - 330px - var(--large-space));
            --kfit: 2;
        }

        @container about (width >= 940px) { ul { --kfit: 3; } }
        @container about (width >= 1121px) { ul { --kfit: 4; } }
        @container about (width >= 1301px) { ul { --kfit: 5; } }
        @container about (width >= 1481px) { ul { --kfit: 6; } }
        @container about (width >= 1661px) { ul { --kfit: 7; } }
        @container about (width >= 1841px) { ul { --kfit: 8; } }
        @container about (width >= 2022px) { ul { --kfit: 9; } }
    }
}

.tcg-outer {
    position: relative;
    width: min-content;
    cursor: help;

    transform: rotate(4deg) translateY(40px);
    margin: 0 auto var(--large-space);

    /* Beside the content on wide screens; see .about. */
    @media (width > 1200px) {
        grid-area: card;
        margin: 0;
        transform: rotate(4deg) translateY(20px);
    }

    @media (width <= 800px) {
        transform: rotate(0deg);
    }

    .tcg-front {
        transform: rotateY(0deg);
    }

    .tcg-back {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        transform: rotateY(180deg);
        background-color: var(--accent-colour);

        .tcg-back-emboss {
            position: absolute;
            font-size: var(--font-size-xlarge);
            top: 30%;
            left: 0;
            width: 100%;
            text-align: center;
            text-transform: uppercase;
            font-weight: bolder;
            color: color-mix(in srgb, var(--accent-colour), black 20%);
        }

        .tcg-back-hello {
            position: absolute;
            margin: 0;
            bottom: 0;
            right: 0;
            font-size: var(--font-size-tiny);
            color: color-mix(in srgb, var(--accent-colour), black 20%);
        }
    }

    .tcg-flip {
        transform-style: preserve-3d;
        transition: transform 800ms 400ms;
    }

    &:hover .tcg-flip {
        transform: rotateY(180deg);
    }

    .tcg-front,
    .tcg-back {
        /* Firefox doesn't do anti-aliasing in a 3D context, which looks terrible
       as the card is rotated a bit. Adding a transparent outline somehow
       fixes it. https://stackoverflow.com/a/9333891 */
        outline: 1px solid transparent;
        border: 12px solid var(--accent-colour);
        border-radius: var(--border-radius);
        box-shadow: 20px 20px 5px black;
        backface-visibility: hidden;

        @media (width <= 500px) {
            box-shadow: 10px 10px 5px black;
        }

        &::before {
            position: absolute;
            top: -12px;
            left: -12px;
            right: -12px;
            bottom: -12px;
            content: " ";
            border-radius: var(--border-radius);

            transform: translateZ(1.41px);
            overflow: hidden;

            background-image: radial-gradient(
                farthest-corner circle at 300px 400px,
                hsla(0, 0%, 100%, 0.8) 10%,
                hsla(0, 0%, 100%, 0.65) 20%,
                hsla(0, 0%, 0%, 0.5) 90%
            );

            mix-blend-mode: overlay;
        }
    }

    .tcg-inner {
        width: 300px;
        margin: -4px;
        background-color: var(--background-alt-colour);
        border-radius: var(--border-radius);
        overflow: hidden;

        display: flex;
        flex-direction: column;
        align-items: center;

        font-size: var(--font-size-tiny);

        img {
            width: 100%;
            border-bottom: 6px solid var(--accent-colour);
        }

        .tcg-properties {
            width: 100%;
            display: grid;
            grid-template-columns: auto 1fr auto 1fr;
            padding: 10px;
            grid-column-gap: var(--small-space);
            align-items: baseline;

            dt {
                font-weight: bold;
                text-align: right;
            }
        }

        .tcg-skills {
            margin: 0 10px;
            /* Safari doesn't like to calculate the width properly by itself...? */
            max-width: calc(100% - 20px);
            border-bottom: 0;
            background: none;
            box-shadow: none;

            * {
                background: none;
            }

            td {
                border: 0;
                padding: 4px;
                font-size: var(--font-size-tiny);

                &:first-child {
                    text-align: center;
                }
            }

            em {
                font-style: normal;
                font-weight: bold;

                /* The global style adds underscores around emphasis, but we don't want that here */
                &::before {
                    display: none;
                }

                &::after {
                    display: none;
                }
            }
        }

        footer {
            width: 100%;
            border-top: 2px solid var(--accent-colour);
            margin-top: 10px;
            padding: 5px 10px 5px 10px;
            font-size: var(--font-size-tiny);
            font-style: italic;
            display: flex;
            justify-content: right;
        }
    }
}


/* =========================== assets/stylesheet/stylesheet/04-articles.public.css ========================== */

article h2 {
    margin-bottom: 0;
}

article section + section {
    margin-top: var(--medium-space);
}

.date,
.meta {
    margin: var(--small-space) 0 var(--medium-space) 0;
    color: var(--text-alt-colour);
    padding-top: 0;
    font-size: var(--font-size-tiny);
    font-family: "Berkeley Mono", monospace;
    text-transform: uppercase;

    &::before {
        content: "// ";
    }
}

.paste-metadata {
    color: var(--text-alt-colour);
    padding: 0;
    margin: 0 0 var(--small-space) 0;
    font-size: var(--font-size-tiny);
    font-family: "Berkeley Mono", monospace;
    text-transform: uppercase;
    float: right;
}

@media (width >= 1200px) {
    .e-content figure.right:first-child {
        margin-top: calc(
            -1 *
                (
                    var(--font-size-xlarge) + var(--font-size-tiny) +
                        var(--medium-space)
                )
        );
    }
}

.footnotes {
    color: var(--text-alt-colour);
    background-color: var(--background-colour);
    border: 1px solid var(--background-alt-colour);
    box-shadow: 3px 3px 5px black;
    border-radius: var(--border-radius);
    margin: var(--smedium-space) 0;
    padding: var(--small-space);
    padding-top: var(--raised-box-title-padding);
    position: relative;

    &::before {
        content: "Footnotes";
        font-family: "Berkeley Mono", monospace;
        text-transform: uppercase;
        font-size: var(--font-size-tiny);
        line-height: calc(1.5 * var(--font-size-tiny));
        color: var(--text-alt-colour);
        white-space: pre;
        text-overflow: ellipsis;
        overflow: hidden;
        position: absolute;
        top: 5px;
        left: 0;
        right: 0;
        border-bottom: 1px solid var(--background-alt-colour);
        padding-bottom: 5px;
        padding-left: calc(5px + var(--border-radius) / 2);
    }

    p {
        margin: var(--smedium-space) 0;
    }

    hr {
        display: none;
    }

    li:first-child p {
        margin-top: 0;
    }

    li:last-child p {
        margin-bottom: 0;
    }
}

/* Footnotes become handwritten notes in the margin, alongside the block that
   cites them (see content.WithMarginNotes). They float out past the right edge
   of the prose column, taking no space in it, and clear each other so a long
   note pushes the next one down. The notes are copies, so on screens without
   room for them they're hidden and the footnotes are shown instead. On wider
   screens, the article script hides the footnote list and points the
   references at the notes. */
.marginnote {
    display: none;

    @media (width >= 1420px) {
        --note-gap: 2.5rem;
        --note-width: clamp(12rem, var(--content-margin) - var(--page-gutter) - var(--note-gap), 18rem);

        display: block;
        float: right;
        clear: right;
        width: var(--note-width);
        margin: 0 calc(-1 * (var(--note-width) + var(--note-gap))) 1.2em 0;
        font-family: "Chris Hand", sans-serif;
        font-size: 1.3rem;
        line-height: 1.2;
        color: var(--pen-ink-colour);

        & > div {
            padding-top: 0.25em;
            scroll-margin-top: var(--medium-space);
            transform: rotate(-1.5deg);

            & + div {
                margin-top: 1.2em;
            }
        }

        &:nth-of-type(3n + 2) > div {
            transform: rotate(-0.4deg);
        }

        &:nth-of-type(3n) > div {
            transform: rotate(-2.2deg);
        }

        b {
            display: inline-block;
            font-family: "Berkeley Mono", monospace;
            font-size: var(--font-size-tiny);
            font-weight: 400;
            line-height: 1.5;
            color: var(--background-colour);
            background: var(--pen-ink-colour);
            padding: 0 0.45em;
            margin-right: 0.45em;
            vertical-align: 2px;
        }

        p {
            display: inline;
            margin: 0;
        }

        a:not(.plain-link) {
            color: inherit;
        }

        code {
            font-size: 0.7em;
        }
    }
}

/* Footnote references (and littlefoot's buttons, which use the same markup)
   as small versions of the margin notes' number badges. */
a.footnote-ref,
sup.footnote-ref > a {
    display: inline-block;
    font-family: "Berkeley Mono", monospace;
    font-size: 0.7rem;
    font-weight: 400;
    line-height: 1.4;
    padding: 0 0.35em;
    margin-inline: 0.25em;
    color: var(--background-colour);
    background: var(--pen-ink-colour);
    text-decoration: none;

    &:hover,
    &:focus-visible {
        background: var(--text-highlight-colour);
    }
}


/* =========================== assets/stylesheet/stylesheet/04-asides.public.css ========================== */

/* Blockquotes: a hand-drawn biro stroke down the left, in the same style as
   the heading rules. */
blockquote {
    position: relative;
    margin: var(--medium-space) 0;
    padding-left: 2rem;
    font-style: italic;

    &::before {
        content: "";
        position: absolute;
        inset: 0.2em auto 0.2em 0;
        width: 12px;
        background: var(--accent-colour);
        mask: url("/paper/quote-rule.svg") 0 0 / 100% 100% no-repeat;
        pointer-events: none;
    }

    p {
        margin-block: var(--small-space);

        &:first-child {
            margin-top: 0;
        }

        &:last-child {
            margin-bottom: 0;
        }
    }
}

aside.old-post-warning {
    padding: var(--small-space) var(--medium-space);
    margin: var(--medium-space) 0;
}


/* =========================== assets/stylesheet/stylesheet/04-components.public.css ========================== */

:root {
    --raised-box-title-padding: calc(
        10px + 3 * var(--small-space) + var(--font-size-tiny)
    );
}

@layer components {
    .raised-box {
        background-color: var(--background-colour);
        border: 1px solid var(--background-alt-colour);
        box-shadow: 3px 3px 5px black;
        border-radius: var(--border-radius);

        &:is(a, .raised-box-interactive) {
            transition:
                box-shadow 500ms var(--timing-ease-in-out-quad),
                border-color 500ms var(--timing-ease-in-out-quad);
            border-color: var(--accent-alt-colour);

            &:hover,
            &:focus,
            &:active {
                box-shadow: 0 0 10px var(--accent-colour);
                border-color: var(--accent-colour);
            }
        }

        &[data-title] {
            padding-top: var(--raised-box-title-padding);
            position: relative;

            &::before {
                content: attr(data-title);
                font-family: "Berkeley Mono", monospace;
                text-transform: uppercase;
                font-size: var(--font-size-tiny);
                line-height: calc(1.5 * var(--font-size-tiny));
                color: var(--text-alt-colour);
                white-space: pre;
                text-overflow: ellipsis;
                overflow: hidden;
                position: absolute;
                top: 5px;
                left: 0;
                right: 0;
                border-bottom: 1px solid var(--background-alt-colour);
                padding-bottom: 5px;
                padding-left: calc(5px + var(--border-radius) / 2);
            }
        }
    }

    @keyframes rotation {
        0% {
            transform: rotate(0deg);
        }
        100% {
            transform: rotate(360deg);
        }
    }

    .submittable {
        position: relative;

        .loading,
        .result {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            display: flex;
            justify-content: center;
            align-items: center;

            span {
                width: 48px;
                height: 48px;
                border: 5px solid var(--accent-colour);
                border-bottom-color: transparent;
                border-radius: 50%;
                display: inline-block;
                box-sizing: border-box;
                animation: rotation 1s linear infinite;
            }

            p {
                background-color: var(--accent-colour);
                padding: var(--medium-space);
                color: var(--text-colour);
                text-align: center;
                border-radius: var(--border-radius);
            }
        }

        &:has(.loading) form,
        &:has(.result) form {
            opacity: 0.5;
        }

        form {
            margin: var(--smedium-space) 0;
            padding-left: var(--smedium-space);
            padding-right: var(--smedium-space);
            padding-bottom: var(--smedium-space);
        }
    }
}


/* =========================== assets/stylesheet/stylesheet/04-footer.public.css ========================== */

body > footer {
    position: relative;
    isolation: isolate;
    margin-top: var(--large-space);
    padding: calc(var(--medium-space) + 20px) var(--medium-space) var(--small-space);

    /* The edge the page is torn along. tear-shadow.svg traces the same
       points (with x as a percentage), so keep the two in sync. */
    --tear: polygon(0 18px, 4% 6px, 9% 20px, 14% 4px, 21% 16px, 27% 2px, 33% 18px, 40% 6px, 46% 20px, 53% 3px, 60% 15px, 66% 4px, 72% 19px, 79% 5px, 85% 17px, 91% 2px, 96% 14px, 100% 6px, 100% 100%, 0 100%);

    /* The footer's paper, torn along the top. It's a pseudo-element so that
       the tear doesn't clip anything hanging off the footer. */
    &::before {
        content: "";
        position: absolute;
        inset: 0;
        z-index: -1;
        background: #131315;
        clip-path: var(--tear);
    }

    /* The shadow the page casts over the footer along the tear. */
    &::after {
        content: "";
        position: absolute;
        inset: 0;
        z-index: -1;
        background: url("/paper/tear-shadow.svg") 0 0 / 100% 40px no-repeat;
        clip-path: var(--tear);
        pointer-events: none;
    }

    .columns {
        display: flex;
        flex-direction: row;
        justify-content: space-around;

        @media (width <= 1400px) {
            display: flex;
            flex-direction: column;
        }
    }

    li p {
        font-family: "Berkeley Mono", monospace;
        font-size: var(--font-size-small);
        color: var(--text-alt-colour);
    }

    section.licence {
        margin-top: var(--medium-space);
        text-align: center;

        font-family: "Berkeley Mono", monospace;
        font-size: var(--font-size-tiny);

        @media (width <= 500px) {
            text-align: left;
            p {
                margin-bottom: var(--medium-space);
            }
        }

        p + p {
            margin-top: var(--small-space);
        }

        svg {
            fill: var(--text-colour);
            vertical-align: bottom;
        }
    }

    h2 {
        font-size: var(--font-size-xlarge);
        margin: var(--smedium-space) 0;

        &:has(a) {
            display: flex;
        }

        &::before {
            font-size: var(--font-size-xlarge);
        }

        a {
            color: var(--text-highlight-colour);
            display: inline-block;
            height: 24px;
            width: 24px;
            margin-left: auto;
            align-self: center;
            transform: translateY(-0.2em);
            /* Matches the heading's text-shadow, which doesn't apply to SVGs. */
            filter: drop-shadow(2px 2px 3px rgb(0 0 0 / 0.6));
            transition: color 300ms ease-in-out;

            &:hover,
            &:active,
            &:focus {
                color: var(--accent-colour);
            }
        }
    }

    ul,
    a,
    p {
        list-style-type: none;
        margin: 0;
        padding: 0;
    }

    li {
        margin-bottom: var(--small-space);
    }

    ul.icons {
        display: flex;
        flex-direction: row;
        gap: var(--smedium-space);

        a {
            background: none;

            &::after {
                display: none;
            }
        }

        svg {
            width: 48px;
            height: 48px;
            fill: var(--text-colour);
            transition: fill 150ms ease-out;

            &:hover {
                fill: var(--link-colour);
            }
        }
    }

    .stats {
        .stats-rollover {
            position: absolute;
            bottom: var(--smedium-space);
            right: var(--smedium-space);
            border-radius: 100%;
            width: calc(1em + 3 * var(--small-space));
            height: calc(1em + 3 * var(--small-space));
            background-color: var(--background-alt-colour);
            cursor: help;
            text-align: center;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .stats-details {
            position: absolute;
            bottom: var(--smedium-space);
            right: calc(
                2 * var(--smedium-space) + 1em + 3 * var(--small-space)
            );
            display: none;
            background-color: var(--background-alt-colour);
            font-size: var(--font-size-tiny);
            transition: all 200ms ease-in-out;
            border-radius: 10px;
            padding: var(--small-space);

            code {
                font-family: "Berkeley Mono", monospace;
                color: var(--text-alt-colour);
            }
        }

        &:has(span:hover),
        &:has(span:focus) {
            .stats-details {
                display: block;
            }
        }
    }
}


/* =========================== assets/stylesheet/stylesheet/04-global.public.css ========================== */

:root {
    --timing-ease-in-out-quad: cubic-bezier(0.45, 0, 0.55, 1);
    --background-texture: url(/background.png);
}

/* Registered so the ch measure resolves at body text size on main, rather than
   in each heading's larger font. */
@property --prose-width {
    syntax: "<length>";
    inherits: true;
    initial-value: 0px;
}

body {
    background: var(--background-texture) var(--background-colour);
    color: var(--text-colour);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-height: 100vh;
    min-width: 100vw;

    /* In chromium, 100vw includes the space taken by the vertical scrollbar, so
     having any content that's 100vw wide will cause horizontal scrolling.
     There's no good way to fix this, AFAICT. So just hide the overflow. */
    overflow-x: hidden;
}

main {
    width: var(--content-width);
    margin: 0 auto;
    flex-grow: 1;

    --prose-width: 70ch;

    /* Long-form bodies (posts and pastes, and static pages guessed from a run of
       paragraphs) are narrowed to a comfortable measure, along with their titles.
       Widgets after the body keep the full width, and full-bleed blocks inside it
       still reach the edges. */
    & > article.h-entry > :is(header, .old-post-warning, .e-content),
    &:has(> .page-content > p + p + p) > :is(h2, .page-content) {
        max-width: var(--prose-width);
        margin-inline: auto;
        --content-margin: calc((100vw - min(var(--prose-width), var(--content-width))) / 2);
        --float-overhang: 20rem;
        --float-max-width: 50%;
    }

    & > h2 {
        margin-top: 0;
    }
}

hr {
    border: 0;
    border-top: 5px solid var(--accent-colour);
    margin: var(--medium-space) 0;
    width: 100%;
    box-shadow: 3px 3px 5px black;
    border-radius: var(--border-radius);
}

ol {
    list-style-type: decimal;
    padding-left: 2em;

    li {
        padding-left: 0.5em;
        margin-bottom: var(--small-space);
    }
}

ul {
    list-style-type: disc;
    padding-left: 1.5em;
}

*[hidden] {
    display: none;
}


/* =========================== assets/stylesheet/stylesheet/04-header.public.css ========================== */

@property --loop-sweep {
    syntax: "<angle>";
    inherits: true;
    initial-value: 0deg;
}

body > header {
    width: var(--content-width);
    margin: clamp(1.5rem, 3vw, 2.75rem) auto clamp(2.5rem, 4vw, 3.75rem);
    padding: 0 0 1.1rem;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.25rem 3rem;
    container-type: inline-size;
    position: relative;

    /* A faint biro rule under the header, in place of a hard border. */
    &::after {
        content: "";
        position: absolute;
        inset: auto 0 -15px;
        height: 30px;
        background: color-mix(in srgb, var(--text-colour) 22%, transparent);
        mask: url("/paper/header-rule.svg") 0 0 / 100% 100% no-repeat;
        pointer-events: none;
    }

    @media (width <= 1080px) {
        flex-direction: column;
        align-items: center;
    }

    & > a {
        /* Safari underlines block level elements within an A... */
        text-decoration: none;
        color: inherit;
    }

    h1 {
        display: grid;
        justify-items: start;
        color: var(--accent-colour);
    }

    .banner {
        margin: 0;
        font-family: "Berkeley Mono", monospace;
        /* Size the art by a whole-pixel character width (Berkeley Mono is 0.6em
           wide), as Firefox snaps each glyph to whole pixels. Fractional widths
           make it overflow and the lines misalign. */
        --advance: clamp(3px, round(0.312vw + 0.6px, 1px), 7px);
        font-size: calc(var(--advance) / 0.6);
        line-height: 1;
        white-space: pre;
        --flood-steps: attr(data-steps type(<number>), 0);
        /* Smears each glyph a hair sideways to fill the seams between blocks. */
        text-shadow: 0.1px 0 currentColor, -0.1px 0 currentColor;

        /* The solid blocks; the box-drawing outlines take the h1 colour. Glyphs
           are 1.2em tall so rows overlap slightly; positioning the blocks paints
           them over any outline poking up from the row below. */
        span {
            position: relative;
            color: var(--link-colour);
            /* data-step is each block's distance from the top-left of the C in a
               flood fill (the pre's data-steps is the largest). Hovering snaps each
               block on in that order, leaving un-fills in reverse. */
            transition: color 0s calc((var(--flood-steps) - attr(data-step type(<number>), 0)) * 6ms);

            @media (prefers-reduced-motion: reduce) {
                transition-delay: 0s;
            }
        }

        /* Once the nav drops below, the art can use the full width (91 characters). */
        @media (width <= 1080px) {
            --advance: clamp(3px, round(down, (100cqi - 2px) / 91, 1px), 7px);
        }
    }

    .title {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .byline {
        font-family: "Chris Hand", sans-serif;
        font-size: clamp(1.1rem, 1.1vw, 1.4rem);
        line-height: 1;
        color: var(--accent-colour);
        margin: 0.6rem 0 0 var(--medium-space);
        transform: rotate(-1.5deg);
        text-wrap: nowrap;

        /* A biro arrow curving up to the logo, drawn in the text colour. */
        &::before {
            content: "";
            display: inline-block;
            width: 1.1em;
            height: 1.2em;
            margin-right: 0.15em;
            vertical-align: -0.1em;
            background: currentColor;
            mask: url("/paper/byline-arrow.svg") center / contain no-repeat;
        }
    }

    & > a:is(:hover, :focus-visible) .banner span {
        color: var(--text-highlight-colour);
        transition-delay: calc(attr(data-step type(<number>), 0) * 18ms);

        @media (prefers-reduced-motion: reduce) {
            transition-delay: 0s;
        }
    }

    nav {
        display: flex;
        gap: 1.4em;
        align-items: flex-end;
        font-family: "Chris Hand", sans-serif;
        font-size: clamp(1.2rem, 1.3vw, 1.6rem);

        a {
            position: relative;
            color: var(--text-colour);
            text-transform: lowercase;
            white-space: nowrap;
            text-decoration: none;
            background: none;

            /* A biro loop drawn round the link by sweeping conic masks over it.
               The overshoot tail crosses the start of the loop, so it's a separate
               piece revealed only once the sweep passes a full turn. */
            transition: --loop-sweep 200ms ease-in;

            &::before,
            &::after {
                content: "";
                position: absolute;
                inset: -0.3em -0.45em -0.2em;
                background: var(--accent-colour);
                pointer-events: none;
            }

            &::before {
                mask:
                    url("/paper/nav-loop.svg") 0 0 / 100% 100% no-repeat,
                    conic-gradient(from 280deg, #000 var(--loop-sweep), transparent 0);
                mask-composite: intersect;
            }

            &::after {
                mask:
                    url("/paper/nav-loop-tail.svg") 0 0 / 100% 100% no-repeat,
                    conic-gradient(from 260deg, #000 calc(var(--loop-sweep) - 340deg), transparent 0);
                mask-composite: intersect;
            }

            &:is(:hover, :focus-visible) {
                --loop-sweep: 420deg;
                transition: --loop-sweep 500ms ease-out;
            }
        }

        @media (width <= 700px) {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            justify-items: center;
            gap: 0.8em 2.5em;
        }
    }
}


/* =========================== assets/stylesheet/stylesheet/04-links.public.css ========================== */

@layer links {
    a {
        color: var(--text-highlight-colour);
        text-decoration: none;
        line-height: 1;

        &:not(.plain-link) {
            text-decoration: underline;
            text-decoration-color: var(--accent-colour);
            text-decoration-thickness: 4px;
            text-decoration-skip-ink: none;

            background: linear-gradient(
                    to bottom,
                    transparent 50%,
                    var(--accent-colour) 50%
                )
                top;
            background-size: 100% 200%;

            transition: background 1s ease-out;

            &:hover,
            &:active,
            &:focus {
                background-position: bottom;
                transition-duration: 150ms;
            }

            &[href*="://"]:not([href*="://chameth.com"])::after {
                content: "↗";
                font-family: "Berkeley Mono", monospace;
                color: var(--accent-colour);
            }
        }
    }
}


/* =========================== assets/stylesheet/stylesheet/04-littlefoot.public.css ========================== */

/**
 * littlefoot 4.1.2, with modifications.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Chris Sauvé and Luís Rodrigues.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
@custom-media --breakpoint (width < 768px);

.littlefoot {
    --popover-background-color: var(--accent-colour);
    --popover-text-color: var(--text-colour);
    --popover-border: 0;
    --popover-border-radius: 0.5rem;
    --popover-max-height: 15em;
    --popover-max-width: 90%;
    --popover-horizontal-padding: calc(var(--medium-space) / 2);
    --popover-vertical-padding: calc(var(--medium-space) / 2);
    --popover-shadow: 8px 8px 8px #000000cc;
    --popover-transform-origin: 50% 0;
    --popover-transform: scale(0.1) translateZ(0);
    --popover-active-transform: scale(1) translateZ(0);
    --popover-transition: opacity 0.25s ease, transform 0.25s ease;
    --popover-width: 22em;
    --popover-scroll-indicator-color: var(--text-alt-colour);
    --popover-tooltip-size: 0.5rem;

    position: relative;
}
.littlefoot__popover {
    border: var(--popover-border);
    border-radius: var(--popover-border-radius);
    box-shadow: var(--popover-shadow);
    margin: calc(var(--popover-tooltip-size) + 1.25 * var(--font-size-regular))
        0;
    max-width: var(--popover-max-width);
    position: absolute;
    top: 0;
    transform-origin: var(--popover-transform-origin);
    transform: var(--popover-transform);
    transition: var(--popover-transition);
    width: var(--popover-width);
    z-index: 99999;

    &.is-above {
        bottom: 0;
        top: auto;
    }

    &.is-active {
        transform: var(--popover-active-transform);
    }
}

.littlefoot__wrapper {
    border-radius: var(--popover-border-radius);
    position: relative;
    z-index: 1;
}

.littlefoot__content {
    -webkit-overflow-scrolling: touch;
    background-color: var(--popover-background-color);
    border-radius: var(--popover-border-radius);
    box-sizing: border-box;
    color: var(--popover-text-color);
    font-family: var(--popover-font-family, initial);
    font-size: var(--popover-font-size, initial);
    font-style: var(--popover-font-style, initial);
    font-weight: var(--popover-font-weight, initial);
    line-height: var(--popover-line-height, normal);
    max-height: var(--popover-max-height);
    overflow: auto;
    padding: var(--popover-vertical-padding) var(--popover-horizontal-padding);
    width: 100%;

    & img {
        max-width: 100%;
    }

    &:focus {
        outline: none;
    }

    p {
        margin: 0;
    }

    em::before,
    em::after {
        display: none;
    }

    a {
        text-decoration: underline;

        &::after {
            display: none;
        }
    }
}

.is-scrollable {
    --arrow-x: calc(-1 * var(--popover-horizontal-padding));
    --arrow-y: calc(var(--popover-vertical-padding) / 2);

    & .littlefoot__content::after {
        bottom: 0;
        color: var(--popover-scroll-indicator-color);
        content: "\21E3";
        display: block;
        left: 0;
        opacity: 1;
        position: sticky;
        text-align: center;
        transform: translateX(var(--arrow-x)) translateY(var(--arrow-y));
        transition: var(--popover-transition);
        width: var(--popover-horizontal-padding);
    }

    &.is-fully-scrolled .littlefoot__content::after {
        opacity: 0;
    }
}

.littlefoot__tooltip {
    --tooltip-margin: calc(-1 * var(--popover-tooltip-size));

    background-color: var(--popover-background-color);
    border: var(--popover-border);
    box-shadow: var(--popover-shadow);
    height: calc(2 * var(--popover-tooltip-size));
    margin-left: var(--tooltip-margin);
    position: absolute;
    transform: rotate(45deg);
    width: calc(2 * var(--popover-tooltip-size));
}

.is-below .littlefoot__tooltip {
    top: var(--tooltip-margin);
}

.is-above .littlefoot__tooltip {
    bottom: var(--tooltip-margin);
}

@media (--breakpoint) {
    .littlefoot__popover {
        border-radius: 0;
        border-width: 1px 0 0;
        inset: auto 0 0 !important;
        margin: 0;
        max-width: 100% !important;
        position: fixed;
        transform: translateY(100%);
        width: 100%;

        &.is-active {
            transform: translateY(0);
        }
    }

    .littlefoot__wrapper {
        border-radius: 0;
        max-width: 100% !important;
        transform: none;
    }

    .littlefoot__tooltip {
        display: none;
    }
}

@media not print {
    sup.littlefoot--print {
        display: none;
    }
}

@media print {
    .littlefoot__popover,
    .littlefoot__button {
        display: none;
    }
}


/* =========================== assets/stylesheet/stylesheet/04-pagination.public.css ========================== */

nav ol {
    display: flex;
    list-style-type: none;
    justify-content: center;
    gap: var(--medium-space);
    padding: 0;
    margin: var(--medium-space) 0 0 0;

    @media (width <= 800px) {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--small-space);
    }

    a[aria-current] {
        font-weight: bold;
    }
}

nav.readmore {
    margin-top: var(--small-space);

    a {
        font-family: "Berkeley Mono", monospace;
        text-transform: uppercase;
    }
}

.pages-intro {
    p {
        background: var(--background-alt-colour);
        border-radius: var(--border-radius);
        padding: var(--medium-space);
    }

    &::after {
        margin: var(--large-space) calc(-1 * var(--content-margin));
        width: 100vw;
        display: block;
        content: "";
        border-bottom: 2px solid var(--accent-colour);
        clear: both;
    }
}

.excerpt {
    &::after {
        margin: var(--large-space) calc(-1 * var(--content-margin));
        width: 100vw;
        display: block;
        content: "";
        border-bottom: 2px solid var(--accent-colour);
        clear: both;
    }

    @media (width >= 1200px) {
        p.date + figure.right {
            margin-top: calc(
                -1 *
                    (
                        var(--font-size-large) + var(--font-size-tiny) +
                            var(--medium-space)
                    )
            );
        }
    }
}

.sitemap time {
    color: var(--text-alt-colour);
    font-family: "Berkeley Mono", monospace;
    font-size: var(--font-size-tiny);
    padding-left: var(--small-space);
}


/* =========================== assets/stylesheet/stylesheet/04-syntax.public.css ========================== */

/**
 * Dracula Theme originally by Zeno Rocha [@zenorocha]
 * https://draculatheme.com/
 *
 * Ported for PrismJS by Albert Vallverdu [@byverdu]
 */

code[class*="language-"],
pre[class*="language-"],
code[class*="chroma-"],
pre[class*="chroma-"] {
    color: #f8f8f2;
    background: none;
    text-shadow: 0 1px rgba(0, 0, 0, 0.3);
    font-family: "Berkeley Mono", monospace;
    font-size: var(--font-size-tiny);
    text-align: left;
    white-space: pre;
    word-spacing: normal;
    word-break: normal;
    word-wrap: normal;
    line-height: 1.5;
    -moz-tab-size: 4;
    -o-tab-size: 4;
    tab-size: 4;
    -webkit-hyphens: none;
    -moz-hyphens: none;
    -ms-hyphens: none;
    hyphens: none;
}

/* Code blocks */
pre[class*="language-"],
pre[class*="chroma-"] {
    margin: var(--medium-space) 0;
    overflow: auto;
    border-radius: var(--border-radius);
    padding: var(--medium-space);
    box-shadow: 3px 3px 5px black;
}

:not(pre) > code[class*="language-"],
:not(pre) > code[class*="chroma-"],
pre[class*="language-"],
pre[class*="chroma-"] {
    background: var(--background-alt-colour);
}

/* Inline code */
:not(pre) > code[class*="language-"],
:not(pre) > code[class*="chroma-"] {
    padding: 0.1em;
    border-radius: 0.3em;
    white-space: normal;
}

.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
    color: #6272a4;
}

.token.punctuation {
    color: #f8f8f2;
}

.namespace {
    opacity: 0.7;
}

.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
    color: #ff79c6;
}

.token.boolean,
.token.number {
    color: #bd93f9;
}

.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
    color: #50fa7b;
}

.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
    color: #f8f8f2;
}

.token.atrule,
.token.attr-value,
.token.function,
.token.class-name {
    color: #f1fa8c;
}

.token.keyword {
    color: #8be9fd;
}

.token.regex,
.token.important {
    color: #ffb86c;
}

.token.important,
.token.bold {
    font-weight: bold;
}

.token.italic {
    font-style: italic;
}

.token.entity {
    cursor: help;
}

/** Chroma **/
/* Error */
.chroma-chroma .chroma-err {
    color: #ff0000;
}
/* Line */
.chroma-chroma .chroma-line {
    display: flex;
}
/* Keyword */
.chroma-chroma .chroma-k {
    color: #8cb8fa;
}
/* KeywordConstant */
.chroma-chroma .chroma-kc {
    color: #8cb8fa;
}
/* KeywordDeclaration */
.chroma-chroma .chroma-kd {
    color: #8cb8fa;
}
/* KeywordNamespace */
.chroma-chroma .chroma-kn {
    color: #8cb8fa;
}
/* KeywordPseudo */
.chroma-chroma .chroma-kp {
    color: #8cb8fa;
}
/* KeywordReserved */
.chroma-chroma .chroma-kr {
    color: #8cb8fa;
}
/* KeywordType */
.chroma-chroma .chroma-kt {
    color: #50fa7b;
}
/* NameAttribute */
.chroma-chroma .chroma-na {
    color: #50fa7b;
}
/* NameBuiltin */
.chroma-chroma .chroma-nb {
    color: #faeb8c;
}
/* NameFunction */
.chroma-chroma .chroma-nf {
    color: #faeb8c;
}
/* NameTag */
.chroma-chroma .chroma-nt {
    color: #ff79c6;
}
/* LiteralDate */
.chroma-chroma .chroma-ld {
    color: #50fa7b;
}
/* LiteralString */
.chroma-chroma .chroma-s {
    color: #50fa7b;
}
/* LiteralStringAffix */
.chroma-chroma .chroma-sa {
    color: #50fa7b;
}
/* LiteralStringBacktick */
.chroma-chroma .chroma-sb {
    color: #50fa7b;
}
/* LiteralStringChar */
.chroma-chroma .chroma-sc {
    color: #50fa7b;
}
/* LiteralStringDelimiter */
.chroma-chroma .chroma-dl {
    color: #50fa7b;
}
/* LiteralStringDoc */
.chroma-chroma .chroma-sd {
    color: #50fa7b;
}
/* LiteralStringDouble */
.chroma-chroma .chroma-s2 {
    color: #50fa7b;
}
/* LiteralStringEscape */
.chroma-chroma .chroma-se {
    color: #50fa7b;
}
/* LiteralStringHeredoc */
.chroma-chroma .chroma-sh {
    color: #50fa7b;
}
/* LiteralStringInterpol */
.chroma-chroma .chroma-si {
    color: #50fa7b;
}
/* LiteralStringOther */
.chroma-chroma .chroma-sx {
    color: #50fa7b;
}
/* LiteralStringRegex */
.chroma-chroma .chroma-sr {
    color: #50fa7b;
}
/* LiteralStringSingle */
.chroma-chroma .chroma-s1 {
    color: #50fa7b;
}
/* LiteralStringSymbol */
.chroma-chroma .chroma-ss {
    color: #50fa7b;
}
/* LiteralNumber */
.chroma-chroma .chroma-m {
    color: #bd93f9;
}
/* LiteralNumberBin */
.chroma-chroma .chroma-mb {
    color: #bd93f9;
}
/* LiteralNumberFloat */
.chroma-chroma .chroma-mf {
    color: #bd93f9;
}
/* LiteralNumberHex */
.chroma-chroma .chroma-mh {
    color: #bd93f9;
}
/* LiteralNumberInteger */
.chroma-chroma .chroma-mi {
    color: #bd93f9;
}
/* LiteralNumberIntegerLong */
.chroma-chroma .chroma-il {
    color: #bd93f9;
}
/* LiteralNumberOct */
.chroma-chroma .chroma-mo {
    color: #bd93f9;
}
/* Comment */
.chroma-chroma .chroma-c {
    color: #6272a4;
}
/* CommentHashbang */
.chroma-chroma .chroma-ch {
    color: #6272a4;
}
/* CommentMultiline */
.chroma-chroma .chroma-cm {
    color: #6272a4;
}
/* CommentSingle */
.chroma-chroma .chroma-c1 {
    color: #6272a4;
}
/* CommentSpecial */
.chroma-chroma .chroma-cs {
    color: #6272a4;
}
/* CommentPreproc */
.chroma-chroma .chroma-cp {
    color: #6272a4;
}
/* CommentPreprocFile */
.chroma-chroma .chroma-cpf {
    color: #6272a4;
}


/* =========================== assets/stylesheet/stylesheet/04-tables.public.css ========================== */

.table-holder {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
}

table:not(.plain-table) {
    width: 100%;
    margin: var(--medium-space) 0;
    background: var(--background-colour);
    border: 1px solid var(--background-alt-colour);
    box-shadow: 3px 3px 5px black;
    border-radius: var(--border-radius);
    border-collapse: separate;
    overflow: hidden;

    tr:not(:last-child) td {
        border-bottom: 1px solid var(--background-alt-colour);
    }
}

td {
    padding: var(--small-space);
    font-size: var(--font-size-small);
}

th:not(.plain-header) {
    background-color: var(--background-colour);
    border-bottom: 2px solid var(--accent-colour);
    padding: 0.4em;
    text-align: left;
    font-weight: bold;
    color: var(--text-alt-colour);
    text-transform: uppercase;
    font-family: "Berkeley Mono", monospace;
    font-size: var(--font-size-tiny);
}


/* =========================== assets/stylesheet/stylesheet/04-typography.public.css ========================== */

:root {
    --font-body: "Charis", Georgia, serif;

    --font-size-tiny: 13px;
    --font-size-small: 15.5px;
    --font-size-regular: clamp(18.5px, 0.3vw + 16px, 22.5px);
    --font-size-large: calc(1.2 * var(--font-size-regular));
    --font-size-xlarge: 1.75rem;
    --font-size-xxlarge: clamp(2rem, 2.6vw, 2.6rem);
    --font-size-giant: clamp(2.5rem, 4.4vw, 4.2rem);

    @media (width <= 600px) {
        --font-size-regular: 17.5px;
    }
}

@font-face {
    font-family: "Charis";
    src: url("/fonts/Charis-Regular.woff2") format("woff2");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Charis";
    src: url("/fonts/Charis-Regular-Ext.woff2") format("woff2");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Charis";
    src: url("/fonts/Charis-Italic.woff2") format("woff2");
    font-weight: normal;
    font-style: italic;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Charis";
    src: url("/fonts/Charis-Italic-Ext.woff2") format("woff2");
    font-weight: normal;
    font-style: italic;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Charis";
    src: url("/fonts/Charis-Bold.woff2") format("woff2");
    font-weight: bold;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Charis";
    src: url("/fonts/Charis-Bold-Ext.woff2") format("woff2");
    font-weight: bold;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Charis";
    src: url("/fonts/Charis-BoldItalic.woff2") format("woff2");
    font-weight: bold;
    font-style: italic;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Charis";
    src: url("/fonts/Charis-BoldItalic-Ext.woff2") format("woff2");
    font-weight: bold;
    font-style: italic;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Berkeley Mono";
    src:
        local("Berkeley Mono"),
        url("/fonts/BerkeleyMono-Regular.woff2") format("woff2"),
        url("/fonts/BerkeleyMono-Regular.woff") format("woff");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Chris Hand";
    src:
        url("/fonts/ChrisHand-Regular.woff2") format("woff2"),
        url("/fonts/ChrisHand-Regular.woff") format("woff");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

body {
    font-size: var(--font-size-regular);
    font-family: var(--font-body);
    line-height: 1.58;
}

@layer headers {
    h2,
    h3,
    h4,
    h5,
    h6 {
        font-family: "Chris Hand", sans-serif;
        font-size: var(--font-size-xxlarge);
        color: var(--text-highlight-colour);
        margin: var(--medium-space) 0;
        line-height: 1;

        &:not(.plain-header) {
            transform: rotate(-0.15deg);
            padding-bottom: 0.05em;
            text-shadow: 2px 2px 3px rgb(0 0 0 / 0.6);
            font-weight: 800;
            position: relative;

            /* A hand-drawn rule under the heading, in the accent colour (darkened
               for lower heading levels below). */
            &::before {
                content: "";
                position: absolute;
                inset: auto 0 0;
                height: 10px;
                z-index: -1;
                background: var(--accent-colour);
                mask: url("/paper/heading-rule.svg") 0 0 / 100% 100% no-repeat;
                pointer-events: none;
            }
        }

        /* Links are shown by colour alone, as an underline would clash with
           the heading's rule. */
        a {
            background: none;
            text-decoration: none;
            color: var(--link-colour);
            transition: color 500ms var(--timing-ease-in-out-quad);

            &:hover,
            &:focus,
            &:active {
                color: var(--accent-colour);
                transition-duration: 150ms;
            }

            &::after {
                color: var(--text-alt-colour);
            }
        }
    }

    h3 {
        font-size: calc(0.8 * var(--font-size-xxlarge));
        &:not(.plain-header)::before {
            filter: brightness(0.8);
        }
    }

    h4 {
        font-size: calc(0.6 * var(--font-size-xxlarge));
        &:not(.plain-header)::before {
            filter: brightness(0.6);
        }
    }

    h5 {
        font-size: calc(0.4 * var(--font-size-xxlarge));
        &:not(.plain-header)::before {
            filter: brightness(0.4);
        }
    }

    h6 {
        font-size: calc(0.2 * var(--font-size-xxlarge));
        &:not(.plain-header)::before {
            filter: brightness(0.2);
        }
    }
}

p {
    margin: var(--medium-space) 0;
}

p code,
li code {
    background-color: var(--background-alt-colour);
    border-radius: var(--border-radius);
    padding: 0.1em 0.5em;
    font-family: "Berkeley Mono", monospace;
}

em,
i {
    font-style: italic;

    &::before,
    &::after {
        color: var(--accent-colour);
        font-size: var(--font-size-tiny);
        content: "_";
    }
}

strong {
    font-weight: bold;
}

/* via https://css-tricks.com/fluid-superscripts-and-subscripts/ */
sup,
sub {
    font-size: calc(0.5em + 4px);
    vertical-align: baseline;
    position: relative;
    top: calc(-0.5 * 0.83 * 2 * (1em - 4px));
}

sub {
    top: calc(0.25 * 0.83 * 2 * (1em - 4px));
}

.poem {
    font-family: "Berkeley Mono", monospace;
    background-color: var(--background-alt-colour);
    padding: 1em;
    margin: var(--medium-space) 0;
    border-radius: var(--border-radius);
    white-space: preserve-spaces;
}

.ascii-art {
    font-family: "Berkeley Mono", monospace;
    font-size: var(--font-size-tiny);
    color: var(--text-alt-colour);

    @media (width <= 600px) {
        font-size: 6pt;
    }
}


/* =========================== moods/halloween.css ========================== */

body {
  background:
    url(/moods/cobweb.png) 0 0 no-repeat fixed,
    var(--background-texture) var(--background-colour);
}


/* =========================== features/boardgames/list/style.public.css ========================== */

.boardgame-list {
    display: flex;
    flex-direction: column;
    gap: var(--smedium-space);
    list-style-type: none;
    margin: 0 0 var(--large-space) 0;
    padding: 0;

    li {
        display: grid;
        grid-template-areas: "image header" "image watches" "image rating" "image blank";
        grid-template-columns: 200px 1fr;
        grid-template-rows: auto auto auto 1fr;
        grid-column-gap: var(--smedium-space);
        grid-row-gap: var(--smedium-space);
        overflow: hidden;

        &,
        * {
            margin: 0;
            padding: 0;
        }

        .image-container {
            grid-area: image;
            position: relative;
            width: 200px;
            height: 200px;
            overflow: hidden;
            border-right: 1px solid var(--background-alt-colour);

            img {
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
            }

            .background {
                object-fit: cover;
                filter: blur(12px) saturate(0.5);
                transform: scale(1.1);
                opacity: 0.5;
            }

            .foreground {
                object-fit: contain;
                padding: var(--small-space);
                filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.5));
            }
        }

        .details {
            display: contents;

            h3 {
                margin-top: var(--smedium-space);

                .year {
                    color: var(--text-alt-colour);
                    font-size: var(--font-size-large);
                }

                .position {
                    color: var(--text-alt-colour);
                }
            }

            p {
                color: var(--text-alt-colour);
                font-family: "Berkeley Mono", monospace;
                font-size: var(--font-size-small);
            }
        }
    }
}


/* =========================== features/boardgames/played/style.public.css ========================== */

.played-boardgames {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    list-style-type: none;
    gap: var(--smedium-space);
    margin: var(--small-space) 0;
    padding: 0;

    li {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: var(--small-space);
        padding-bottom: var(--small-space);
        overflow: hidden;

        .image-container {
            position: relative;
            width: 100%;
            aspect-ratio: 1;
            overflow: hidden;
            border-bottom: 1px solid var(--background-alt-colour);

            img {
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
            }

            .background {
                object-fit: cover;
                filter: blur(12px) saturate(0.5);
                transform: scale(1.1);
                opacity: 0.5;
            }

            .foreground {
                object-fit: contain;
                padding: var(--small-space);
                filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.5));
            }
        }

        p {
            color: var(--text-alt-colour);
            font-family: "Berkeley Mono", monospace;
            font-size: var(--font-size-small);
            margin: 0;
        }
    }
}


/* =========================== features/contact/form/style.public.css ========================== */

.contact-container form.contact {
    display: flex;
    flex-direction: column;
    gap: var(--small-space);
    margin: var(--smedium-space) 0;

    &:not([data-title]) {
        padding-top: var(--smedium-space);
    }

    input.subject {
        position: absolute;
        opacity: 0;
        height: 0;
        width: 0;
        padding: 0;
        border: none;
        pointer-events: none;
    }

    input,
    textarea {
        font-size: var(--font-size-small);
        background-color: var(--background-alt-colour);
        color: var(--text-colour);
        border: 1px solid var(--accent-alt-colour);
        border-radius: 5px;
        padding: var(--small-space);
    }

    textarea {
        min-height: 200px;
        resize: vertical;
    }

    button {
        font-size: var(--font-size-small);
        background-color: var(--accent-colour);
        color: var(--text-colour);
        border: 0;
        text-transform: uppercase;
        padding: var(--small-space);
        border-radius: 5px;
        cursor: pointer;
    }

    p.privacy {
        font-size: var(--font-size-tiny);
        text-align: center;
        margin: var(--small-space) 0 0;
        color: var(--text-alt-colour);
    }
}


/* =========================== features/feeds/style.public.css ========================== */

.feed-builder-button {
    display: inline-flex;
    align-items: center;
    gap: var(--small-space);
    padding: var(--smedium-space) calc(2 * var(--smedium-space));
    background-color: var(--background-alt-colour);
    color: var(--text-highlight-colour);
    border-radius: var(--border-radius);
    box-shadow: 3px 3px 5px black;
    font-family: inherit;
    font-size: 1.4em;
    font-weight: bold;
    text-decoration: none;
    border: none;
    cursor: pointer;

    &:hover,
    &:focus {
        background-color: var(--accent-colour);
    }
}

.feed-builder-section {
    margin-top: var(--medium-space);

    h3 {
        margin-bottom: var(--small-space);
    }
}

.feed-builder-posts {
    list-style-type: none;
    padding-left: 0;

    li {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: var(--small-space);
        padding: var(--small-space) 0;
        border-bottom: 1px solid var(--background-alt-colour);
    }
}

.feed-builder-post {
    display: inline-flex;
    align-items: center;
    gap: var(--small-space);
}

.feed-builder-pin {
    flex-shrink: 0;
}

.feed-builder-date {
    color: var(--text-alt-colour);
}

.feed-builder-actions {
    margin-left: auto;
    display: flex;
    flex-wrap: wrap;
    gap: var(--small-space);

    form {
        display: contents;
    }

    button {
        font: inherit;
        font-size: small;
        color: var(--text-colour);
        background-color: var(--background-alt-colour);
        padding: calc(var(--small-space) / 2) var(--small-space);
        border: none;
        border-radius: var(--border-radius);
        cursor: pointer;

        &:hover,
        &:focus {
            color: var(--text-highlight-colour);
            background-color: var(--accent-colour);
        }
    }
}


/* =========================== features/films/calendar/style.public.css ========================== */

/* Film calendar: reuses the workout calendar's .calendar-grid, with one
   ramp shaded by the day's watch count relative to the busiest day in the
   window (s0 dimmest, s3 full tint). A year doesn't fit narrow viewports
   at the workout calendar's cell size, so cells are smaller and the grid
   scrolls horizontally when it still doesn't fit. */
.film-calendar {
    display: inline-block;
    max-width: 100%;
    margin: var(--smedium-space) 0;
    padding: var(--smedium-space);
    padding-top: var(--raised-box-title-padding);

    .calendar-grid {
        --cell-size: 0.7rem;
        --cell-gap: 0.15rem;
    }

    .s0 { background-color: var(--accent-alt-colour); }
    .s1 { background-color: var(--accent-colour); }
    .s2 { background-color: color-mix(in srgb, var(--accent-colour), var(--link-colour)); }
    .s3 { background-color: var(--link-colour); }
}


/* =========================== features/films/list/style.public.css ========================== */

a.film-list {
    display: grid;
    max-height: calc(
        200px + var(--smedium-space) * 2 + var(--raised-box-title-padding)
    );
    grid-template-areas: "header images" "description images" "meta images";
    grid-template-columns: 1fr auto;
    grid-template-rows: auto 1fr auto;
    row-gap: var(--small-space);

    @media (width <= 800px) {
        grid-template-areas: "header" "description" "images" "meta";
        grid-template-columns: 1fr;
        grid-template-rows: auto auto auto auto;
        max-height: inherit;
    }

    padding-left: var(--smedium-space);
    padding-right: var(--smedium-space);
    padding-bottom: var(--smedium-space);

    & + & {
        margin-top: var(--medium-space);
    }

    *,
    *:hover,
    *:active,
    *:focus {
        margin: 0;
        padding: 0;
    }

    h3 {
        font-size: var(--font-size-xxlarge);
    }

    .description {
        p + p {
            margin-top: var(--smedium-space);
        }

        overflow: hidden;
        --mask-height: 1.5em;
        mask: linear-gradient(
            to bottom,
            black,
            black var(--mask-height),
            transparent calc(100% - var(--mask-height)),
            transparent
        );
    }

    .count {
        color: var(--text-alt-colour);
        font-size: var(--font-size-small);
        font-family: "Berkeley Mono", monospace;
    }

    .poster-stack {
        --overlap: 0.3;
        grid-area: images;
        position: relative;
        width: calc(133px + (133px * 4 * var(--overlap)));
        height: 200px;

        @media (width < 400px) {
            --overlap: 0.2;
        }

        img {
            max-height: 200px;
            max-width: 133px;
            border-radius: var(--border-radius);
            position: absolute;
            top: 0;
            left: calc(133px * var(--overlap) * (sibling-index() - 1));
            /* earlier posters sit on top of later ones */
            z-index: calc(sibling-count() - sibling-index() + 1);
        }
    }
}


/* =========================== features/films/ratingdistribution/style.public.css ========================== */

.rating-distribution {
    display: inline-block;

    .chart-container {
        display: flex;
        align-items: flex-end;
        justify-content: space-between;
        gap: var(--small-space);
        padding: 0 var(--small-space) var(--small-space);
    }

    svg {
        margin-bottom: var(--small-space);
    }

    .left-label,
    .right-label {
        .star-rating img {
            width: 20px;
            height: 20px;
        }
    }
}


/* =========================== features/films/review/style.public.css ========================== */

.film-review-parent {
    container-type: inline-size;
}

.film-review {
    display: grid;
    grid-template-areas:
        "image header"
        "image body";
    grid-template-columns: auto 1fr;
    grid-template-rows: auto 1fr;
    padding: 0;
    column-gap: var(--smedium-space);
    margin: var(--smedium-space) 0;
    overflow: hidden;

    @container (width >= 700px) {
        height: 350px;

        img {
            border-top-left-radius: var(--border-radius);
            border-bottom-left-radius: var(--border-radius);
        }
    }

    @container (width < 700px) {
        grid-template-areas: "header" "image" "body";
        grid-template-rows: auto auto auto;
        grid-template-columns: 1fr;
        row-gap: var(--small-space);
        padding: var(--smedium-space);

        header {
            grid-template-columns: 100% !important;
            grid-template-rows: auto auto auto auto;

            time {
                text-align: left !important;
            }
        }
    }

    img {
        grid-area: image;
        max-width: 100%;
        max-height: 350px;
    }

    header {
        grid-area: header;
        display: grid;
        grid-template-columns: 1fr auto auto auto;
        align-items: center;
        column-gap: var(--small-space);
        margin-top: var(--small-space);
        margin-right: var(--smedium-space);

        div {
            display: flex;
            align-items: center;
        }

        h3 {
            padding: 0;
            font-size: var(--font-size-xlarge);
            line-height: var(--font-size-xlarge);
            margin: 0;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        time {
            text-align: right;
            font-size: var(--font-size-tiny);
            font-family: "Berkeley Mono", monospace;
            text-transform: uppercase;
        }
    }

    & > div {
        padding-bottom: var(--small-space);
        padding-right: var(--small-space);
        overflow-y: auto;
        font-size: var(--font-size-small);

        p {
            margin-top: var(--smedium-space);
            margin-bottom: var(--smedium-space);

            &:first-child {
                margin-top: 0;
            }

            &:last-child {
                margin-bottom: 0;
            }
        }

        i {
            font-style: italic;
        }
    }
}


/* =========================== features/films/reviews/style.public.css ========================== */

.film-reviews-parent {
    container-type: inline-size;
}

.film-reviews {
    display: grid;
    column-gap: var(--smedium-space);

    @container (width >= 1500px) {
        grid-template-columns: 1fr 1fr;
    }

    @container (width < 1500px) {
        grid-template-columns: 1fr;
    }
}


/* =========================== features/films/search/style.public.css ========================== */

.film-search {
    .results.hidden,
    .results:empty {
        display: none;
    }

    .results.visible {
        display: block;
    }

    input {
        width: 100%;
        font-size: var(--font-size-large);
        padding: var(--small-space);
        anchor-name: --film-search-box;
        background-color: var(--background-alt-colour);
        border: 2px solid var(--accent-alt-colour);
        border-radius: var(--border-radius);
        color: var(--text-alt-colour);

        &:has(+ .results:not(:empty)) {
            border-bottom-left-radius: 0;
            border-bottom-right-radius: 0;
            box-shadow: 0 5px 5px var(--accent-colour);
        }

        &:focus,
        &:active {
            border-color: var(--accent-colour);
            outline: none;
        }
    }

    .results {
        background-color: var(--background-alt-colour);
        padding: var(--small-space);
        max-height: 400px;
        overflow-y: auto;
        position: absolute;
        position-anchor: --film-search-box;
        position-area: bottom center;
        position-visibility: always;
        width: anchor-size();
        border: 2px solid var(--accent-colour);
        border-top: none;
        border-bottom-left-radius: var(--border-radius);
        border-bottom-right-radius: var(--border-radius);
        z-index: 10;
        box-shadow: 0 5px 5px var(--accent-colour);

        a {
            display: flex;
            flex-direction: row;
            padding: var(--small-space);
            gap: var(--small-space);
            border: 0;
            background: none;
            text-decoration: none;

            &:hover,
            &:focus,
            &:active {
                background-color: var(--accent-colour);
            }

            img {
                max-height: 100px;
                max-width: 66px;
            }

            h3 {
                margin: 0;
                padding: 0 0 var(--small-space) 0;
                font-family: var(--font-body);
                font-size: var(--font-size-large);
            }

            p {
                color: var(--text-alt-colour);
                padding: 0 0 var(--small-space) 0;
                margin: 0;
            }
        }
    }
}


/* =========================== features/films/style.public.css ========================== */

.films-list {
    display: flex;
    flex-direction: column;
    gap: var(--smedium-space);
    list-style-type: none;
    margin: 0 0 var(--large-space) 0;
    padding: 0;

    li {
        &,
        * {
            margin: 0;
            padding: 0;
        }

        a {
            display: grid;
            grid-template-areas: "image header" "image watches" "image rating" "image blank";
            grid-template-columns: auto 1fr;
            grid-template-rows: auto auto auto 1fr;
            grid-column-gap: var(--smedium-space);
            grid-row-gap: var(--smedium-space);
            overflow: hidden;

            & > img {
                grid-area: image;
                max-height: 200px;
                border-right: 1px solid var(--background-alt-colour);
            }

            h3 {
                margin-top: var(--smedium-space);
                .year {
                    color: var(--text-alt-colour);
                    font-size: var(--font-size-large);
                }
                .position {
                    color: var(--text-alt-colour);
                }
            }

            p {
                color: var(--text-alt-colour);
                font-family: "Berkeley Mono", monospace;
                font-size: var(--font-size-small);
            }
        }
    }
}

ol.recent-films,
ol.watched-films {
    list-style-type: none;
    gap: var(--smedium-space);
    margin: var(--small-space) 0;
    padding: 0;

    &.recent-films {
        display: flex;
        flex-direction: row;
        overflow-x: hidden;
        mask: linear-gradient(to right, black, black 95%, transparent 100%);
        padding: 3px 0 5px 3px;
        margin-left: -3px;

        li {
            width: 150px;
            flex-shrink: 0;
        }
    }

    &.watched-films {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    }

    li {
        margin: 0;
        padding: 0;

        a {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: var(--small-space);
            padding-bottom: var(--small-space);
            overflow: hidden;

            & > img {
                width: 100%;
                height: auto;
                border-bottom: 1px solid var(--background-alt-colour);
            }

            time,
            & > div {
                padding: 0 var(--small-space);
                font-family: "Berkeley Mono", monospace;
                font-size: var(--font-size-small);
                color: var(--text-alt-colour);
            }
        }
    }
}

.film-rewatch {
    display: inline-block;
    font-size: var(--font-size-tiny);
    padding: 0 var(--small-space);
    background-color: var(--accent-colour);
    border-radius: var(--border-radius);
}

.film-spoilers {
    display: inline-block;
    font-size: var(--font-size-tiny);
    padding: 0 var(--small-space);
    background-color: darkred;
    border-radius: var(--border-radius);
}

.film-page {
    --film-poster-width: 260px;

    /* Wide enough for the poster on one side and an equal gap on the other,
       so the hero's text lines up with the reviews below. */
    .film-hero {
        max-width: calc(var(--prose-width) + 2 * (var(--film-poster-width) + 2 * var(--medium-space)) + 2px);
        margin-inline: auto;
        position: relative;
        isolation: isolate;
        overflow: hidden;
        border-radius: var(--border-radius);
        border: 1px solid var(--background-alt-colour);
        box-shadow: 3px 3px 8px black;
        background: var(--background-alt-colour);
    }

    /* The poster again, blurred out to tint the hero. */
    .film-backdrop {
        position: absolute;
        inset: -60px;
        width: calc(100% + 120px);
        height: calc(100% + 120px);
        object-fit: cover;
        filter: blur(40px) brightness(0.35) saturate(1.3);
        z-index: -1;
    }

    .film-details {
        display: grid;
        /* The text column is centred to line up with the reviews; the poster
           shrinks a little to make room before it pushes the text off centre. */
        grid-template-columns: minmax(180px, 1fr) minmax(0, var(--prose-width)) minmax(0, 1fr);
        grid-template-rows: auto auto 1fr;
        column-gap: var(--medium-space);
        align-items: start;
        padding: var(--medium-space);

        & > :not(.film-poster) {
            grid-column: 2;
        }

        @media (width <= 700px) {
            grid-template-columns: 110px 1fr;
            grid-template-rows: auto 1fr auto;
            column-gap: var(--smedium-space);
            padding: var(--smedium-space);

            h2 {
                font-size: var(--font-size-xxlarge);
            }

            .film-overview {
                grid-column: 1 / -1;
                margin-top: var(--smedium-space);
            }
        }
    }

    .film-poster {
        grid-row: 1 / -1;
        justify-self: end;
        width: 100%;
        max-width: var(--film-poster-width);
        border-radius: 4px;
        box-shadow: 4px 4px 12px rgb(0 0 0 / 0.7);

        @media (width <= 700px) {
            grid-row: 1 / 3;
        }
    }

    .film-breadcrumb {
        margin: 0;
        font-family: "Berkeley Mono", monospace;
        font-size: var(--font-size-small);
        color: var(--text-alt-colour);
    }

    h2 {
        margin: var(--small-space) 0 var(--smedium-space);
        font-size: var(--font-size-giant);
        text-shadow: 2px 2px 6px rgb(0 0 0 / 0.7);

        .film-year {
            font-size: 0.5em;
            color: var(--text-alt-colour);
            text-shadow: none;
            margin-left: var(--small-space);
        }
    }

    .film-overview {
        color: var(--text-highlight-colour);
        text-shadow: 0 1px 3px rgb(0 0 0 / 0.6);

        p {
            margin: 0 0 var(--small-space);
        }
    }

    .film-summary {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: space-between;
        gap: var(--small-space) var(--medium-space);
        padding: var(--smedium-space) var(--medium-space);
        background: rgb(0 0 0 / 0.35);
        border-top: 1px solid rgb(255 255 255 / 0.08);
        font-family: "Berkeley Mono", monospace;
        font-size: var(--font-size-small);

        @media (width <= 700px) {
            padding: var(--smedium-space);
        }

        p {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: var(--small-space) var(--medium-space);
            margin: 0;
        }

        .star-rating img {
            width: 20px;
            height: 20px;
            vertical-align: -4px;
        }
    }

    .film-links {
        margin-left: auto;
    }

    /* Reviews read like a blog post: centred, at prose width. */
    .film-reviews {
        max-width: var(--prose-width);
        margin: var(--large-space) auto 0;

        & > :first-child h3 {
            margin-top: 0;
        }
    }

    .h-review {
        & + .h-review {
            margin-top: var(--large-space);
        }

        h3 {
            margin-bottom: var(--smedium-space);
        }

        .e-content {
            p:first-child {
                margin-top: 0;
            }

            p:last-child {
                margin-bottom: 0;
            }
        }
    }

    .film-review-meta {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--small-space) var(--smedium-space);
        margin: 0 0 var(--smedium-space);

        .star-rating img {
            width: 24px;
            height: 24px;
        }

        .film-rewatch,
        .film-spoilers {
            font-family: "Berkeley Mono", monospace;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            line-height: 1.8;
            color: var(--text-highlight-colour);
        }
    }

    .film-no-review {
        margin: 0;
        color: var(--text-alt-colour);
        font-style: italic;
    }

    .film-lists,
    .syndications {
        margin-top: var(--large-space);
    }
}


/* =========================== features/media/labelledfigure/labelledfigure.public.css ========================== */

.labelled-figure {
    .labelled-figure-controls {
        display: block;
        text-align: right;
        margin-bottom: var(--small-space);
        cursor: pointer;
        user-select: none;
        font-size: var(--font-size-small);
        font-family: "Berkeley Mono", monospace;

        input {
            margin-right: var(--small-space);
        }
    }

    .labelled-figure-container {
        position: relative;

        picture {
            display: block;
        }

        img {
            display: block;
            width: 100%;
            height: auto;
        }
    }

    svg.labelled-figure-overlay {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
    }

    .region-hit {
        cursor: pointer;
    }

    .region-border,
    .region-label {
        opacity: 0;
        transition: opacity 0.2s ease-in-out;
        pointer-events: none;
    }

    .region:hover .region-border,
    .region:hover .region-label,
    .region:focus .region-border,
    .region:focus .region-label {
        opacity: 1;
    }

    .region:focus {
        outline: none;
    }

    .region-label {
        paint-order: stroke fill;
        stroke: rgba(0, 0, 0, 0.85);
        stroke-width: 3px;
        stroke-linecap: round;
        stroke-linejoin: round;
        text-anchor: middle;
        dominant-baseline: central;
    }

    &:has(.show-all-regions:checked) .region-border,
    &:has(.show-all-regions:checked) .region-label {
        opacity: 1;
    }
}


/* =========================== features/media/style.public.css ========================== */

figure.image,
figure.video {
    margin: var(--medium-space) var(--medium-space) var(--small-space)
        var(--medium-space);
    padding: var(--medium-space);
    border-radius: var(--border-radius);
    text-align: center;
    background-color: var(--background-alt-colour);
    max-width: 100%;
    font-family: "Chris Hand", sans-serif;
    font-size: var(--font-size-large);
    line-height: 1;
    color: var(--text-alt-colour);
    position: relative;
    z-index: 1;

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

    @media (width <= 500px) {
        margin: 0;
    }

    @media (width >= 1200px) {
        /* Floats overlap the text column by a fixed amount and hang the rest out
           into the margin, up to the overhang limit and never past the page
           gutter. The width comes from the image's data-width (it's border-box,
           so includes the figure's padding). */
        &.left,
        &.right {
            --float-width: min(
                attr(data-width type(<number>), 0) * 1px + 2 * var(--medium-space),
                var(--float-max-width, 30%)
            );
            --float-hang: clamp(
                0px,
                var(--content-margin) - var(--page-gutter),
                min(var(--float-overhang, 50px), var(--float-width) - var(--float-overlap, 100px))
            );
        }

        &.left {
            float: left;
            max-width: var(--float-max-width, 30%);
            margin-left: calc(-1 * var(--float-hang));
            transform: rotate(-2deg);
            margin-right: calc(var(--medium-space) * 1.5);

            img,
            video {
                transform: rotate(1.5deg);
            }
        }

        &.right {
            float: right;
            max-width: var(--float-max-width, 30%);
            margin-right: calc(-1 * var(--float-hang));
            transform: rotate(2deg);
            margin-left: calc(var(--medium-space) * 1.5);

            img,
            video {
                transform: rotate(-1.5deg);
            }
        }

        &.left,
        &.right {
            position: relative;
            box-shadow: 8px 8px 20px black;
            margin-bottom: var(--medium-space);

            &::before {
                content: "";
                display: block;
                position: absolute;
                left: calc(50% - 50px);
                width: 100px;
                height: 40px;
                background-color: var(--accent-colour);
                opacity: 0.15;
                box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
                top: -20px;
                transform: rotate(4deg);
            }
        }
    }

    figcaption {
        margin-top: var(--medium-space);

        p {
            margin: 0;
        }
    }

    &.full {
        margin: var(--medium-space) calc(-1 * var(--content-margin));
        width: 100vw;
        max-width: 100vw;
        border-radius: 0;
    }
}


/* =========================== features/music/newalbums/style.public.css ========================== */

.new-albums {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    list-style-type: none;
    gap: var(--smedium-space);
    margin: var(--small-space) 0;
    padding: 0;

    li {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: var(--small-space);
        padding-bottom: var(--small-space);
        overflow: hidden;

        .image-container,
        .image-placeholder {
            width: 100%;
            border-bottom: 1px solid var(--background-alt-colour);
        }

        .image-container img {
            display: block;
            width: 100%;
            height: auto;
        }

        .image-placeholder {
            aspect-ratio: 1;
            background-color: var(--background-alt-colour);
        }

        p {
            margin: 0;
            padding: 0 var(--small-space);
            text-align: center;
        }

        .name {
            margin-top: auto;
        }

        .artist {
            color: var(--text-alt-colour);
            font-family: "Berkeley Mono", monospace;
            font-size: var(--font-size-small);
        }
    }
}


/* =========================== features/music/nowplaying/style.public.css ========================== */

.now-playing {
    display: inline-flex;
    align-items: stretch;
    gap: var(--smedium-space);
    padding-left: var(--smedium-space);
    padding-right: var(--smedium-space);
    padding-bottom: var(--small-space);

    img {
        height: 120px;
        box-shadow: 2px 2px 4px black;
    }

    .now-playing-info {
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: var(--small-space);

        .artist-track {
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .album-name {
            color: var(--text-alt-colour);
        }

        .play-status {
            font-family: "Berkeley Mono", monospace;
            font-size: var(--font-size-small);
            color: var(--text-alt-colour);
        }
    }
}


/* =========================== features/music/playedalbums/style.public.css ========================== */

/* Most played albums: a ranked table of albums for a date range inside a
   raised box. plain-table skips the site's default boxed table styling (the
   raised box already provides the box); row separators and column alignment
   are styled here. Cell side padding is zeroed so the table lines up with the
   box padding. */
.played-albums {
    margin: var(--smedium-space) 0;
    padding: var(--smedium-space);
    padding-top: var(--raised-box-title-padding);

    table {
        width: 100%;
        border-collapse: collapse;
    }

    th {
        padding-left: 0;
        padding-right: 0;
    }

    td {
        padding: var(--small-space) 0;
        border-bottom: 1px solid var(--background-alt-colour);
        vertical-align: middle;
    }

    /* The last row drops its cell bottom padding along with its border so it
       doesn't stack on top of the box's own bottom padding. */
    tbody tr:last-child td {
        border-bottom: 0;
        padding-bottom: 0;
    }

    .numeric {
        text-align: right;
        white-space: nowrap;
    }

    .position {
        width: 1%;
        white-space: nowrap;
        padding-right: var(--small-space);
        color: var(--text-alt-colour);
    }

    .movement {
        width: 1%;
        white-space: nowrap;
        padding-right: var(--small-space);

        svg {
            display: block;
        }
    }

    .movement-up,
    .movement-new {
        color: var(--link-colour);
    }

    .movement-down,
    .movement-same {
        color: var(--text-alt-colour);
    }

    .new-entry {
        display: block;
        font-size: var(--font-size-large);
        line-height: 16px;
        text-align: center;
    }

    .art {
        width: 1%;
        padding-right: var(--small-space);

        img,
        .art-placeholder {
            display: block;
            height: 40px;
            box-shadow: 2px 2px 4px black;
        }

        .art-placeholder {
            width: 40px;
            background-color: var(--background-alt-colour);
        }
    }

    .artist {
        color: var(--text-alt-colour);
    }
}


/* =========================== features/music/topalbums/style.public.css ========================== */

ol.top-albums {
    list-style-type: none;
    gap: var(--smedium-space);
    margin: var(--small-space) 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));

    li {
        margin: 0;
        padding: 0;

        .raised-box {
            display: flex;
            flex-direction: column;
            align-items: center;
            height: 100%;
            box-sizing: border-box;
            gap: var(--small-space);
            padding: var(--small-space);
            overflow: hidden;

            & > img,
            .album-placeholder {
                width: 100%;
                object-fit: cover;
                margin-bottom: var(--small-space);
                box-shadow: 2px 2px 4px black;
            }

            .album-placeholder {
                background-color: var(--background-alt-colour);
            }

            h3 {
                padding: 0 var(--small-space);
                margin: 0;
                text-align: center;
                font-size: var(--font-size-large);

                .position {
                    font-size: var(--font-size-regular);
                    color: var(--text-alt-colour);
                }
            }

            .artist-name {
                padding: 0 var(--small-space);
            }

            .album-details {
                padding: 0 var(--small-space);
                font-size: var(--font-size-small);
                color: var(--text-alt-colour);
            }
        }
    }
}


/* =========================== features/music/topartists/style.public.css ========================== */

ol.top-artists {
    list-style-type: none;
    gap: var(--smedium-space);
    margin: var(--small-space) 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));

    li {
        margin: 0;
        padding: 0;

        .raised-box {
            display: flex;
            flex-direction: column;
            align-items: center;
            height: 100%;
            box-sizing: border-box;
            gap: var(--small-space);
            padding-bottom: var(--small-space);
            overflow: hidden;

            & > img,
            .artist-placeholder {
                width: 100%;
                aspect-ratio: 1;
                object-fit: cover;
                border-bottom: 1px solid var(--background-alt-colour);
                margin-bottom: var(--small-space);
            }

            .artist-placeholder {
                background-color: var(--background-alt-colour);
            }

            h3 {
                padding: 0 var(--small-space);
                margin: 0;
                text-align: center;
                font-size: var(--font-size-large);

                .position {
                    font-size: var(--font-size-regular);
                    color: var(--text-alt-colour);
                }
            }

            .artist-details {
                padding: 0 var(--small-space);
                font-size: var(--font-size-small);
                color: var(--text-alt-colour);
            }
        }
    }
}


/* =========================== features/nod/form/style.public.css ========================== */

/**
 * This file incorporates code by Thierry Michel from https://codepen.io/thierrymichel/pen/Pwzbmd
 *
 * Copyright (c) 2024 Thierry Michel
 * Copyright (c) 2026 Chris Smith
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
.nod-container {
    form.nod {
        --button-size: 125px;

        cursor: pointer;
        display: grid;
        grid-template-columns: auto 1fr;
        gap: var(--smedium-space);
        margin-top: var(--large-space);

        &:hover,
        &:active,
        &:focus {
            button {
                box-shadow:
                    inset 0 calc(var(--button-size) / 24) 0
                        hsl(from var(--accent-colour) h s calc(l + 5)),
                    inset 0 calc(-1 * var(--button-size) / 24)
                        calc(var(--button-size) / 60)
                        hsl(from var(--accent-colour) h s calc(l - 5)),
                    0 0 calc(var(--button-size) / 60) var(--accent-colour),
                    inset 0 0 calc(var(--button-size) / 30)
                        hsl(from var(--accent-colour) h s calc(l - 15)),
                    inset 0 0 calc(var(--button-size) / 30)
                        hsla(from var(--accent-alt-colour) h s l / 0.5),
                    inset 0 0 calc(var(--button-size) / 60)
                        calc(var(--button-size) / 12) var(--accent-colour),
                    inset 0 calc(-1 * var(--button-size) / 30)
                        calc(var(--button-size) / 40) calc(var(--button-size) / 10)
                        hsla(from var(--accent-alt-colour) h s l / 0.7),
                    inset 0 0 calc(var(--button-size) / 60)
                        calc(var(--button-size) / 10)
                        hsl(from var(--accent-colour) h s calc(l - 20)),
                    inset 0 0 calc(var(--button-size) / 60)
                        calc(var(--button-size) / 10)
                        hsla(from var(--accent-alt-colour) h s l / 0.7),
                    inset 0 0 calc(var(--button-size) / 40)
                        calc(var(--button-size) / 8.5)
                        hsl(from var(--accent-colour) h s calc(l - 40)),
                    inset 0 0 calc(var(--button-size) / 120)
                        calc(var(--button-size) / 7.5)
                        hsla(from var(--accent-colour) h s calc(l + 30) / 0.2),
                    inset 0 calc(var(--button-size) / 20) 0
                        calc(var(--button-size) / 8.5)
                        hsla(from var(--accent-colour) h s calc(l + 15) / 0.5),
                    inset 0 calc(-1 * var(--button-size) / 20)
                        calc(var(--button-size) / 60)
                        calc(var(--button-size) / 8.5)
                        hsla(from var(--accent-colour) h s calc(l - 10) / 0.8),
                    inset 0 0 0 calc(var(--button-size) / 5.5)
                        hsl(from var(--accent-colour) h s calc(l - 3)),
                    inset 0 calc(var(--button-size) / 2.5)
                        calc(var(--button-size) / 7.5)
                        hsl(from var(--accent-colour) h s calc(l - 8)),
                    inset 0 0 calc(var(--button-size) / 10)
                        calc(var(--button-size) / 6)
                        hsl(from var(--accent-colour) h s calc(l - 15)),
                    0 calc(var(--button-size) / 40)
                        calc(var(--button-size) / 20) rgba(0, 0, 0, 0.5);

                background-color: hsl(
                    from var(--accent-colour) h s calc(l - 2)
                );
                color: hsl(from var(--text-colour) h s calc(l - 10) / 0.8);

                &:before {
                    opacity: 0.5;
                }
            }
        }

        button {
            position: relative;
            display: inline-block;
            width: var(--button-size);
            height: var(--button-size);
            border: 0;
            outline: none;
            background-color: var(--accent-colour);
            border-radius: 50%;
            cursor: pointer;
            transition:
                box-shadow 200ms,
                color 200ms;
            color: hsl(from var(--text-colour) h s l / 0.8);
            text-shadow:
                -1px 1px 0 rgba(255, 255, 255, 0.1),
                1px -1px 0 rgba(0, 0, 0, 0.4);
            font-size: var(--font-size-large);
            font-family: var(--font-body);
            font-weight: bolder;

            box-shadow:
                inset 0 calc(var(--button-size) / 24) 0
                    hsl(from var(--accent-colour) h s calc(l + 5)),
                inset 0 calc(-1 * var(--button-size) / 24)
                    calc(var(--button-size) / 60)
                    hsl(from var(--accent-colour) h s calc(l - 5)),
                0 0 calc(var(--button-size) / 60) var(--accent-colour),
                inset 0 0 calc(var(--button-size) / 30)
                    hsl(from var(--accent-colour) h s calc(l - 15)),
                inset 0 0 calc(var(--button-size) / 30)
                    hsla(from var(--accent-alt-colour) h s l / 0.5),
                inset 0 0 calc(var(--button-size) / 60)
                    calc(var(--button-size) / 12) var(--accent-colour),
                inset 0 calc(-1 * var(--button-size) / 30)
                    calc(var(--button-size) / 40) calc(var(--button-size) / 10)
                    hsla(from var(--accent-alt-colour) h s l / 0.7),
                inset 0 0 calc(var(--button-size) / 60)
                    calc(var(--button-size) / 10)
                    hsl(from var(--accent-colour) h s calc(l - 20)),
                inset 0 0 calc(var(--button-size) / 60)
                    calc(var(--button-size) / 10)
                    hsla(from var(--accent-alt-colour) h s l / 0.7),
                inset 0 0 calc(var(--button-size) / 120)
                    calc(var(--button-size) / 9.2)
                    hsl(from var(--accent-colour) h s calc(l - 50)),
                inset 0 0 calc(var(--button-size) / 120)
                    calc(var(--button-size) / 8)
                    hsla(from var(--accent-colour) h s calc(l + 30) / 0.7),
                inset 0 calc(var(--button-size) / 20) 0
                    calc(var(--button-size) / 8.5)
                    hsla(from var(--accent-colour) h s calc(l + 15) / 0.7),
                inset 0 calc(-1 * var(--button-size) / 20)
                    calc(var(--button-size) / 60) calc(var(--button-size) / 8.5)
                    hsla(from var(--accent-colour) h s calc(l - 10) / 0.2),
                inset 0 0 0 calc(var(--button-size) / 5.5) var(--accent-colour),
                inset 0 calc(var(--button-size) / 2.5)
                    calc(var(--button-size) / 7.5)
                    hsl(from var(--accent-colour) h s calc(l - 5)),
                inset 0 0 calc(var(--button-size) / 10)
                    calc(var(--button-size) / 6)
                    hsl(from var(--accent-colour) h s calc(l - 10)),
                0 calc(var(--button-size) / 40) calc(var(--button-size) / 20)
                    rgba(0, 0, 0, 0.5);

            &:before {
                content: "";
                position: absolute;
                bottom: calc(var(--button-size) / 4.5);
                left: calc(var(--button-size) / 3.6);
                display: block;
                width: calc(var(--button-size) / 2.2);
                height: calc(var(--button-size) / 3.3);
                background: hsla(
                    from var(--accent-colour) h s calc(l + 30) / 0.2
                );
                background: linear-gradient(
                    to top,
                    hsla(from var(--accent-colour) h s calc(l + 40) / 0.3) 0%,
                    hsla(from var(--accent-colour) h s l / 0.1) 100%
                );
                border-radius: 40% 40% 60% 60%;
                transition: opacity 200ms;
            }
        }

        p {
            font-family: "Chris Hand", sans-serif;
            font-size: var(--font-size-xlarge);
            line-height: var(--font-size-xlarge);
            margin: 0;
            padding: var(--small-space);

            @media (width <= 900px) {
                font-size: var(--font-size-large);
                line-height: var(--font-size-large);
            }

            @media (width <= 800px) {
                font-size: var(--font-size-regular);
                line-height: var(--font-size-regular);
            }

            @media (width <= 600px) {
                font-family: inherit;
                font-size: var(--font-size-tiny);
                line-height: var(--font-size-tiny);
            }
        }

        div {
            align-self: center;
            text-align: center;
        }
    }
}

.raised-box + .nod-container,
.footnotes + .nod-container {
    form.nod {
        margin-top: 0;
    }
}


/* =========================== features/posts/link/postlinks.public.css ========================== */

.post-links-parent {
    container-type: inline-size;
}

.post-links {
    display: grid;
    gap: var(--medium-space);
    grid-template-columns: 1fr;

    @container (width >= 640px) {
        grid-template-columns: repeat(2, 1fr);
    }

    @container (width >= 1280px) {
        grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
    }

    /* Four links would wrap 3+1 between the three and four column widths;
       split them 2+2 instead. */
    &:has(> :nth-child(4):last-child) {
        @container (1280px <= width < 1720px) {
            grid-template-columns: repeat(2, 1fr);
        }
    }
}

.post-catalogue {
    display: grid;
    gap: var(--medium-space);
    grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
}


/* =========================== features/posts/link/style.public.css ========================== */

.post-link {
    overflow: hidden;
    padding-bottom: var(--small-space);

    &:hover,
    &:focus,
    &:active {
        .img-holder {
            img,
            .placeholder {
                transform: scale(1.05);
            }
        }
    }

    article {
        z-index: 2;
        display: grid;
        grid-template-columns: 1fr;
        grid-template-rows: 200px auto;
        gap: var(--small-space);

        .img-holder {
            grid-row: 1;
            grid-column: 1;
            width: 100%;
            height: 200px;
            overflow: hidden;
        }

        img,
        .placeholder {
            width: 100%;
            height: 100%;
            object-fit: cover;
            transition: transform 500ms var(--timing-ease-in-out-quad);
        }

        .placeholder {
            background-color: color-mix(
                in srgb,
                var(--accent-colour),
                black 40%
            );
            color: color-mix(in srgb, var(--accent-colour), black 30%);
            font-size: var(--font-size-giant);
            padding-bottom: 1em;
            overflow: hidden;

            div {
                font-size: 60px;
                transform: rotate(10deg) translateX(-20px) translateY(-30px);
                white-space: nowrap;

                span {
                    display: inline-block;
                    transform: rotate(180deg) translateY(-4px);
                    color: color-mix(in srgb, var(--accent-colour), black 48%);
                }
            }
        }

        .post-date {
            z-index: 1;
            grid-row: 1;
            grid-column: 1;
            align-self: start;
            justify-self: end;
            margin: var(--small-space);
            padding: 0.3em 0.6em;
            font-family: "Berkeley Mono", monospace;
            font-size: var(--font-size-tiny);
            line-height: 1.2;
            text-transform: uppercase;
            color: var(--text-highlight-colour);
            background-color: color-mix(
                in srgb,
                var(--background-colour) 80%,
                transparent
            );
            border: 1px solid var(--accent-alt-colour);
            border-radius: calc(var(--border-radius) / 2);
        }

        h3 {
            z-index: 1;
            grid-row: 1;
            grid-column: 1;
            margin: 0;
            /* Overflow clips at the padding edge, so the bottom spacing is a
               border, and the line height fits the font's ascenders and
               descenders, so a third line can't peek out. */
            padding: var(--small-space) var(--small-space) 0;
            border-bottom: var(--small-space) solid transparent;
            font-size: var(--font-size-xlarge);
            font-weight: bold;
            line-height: 1.25em;
            align-self: end;
            box-sizing: content-box;
            max-height: 2.5em;
            overflow: hidden;
            background-color: color-mix(
                in srgb,
                var(--background-alt-colour) 80%,
                transparent
            );
        }

        p {
            position: relative;
            margin: 0;
            height: calc(5 * 1.2em);
            padding: 0 var(--small-space);
            overflow: hidden;
            line-height: 1.2em;
            mask:
                linear-gradient(#000 0% 0%) top/100% calc(100% - 1.2em)
                    no-repeat,
                linear-gradient(to left, #0000, #000 50%) bottom / 100% 1em
                    no-repeat;
        }
    }
}


/* =========================== features/prints/style.public.css ========================== */

.print-list {
    display: flex;
    flex-direction: column;
    gap: 75px;
    padding-top: 50px;
    padding-bottom: 50px;
}

section.print {
    display: grid;
    grid-template-columns: 200px auto 200px;
    grid-gap: 20px;

    @media (width <= 800px) {
        grid-template-columns: 200px auto 200px;

        img:first-child {
            grid-area: 1 / 1;
        }

        img:last-child {
            grid-area: 1 / 3;
        }

        div {
            grid-area: 2 / 1 / 2 / 4;
        }
    }

    img {
        max-width: 200px;
        max-height: 150px;
        justify-self: end;

        &:first-child {
            border: 1px solid var(--accent-colour);
            border-radius: 5px;
            justify-self: start;
        }
    }

    div {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
    }

    * {
        margin: 0;
    }

    ul {
        list-style-type: none;
        padding: 0;
        display: flex;
        gap: 25px;

        a {
            font-family: "Berkeley Mono", monospace;
            text-transform: uppercase;
            font-size: var(--font-size-small);

            &[href*=".stl"]::after,
            &[href*=".step"]::after {
                content: "↓";
                color: var(--accent-colour);
            }
        }
    }
}


/* =========================== features/projects/style.public.css ========================== */

.projects {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-gap: var(--medium-space);
    margin-top: var(--medium-space);

    @media (width <= 800px) {
        grid-template-columns: repeat(1, 1fr);
    }

    .project {
        display: flex;
        flex-direction: column;
        height: 100%;
        padding: var(--medium-space);

        h4 {
            margin: 0;
            padding: 0;
            font-size: var(--font-size-xxlarge);

            svg {
                width: 48px;
                height: 48px;
            }

            svg.icon-tabler-pinned {
                float: right;
                width: 24px;
                height: 24px;
            }
        }

        p {
            flex-grow: 1;
        }

        ul {
            list-style-type: none;
            margin: 0;
            padding: 0;
            display: flex;
            gap: var(--small-space);
            flex-direction: column;

            a {
                font-family: "Berkeley Mono", monospace;
                text-transform: uppercase;
                font-size: var(--font-size-small);
            }
        }
    }
}


/* =========================== features/quotes/style.public.css ========================== */

.random-quote {
    font-style: italic;
    margin: 0;
    color: var(--text-alt-colour);

    p {
        margin: 0;
    }

    cite {
        display: block;
        font-style: normal;
        margin-top: var(--small-space);
    }
}


/* =========================== features/shortcodes/countdown/countdown.public.css ========================== */

aside.countdown {
    margin: var(--smedium-space) 0;
    padding: var(--smedium-space);
    padding-top: var(--raised-box-title-padding);

    .countdown-event {
        margin: 0;
        font-size: var(--font-size-regular);

        .countdown-leadin {
            color: var(--text-alt-colour);
        }
    }

    .countdown-remaining {
        margin: var(--small-space) 0 0;
        font-size: var(--font-size-xlarge);
        color: var(--text-highlight-colour);
    }
}


/* =========================== features/shortcodes/link/style.public.css ========================== */

.page-link {
    display: inline-flex;
    align-items: center;
    gap: var(--medium-space);
    padding-top: calc(var(--raised-box-title-padding) + var(--smedium-space));
    padding-left: var(--medium-space);
    padding-right: var(--medium-space);
    padding-bottom: var(--medium-space);
    color: var(--text-colour);
    width: min(100%, 400px);

    svg:first-child {
        color: var(--text-colour);
        width: 32px;
        height: 32px;
    }

    span {
        font-family: "Berkeley Mono", monospace;
        flex-grow: 1;
        text-align: center;
    }

    svg.chevron {
        color: var(--text-alt-colour);
        width: 32px;
        height: 32px;
    }
}


/* =========================== features/shortcodes/rating/style.public.css ========================== */

.star-rating {
    vertical-align: middle;

    img:not(:first-child) {
        margin-left: -3px;
    }

    img:first-child {
        rotate: -3deg;
    }

    img:nth-child(2) {
        rotate: 5deg;
    }

    img:nth-child(3) {
        rotate: 10deg;
    }

    img:nth-child(4) {
        rotate: -10deg;
    }

    img:nth-child(5) {
        rotate: 15deg;
    }

    .rot-1 {
        transform: rotate(70deg);
    }

    .rot-2 {
        transform: rotate(140deg);
    }

    .rot-3 {
        transform: rotate(210deg);
    }

    .rot-4 {
        transform: rotate(280deg);
    }
}


/* =========================== features/shortcodes/sidenote/sidenote.public.css ========================== */

aside.sidenote {
    padding: var(--small-space);
    color: var(--text-alt-colour);

    :first-child {
        margin-top: 0;
    }

    :last-child {
        margin-bottom: 0;
    }

    h5 {
        margin: 0;
    }

    p {
        margin: var(--smedium-space) 0;
    }
}


/* =========================== features/shortcodes/update/update.public.css ========================== */

aside.update {
    clear: both;
    padding: var(--medium-space);
    margin: var(--large-space) 0;

    ins {
        text-decoration: none;
    }

    h5 {
        text-transform: uppercase;
        color: var(--text-highlight-colour);
        font-size: var(--font-size-large);
        margin-top: 0;
        padding: 0;
        margin-bottom: var(--small-space);

        & + p {
            margin-top: var(--small-space);
        }
    }

    *:last-child {
        margin-bottom: 0;
    }
}


/* =========================== features/shortcodes/warning/style.public.css ========================== */

aside.warning {
    clear: both;
    background-image: repeating-linear-gradient(
        -45deg,
        red 0,
        red 10px,
        white 10px,
        white 20px,
        red 20px
    );
    border-radius: var(--border-radius);
    padding: 10px;
    border: 1px solid var(--background-alt-colour);
    box-shadow: 3px 3px 5px black;
    margin: var(--medium-space) 0;
    color: black;

    & > div {
        background-color: rgba(255, 255, 255, 0.95);
        border-radius: var(--border-radius);
        width: 100%;
        padding: calc(var(--medium-space) / 2);

        h5 {
            &::before {
                position: relative;
                font-size: var(--font-size-xlarge);
                font-family: "Berkeley Mono", monospace;
                content: "⚠";
                margin: 0;
                color: inherit;
                background: none;
                filter: none;
                clip-path: none;
            }

            color: inherit;
            text-transform: uppercase;
            font-family: inherit;
            font-weight: 800;
            font-size: var(--font-size-large);
            margin-top: 0;
            margin-bottom: var(--small-space);
            filter: none;
            padding: 0;

            & + p {
                margin-top: var(--small-space);
            }
        }

        *:last-child {
            margin-bottom: 0;
        }
    }
}


/* =========================== features/snippets/style.public.css ========================== */

.snippets {
    columns: 400px 2;
    column-fill: balance;

    section {
        margin-bottom: var(--medium-space);
        -webkit-column-break-inside: avoid;
        page-break-inside: avoid;
        break-inside: avoid;
    }

    h1,
    h2,
    h3,
    h4,
    h5,
    h6 {
        margin-top: 0;
    }

    a {
        font-family: "Berkeley Mono", monospace;
        font-size: var(--font-size-small);
        text-decoration-thickness: 1px;
    }
}


/* =========================== features/syndications/display/style.public.css ========================== */

.syndications {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--small-space);
    color: var(--text-alt-colour);
    padding-left: var(--smedium-space);
    padding-right: var(--smedium-space);
    padding-bottom: var(--smedium-space);
    margin: var(--smedium-space) 0;

    ul {
        display: contents;
        list-style-type: none;
    }

    p,
    ul,
    li {
        margin: 0;
        padding: 0;
    }

    a {
        text-decoration: none;
        border-bottom: 1px solid var(--accent-colour);

        svg {
            margin-left: var(--small-space);
            fill: var(--text-colour);
            vertical-align: sub;
        }
    }
}


/* =========================== features/walks/distance/style.public.css ========================== */

.walking-stats-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
    gap: var(--smedium-space);
}

.walkingdistance-badge {
    display: inline-grid;
    grid-template-areas:
        "image title"
        "image reps"
        "progress progress";

    grid-template-columns: auto 1fr;

    padding: var(--smedium-space);
    row-gap: var(--small-space);
    column-gap: var(--smedium-space);

    svg {
        grid-area: image;
        fill: var(--text-colour);
        width: 64px;
        height: 64px;
    }

    h4 {
        grid-area: title;
        font-size: var(--font-size-regular);
        font-family: inherit;
        margin: 0;
        padding: 0;
    }

    .times {
        grid-area: reps;
        margin: 0;
        font-size: var(--font-size-large);

        span {
            color: var(--text-alt-colour);
        }
    }

    .progress-bar {
        grid-area: progress;
        border-radius: 5px;
        height: 0.5em;
        width: 100%;
        background-color: var(--background-alt-colour);

        .progress-fill {
            fill: var(--accent-colour);
        }
    }
}


/* =========================== features/walks/list/style.public.css ========================== */

.walks-table {
    border-bottom: none;

    td {
        white-space: nowrap;
    }

    time {
        color: var(--text-alt-colour);
    }

    svg {
        vertical-align: middle;
    }

    .distance-bar-cell {
        width: 100%;

        .distance-bar {
            display: inline-block;
            overflow: hidden;
            border-radius: 5px;
            background-color: var(--background-alt-colour);
            height: 0.5em;
            width: 100%;
            vertical-align: middle;

            .distance-bar-fill {
                fill: var(--accent-colour);
            }
        }
    }
}


/* =========================== features/walks/speed/style.public.css ========================== */

.walkingspeed {
    margin: var(--smedium-space) 0;

    svg {
        width: 100%;
        height: auto;

        text {
            font-family: "Berkeley Mono", monospace;
        }
    }
}


/* =========================== features/workouts/calendar/style.public.css ========================== */

/* Workout calendar: a GitHub-style heatmap grid with one row per weekday
   and one column per week (oldest left, most recent right). Filled cells
   carry one or more horizontal stripes — one per activity type present
   that day — each coloured by the type's palette below and shaded by the
   type's quantised intensity step (s0 dimmest → s3 full tint).

   Colours live here as fixed type × step classes rather than inline
   styles: the site's CSP blocks style attributes. Each scaling type's
   ramp is floored above black so the dimmest shade stays recognisably its
   colour; walk's ramp starts lighter still because its muted grey-brown
   would otherwise fade into the empty-cell background. The catch-all
   "other" bucket (gym, rowing, dance, ...) doesn't scale by distance, so
   it has a single full-tint class. */
.workout-calendar {
    display: inline-block;
    margin: var(--smedium-space) 0;
    padding: var(--smedium-space);
    padding-top: var(--raised-box-title-padding);

    .run.s0 { background-color: rgb(0, 34, 52); }
    .run.s1 { background-color: rgb(1, 61, 92); }
    .run.s2 { background-color: rgb(1, 87, 133); }
    .run.s3 { background-color: rgb(1, 114, 173); }

    .cycle.s0 { background-color: rgb(57, 18, 6); }
    .cycle.s1 { background-color: rgb(101, 32, 10); }
    .cycle.s2 { background-color: rgb(145, 46, 15); }
    .cycle.s3 { background-color: rgb(189, 60, 19); }

    .walk.s0 { background-color: rgb(59, 57, 51); }
    .walk.s1 { background-color: rgb(76, 73, 66); }
    .walk.s2 { background-color: rgb(93, 90, 81); }
    .walk.s3 { background-color: rgb(110, 106, 96); }

    .other { background-color: rgb(0, 122, 80); }
}

/* Rows are flexboxes rather than grids so no per-render column count —
   and therefore no inline custom property — is needed: every cell is a
   fixed square and simply flows. Cell dimensions are pinned to a 1:1
   aspect ratio via the --cell-size custom property so the grid renders
   as squares. */
.calendar-grid {
    --cell-size: 1rem;
    --cell-gap: 0.2rem;
    width: fit-content;
    margin: 0 auto;
    border-collapse: separate;

    tbody tr {
        display: flex;
        align-items: center;
        column-gap: var(--cell-gap);
        margin-bottom: var(--cell-gap);
    }

    th[scope="row"] {
        font-size: var(--font-size-tiny);
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        color: var(--text-alt-colour);
        background: transparent;
        border: 0;
        padding: 0 0.4rem 0 0;
        line-height: var(--cell-size);
        text-align: right;
    }

    td {
        padding: 0;
        border: 0;
        flex: 0 0 auto;
        width: var(--cell-size);
        height: var(--cell-size);
        border-radius: 0.2rem;
        line-height: 0;
    }

    td.empty {
        background-color: var(--background-alt-colour);
    }

    td.inactive {
        background-color: transparent;
    }

    td.filled {
        display: flex;
        flex-direction: column;
        overflow: hidden;

        .stripe {
            flex: 1 1 0;
            width: 100%;
            min-height: 0;
        }
    }

    /* Days inside a requested date range are ringed so the range reads as
       a block, covering both filled and empty (rest) days. */
    td.in-range {
        box-shadow: 0 0 0 1px var(--accent-colour);
    }
}

/* Legend below the calendar: one inline row of (label + four swatches)
   entries, one per activity type that appears in the visible window.
   Wraps onto further lines on narrow viewports rather than overflowing
   the box. */
.calendar-legend {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    column-gap: var(--smedium-space);
    row-gap: var(--small-space);
    margin: var(--smedium-space) auto 0;
    font-size: var(--font-size-tiny);
    color: var(--text-alt-colour);

    div {
        display: flex;
        align-items: center;
        gap: 0.25rem;
    }

    dt {
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.03em;
    }

    dd {
        display: flex;
        gap: 0.15rem;
        margin: 0;

        span {
            display: block;
            width: 0.8rem;
            height: 0.8rem;
            border-radius: 0.15rem;
        }
    }
}


/* =========================== features/workouts/longest/style.public.css ========================== */

.longest-workout {
    margin: var(--smedium-space) 0;
    padding: var(--smedium-space);
    padding-top: var(--raised-box-title-padding);

    .longest-stats-row {
        display: flex;
        align-items: baseline;
        column-gap: var(--small-space);
        margin-bottom: var(--small-space);

        .distance {
            margin: 0;
            font-size: var(--font-size-xlarge);
        }

        .workout-date {
            margin: 0;
            font-size: var(--font-size-small);
            color: var(--text-alt-colour);
        }

        .next-milestone {
            margin: 0 0 0 auto;
            font-size: var(--font-size-large);

            .label {
                font-size: var(--font-size-small);
                color: var(--text-alt-colour);
            }
        }
    }

    .progress-bar {
        border-radius: 5px;
        height: 0.5em;
        width: 100%;
        background-color: var(--background-alt-colour);

        .progress-fill {
            fill: var(--accent-colour);
        }
    }
}


/* =========================== features/workouts/nextraces/style.public.css ========================== */

/* A row of countdown boxes, one per upcoming race distance. The boxes
   are the shared countdown shortcode; the row only lays them out. */
.next-races {
    display: flex;
    flex-wrap: wrap;
    gap: var(--smedium-space);
    margin: var(--smedium-space) 0;

    aside.countdown {
        flex: 1 1 10em;
        margin: 0;
    }
}


/* =========================== features/workouts/parkruns/style.public.css ========================== */

/* Parkrun stats and table. The stats row lays its raised boxes out in a
   line, wrapping to stack them on narrow screens. The table skips the
   site's default boxed table styling (the raised box already provides
   the box); row separators and right-aligned numeric columns are styled
   here. Cell padding is zeroed so the table lines up with the box
   padding. */
.parkrun-stats {
    display: flex;
    flex-wrap: wrap;
    gap: var(--smedium-space);
    margin: var(--smedium-space) 0;

    .parkrun-stat {
        flex: 1 1 10em;
        padding: var(--smedium-space);
        padding-top: var(--raised-box-title-padding);

        .parkrun-stat-value {
            margin: 0;
            font-size: var(--font-size-large);
        }

        .parkrun-stat-detail {
            margin: 0;
            color: var(--text-alt-colour);
        }
    }
}

.parkruns-table {
    margin: var(--smedium-space) 0;
    padding: var(--smedium-space);
    padding-top: var(--raised-box-title-padding);

    table {
        width: 100%;
        border-collapse: collapse;
    }

    th:nth-child(n + 3),
    td:nth-child(n + 3) {
        text-align: right;
    }

    th {
        padding-left: 0;
        padding-right: 0;
    }

    td {
        padding-left: 0;
        padding-right: 0;
        border-bottom: 1px solid var(--background-alt-colour);
    }

    /* The last row drops its cell bottom padding along with its border so
       it doesn't stack on top of the box's own bottom padding. */
    tbody tr:last-child td {
        border-bottom: 0;
        padding-bottom: 0;
    }
}


/* =========================== features/workouts/pbs/style.public.css ========================== */

/* Workout PBs: a table of current all-time records per segment distance
   inside a raised box. plain-table skips the site's default boxed table
   styling (the raised box already provides the box); row separators and
   right-aligned numeric columns are styled here. Cell padding is zeroed
   so the table lines up with the box padding. */
.workout-pbs {
    margin: var(--smedium-space) 0;
    padding: var(--smedium-space);
    padding-top: var(--raised-box-title-padding);

    table {
        width: 100%;
        border-collapse: collapse;
    }

    th:not(:first-child),
    td:not(:first-child) {
        text-align: right;
    }

    th {
        padding-left: 0;
        padding-right: 0;
    }

    td {
        padding-left: 0;
        padding-right: 0;
        border-bottom: 1px solid var(--background-alt-colour);
    }

    /* The last row drops its cell bottom padding along with its border so
       it doesn't stack on top of the box's own bottom padding. */
    tbody tr:last-child td {
        border-bottom: 0;
        padding-bottom: 0;
    }
}


/* =========================== features/workouts/summary/style.public.css ========================== */

.workout-summary-sections {
    display: flex;
    flex-direction: column;
    gap: var(--smedium-space);
    margin: var(--smedium-space) 0;

    @media (min-width: 1000px) {
        flex-direction: row;

        .workout-summary-section {
            flex: 1;
        }
    }

    .workout-summary-section {
        container-type: inline-size;
        padding: var(--smedium-space);
        padding-top: var(--raised-box-title-padding);
    }

    .stat-row {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
        gap: var(--smedium-space);

        @container (width < 500px) {
            grid-template-columns: repeat(2, 1fr);
        }

        @container (width < 250px) {
            grid-template-columns: 1fr;
        }
    }

    .stat {
        text-align: center;

        .stat-value {
            margin: 0;
            font-size: var(--font-size-large);
        }

        .stat-label {
            margin: 0;
            color: var(--text-alt-colour);
        }
    }

    .workout-summary-pbs {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        list-style: none;
        margin: var(--smedium-space) 0 0;
        padding: 0;
        gap: var(--smedium-space);
    }

    .workout-summary-pb {
        display: flex;
        flex-direction: column;
        align-items: center;
        width: 7em;
        text-align: center;

        .pb-trophy {
            font-size: var(--font-size-large);
        }

        .pb-label {
            font-size: var(--font-size-tiny);
            color: var(--text-alt-colour);
        }

        .pb-distance {
            font-size: var(--font-size-large);
            line-height: 1em;
        }

        .pb-previous {
            font-size: var(--font-size-small);
            color: var(--text-alt-colour);
            text-decoration: line-through;
        }

        .pb-time {
            line-height: 1em;
        }
    }
}


/* =========================== features/wow/achievements/style.public.css ========================== */

.wow-achievements {
    margin: var(--smedium-space) 0;
    padding: var(--raised-box-title-padding) var(--smedium-space)
        var(--smedium-space);

    .achievement-list {
        font-size: var(--font-size-small);
        width: 100%;

        td {
            vertical-align: middle;
            padding: 2px 0;
        }

        .achievement-name {
            color: var(--text-colour);
        }

        .achievement-date {
            color: var(--text-alt-colour);
            font-size: var(--font-size-tiny);
            text-align: right;
            padding-left: var(--small-space);
            white-space: nowrap;
        }

        .achievement-link {
            color: var(--text-alt-colour);
            font-size: var(--font-size-tiny);
            text-align: right;
            padding-left: var(--small-space);
            white-space: nowrap;

            a {
                text-decoration-thickness: 2px;
            }
        }
    }
}


/* =========================== features/wow/char/style.public.css ========================== */

.wow-char {
    display: flex;
    align-items: stretch;
    width: 600px;
    padding-right: var(--smedium-space);
    gap: var(--smedium-space);

    .overview {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: var(--small-space);

        img {
            height: 400px;
            filter: drop-shadow(10px 10px 10px var(--background-alt-colour));
            margin-bottom: var(--smedium-space);
        }
    }

    .detail {
        font-size: var(--font-size-small);
        color: var(--text-alt-colour);
        margin: 0;
        padding: 0;
    }

    .info {
        display: flex;
        flex-direction: column;
        flex: 1;
        gap: var(--small-space);
        padding: var(--small-space) var(--smedium-space);

        h3,
        h4 {
            margin: 0;
            padding: 0;
        }

        .realm {
            color: var(--text-alt-colour);
            font-size: var(--font-size-small);
            padding-left: 4px;
        }

        .professions {
            font-size: var(--font-size-small);

            td {
                vertical-align: middle;
                padding: 1px 0;
            }

            td:first-child {
                color: var(--text-alt-colour);
                padding-right: var(--small-space);
            }

            .tier-count {
                color: var(--text-alt-colour);
                padding-left: var(--small-space);
                text-align: right;
            }

            .tier-progress {
                accent-color: var(--accent-colour);
            }
        }

        table + h4 {
            margin-top: var(--small-space);
        }

        .mythic-plus {
            font-size: var(--font-size-small);

            td,
            th {
                vertical-align: middle;
                padding: 1px 0;
                text-align: right;
            }

            .dungeon {
                color: var(--text-alt-colour);
                text-align: left;
                padding-right: var(--small-space);
            }

            .level,
            .duration {
                color: var(--text-alt-colour);
                padding-left: var(--small-space);
            }

            .rating {
                padding-left: var(--small-space);
            }

            .total th,
            .total td {
                border-top: 1px solid var(--background-alt-colour);
                font-weight: normal;
            }
        }

        .links {
            margin-top: auto;
            display: flex;
            justify-content: flex-end;
            gap: var(--smedium-space);
            font-size: var(--font-size-tiny);
            padding-top: var(--smedium-space);

            a {
                text-decoration-thickness: 2px;
            }
        }
    }

    @media (width <= 750px) {
        width: unset;
        flex-direction: column;

        .info {
            padding: var(--medium-space);
        }
    }
}

.wow-class-death-knight {
    color: #c41e3a;
}
.wow-class-demon-hunter {
    color: #a330c9;
}
.wow-class-druid {
    color: #ff7c0a;
}
.wow-class-evoker {
    color: #33937f;
}
.wow-class-hunter {
    color: #aad372;
}
.wow-class-mage {
    color: #3fc7eb;
}
.wow-class-monk {
    color: #00ff98;
}
.wow-class-paladin {
    color: #f48cba;
}
.wow-class-priest {
    color: #ffffff;
}
.wow-class-rogue {
    color: #fff468;
}
.wow-class-shaman {
    color: #0070dd;
}
.wow-class-warlock {
    color: #8788ee;
}
.wow-class-warrior {
    color: #c69b6d;
}

.wow-char-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(600px, 1fr));
    gap: var(--smedium-space);

    .wow-char {
        width: unset;
        padding-right: unset;
    }

    @media (width <= 750px) {
        grid-template-columns: 1fr;
    }
}
