/* albatros: one centred column, a system type stack, and two colour sets.
   The reader's OS preference decides until they press the toggle, which stamps
   `data-theme` on the root and wins from then on.

   Every colour is a custom property declared three times: once for light, once
   inside `prefers-color-scheme: dark` (guarded so an explicit light choice
   survives it), and once under `[data-theme="dark"]`. That is the whole
   mechanism; nothing below reads a raw colour. */

:root {
  --measure: 44rem;
  --fg: #16181d;
  --muted: #5c6672;
  --bg: #ffffff;
  --raised: #f5f6f8;
  --accent: #2f5eea;
  --accent-soft: #eaefff;
  --rule: #e4e7eb;
  --shadow: 0 1px 2px rgb(16 18 29 / 6%), 0 8px 24px rgb(16 18 29 / 6%);

  --sx-comment: #6b7280;
  --sx-string: #0f7b3f;
  --sx-number: #b45309;
  --sx-keyword: #b02a56;
  --sx-function: #2f5eea;
  --sx-variable: #1f2937;
  --sx-type: #0f766e;
  --sx-punctuation: #6b7280;

  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --fg: #e8eaee;
    --muted: #98a1ae;
    --bg: #101216;
    --raised: #191c22;
    --accent: #8aa9ff;
    --accent-soft: #1b2236;
    --rule: #262a32;
    --shadow: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px rgb(0 0 0 / 30%);

    --sx-comment: #7f8a9a;
    --sx-string: #79d18b;
    --sx-number: #e8b06a;
    --sx-keyword: #ff8fae;
    --sx-function: #8aa9ff;
    --sx-variable: #dfe3ea;
    --sx-type: #63d5c2;
    --sx-punctuation: #98a1ae;

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --fg: #e8eaee;
  --muted: #98a1ae;
  --bg: #101216;
  --raised: #191c22;
  --accent: #8aa9ff;
  --accent-soft: #1b2236;
  --rule: #262a32;
  --shadow: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px rgb(0 0 0 / 30%);

  --sx-comment: #7f8a9a;
  --sx-string: #79d18b;
  --sx-number: #e8b06a;
  --sx-keyword: #ff8fae;
  --sx-function: #8aa9ff;
  --sx-variable: #dfe3ea;
  --sx-type: #63d5c2;
  --sx-punctuation: #98a1ae;

  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Fluid, but only between the two sizes worth having: comfortable on a
     phone, unchanged past a tablet. */
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.06rem);
  line-height: 1.7;
  color: var(--fg);
  background: var(--bg);
  text-rendering: optimizeLegibility;
  -webkit-text-size-adjust: 100%;
}

.site-header,
.content,
.site-footer {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

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

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

::selection {
  background: var(--accent-soft);
  color: var(--fg);
}

/* Header ------------------------------------------------------------------ */

.site-header {
  display: flex;
  align-items: center;
  gap: 0.5rem 1.25rem;
  min-height: 4rem;
  border-bottom: 1px solid var(--rule);
  flex-wrap: wrap;
}

/* Off the top of the viewport rather than off to the side, and moved by a
   transform: taking it out of the flow and putting it back reflows the header
   under the reader the moment they tab into the page. */
.skip {
  position: absolute;
  z-index: 20;
  top: 0.5rem;
  left: 0.5rem;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--rule);
  border-radius: 0.5rem;
  background: var(--raised);
  color: var(--fg);
  text-decoration: none;
  transform: translateY(-250%);
}

.skip:focus {
  transform: none;
}

.brand {
  font-weight: 650;
  font-size: 1.05rem;
  color: var(--fg);
  text-decoration: none;
}

.top-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-right: auto;
}

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

.top-nav a:hover {
  color: var(--fg);
}

.controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.langs {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
}

.langs-icon {
  display: grid;
  place-items: center;
  color: var(--muted);
}

.lang {
  color: var(--muted);
  text-decoration: none;
}

.lang:hover {
  color: var(--fg);
}

.lang.active {
  color: var(--fg);
  font-weight: 600;
}

/* Every edition but the first gets a separator drawn in CSS, so the markup
   stays a plain list of links. */
.lang + .lang::before {
  content: "/";
  margin-inline-end: 0.35rem;
  color: var(--rule);
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 0.5rem;
  background: var(--raised);
  color: var(--fg);
  cursor: pointer;
}

.icon-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.icon-btn > * {
  display: grid;
  place-items: center;
}

.on-dark {
  display: none;
}

:root[data-theme="dark"] .on-dark {
  display: grid;
}

:root[data-theme="dark"] .on-light {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .on-dark {
    display: grid;
  }

  :root:not([data-theme="light"]) .on-light {
    display: none;
  }
}

/* Article ----------------------------------------------------------------- */

.content {
  padding-block: 2.5rem 3.5rem;
}

