/*
 * The default theme's only stylesheet. Plain CSS, no build step, no
 * dependencies: a site that wants something else puts its own
 * `static/style.css` in the theme it wears and this file is never read again.
 *
 * The design is the andrewshell.org one (decision-16): a serif body and sans
 * headings at an 18px root on a 1.2 minor-third scale, warm paper, near-black
 * text, a rust primary and a blue secondary, one column at 42rem, links that
 * invert on hover and a rule in the primary colour.
 *
 * The source is light only. The dark scheme below is the same design on dark
 * paper, with the rust and the blue lifted until every text and background pair
 * meets WCAG 2.2 AA — 4.5:1 for body text, 3:1 for large text, rules and focus
 * outlines — in both schemes. `src/web/theme-colors.test.ts` reads the custom
 * properties out of this file and computes the ratios, so a colour changed here
 * that breaks one fails the build rather than a reader.
 */

:root {
  /* Light and dark are both drawn below, so a browser may paint its own form
     controls, scrollbars and spellcheck marks to match. */
  color-scheme: light dark;

  --maxWidth-xs: 20rem;
  --maxWidth-sm: 24rem;
  --maxWidth-md: 28rem;
  --maxWidth-lg: 32rem;
  --maxWidth-xl: 36rem;
  --maxWidth-2xl: 42rem;
  --maxWidth-3xl: 48rem;
  --maxWidth-4xl: 56rem;
  --maxWidth-wrapper: var(--maxWidth-2xl);

  --spacing-0: 0;
  --spacing-1: 0.25rem;
  --spacing-2: 0.5rem;
  --spacing-3: 0.75rem;
  --spacing-4: 1rem;
  --spacing-5: 1.25rem;
  --spacing-6: 1.5rem;
  --spacing-8: 2rem;
  --spacing-10: 2.5rem;
  --spacing-12: 3rem;
  --spacing-16: 4rem;
  --spacing-20: 5rem;
  --spacing-24: 6rem;
  --spacing-32: 8rem;

  --fontFamily-sans: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --fontFamily-serif: 'Iowan Old Style', 'Palatino Linotype', 'URW Palladio L', P052, serif;
  --fontFamily-mono:
    ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace;
  --font-body: var(--fontFamily-serif);
  --font-heading: var(--fontFamily-sans);

  --fontWeight-normal: 400;
  --fontWeight-medium: 500;
  --fontWeight-semibold: 600;
  --fontWeight-bold: 700;
  --fontWeight-extrabold: 800;
  --fontWeight-black: 900;

  --fontSize-root: 18px;
  --lineHeight-none: 1;
  --lineHeight-tight: 1.1;
  --lineHeight-normal: 1.5;
  --lineHeight-relaxed: 1.625;

  /* 1.200 minor third type scale */
  --fontSize-0: 0.833rem;
  --fontSize-1: 1rem;
  --fontSize-2: 1.15rem;
  --fontSize-3: 1.31rem;
  --fontSize-4: 1.5rem;
  --fontSize-5: 1.72rem;
  --fontSize-6: 1.97rem;
  --fontSize-7: 2.25rem;

  --content-letter-spacing: -0.01em;

  /* Colours. `body` is the paper and `text` the ink; `base`, `base-2` and
     `base-3` are the surfaces that sit on the paper, warm, cool and raised.
     `code-background` and `code-text` are a block of code, named rather than
     folded into `base` so a highlighting theme has something to be measured
     against (TASK-86). */
  --color-body: #fdfcfb;
  --color-text: #240b00;
  --color-primary: #b33900;
  --color-secondary: #007ab3;
  --color-base: rgb(245 243 243);
  --color-base-2: rgb(247 248 249);
  --color-base-3: rgb(255 255 255);
  --color-code-background: #f6f3f1;
  --color-code-text: #240b00;
  --color-error: #b3261e;

  /* Syntax highlighting: the Tomorrow palette, light member (TASK-86). The
     names are what each colour marks up, and the base16 slot they come from is
     in the comment; the highlighter is highlight.js, whose base16 Tomorrow
     theme is the mapping these follow.

     Five of them are not the stock colour. Tomorrow was drawn for an editor,
     where a faint comment is a feature; on this paper the stock greys, orange,
     yellow, green and teal read at 1.7:1 to 3.5:1, so each was darkened along
     its own hue until it made 4.5:1 and no further. `src/web/theme-colors.test.ts`
     is what keeps that true. */
  --color-code-comment: #6c6d6a; /* base03, stock #8e908c */
  --color-code-tag: #6b6d6b; /* base04, stock #969896 */
  --color-code-name: #c82829; /* base08 */
  --color-code-literal: #a95608; /* base09, stock #f5871f */
  --color-code-class: #846700; /* base0A, stock #eab700 */
  --color-code-string: #5e7500; /* base0B, stock #718c00 */
  --color-code-support: #30767a; /* base0C, stock #3e999f */
  --color-code-function: #4271ae; /* base0D */
  --color-code-keyword: #8959a8; /* base0E */
  --color-code-meta: #945f52; /* base0F, stock #a3685a */
  --color-code-added-background: #dff0d8;
  --color-code-removed-background: #f8dcdc;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-body: #191110;
    --color-text: #f4ece7;
    --color-primary: #ef7a48;
    --color-secondary: #3ea0d8;
    --color-base: rgb(38 30 28);
    --color-base-2: rgb(34 33 36);
    --color-base-3: rgb(45 36 33);
    --color-code-background: rgb(30 24 22);
    --color-code-text: #f4ece7;
    --color-error: #ff8093;

    /* The other member of the family, Tomorrow Night — the palette both source
       sites highlighted with, and the one highlight.js ships under that name.
       Only base0F needed lifting off this darker paper. */
    --color-code-comment: #999999; /* base03 */
    --color-code-tag: #b4b7b4; /* base04 */
    --color-code-name: #f2777a; /* base08 */
    --color-code-literal: #f99157; /* base09 */
    --color-code-class: #ffcc66; /* base0A */
    --color-code-string: #99cc99; /* base0B */
    --color-code-support: #66cccc; /* base0C */
    --color-code-function: #6699cc; /* base0D */
    --color-code-keyword: #cc99cc; /* base0E */
    --color-code-meta: #ae786b; /* base0F, stock #a3685a */
    --color-code-added-background: rgb(32 54 34);
    --color-code-removed-background: rgb(64 30 30);
  }
}

