/* Tokens: mirror the vinta.ws homepage's token block in docker/static-files/homepage/css/main.css; keep the two in step. */
:root {
  color-scheme: light;
  --space-2xs: 4px; --space-xs: 8px; --space-sm: 12px; --space-md: 16px; --space-lg: 24px; --space-xl: 40px; --space-2xl: 64px; --space-3xl: 96px;
  --text-sm: 0.875rem; --text-md: 1rem; --text-lg: 1.25rem; --text-xl: 1.5625rem; --text-2xl: 1.953rem;
  --text-display-s: clamp(2.25rem, 4vw + 0.5rem, 3.75rem); --text-display: clamp(2.75rem, 5vw + 1rem, 5.25rem);
  --text-section: clamp(2rem, 2.5vw + 1rem, 3.5rem); --text-lead: clamp(1.125rem, 0.35vw + 1rem, 1.375rem);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-micro: 120ms;
  --container: calc(75rem + 2 * var(--gutter)); --gutter: 64px; --section-gap-s: 120px;
  --z-toast: 500;
  --color-paper: oklch(96.5% 0.016 82); --color-paper-2: oklch(93.5% 0.02 80);
  --color-ink: oklch(17% 0.012 60); --color-ink-2: oklch(28% 0.014 60); --color-muted: oklch(42% 0.014 65);
  --color-rule: oklch(80% 0.018 75); --color-rule-2: oklch(66% 0.02 72);
  --color-accent: oklch(45% 0.18 262); --color-focus: oklch(50% 0.18 262);
  --color-guide: oklch(55% 0.16 262 / 0.5);
  --color-code-string: oklch(42% 0.11 150); --color-code-number: oklch(45% 0.13 45); --color-code-function: oklch(42% 0.15 305); --color-code-property: oklch(44% 0.15 25); --color-code-variable: oklch(43% 0.09 205);
  --font-display: "Source Serif 4", "Noto Serif TC", ui-serif, Georgia, serif;
  /* headings people read (titles, in-post headings, list titles) use the body sans; Source Serif 4 stays on the blog name */
  --font-heading: var(--font-body);
  --font-body: "Geist", "Noto Sans TC", ui-sans-serif, system-ui, sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", "Cascadia Code", "JetBrains Mono", Menlo, Consolas, monospace;
  --rule-hair: 1px;
  --tracking-display: -0.02em; --display-weight: 600; --display-optical: 16;
}

/* Base: the homepage's base rules, minus the slot and photo rules the blogs have no use for */
*, *::before, *::after { box-sizing: border-box; }
html, body { overflow-x: clip; }
html { scrollbar-color: var(--color-muted) var(--color-paper); scroll-padding-top: var(--space-3xl); }
body { margin: 0; background: var(--color-paper); color: var(--color-ink); font-family: var(--font-body); font-size: 1.125rem; line-height: 1.6; -webkit-font-smoothing: antialiased; caret-color: var(--color-accent); }
::selection { background: color-mix(in oklab, var(--color-accent) 22%, transparent); color: var(--color-ink); }
:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
a { color: inherit; text-decoration-color: var(--color-accent); text-decoration-thickness: 1px; text-underline-offset: 0.2em; transition: text-decoration-thickness var(--dur-micro) var(--ease-out); }
a:hover { text-decoration-thickness: 2px; }
h1, h2, h3 { margin: 0; font-family: var(--font-heading); font-weight: var(--display-weight); font-synthesis: none; letter-spacing: var(--tracking-display); line-height: 1.1; overflow-wrap: break-word; min-width: 0; text-wrap: pretty; }
p { margin: 0; text-wrap: pretty; }
/* Traditional Chinese pages set headings in the serif display stack, Source Serif 4 at its sturdy optical size for any Latin, without the negative tracking that cramps Han characters */
:root:lang(zh) { --font-heading: var(--font-display); }
:lang(zh) :is(h1, h2, h3, h4, h5, h6, .site-title, .post-navigation .nav-title) { font-variation-settings: "opsz" var(--display-optical); letter-spacing: 0; }
img, video { max-width: 100%; height: auto; }
/* embeds never overflow the column; YouTube videos fill it, their height following the player's 16:9 */
iframe, embed { max-width: 100%; }
iframe[src*="youtube"] { width: 100%; height: auto; aspect-ratio: 16 / 9; }
button, input, select, textarea { font: inherit; }
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.visually-hidden, .screen-reader-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
body:lang(zh) { line-height: 1.75; }
@media (max-width: 60rem) { :root { --gutter: 24px; --section-gap-s: 80px; } }
@media (max-width: 40rem) { :root { --gutter: 16px; --section-gap-s: 56px; } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 0.01ms !important; scroll-behavior: auto !important; } }