h1 {
  font-size: clamp(1.7rem, 1.5rem + 1vw, 2.1rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin-block: 0 0.5rem;
  text-wrap: balance;
}

h2,
h3,
h4 {
  margin-block: 2.2rem 0.5rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

h2 {
  font-size: 1.4rem;
}

h3 {
  font-size: 1.15rem;
}

/* `html { anchors }` slugs every heading; the link is the heading itself. */
h2 > a,
h3 > a,
h4 > a {
  color: inherit;
  text-decoration: none;
}

h2 > a:hover::after,
h3 > a:hover::after {
  content: " #";
  color: var(--muted);
}

.byline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-block: 0 2rem;
  color: var(--muted);
  font-size: 0.9rem;
}

.authors {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.author {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.avatar {
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 999px;
  object-fit: cover;
}

.author-name {
  color: var(--fg);
}

a.author-name {
  color: var(--accent);
  text-decoration: none;
}

a.author-name:hover {
  text-decoration: underline;
}

/* The lead image, above the prose and out to the full column. */
.cover {
  margin: 0 0 2rem;
}

.cover img {
  width: 100%;
  aspect-ratio: 2 / 1;
  object-fit: cover;
  border-radius: 0.6rem;
}

p,
ul,
ol {
  margin-block: 0 1.15rem;
}

li {
  margin-block: 0.25rem;
}

hr {
  margin-block: 2.5rem;
  border: 0;
  border-top: 1px solid var(--rule);
}

.post img,
.post video {
  max-width: 100%;
  height: auto;
  border-radius: 0.5rem;
}

figure {
  margin-inline: 0;
}

figcaption {
  margin-top: 0.5rem;
  color: var(--muted);
  font-size: 0.88rem;
}

blockquote {
  margin-inline: 0;
  padding-inline-start: 1rem;
  border-inline-start: 3px solid var(--rule);
  color: var(--muted);
  font-style: italic;
}

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

mark {
  background: var(--accent-soft);
  color: var(--fg);
  padding-inline: 0.15em;
  border-radius: 0.2em;
}

kbd {
  padding: 0.1em 0.4em;
  border: 1px solid var(--rule);
  border-bottom-width: 2px;
  border-radius: 0.35em;
  background: var(--raised);
  font-family: inherit;
  font-size: 0.85em;
}

details {
  margin-block: 1.15rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--rule);
  border-radius: 0.6rem;
  background: var(--raised);
}

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

/* Footnotes: baudelaire places the note list inside the article, so it needs
   to read as an aside rather than as more prose. */
[role="doc-endnotes"] {
  margin-top: 3rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: 0.9rem;
}

pre {
  padding: 0.9rem 1rem;
  border-radius: 0.6rem;
  background: var(--raised);
  border: 1px solid var(--rule);
  overflow-x: auto;
  line-height: 1.55;
}

/* The wrapper `theme.js` puts around a code block, so the copy button can sit
   in its corner without scrolling away with the code. */
.codeblock {
  position: relative;
  margin-block: 0 1.15rem;
}

.codeblock pre {
  margin: 0;
}

.copy {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  background: var(--bg);
  color: var(--muted);
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.codeblock:hover .copy,
.copy:focus-visible,
.copy.copied {
  opacity: 1;
}

.copy:hover {
  color: var(--fg);
  border-color: var(--accent);
}

.copy.copied {
  color: var(--accent);
  border-color: var(--accent);
}

/* A pointer is what reveals the button; without one it is always there, and the
   block needs room for it: it cannot appear only when it would not be in the
   way. */
@media (hover: none) {
  .copy {
    opacity: 1;
  }

  .codeblock pre {
    padding-inline-end: 4rem;
  }
}

code {
  font-family: ui-monospace, SFMono-Regular, "JetBrains Mono", Menlo, monospace;
  /* Same size as the prose around it. Monospace reads larger at a given size,
     so `font-size-adjust` matches the x-height instead of shrinking the text. */
  font-size: 1em;
  font-size-adjust: ex-height 0.53;
}

/* Inline code only: a `<pre>` already carries the block's own background. */
:not(pre) > code {
  padding: 0.1em 0.35em;
  border-radius: 0.35em;
  background: var(--raised);
}

/* Highlight palette. Typst bakes its colours inline; `html { highlight }` classes
   a code block's tokens instead, so the colours live here and follow the toggle.
   Eight variables for twenty-odd tokens: the ones a reader has to tell apart get
   a colour of their own, and the rest join whichever is closest. */

.sx-comment {
  color: var(--sx-comment);
  font-style: italic;
}
.sx-string, .sx-escape { color: var(--sx-string); }
.sx-number, .sx-constant { color: var(--sx-number); }
.sx-keyword, .sx-operator { color: var(--sx-keyword); }
.sx-function, .sx-tag, .sx-heading, .sx-label { color: var(--sx-function); }
.sx-variable, .sx-parameter, .sx-property, .sx-attribute { color: var(--sx-variable); }
.sx-type, .sx-namespace { color: var(--sx-type); }
.sx-punctuation { color: var(--sx-punctuation); }
.sx-invalid { color: var(--sx-keyword); text-decoration: underline wavy; }
.sx-strong { font-weight: 700; }
.sx-emph { font-style: italic; }
.sx-link { text-decoration: underline; }
.sx-raw { font-style: normal; }

/* A table wider than the column scrolls rather than crushing its cells. The
   block box caps at the column while its contents keep their natural width,
   which is what makes the overflow scrollable without a wrapper element the
   theme has no way to add. */
table {
  display: block;
  width: max-content;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  margin-block: 1.5rem;
  font-size: 0.95em;
}

th,
td {
  padding: 0.5rem 0.85rem;
  text-align: left;
  border-bottom: 1px solid var(--rule);
}

thead th {
  border-bottom: 2px solid var(--rule);
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}

tbody tr:last-child td {
  border-bottom: 0;
}

td {
  font-variant-numeric: tabular-nums;
}

/* Listings ---------------------------------------------------------------- */

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

.entry {
  display: grid;
  gap: 0.2rem;
  padding-block: 1.1rem;
  border-bottom: 1px solid var(--rule);
}

/* A listing with any picture in it gets the column for every row, so a row
   without one still starts its title where its neighbours do. */
.listing.illustrated .entry {
  grid-template-columns: 7.5rem 1fr;
  gap: 0 1.1rem;
  align-items: start;
}

.listing.illustrated .entry > .entry-text {
  grid-column: 2;
}

.entry-thumb img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: 0.45rem;
}

.entry-text {
  display: grid;
  gap: 0.2rem;
}

.entry:last-child {
  border-bottom: 0;
}

.entry-title {
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--fg);
  text-decoration: none;
}

.entry-title:hover {
  color: var(--accent);
}

.entry-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
}