/* Reset. The source theme leans on a normalize file; the handful of rules it
   actually depends on are folded in here instead, so the theme is one file. */

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

body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
figure,
blockquote,
dl,
dd {
  margin: 0;
}

/* HTML elements */

html {
  font-size: var(--fontSize-root);
  line-height: var(--lineHeight-relaxed);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  background-color: var(--color-body);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fontSize-1);
  text-rendering: optimizeSpeed;
}

footer {
  padding: var(--spacing-6) var(--spacing-0);
  font-family: var(--fontFamily-sans);
}

nav,
.bio {
  font-family: var(--fontFamily-sans);
}

hr {
  height: 1px;
  border: 0;
  background: var(--color-primary);
}

img {
  max-width: 100%;
  height: auto;
}

figure {
  margin: var(--spacing-0) var(--spacing-0) var(--spacing-4) var(--spacing-0);
}

figcaption {
  font-size: var(--fontSize-0);
  text-align: center;
}

time {
  white-space: nowrap;
}

small,
.small {
  font-size: var(--fontSize-0);
}

/* Headings */

h1,
h2,
h3,
h4,
h5,
h6 {
  margin-top: var(--spacing-12);
  margin-bottom: var(--spacing-6);
  color: var(--color-text);
  font-family: var(--font-heading);
  font-weight: var(--fontWeight-bold);
  line-height: var(--lineHeight-tight);
  letter-spacing: -0.025em;
}