.skip { position: absolute; left: var(--space-md); top: calc(-1 * var(--space-3xl)); z-index: var(--z-toast); padding: var(--space-xs) var(--space-md); background: var(--color-ink); color: var(--color-paper); text-decoration-color: currentcolor; }
.skip:focus-visible { top: var(--space-md); }

/* header: the blog's name as the wordmark, the categories on their own row so long Chinese names can wrap */
.site-header { border-bottom: var(--rule-hair) solid var(--color-guide); }
.site-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--space-lg); min-height: 72px; }
.site-title { font-family: var(--font-display); font-weight: var(--display-weight); font-variation-settings: "opsz" var(--display-optical); font-size: var(--text-xl); line-height: 1.2; letter-spacing: var(--tracking-display); }
.site-title a { text-decoration: none; }
.site-owner { display: inline-block; padding-block: var(--space-xs); font-weight: 500; white-space: nowrap; }
.site-nav { border-top: var(--rule-hair) solid var(--color-rule); }
/* the extra 6px at the bottom matches the underline's drop below the baseline, so the gaps above the capitals and below the underlines read equal */
.site-nav .menu { display: flex; flex-wrap: wrap; column-gap: var(--space-lg); row-gap: var(--space-2xs); margin: 0; padding: var(--space-sm) 0 calc(var(--space-sm) + 0.375rem); list-style: none; }
.site-nav a { display: inline-block; padding-block: var(--space-2xs); font-size: var(--text-md); font-weight: 500; }
.site-nav .current-menu-item > a, .site-nav .current-cat > a { text-decoration-thickness: 2px; }

/* lists: the front page, archives and search */
.page-head { display: grid; gap: var(--space-md); padding-block: var(--space-2xl); }
/* trimmed to cap height and baseline so the padding above and below reads equal; 0.2em under the baseline leaves room for descenders */
.page-title { font-size: var(--text-section); text-box: trim-both cap alphabetic; margin-bottom: 0.2em; }
/* the blog name, like the header wordmark, keeps the serif */
.home .page-title { font-family: var(--font-display); font-variation-settings: "opsz" var(--display-optical); font-size: var(--text-display); }
.page-intro { max-width: 60ch; font-size: var(--text-lead); color: var(--color-ink-2); }
.page-intro p + p { margin-top: var(--space-sm); }