.entry-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.entry-summary {
  margin: 0.15rem 0 0;
  color: var(--muted);
}

/* The home page's recent posts, and the related ones at the foot of a post:
   the same block, from the same catalogue. */

.recent,
.related {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}

.recent > h2,
.related > h2 {
  margin-top: 0;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.more {
  margin-top: 1.25rem;
  font-size: 0.92rem;
}

.more a {
  text-decoration: none;
}

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

/* Tags and pagers --------------------------------------------------------- */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-block: 2rem 0;
}

.chip {
  padding: 0.15rem 0.6rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--raised);
  color: var(--muted);
  font-size: 0.85rem;
  text-decoration: none;
  white-space: nowrap;
}

.chip:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.pager {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  margin-top: 3rem;
}

.pager a {
  display: grid;
  gap: 0.15rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--rule);
  border-radius: 0.6rem;
  background: var(--raised);
  color: var(--fg);
  text-decoration: none;
}

.pager a:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow);
}

.pager .next {
  text-align: right;
}

.pager-label {
  color: var(--muted);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.pager-title {
  font-weight: 600;
  line-height: 1.35;
}

/* Contents ----------------------------------------------------------------
   A `<details>`, so a reader can fold it away. Baudelaire fills the list after
   the page compiles, so it is in the markup a reader without script gets. */

.toc {
  margin-block: 0 2rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--rule);
  border-radius: 0.6rem;
  background: var(--raised);
}

/* Built into the page rather than by a script, so there is nothing to unhide.
   What is left is what markup cannot decide: a contents list of one entry is
   furniture, and an empty one has nothing to show. */
.toc:has(.toc-list:empty),
.toc:has(.toc-list > ol > li:only-child):not(:has(.toc-list li li)) {
  display: none;
}

.toc-title {
  cursor: pointer;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.toc-list {
  display: block;
  margin-block-start: 0.6rem;
}

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

.toc-list a {
  display: block;
  padding: 0.1rem 0;
  color: var(--muted);
  text-decoration: none;
  line-height: 1.45;
}

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

/* A subsection sits under the section above it, however deep it goes. */
.toc-list ol ol a {
  padding-inline-start: 1rem;
  font-size: 0.94em;
}

/* Not found --------------------------------------------------------------- */

.notfound-code {
  margin: 0;
  color: var(--rule);
  font-size: clamp(4rem, 3rem + 8vw, 7rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
}

.notfound-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 2rem;
}

/* Footer ------------------------------------------------------------------ */

.site-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1.5rem 2.5rem;
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: 0.88rem;
}

.feeds {
  display: flex;
  gap: 0.75rem;
}

.icon {
  display: block;
}

@media (max-width: 30rem) {
  .pager {
    grid-template-columns: 1fr;
  }

  .pager .next {
    text-align: left;
  }

  /* A thumbnail beside the words leaves neither enough room on a phone, so the
     picture goes above them and runs the full width. */
  .listing.illustrated .entry {
    grid-template-columns: 1fr;
    gap: 0.6rem;
  }

  .listing.illustrated .entry > .entry-text {
    grid-column: auto;
  }

  .entry-thumb img {
    aspect-ratio: 2 / 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}

@media print {
  .site-header,
  .site-footer,
  .pager,
  .chips {
    display: none;
  }

  body {
    color: #000;
    background: #fff;
  }
}