h1 {
  font-size: var(--fontSize-6);
  font-weight: var(--fontWeight-black);
}

h2 {
  font-size: var(--fontSize-5);
}

h3 {
  font-size: var(--fontSize-3);
}

h4,
h5,
h6 {
  font-size: var(--fontSize-1);
}

h2 > a,
h3 > a,
h4 > a,
h5 > a,
h6 > a {
  color: inherit;
  text-decoration: none;
}

/* Links. A link inverts on hover: the primary colour behind it and the paper
   colour on top, which is the source design's one flourish. `:focus-visible`
   draws an outline instead, so a keyboard reader sees where they are without
   the colour swapping under them. */

a,
a:visited {
  color: var(--color-primary);
}

a:hover,
a:focus {
  background-color: var(--color-primary);
  color: var(--color-body);
  text-decoration: none;
}

a:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  background-color: transparent;
  color: var(--color-primary);
}

/* The two links that are the page saying where it is rather than somewhere to
   go: the site title at the root and the small link home everywhere else. Both
   read as plain text, in the heading font the rules below give them.

   Named rather than reached for through the element they sit in (TASK-111). A
   bare `header a` also caught the site menu, which is navigation somebody is
   meant to use, and every link inside a post's own `<header>`. The `:visited`
   halves are here because `a:visited` outweighs a bare class, and the hover
   and focus halves because `a:focus-visible` outweighs one too: without them
   these two would take the outline rather than the flourish. */

.main-heading a,
.main-heading a:visited,
.header-link-home,
.header-link-home:visited {
  color: var(--color-text);
  text-decoration: none;
}

.main-heading a:hover,
.main-heading a:focus,
.header-link-home:hover,
.header-link-home:focus {
  background-color: var(--color-primary);
  color: var(--color-body);
  text-decoration: none;
}

/* Prose */

p {
  margin: var(--spacing-0) var(--spacing-0) var(--spacing-4) var(--spacing-0);
  padding: var(--spacing-0);
  line-height: var(--lineHeight-relaxed);
}

ul,
ol {
  margin-top: var(--spacing-0);
  margin-right: var(--spacing-0);
  margin-bottom: var(--spacing-8);
  margin-left: var(--spacing-4);
  padding: var(--spacing-0);
  list-style-position: inside;
  list-style-image: none;
}

ul li,
ol li {
  margin-bottom: var(--spacing-0);
  padding-left: var(--spacing-0);
}

li > p {
  display: inline;
}

li *:last-child {
  margin-bottom: var(--spacing-0);
}

details {
  margin-left: var(--spacing-4);
}

details summary {
  cursor: pointer;
}

.list-none {
  list-style-type: none;
}

.hlist {
  display: flex;
  flex-wrap: wrap;
  margin: 0;
}

.hlist li {
  margin: 0;
  padding: 0 0.5em 0 0;
  list-style-type: none;
}

blockquote {
  margin: var(--spacing-8) var(--spacing-8) var(--spacing-8) var(--spacing-0);
  padding: var(--spacing-0) var(--spacing-0) var(--spacing-0) var(--spacing-6);
  border-left: var(--spacing-1) solid var(--color-secondary);
  color: var(--color-secondary);
  font-size: var(--fontSize-2);
  font-style: italic;
}

blockquote > :last-child {
  margin-bottom: var(--spacing-0);
}

blockquote > ul,
blockquote > ol {
  list-style-position: inside;
}

table {
  width: 100%;
  margin-bottom: var(--spacing-8);
  border-collapse: collapse;
  border-spacing: 0.25rem;
}

table thead tr th {
  border-bottom: 1px solid var(--color-primary);
}

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

code {
  padding: 0.1em 0.3em;
  border-radius: 4px;
  background-color: var(--color-code-background);
  color: var(--color-code-text);
  font-size: 0.9em;
  /* A file path or an identifier is one long word, and a narrow screen would
     otherwise carry it off the side of the page. A block of code scrolls
     instead — see `pre` below. */
  overflow-wrap: break-word;
}