.post-list { margin: 0; padding: 0; list-style: none; border-top: var(--rule-hair) solid var(--color-rule-2); }
/* the title, category and excerpt share one cell, so a two-line date block beside a one-line title cannot open a gap under the title */
/* an unbreakable URL in an excerpt would otherwise widen the body's column past the row on phones */
.post-row-body { display: grid; row-gap: var(--space-xs); min-width: 0; overflow-wrap: anywhere; }
.post-row-date { display: grid; gap: var(--space-2xs); align-content: start; font-size: var(--text-md); font-variant-numeric: tabular-nums; color: var(--color-muted); white-space: nowrap; }
.post-row-title { font-size: var(--text-2xl); line-height: 1.2; }
.post-row-title a { text-decoration: none; }
.post-row-title a:hover { text-decoration: underline; text-decoration-color: var(--color-accent); text-decoration-thickness: 2px; text-underline-offset: 0.14em; }
/* the whole row opens the post: the title's link stretches over the row, the category links sit above it, and the hover tint stays within the row's rules */
.post-row { position: relative; isolation: isolate; display: grid; row-gap: var(--space-xs); padding: var(--space-xl) var(--space-md); border-bottom: var(--rule-hair) solid var(--color-rule); }
.post-row::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--color-paper-2); opacity: 0; transition: opacity var(--dur-micro) var(--ease-out); }
.post-row:hover::before { opacity: 1; }
.post-row:has(.post-row-title a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.post-row-title a:focus-visible { outline: none; }
.post-row-title a::after { content: ""; position: absolute; inset: 0; }
.post-row-cats a { position: relative; z-index: 1; color: var(--color-ink); }
.post-row-cats { font-size: var(--text-md); color: var(--color-muted); }
.post-row-excerpt { color: var(--color-ink-2); }
@media (min-width: 60rem) {
  /* rows share the list's columns through subgrid, so the date column is as wide as its widest date in every row */
  .post-list { display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: var(--space-xl); }
  /* the inline padding keeps the hover tint off the text on both sides */
  .post-row { grid-column: 1 / -1; grid-template-columns: subgrid; align-items: baseline; }
  .post-row-date { justify-items: end; text-align: right; }
}

.pagination { padding-block: var(--space-xl) 0; }
.pagination .nav-links { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs); }
.pagination .page-numbers { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; border: var(--rule-hair) solid var(--color-rule-2); text-decoration: none; font-variant-numeric: tabular-nums; transition: background-color var(--dur-micro) var(--ease-out); }
.pagination a.page-numbers:hover { background: var(--color-paper-2); }
.pagination .page-numbers.current { background: var(--color-ink); border-color: var(--color-ink); color: var(--color-paper); }
.pagination .page-numbers.dots { border-color: transparent; }
/* "Previous page" and "Next page" sit at the list's two edges, so the row spans its full width */
.pagination .prev { margin-inline-end: auto; }
.pagination .next { margin-inline-start: auto; }
.pagination :is(.prev, .next) { padding: 0 var(--space-sm); }
/* a phone row fits only "Previous page", the current page and "Next page"; the other numbers wrap it onto several lines */
@media (max-width: 40rem) {
  .pagination .page-numbers:not(.prev):not(.next):not(.current) { display: none; }
  /* phones: the blog name keeps to one line, in the header and as the front page heading; the vinta.ws link gives up its room */
  .site-owner { display: none; }
  .site-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .home .page-title { font-size: 8vw; white-space: nowrap; }
  /* the post titles drop with it, so the 30px heading stays the largest on the page */
  .post-row-title { font-size: 1.5rem; }
  /* archive headings drop their "Category:" or "Tag:" prefix; the name alone fits one line more often */
  .archive-title-prefix { display: none; }
  .page-head { padding-block: var(--space-xl); }
}

.empty { display: grid; gap: var(--space-lg); padding-block: var(--space-xl); }

/* a single post or page */
.entry-header { display: grid; gap: var(--space-md); padding-block: var(--space-2xl) var(--space-xl); border-bottom: var(--rule-hair) solid var(--color-rule-2); }
.entry-title { font-size: var(--text-display-s); }
.entry-meta { display: flex; flex-wrap: wrap; column-gap: var(--space-lg); row-gap: var(--space-2xs); font-size: var(--text-md); color: var(--color-muted); }
.entry-meta time, .entry-meta a { color: var(--color-ink); }

/* the post body fills the container, its text 18px on phones and 20px from tablet width up */
.entry-content { padding-block: var(--space-xl) var(--space-2xl); font-size: clamp(1.125rem, 0.625vw + 0.875rem, 1.25rem); }
.entry-content > * { margin-block: 0 1em; }
.entry-content p:empty { display: none; }
/* posts often use a bare URL as the link text, which would push the page sideways on a phone */
.entry-content a { overflow-wrap: anywhere; }
/* sized from the post text so every level stays above it and at least 4px from its neighbour, at 18px and at 20px */
.entry-content h2 { margin-block: 1.8em 0.6em; padding-bottom: 0.3em; font-size: 1.6em; border-bottom: var(--rule-hair) solid var(--color-rule); }
.entry-content h3 { margin-block: 1.5em 0.5em; font-size: 1.34em; }
.entry-content h4, .entry-content h5, .entry-content h6 { margin-block: 1.4em 0.4em; font-family: var(--font-heading); font-weight: 600; font-size: 1.1em; line-height: 1.4; }
.entry-content > :first-child { margin-top: 0; }
.entry-content ul, .entry-content ol { padding-inline-start: 1.5em; }
.entry-content li + li { margin-top: 0.3em; }
.entry-content li > ul, .entry-content li > ol { margin-block: 0.3em 0; }
.entry-content blockquote { margin-inline: 0; padding-inline-start: 1.2em; border-left: 2px solid var(--color-rule-2); color: var(--color-ink-2); }
.entry-content blockquote > :last-child { margin-bottom: 0; }
.entry-content hr { width: 100%; height: 0; border: 0; border-top: var(--rule-hair) solid var(--color-rule); margin-block: 2em; }
.entry-content img { display: inline-block; vertical-align: middle; }
/* an edge for screenshots whose white meets the paper; WordPress emoji images stay bare */
.entry-content img:not(.emoji) { outline: 1px solid color-mix(in oklab, var(--color-ink) 10%, transparent); outline-offset: -1px; }
.entry-content figure { margin-inline: 0; }
.entry-content figcaption, .entry-content .wp-caption-text { margin-top: var(--space-xs); font-size: var(--text-sm); color: var(--color-muted); }
.entry-content .aligncenter { display: block; margin-inline: auto; }
.entry-content .alignleft { float: left; margin: 0 1.5em 1em 0; }
.entry-content .alignright { float: right; margin: 0 0 1em 1.5em; }
.entry-content table { display: block; overflow-x: auto; border-collapse: collapse; font-size: var(--text-md); }
.entry-content th, .entry-content td { padding: var(--space-xs) var(--space-sm); border: var(--rule-hair) solid var(--color-rule); text-align: left; vertical-align: top; }
.entry-content th { font-weight: 600; background: var(--color-paper-2); }

