/* The whole stylesheet. No build step and no preprocessor.
   Spacing is font-relative, so browser zoom scales the whole layout. Colors
   are the Modus palettes, switched by light-dark() against the user's
   color-scheme.
   Order below: tokens, base, code, type, layout, nav, notes, figures, lists,
   tables.

   proto/hybrid: ET Book body at reading size, gingerBill's layout copied from
   his CSS. body is width:87.5% with a 12.5% viewport-relative left padding, so
   the content box centres and its indent scales with the window; the article
   column takes 60% of it and sidenotes float into the rest. Below the sheet
   cap the layout goes fluid and full width and notes collapse to a tap
   target. The header is the breadcrumb, then a rule at the article width with
   the theme toggle on its right end. Big headings, no colour, a rule under
   h2; an h2/h3 self-link shows a § in the margin on hover. Metadata is mono.
   Inline code and code blocks sit in a bordered box on --color-surface,
   gingerBill's treatment; tables are enclosed and zebra-striped on the same
   surface. Blockquote stays a hairline. One accent (--color-accent) on the
   breadcrumb link, the toggle, the § and the note markers. */

/* ET Book, Tufte's Bembo digitisation and the face gingerBill.org is set in.
   Self-hosted from static/font; MIT, notice beside the files.

   font-display: optional lets the browser use the face only if it is ready by
   first paint and skip it otherwise, so text never reflows mid-sentence. The
   preload in the head makes ready-in-time the usual case; a cold visit on a
   slow line reads in Palatino. */