pre {
  overflow-x: auto;
  margin-bottom: var(--spacing-8);
  padding: var(--spacing-3) var(--spacing-4);
  border-radius: 6px;
  background-color: var(--color-code-background);
  color: var(--color-code-text);
  font-size: var(--fontSize-0);
  line-height: var(--lineHeight-normal);
}

pre code {
  padding: 0;
  border-radius: 0;
  background: none;
  font-size: inherit;
}

/* Syntax highlighting (TASK-86).
 *
 * The CMS renders a fenced block as `pre > code.language-x` and highlights
 * nothing; `static/highlight.js` marks the tokens up on the client, and these
 * are its colours. The scopes and the slots they map to are highlight.js's own
 * base16 Tomorrow theme, so a token it invents later lands somewhere sensible
 * rather than nowhere.
 *
 * Every colour is a custom property, so a site that wants another palette
 * redefines a dozen tokens instead of writing a syntax theme. Delimiters,
 * operators and substitutions are deliberately the block's own ink: they are
 * most of the characters on screen and a colour there is noise.
 */

.hljs-comment {
  color: var(--color-code-comment);
}

.hljs-tag {
  color: var(--color-code-tag);
}

.hljs-subst,
.hljs-punctuation,
.hljs-operator {
  color: var(--color-code-text);
}

.hljs-bullet,
.hljs-variable,
.hljs-template-variable,
.hljs-selector-tag,
.hljs-name {
  color: var(--color-code-name);
}

.hljs-symbol,
.hljs-number,
.hljs-link,
.hljs-attr,
.hljs-variable.constant_,
.hljs-literal {
  color: var(--color-code-literal);
}

.hljs-title,
.hljs-class .hljs-title,
.hljs-title.class_ {
  color: var(--color-code-class);
}

.hljs-strong {
  color: var(--color-code-class);
  font-weight: var(--fontWeight-bold);
}

.hljs-code,
.hljs-string,
.hljs-title.class_.inherited__ {
  color: var(--color-code-string);
}

.hljs-built_in,
.hljs-doctag,
.hljs-quote,
.hljs-regexp,
.hljs-keyword.hljs-atrule {
  color: var(--color-code-support);
}

.hljs-attribute,
.hljs-function .hljs-title,
.hljs-section,
.hljs-title.function_ {
  color: var(--color-code-function);
}

.hljs-keyword,
.hljs-template-tag,
.hljs-type {
  color: var(--color-code-keyword);
}

.hljs-emphasis {
  color: var(--color-code-keyword);
  font-style: italic;
}

.hljs-meta,
.hljs-meta .hljs-keyword,
.hljs-meta .hljs-string {
  color: var(--color-code-meta);
}

/* A diff reads by the line, not by the token, which is what prism-diff.css did
 * on the site this design comes from: the whole line takes a tint out to the
 * edges of the block — the negative margin cancels the `pre` padding and the
 * padding puts it back — and keeps the block's own ink, which is the pair the
 * contrast test checks. The `+` and the `-` stay in the text, so the meaning
 * does not rest on the colour alone.
 */

.hljs-addition,
.hljs-deletion {
  display: block;
  margin-right: calc(-1 * var(--spacing-4));
  margin-left: calc(-1 * var(--spacing-4));
  padding-right: var(--spacing-4);
  padding-left: var(--spacing-4);
  color: var(--color-code-text);
  text-decoration: none;
}

.hljs-addition {
  background-color: var(--color-code-added-background);
}

.hljs-deletion {
  background-color: var(--color-code-removed-background);
}

/* Screen reader text. The skip link is this until it is focused, and then it
   is a box at the top left of the page. */

.screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  border: 0;
  clip-path: inset(50%);
  word-wrap: normal !important;
}