/* Githuber MD's table of contents: a hairline box on the paper, its numbers in the muted grey */
.entry-content .post-toc-block, .entry-content .post-toc-block.with-border { margin: 0 0 2em; padding: var(--space-lg); background: none; border: var(--rule-hair) solid var(--color-rule-2); border-radius: 0; }
.entry-content .post-toc-header { margin-bottom: var(--space-sm); font-weight: 600; font-size: var(--text-md); color: var(--color-ink); }
.entry-content .md-post-toc { font-size: var(--text-md); line-height: 1.5; }
.entry-content .md-post-toc ol, .entry-content .md-post-toc ul { margin: 0; padding-inline-start: 1.6em; }
.entry-content .md-post-toc li + li, .entry-content .md-post-toc li > ol, .entry-content .md-post-toc li > ul { margin-top: var(--space-2xs); }
.entry-content .md-post-toc li::marker { color: var(--color-muted); font-variant-numeric: tabular-nums; }
.entry-content .md-post-toc a { color: var(--color-ink); }

/* code: Githuber MD prints <pre class="line-numbers"><code class="language-*">; Prism adds the colours */
.entry-content code { font-family: var(--font-mono); font-size: 0.85em; }
.entry-content :not(pre) > code { padding: 0.1em 0.35em; background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); overflow-wrap: anywhere; }
.entry-content pre, .entry-content pre[class*="language-"] { margin-block: 0 1.5em; padding: var(--space-md) var(--space-lg); overflow-x: auto; background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: 0; font-size: 0.875rem; line-height: 1.6; white-space: pre; tab-size: 4; }
/* the code keeps the pre's line height, or Prism's line-number gutter (stepped at the code's line height) drifts from the text */
.entry-content pre code, .entry-content pre code[class*="language-"] { font-size: inherit; line-height: inherit; background: none; border: 0; padding: 0; white-space: inherit; }
.entry-content pre.line-numbers { padding-left: 3.8em; }
/* the fence's language name sits in the block's top right corner, on the block's own paper so it covers a long first line; the top padding is 2px less, the line box's room above the capitals, so the gaps above and beside the letters read equal */
.entry-content pre[data-language] { position: relative; }
.entry-content pre[data-language]::before { content: attr(data-language); position: absolute; top: 0; right: 0; padding: 6px var(--space-xs) var(--space-xs); background: var(--color-paper-2); font: 500 0.75rem/1 var(--font-body); letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-muted); }
.entry-content .line-numbers .line-numbers-rows { border-right-color: var(--color-rule); }
.entry-content .line-numbers-rows > span::before { color: var(--color-muted); }