@font-face {
    font-family: "ET Book";
    src: url("/font/et-book-roman-line-figures.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: optional;
}

@font-face {
    font-family: "ET Book";
    src: url("/font/et-book-display-italic-old-style-figures.woff2") format("woff2");
    font-weight: 400;
    font-style: italic;
    font-display: optional;
}

@font-face {
    font-family: "ET Book";
    src: url("/font/et-book-bold-line-figures.woff2") format("woff2");
    font-weight: 700;
    font-style: normal;
    font-display: optional;
}

/* Modus Operandi light, Modus Vivendi dark. */
:root {
    color-scheme: light dark;

    /* Page and sheet share one background. Code is the exception: it sits on
       --color-surface, a step lighter in dark and a step darker in light, in
       a bordered block the way gingerBill's does. */
    --color-bg:           light-dark(#ffffff, #181818);
    --color-page:         var(--color-bg);
    --color-surface:      light-dark(#f7f7f7, #333333);
    --color-text:         light-dark(#000000, #ffffff);
    --color-muted:        light-dark(#595959, #989898);
    --color-border:       light-dark(#c4c4c4, #535353);
    --color-code-border:  light-dark(#cccccc, #000000);
    --color-link:         light-dark(#0031a9, #2fafff);
    --color-link-muted:   light-dark(#40588a, #6f91ad);
    --color-link-hover:   light-dark(#005e8b, #00d3d0);

    /* One accent, one variable. Change it here. Used on links in the header,
       the wordmark dot, and the sidenote markers. Headings stay text-coloured. */
    --color-accent:       #0089fe;
    --color-heading-1:    var(--color-text);
    --color-heading-2:    var(--color-text);
    --color-heading-3:    var(--color-text);

    /* The fallbacks are the ones Tufte CSS names: under font-display: optional
       a cold first visit reads in Palatino. */
    --font-body:  "ET Book", Palatino, "Palatino Linotype", "Palatino LT STD",
                  "Book Antiqua", Georgia, serif;
    --font-mono:  ui-monospace, "Hack", "DejaVu Sans Mono", monospace;

    --body-size: 1.25rem;

    --space-xs: 0.35rem;
    --space-sm: 0.7rem;
    --space-md: 1.1rem;
    --space-lg: 1.5rem;

    /* gingerBill's layout, his numbers. body is width:87.5% with
       padding-inline-start:12.5%; both resolve against the viewport, so the
       indent scales with the window and the content box stays centred (the
       12.5% padding matches the auto right margin). --sheet-width caps the
       content box, gingerBill's 1200px. The article column is --main-width of
       that; sidenotes float into the rest. Below --sheet-width the layout
       goes fluid and full width and notes collapse to a tap target. */
    --sheet-width: 80rem;
    --main-width: 60%;
    --note-width: 40%;
    --note-pull: -45%;

    /* The inset inside header, main, and footer. */
    --pad: 1.25rem;
}

@media (min-width: 48em) {
    :root { --pad: 2rem; }
}

:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark;  }

/* Base */

html {
    font-size: 100%;
    -webkit-text-size-adjust: 100%;
    width: 100%;
    background: var(--color-page);
}

body {
    font-family: var(--font-body);
    font-size: var(--body-size);
    font-weight: 400;
    color: var(--color-text);
    background: var(--color-bg);

    /* gingerBill's centring trick. content-box so width and padding compose:
       the content box is 87.5% of the viewport, capped at --sheet-width, and
       the 12.5% left padding equals the auto right margin, so the content box
       lands centred while the article inside it sits left of centre. */
    box-sizing: content-box;
    width: 87.5%;
    max-width: var(--sheet-width);
    margin-block: 0;
    margin-inline: auto;
    padding: 0;
    padding-inline-start: 12.5%;
    line-height: 1.4;

    counter-reset: sidenote-counter;
}

/* Code */

code, pre, kbd, samp {
    font-family: var(--font-mono);
    font-size: 0.889em;
}

/* Inline code and code blocks both sit in a bordered box on --color-surface,
   gingerBill's treatment. Inline is set smaller: a mono face beside ET Book's
   small x-height reads oversized otherwise. */
code {
    background: var(--color-surface);
    border: 1px solid var(--color-code-border);
    border-radius: 2px;
    padding: 0.05em 0.3em;
    font-size: 0.8em;
}

pre {
    background: var(--color-surface);
    border: 1px solid var(--color-code-border);
    border-radius: 2px;
    padding: 0.6em 0.9em;
    margin-block: var(--space-sm);
    overflow-x: auto;
    line-height: 1.4;
}

/* Inside a block the box belongs to the <pre>, not each token. */
pre code {
    background: none;
    border: 0;
    padding: 0;
    font-size: 1em;
}

hr {
    margin-block: var(--space-lg);
    border: 0;
    border-block-start: 1px solid var(--color-border);
}

blockquote {
    margin-block: var(--space-sm);
    padding-inline-start: 1em;
    border-inline-start: 3px solid var(--color-border);
    color: var(--color-muted);
}

/* Chroma writes these token classes. Kept in colour; a block reads the same
   way in either theme. The <pre> carries the box, so .chroma adds no fill. */
.chroma .k,  .chroma .kd,
.chroma .kn, .chroma .kr      { color: light-dark(#5317ac, #b6a0ff); } /* keyword */
.chroma .kt, .chroma .nc,
.chroma .nn                   { color: light-dark(#005e8b, #00d3d0); } /* type, namespace */
.chroma .s,  .chroma .s1,
.chroma .s2, .chroma .sb,
.chroma .sc, .chroma .sd      { color: light-dark(#2544bb, #79a8ff); } /* string */
.chroma .m,  .chroma .mi,
.chroma .mf, .chroma .mh      { color: light-dark(#0000c0, #00bcff); } /* number */
.chroma .nf, .chroma .nd      { color: light-dark(#721045, #feacd0); } /* function */
.chroma .nb, .chroma .bp      { color: light-dark(#884900, #fec43f); } /* builtin */
.chroma .c,  .chroma .c1,
.chroma .cm, .chroma .cs      { color: var(--color-muted); font-style: italic; }
.chroma .err                  { color: light-dark(#a60000, #ff8059); }

/* Big headings, gingerBill's register. They carry no colour and separate on
   size, weight, and the rule under h2. position: relative anchors the §
   marker that a heading self-link shows on hover. */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-body);
    line-height: 1.2;
    margin-block: var(--space-lg) var(--space-xs);
    font-weight: 600;
    color: var(--color-text);
    position: relative;
}

h1 {
    font-size: 2.6rem;
    margin-block-start: 0;
}

h2 {
    font-size: 2rem;
    padding-block-end: 0.1em;
    border-block-end: 1px solid var(--color-border);
}

h3 { font-size: 1.6rem; }

h4 { font-size: 1.3rem; }

h5, h6 { font-size: var(--body-size); }

/* Heading self-links, gingerBill's pattern. The link is invisible until
   hover, when it turns accent and a § appears in the margin. */
a.anchor {
    color: inherit;
    text-decoration: none;
}

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

a.anchor::before {
    content: "\A7";
    position: absolute;
    left: -0.85em;
    color: var(--color-accent);
    opacity: 0;
}

a.anchor:hover::before { opacity: 1; }

p {
    margin-block-end: var(--space-sm);
}

/* reset.css clears list-style globally. Restore it for prose. */
main ul, main ol {
    list-style: revert;
    padding-inline-start: 1.5em;
    margin-block: var(--space-sm);
}

main li { margin-block-end: 0.25em; }

/* Dateline under a post title, in mono. */
article > time {
    display: block;
    font-family: var(--font-mono);
    color: var(--color-muted);
    font-size: 0.8rem;
    margin-block-end: var(--space-md);
}

a         { color: var(--color-link); text-decoration: underline; }
a:hover   { color: var(--color-link-hover); text-decoration-style: dashed; }

a:focus-visible,
button:focus-visible,
input:focus-visible + label {
    outline: 2px solid var(--color-link-hover);
    outline-offset: 3px;
}

/* Layout */

/* header, main, and footer all take the same --main-width share of the sheet,
   so the breadcrumb rule and the footer rule line up with the article column
   and never span the full sheet. */
header {
    width: var(--main-width);
    padding: var(--space-md) var(--pad);
}

/* The article column. The space to its right is the note margin. No top
   padding: the h1 sits right under the header rule. */
main {
    width: var(--main-width);
    padding: 0 var(--pad) var(--space-md);
}

section {
    margin-block-end: var(--space-lg);
}

section:last-child { margin-block-end: 0; }

footer {
    width: var(--main-width);
    margin-block-start: var(--space-lg);
    padding: var(--space-sm) var(--pad) var(--space-lg);
    border-block-start: 1px solid var(--color-border);
    color: var(--color-muted);
    font-size: 0.875rem;
}

footer p { margin: 0; }

/* Navigation
   Breadcrumb, then a rule at the article width with the theme toggle on its
   right end. There is no menu. Home is the way in. */

.accent { color: var(--color-accent); }

.crumbs {
    color: var(--color-muted);
}

.crumbs .trail  { margin: 0; }
.crumbs .sep    { padding-inline: 0.4em; }
.crumbs .here   { color: var(--color-muted); }
.crumbs a       { color: var(--color-accent); text-decoration: none; }
.crumbs a:hover { text-decoration: underline; }

/* The rule spans to the toggle and stops. The toggle caps its right end, at
   the article's right edge. */
.header-rule {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-block-start: var(--space-xs);
}

.header-rule hr {
    flex: 1;
    margin: 0;
    border: 0;
    border-block-start: 1px solid var(--color-border);
}

#theme-toggle {
    flex: none;
    background: none;
    border: none;
    color: var(--color-accent);
    font: inherit;
    font-size: 0.95rem;
    letter-spacing: 0.04em;
    cursor: pointer;
    padding: 0;
}

#theme-toggle:hover { color: var(--color-link-hover); }

/* Notes, gingerBill's margin-note pattern. On a wide screen the note floats
   into the right margin and is always visible. Below 85em the article column
   is full width: the note hides and its number becomes a tap target that
   opens it inline. Markup order is checkbox, label.sidenote-number, span. */

.sidenote-number {
    counter-increment: sidenote-counter;
}

.sidenote-number::after {
    content: counter(sidenote-counter);
    font-size: 0.7em;
    font-weight: 600;
    line-height: 0;
    vertical-align: super;
    color: var(--color-accent);
    cursor: pointer;
}

.sidenote-number:hover::after { color: var(--color-link-hover); }

.sidenote {
    float: right;
    clear: right;
    width: var(--note-width);
    margin-right: var(--note-pull);
    margin-block: 0.3rem 0;
    font-size: 0.8em;
    line-height: 1.35;
    color: var(--color-muted);
    text-align: left;
}

.sidenote::before {
    content: counter(sidenote-counter) " ";
    font-weight: 600;
    vertical-align: super;
    font-size: 0.7em;
    line-height: 0;
    color: var(--color-accent);
}

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

/* Hidden but focusable: on a narrow screen this checkbox is the control, and
   a keyboard user still needs to reach it. */
input.margin-toggle {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* gingerBill's breakpoint: at the sheet cap the layout goes fluid and full
   width, the indent shrinks to 8%, and notes collapse. */
@media (max-width: 80rem) {
    body {
        width: 84%;
        padding-inline: 8%;
    }

    header,
    main,
    footer {
        width: 100%;
    }

    .sidenote {
        display: none;
        float: none;
        width: auto;
        margin-right: 0;
    }

    input.margin-toggle:checked + .sidenote-number + .sidenote {
        display: block;
        margin-block: 0.25rem var(--space-sm);
        padding-inline-start: 1em;
        border-inline-start: 2px solid var(--color-border);
    }
}

/* Pictures stay smaller than the page so they remain illustrations. */
figure {
    margin: var(--space-md) 0;
    max-width: 24rem;
}

figure img { height: auto; }
main p > img { height: auto; }

/* A bare markdown image gets the same cap. Goldmark wraps it in a <p>. */
main p > img { max-width: 24rem; }

.article-hero {
    max-width: 42rem;
    margin-inline: auto;
}

.article-hero img {
    width: 100%;
    height: auto;
}

.article-context {
    max-width: 42rem;
    margin-inline: auto;
    color: var(--color-muted);
    font-size: 0.85em;
}

figcaption {
    margin-block-start: 0.35rem;
    color: var(--color-muted);
    font-size: 0.85em;
    line-height: 1.4;
}

/* Sized to the contact list beside it. A taller picture would leave dead
   space under the list. */
.portrait img {
    display: block;
    width: 7rem;
    max-width: 100%;
    height: auto;
    border: 1px solid var(--color-border);
}

.contact-panel {
    display: grid;
    grid-template-columns: 7rem minmax(0, 1fr);
    align-items: center;
    gap: var(--space-lg);
    margin-block-end: var(--space-md);
}

/* With no portrait, the panel is a single column. */
.contact-panel:not(:has(.portrait)) {
    grid-template-columns: 1fr;
    gap: var(--space-sm);
}

/* A heading with the feed link beside it. */
.section-head {
    display: flex;
    align-items: baseline;
    gap: var(--space-md);
}

.section-head h2 {
    border: 0;
    padding: 0;
}

/* Reads as apparatus beside the heading, not a call to action. */
.rss-badge {
    flex: none;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-muted);
    text-decoration: none;
}

.rss-badge:hover {
    color: var(--color-link-hover);
    text-decoration: none;
}

/* Contact list */

.contact-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.25em 1em;
    margin: 0;
}

.contact-list dt          { color: var(--color-muted); }
.contact-list dt::after   { content: ":"; }
.contact-list dd          { margin: 0; }
.contact-list a           { overflow-wrap: anywhere; }

@media (max-width: 32em) {
    .contact-panel {
        grid-template-columns: 1fr;
        justify-items: start;
        gap: var(--space-sm);
    }

    .contact-list {
        grid-template-columns: max-content minmax(0, 1fr);
        width: 100%;
        gap: 0.25em 0.5em;
    }
}

/* Tables. Enclosed, ruled between columns, zebra-striped body rows. */

table {
    border-collapse: collapse;
    width: 100%;
    margin-block: var(--space-md);
    border: 1px solid var(--color-border);
}

th, td {
    border: 1px solid var(--color-border);
    padding: 0.4em 0.8em;
    text-align: left;
    vertical-align: top;
}

th {
    background: var(--color-surface);
    font-weight: 600;
}

tbody tr:nth-child(even) {
    background: var(--color-surface);
}

/* Article and project listings share one title and description hierarchy. */

.post-entry {
    margin-block-end: var(--space-md);
}

.post-entry h2 {
    margin-block: 0;
    border: 0;
    padding: 0;
}

.post-entry > time {
    display: block;
    font-family: var(--font-mono);
    margin-block-start: var(--space-xs);
    color: var(--color-muted);
    font-size: 0.8em;
}

.post-entry > .entry-status {
    font-family: var(--font-mono);
    margin-block: 0.15em 0;
    color: var(--color-muted);
    font-size: 0.8em;
}

.post-entry > .entry-summary {
    margin-block: var(--space-xs) 0;
}

.tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.15em 0.7em;
    padding: 0;
    margin-block: 0.15em 0;
    font-family: var(--font-mono);
    color: var(--color-muted);
    font-size: 0.8em;
    list-style: none;
}

.tag-list li::before {
    content: "#";
}

.home-intro > p:first-of-type {
    font-size: 1.15em;
}

.home-intro > p:last-of-type,
.section-intro {
    color: var(--color-muted);
}

.project-entry {
    margin-block-end: var(--space-md);
}

.project-entry h2 {
    margin-block: 0;
    border: 0;
    padding: 0;
}

.project-entry p {
    margin-block: var(--space-xs) 0;
}

.project-entry .project-status {
    font-family: var(--font-mono);
    color: var(--color-muted);
    font-size: 0.8em;
}

.empty { color: var(--color-muted); }