.screen-reader-text:focus {
  display: block;
  width: auto;
  height: auto;
  top: var(--spacing-2);
  left: var(--spacing-2);
  padding: var(--spacing-4);
  clip-path: none;
  background-color: var(--color-base-3);
  color: var(--color-text);
  font-size: var(--fontSize-1);
  font-weight: var(--fontWeight-bold);
  line-height: normal;
  text-decoration: none;
  z-index: 100000;
}

/* The page shell */

.global-wrapper {
  max-width: var(--maxWidth-wrapper);
  margin: var(--spacing-0) auto;
  padding: var(--spacing-10) var(--spacing-5);
}

.global-wrapper[data-is-root-path='true'] .bio {
  margin-bottom: var(--spacing-20);
}

.global-header {
  margin-bottom: var(--spacing-12);
}

.main-heading {
  margin: 0;
  font-size: var(--fontSize-7);
}

.header-link-home {
  font-family: var(--font-heading);
  font-size: var(--fontSize-2);
  font-weight: var(--fontWeight-bold);
  text-decoration: none;
}

/* The site menu, which the header carries on every page (TASK-105). At the
   root the header is the site title with the tagline under it, and the menu
   is a line of its own under that.

   No size of its own (TASK-111): a menu is navigation somebody is meant to
   use rather than a footnote, so it reads at the page's size, like the footer
   menu, which never had one. */
.global-header .site-nav {
  margin-top: var(--spacing-2);
}

/* Everywhere else the header is the small link home, and the menu sits beside
   it on the same line — the two wrap onto a second line together rather than
   the menu dropping under the link on a narrow screen. */
.global-wrapper:not([data-is-root-path='true']) .global-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--spacing-5);
  row-gap: var(--spacing-1);
}

.global-wrapper:not([data-is-root-path='true']) .global-header .site-nav {
  margin-top: var(--spacing-0);
}

/* An entry: a post or a page (TASK-83). The source design's own rules — the
   title tight against the words under it, a subtitle in the heading font —
   plus the small line the `e-content` ends on, which carries the permalink,
   the published date and, when it is a different day, the updated one. */

.blog-post header h1 {
  margin: var(--spacing-0) var(--spacing-0) var(--spacing-4) var(--spacing-0);
}

.blog-post header p {
  font-family: var(--font-heading);
  font-size: var(--fontSize-2);
}

.entry-meta,
.page-meta {
  margin-top: var(--spacing-8);
}

/* A page usually carries no date, and then this line has nothing in it. The
   layout prints it anyway, so a site has one hook wherever it is; here is
   where it disappears. */
.entry-meta:empty,
.page-meta:empty {
  display: none;
}

/* The bio, which the entry footer prints and an author archive heads with
   (TASK-83). */

.bio {
  display: flex;
  align-items: center;
  margin-bottom: var(--spacing-16);
}

.bio p {
  margin-bottom: var(--spacing-0);
}

/* The name reads as the heading of the card; the source theme printed a
   <strong> around it, which is styling in the markup. */
.bio .p-name {
  font-weight: var(--fontWeight-bold);
}

.bio-note {
  margin-top: var(--spacing-2);
  font-style: italic;
}

/* The links the person calls their own, under the credit: a horizontal list in
   the heading font, at the page's size like every other nav (TASK-111). The
   site menu used to share this rule; it is in the header now (TASK-105) and
   the bio carries nobody but the person. */
.bio-links {
  margin-top: var(--spacing-2);
}

.bio-avatar {
  display: inline-block;
  min-width: 55px;
  margin-right: var(--spacing-4);
  margin-bottom: var(--spacing-0);
  border: 3px solid var(--color-base-3);
  border-radius: 50%;
}

.bio-avatar img {
  display: block;
  width: 50px;
  height: 50px;
  border-radius: 50%;
}

.circle {
  border-radius: 50%;
}