/* Prism token colours: Prism's own themes (solarizedlight on the code blog) fall to 2.2:1 here, so every colour below holds 4.5:1 on --color-paper-2 */
.entry-content pre code[class*="language-"], .entry-content pre[class*="language-"] { color: var(--color-ink); text-shadow: none; }
/* Prism's theme paints selections in its own dark base colour under the page's ink text */
.entry-content pre[class*="language-"] ::selection, .entry-content pre[class*="language-"]::selection { background: color-mix(in oklab, var(--color-accent) 22%, transparent); }
.entry-content .token.comment, .entry-content .token.prolog, .entry-content .token.doctype, .entry-content .token.cdata { color: var(--color-muted); font-style: italic; }
.entry-content .token.punctuation, .entry-content .token.operator, .entry-content .token.entity, .entry-content .token.url { color: var(--color-ink-2); background: none; }
.entry-content .token.keyword, .entry-content .token.atrule, .entry-content .token.important, .entry-content .token.selector { color: var(--color-accent); }
.entry-content .token.string, .entry-content .token.char, .entry-content .token.attr-value, .entry-content .token.inserted, .entry-content .token.builtin { color: var(--color-code-string); }
.entry-content .token.number, .entry-content .token.boolean, .entry-content .token.constant, .entry-content .token.symbol { color: var(--color-code-number); }
.entry-content .token.function, .entry-content .token.class-name { color: var(--color-code-function); }
.entry-content .token.property, .entry-content .token.tag, .entry-content .token.attr-name, .entry-content .token.deleted { color: var(--color-code-property); }
.entry-content .token.regex, .entry-content .token.variable { color: var(--color-code-variable); }
.entry-content .token.important, .entry-content .token.bold { font-weight: 600; }

.entry-footer { padding-block: var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
.post-navigation { padding-block: var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
.tag-links { font-size: var(--text-md); color: var(--color-muted); }
.tag-links a { color: var(--color-ink); }
.post-navigation .nav-links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-xl); }
.post-navigation .nav-next { grid-column: 2; text-align: right; }
/* the newest and oldest posts have only one neighbour, so its link takes the full width */
.post-navigation .nav-links > :only-child { grid-column: 1 / -1; }
.post-navigation a { display: grid; gap: var(--space-2xs); text-decoration: none; }
.post-navigation .nav-label { font-size: var(--text-md); color: var(--color-muted); }
.post-navigation .nav-title { font-family: var(--font-heading); font-weight: var(--display-weight); font-size: var(--text-xl); line-height: 1.25; letter-spacing: var(--tracking-display); overflow-wrap: break-word; min-width: 0; }
.post-navigation a:hover .nav-title { text-decoration: underline; text-decoration-color: var(--color-accent); text-decoration-thickness: 2px; text-underline-offset: 0.14em; }
@media (max-width: 40rem) {
  .post-navigation .nav-links { grid-template-columns: minmax(0, 1fr); }
  .post-navigation .nav-next { grid-column: 1; }
}

/* search */
.search-form { display: flex; gap: var(--space-xs); max-width: 32rem; }
.search-field { flex: 1; min-width: 0; min-height: 48px; padding: 0 var(--space-sm); background: var(--color-paper); color: var(--color-ink); border: var(--rule-hair) solid var(--color-muted); border-radius: 0; }
.search-field:focus-visible { outline-offset: 0; }
.search-submit { min-height: 48px; padding: 0 var(--space-lg); background: var(--color-ink); color: var(--color-paper); border: var(--rule-hair) solid var(--color-ink); border-radius: 0; font-weight: 500; cursor: pointer; transition: background-color var(--dur-micro) var(--ease-out), scale var(--dur-micro) var(--ease-out); }
.search-submit:hover { background: var(--color-ink-2); }
.search-submit:active { scale: 0.96; }

/* footer: categories, tags and search, then the colophon */
.site-footer { margin-top: var(--section-gap-s); border-top: var(--rule-hair) solid var(--color-rule-2); }
.footer-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr); gap: var(--space-2xl); padding-block: var(--space-2xl); }
.footer-grid:not(:has(.footer-block--tags)) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.footer-head { margin-bottom: var(--space-md); font-family: var(--font-body); font-weight: 600; font-size: var(--text-lg); letter-spacing: 0; line-height: 1.4; }
.footer-links { display: grid; gap: var(--space-2xs); margin: 0; padding: 0; list-style: none; font-size: 1.125rem; }
.footer-links--inline { display: flex; flex-wrap: wrap; column-gap: var(--space-md); row-gap: var(--space-2xs); }
.colophon { padding-block: var(--space-xl); text-align: right; border-top: var(--rule-hair) solid var(--color-rule); font-size: var(--text-md); color: var(--color-muted); }
.colophon a { color: var(--color-ink); }
@media (max-width: 60rem) {
  .footer-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-xl); }
}