/* A listing: the feed of entries, and what heads one (TASK-82). The source
   design's own rules, on the tokens above. The feed itself takes no styling —
   it is a stack of articles at the measure — and what makes it read as a list
   is the rule between two of them and the small meta line under each. */

.feed-title {
  margin: var(--spacing-0) var(--spacing-0) var(--spacing-4) var(--spacing-0);
  padding: var(--spacing-0);
  font-size: var(--fontSize-3);
}

.feed-separator {
  margin: var(--spacing-2) var(--spacing-0) var(--spacing-4) var(--spacing-0);
}

.feed-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-2);
  align-items: baseline;
  font-size: 70%;
}

.feed-meta p {
  margin: var(--spacing-0);
}

.post-categories {
  margin-top: var(--spacing-2);
  margin-bottom: var(--spacing-0);
  font-size: 70%;
}

.post-categories a {
  display: inline-block;
  margin-right: var(--spacing-2);
}

/* The categories are already small; inside the meta line they would be small
   twice over, so there they are the size of the line they sit on. */
.feed-meta .post-categories {
  font-size: 100%;
}

.category-header {
  margin-bottom: var(--spacing-8);
}

.category-description {
  margin-top: var(--spacing-2);
  font-style: italic;
}

/* Pagination: two arrows under a listing, the previous one at the left edge
   and the next at the right however few there are. */

.pagination {
  display: flex;
  gap: var(--spacing-4);
  align-items: baseline;
  justify-content: space-between;
  margin-top: var(--spacing-12);
  padding-top: var(--spacing-5);
  border-top: 1px solid var(--color-base);
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
}

.pagination-previous {
  margin-inline-end: auto;
}

.pagination-next {
  margin-inline-start: auto;
}

/* Where a post links its neighbours, which the entry layout prints (TASK-83). */

.blog-post-nav {
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
}

.blog-post-nav ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  margin: var(--spacing-0);
  padding: 0;
  list-style: none;
}

/* Titles: what heads a listing, a 404 and an author archive. The source theme
   prints none of these — it has no archive heading at all — so they are the
   theme's own, sized off the same scale. An entry's own title is
   `.blog-post header h1` above. */

.page-title {
  margin: 0 0 var(--spacing-2);
  font-size: var(--fontSize-6);
}

.empty {
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
}

/* The search box (TASK-22): a field and a button on one line, at the top of
   the search page and nowhere else (TASK-105). The field is drawn the way the
   comment form's are, so the site has one look for a place to type. */

.search-form {
  display: flex;
  gap: var(--spacing-2);
  margin: 0 0 var(--spacing-4);
  font-family: var(--font-heading);
}

.search-form label {
  flex: 1;
  min-width: 0;
}

.search-form input[type='search'] {
  width: 100%;
  padding: var(--spacing-2);
  border: 1px solid var(--color-base);
  background-color: var(--color-base-3);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fontSize-1);
}

.search-form input[type='search']:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -1px;
  border-color: var(--color-primary);
}

.search-form button {
  padding: var(--spacing-2) var(--spacing-4);
  border: none;
  background-color: var(--color-primary);
  color: var(--color-body);
  font-family: var(--font-heading);
  font-size: var(--fontSize-1);
  cursor: pointer;
}

.search-form button:hover,
.search-form button:focus-visible {
  opacity: 0.85;
}

.search-summary {
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
}

.search-result {
  margin: 0 0 var(--spacing-8);
}

.search-result .feed-title {
  margin-bottom: var(--spacing-2);
}

/* A matched word is marked by weight and an underline in the primary colour
   rather than by a highlighter background, so it adds no colour pair the
   contrast test would have to prove in both schemes. */

.search-snippet mark {
  background-color: transparent;
  color: inherit;
  font-weight: var(--fontWeight-bold);
  text-decoration: underline var(--color-primary);
  text-underline-offset: 0.15em;
}

/* An author archive (TASK-67): the person above their posts. The same URL is
   their ActivityPub actor, so this is the page a follower sees when they click
   through from somewhere else on the fediverse. The person themselves is the
   bio above; this is only what is left, the heading over it. */

.author-header {
  margin-bottom: var(--spacing-4);
}

/* The front page (TASK-85): the site's own words, then Recent Posts, then
   where to go next. Almost nothing is needed — the words are `.e-content`
   below, the posts are the feed above, and the heading over them is an
   ordinary `h2` — so this is only the line of links, which follows a feed
   rather than a paragraph and needs the air a paragraph would already have. */

.front-links {
  margin-top: var(--spacing-8);
}

/* An archive page: every post there has ever been, under a heading per month.
   The source design's essays page is plain headings over `ol.list-none` and
   nothing else, so the prose rules draw it; what is here only closes the gap
   between a month and its own posts, which at the prose spacing reads as two
   things rather than as one. */

.archive h2 {
  margin-bottom: var(--spacing-2);
}

/* Body copy: whatever a document's words render into, which is the entry's
   `section.e-content` and the `div.page-body.e-content` a posts page prints
   its own words in. */

.e-content {
  overflow-wrap: break-word;
}

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

.e-content table {
  display: block;
  overflow-x: auto;
}

.e-content th,
.e-content td {
  padding: var(--spacing-1) var(--spacing-3);
  text-align: start;
}

.footnotes {
  margin-top: var(--spacing-10);
  padding-top: var(--spacing-4);
  border-top: 1px solid var(--color-base);
  font-size: var(--fontSize-0);
}

.footnote-item p {
  display: inline;
}

/* Reactions: the likes, the boosts and the pages that mentioned a post,
   grouped by kind as facepiles of small round avatars (TASK-84). */

.reactions-section {
  margin-top: var(--spacing-12);
}

.reaction-group {
  display: flex;
  align-items: center;
  gap: var(--spacing-3);
  margin-bottom: var(--spacing-3);
}

.reaction-title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--fontSize-1);
  white-space: nowrap;
}

.facepile {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-1);
}

.facepile a,
.facepile span {
  display: inline-block;
  line-height: 0;
  text-decoration: none;
}

/* A face is a picture of somebody: the block of colour a link takes on hover
   everywhere else would sit behind it as a frame, so it is taken back off. */

.facepile a:hover,
.facepile a:focus {
  background-color: transparent;
  color: var(--color-primary);
  text-decoration: underline;
}

.facepile img {
  display: block;
  border-radius: 50%;
}

/* A reaction with no avatar has nothing to recognise anybody by, so the emoji
   badge of its kind stands in and the name is printed beside it — which needs
   the line box the faces above do without. */

.facepile a:has(.reaction-name),
.facepile span:has(.reaction-name) {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-1);
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
  line-height: normal;
}

.reaction-icon {
  display: inline-block;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background-color: var(--color-base);
  line-height: 2rem;
  text-align: center;
}

/* The thread under a post: the replies from every door, each one an h-entry
   with its author, its time and its words, and answers nested inside it. */

.comments-area {
  margin-top: var(--spacing-12);
}

.comments-title {
  margin: 0 0 var(--spacing-8);
  font-size: var(--fontSize-4);
}

.comment-list,
.comment-list .children {
  margin: 0;
  padding: 0;
  list-style: none;
}

.comment-list .children {
  margin-left: var(--spacing-8);
}

.comment-body {
  padding: var(--spacing-4) 0;
  border-bottom: 1px solid var(--color-base);
}

.comment-author {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  font-family: var(--font-heading);
}

.comment-author .avatar {
  border-radius: 50%;
}

.comment-metadata {
  margin-bottom: var(--spacing-2);
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
}

/* The permalink is the whole date line, so it is the ink of the page rather
   than a link's colour until somebody points at it. */

.comment-metadata a {
  color: var(--color-text);
  text-decoration: none;
}

.comment-metadata a:hover,
.comment-metadata a:focus {
  background-color: transparent;
  color: var(--color-primary);
}

.comment-content {
  margin-top: var(--spacing-2);
}

.comment-content > :last-child {
  margin-bottom: 0;
}

.reply {
  margin-top: var(--spacing-2);
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
}

.no-comments {
  font-family: var(--font-heading);
  font-style: italic;
}

/* The comment form under an open post, and the contact form on a page that
   asked for one. One set of rules rather than two: they are the same kind of
   form, the contact form wears `comment-respond` to say so, and a site
   restyling one cannot leave the other behind. */

.comment-respond {
  margin-top: var(--spacing-8);
}

.comment-respond .comment-reply-title,
.comment-respond .contact-form-title {
  margin: 0 0 var(--spacing-4);
  font-size: var(--fontSize-4);
}

.comment-respond label {
  display: block;
  margin-bottom: var(--spacing-1);
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
}

.comment-field,
.contact-field,
.comment-check {
  margin: 0 0 var(--spacing-4);
}

/* The one label that belongs beside its field rather than over it. */

.comment-check label {
  display: inline;
}

.comment-respond input[type='text'],
.comment-respond input[type='email'],
.comment-respond input[type='url'],
.comment-respond textarea {
  width: 100%;
  padding: var(--spacing-2);
  border: 1px solid var(--color-base);
  background-color: var(--color-base-3);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fontSize-1);
}

.comment-respond input[type='text']:focus-visible,
.comment-respond input[type='email']:focus-visible,
.comment-respond input[type='url']:focus-visible,
.comment-respond textarea:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -1px;
  border-color: var(--color-primary);
}

.comment-respond textarea {
  min-height: 8rem;
  resize: vertical;
}

.comment-respond .form-submit button,
.comment-respond .form-submit input[type='submit'] {
  padding: var(--spacing-2) var(--spacing-6);
  border: none;
  background-color: var(--color-primary);
  color: var(--color-body);
  font-family: var(--font-heading);
  font-size: var(--fontSize-1);
  cursor: pointer;
}

.comment-respond .form-submit button:hover,
.comment-respond .form-submit button:focus-visible,
.comment-respond .form-submit input[type='submit']:hover,
.comment-respond .form-submit input[type='submit']:focus-visible {
  opacity: 0.85;
}

/* What a form says back: the thank-you after a submission, the message about
   one that was refused, and what a reader is answering. */

.comment-notice,
.comment-error,
.contact-notice,
.contact-error {
  margin: 0 0 var(--spacing-4);
  padding: var(--spacing-2) var(--spacing-3);
  border-inline-start: var(--spacing-1) solid var(--color-secondary);
}

.comment-error,
.contact-error {
  border-inline-start-color: var(--color-error);
}

.comment-replying-to,
.comment-signed-in {
  margin: 0 0 var(--spacing-4);
  font-family: var(--font-heading);
  font-size: var(--fontSize-0);
}

.comment-optional,
.contact-optional {
  font-size: var(--fontSize-0);
}

.comment-hint,
.contact-hint,
.comment-field-error,
.contact-field-error {
  display: block;
  margin-top: var(--spacing-1);
  font-size: var(--fontSize-0);
}

.comment-field-error,
.contact-field-error {
  color: var(--color-error);
}

/*
  The honeypot. Taken out of the flow rather than `display: none`, because some
  form fillers skip fields a browser would not paint at all and this one is
  meant to be filled in.
*/
.comment-trap,
.contact-trap {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Media queries */

@media (max-width: 42rem) {
  .bio {
    flex-direction: column;
  }

  .bio-avatar {
    margin-right: var(--spacing-0);
    margin-bottom: var(--spacing-4);
  }

  blockquote {
    margin-left: var(--spacing-0);
    padding: var(--spacing-0) var(--spacing-0) var(--spacing-0) var(--spacing-4);
  }

  ul,
  ol {
    list-style-position: inside;
  }

  .comment-list .children {
    margin-left: var(--spacing-4);
  }
}
