/*
 * greenfield.css — opt-in stylesheet for pages migrated from the
 * blog-base-template prototype. Loaded when a page sets
 * `useGreenfield: true` in frontmatter (see base.njk).
 *
 * Design tokens live in tokens.css (loaded before this file).
 * @font-face declarations duplicate bbs.css's but kept here so this
 * file is self-contained when applied to non-bbs pages later.
 */

/* The [hidden] attribute must always win, even over explicit display rules
   (e.g. .text-feed > li { display: grid }). Without this, JS filters/toggles
   that set element.hidden = true fail to actually hide grid/flex items. */
[hidden] { display: none !important; }

/* --- Fonts (self-hosted IBM Plex) --------------------------------- */
@font-face {
  font-family: 'IBM Plex Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-serif-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Serif';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-serif-latin-400-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Serif';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-serif-latin-600-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-latin-700-normal.woff2') format('woff2');
}

/* --- Visually-hidden utility (accessibility, screen-reader only) - */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Images: responsive ------------------------------------------- */
article img {
  max-width: 100%;
  height: auto;
}

/* Breathing room between the title/meta header and the body content,
   shared by every article page type (posts + pages). Fixes the .lede sitting
   too close to the Updated line, since .lede has no top margin of its own. */
article > header { margin-bottom: 1.5rem; }

/* --- Post meta (date + reading time) ------------------------------ */
article > header > p {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0;
}
article > header > p svg {
  vertical-align: -0.15em;
  margin-right: 0.25em;
  margin-left: 0.5em;
}
article > header > p svg:first-of-type {
  margin-left: 0;
}

/* --- Reply context (u-in-reply-to) ------------------------------- */
.reply-context {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0 0 1.5rem;
}
.reply-context > svg {
  color: var(--color-accent);
  vertical-align: -0.15em;
  margin-right: 0.35em;
}

/* --- Like page (u-like-of) -------------------------------------- */
.like-context {
  font-family: var(--font-mono);
  font-size: var(--text-md);
  color: var(--color-text);
  margin: 0 0 1.5rem;
}
.like-context > svg {
  color: var(--color-accent-warm);
  vertical-align: -0.15em;
  margin-right: 0.35em;
}
.like-meta {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 1.5rem 0 0.25rem;
}
.like-meta > svg {
  vertical-align: -0.15em;
  margin-right: 0.35em;
}
.like-about {
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0;
  max-width: 55ch;
}

/* --- End-of-article separator (3-mark "wind rose") --------------- */
svg[role="separator"] {
  display: block;
  margin: 2.5rem auto;
  width: 2rem;
  height: auto;
  color: var(--color-muted);
}

/* --- Tag nav (post page "filed under" tags) ---------------------- */
nav[aria-label="Tags"] {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 1.5rem 0 0;
}
nav[aria-label="Tags"] > svg {
  font-size: 1.5em;
  color: var(--color-accent);
  vertical-align: -0.25em;
  margin-right: 0.5em;
}
nav[aria-label="Tags"] a {
  color: var(--color-accent);
  text-decoration: none;
  margin-right: 0.6rem;
}
nav[aria-label="Tags"] a::before {
  content: "#";
}
nav[aria-label="Tags"] a:hover {
  color: var(--color-link-hover);
  text-decoration: underline;
}
nav[aria-label="Tags"] a:last-of-type {
  margin-right: 0;
}

/* --- Skip link (uses base.njk's class="skip-link") --------------- */
.skip-link {
  position: absolute;
  top: -3rem;
  left: 0.5rem;
  padding: 0.5rem 1rem;
  background: var(--color-bg-alt);
  color: var(--color-text);
  border: 1px solid var(--color-accent);
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  z-index: 100;
}
.skip-link:focus {
  top: 0.5rem;
}

/* --- Heading reset (headings inherit body unless overridden) ----- */
h1, h2, h3, h4, h5, h6, p {
  margin: 0;
}
h1, h2, h3, h4, h5, h6 {
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
}

/* --- Body baseline ------------------------------------------------ */
body {
  margin: 0 auto;
  max-width: 68ch;
  padding: 2rem 1.25rem 3rem;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--text-md);
  line-height: 1.55;
}
@media (min-width: 700px) {
  body { font-size: var(--text-lg); }
}

p { margin: 0.85rem 0; }

a { color: var(--color-link); }
a:hover { color: var(--color-link-hover); }

/* Base keyboard focus ring for interactive elements. More specific component
   rules (cards, copy-btn, media tiles, form fields) override where they exist. */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

/* --- Headings ----------------------------------------------------- */
h1 {
  font-family: var(--font-body);
  font-size: var(--text-2xl);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0.25rem 0 0.75rem;
}

/* BBS-style section header: `── HEADING ─────────────────` */
h2 {
  font-family: var(--font-mono);
  font-size: var(--text-md);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-accent);
  margin: 2.75rem 0 1rem;
  display: flex;
  align-items: center;
  gap: 0.7em;
}
h2::before { content: "──"; flex: 0 0 auto; }
h2::after {
  content: "";
  flex: 1 1 auto;
  border-top: 1px solid currentColor;
  opacity: 0.35;
}
/* Mobile: drop the leading "──" so headings sit flush-left and reclaim the
   width (a wrapping heading otherwise hangs indented past the dashes). The
   trailing rule still marks each section. */
@media (max-width: 500px) {
  h2::before { content: none; }
}

/* Post-meta-zone h2s (after the article): smaller than content h2s. */
main > article ~ h2 {
  font-size: var(--text-sm);
}

h3 {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: 600;
  line-height: 1.3;
  margin: 0.75rem 0 0.25rem;
}

/* Post body h2: content section header (larger than chrome h2) */
article > div h2 {
  font-size: var(--text-lg);
  letter-spacing: 0.08em;
}

/* Post body code blocks */
article > div pre {
  font-size: var(--text-sm);
  line-height: 1.45;
  margin: 1rem 0;
  overflow-x: auto;
}

/* Post body h3: BBS subsection header, smaller sibling of h2 */
article > div h3 {
  font-family: var(--font-mono);
  font-size: var(--text-md);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-accent-warm);
  margin: 1.75rem 0 0.75rem;
}
article > div h3::before {
  content: "─ ";
}

/* Heading permalink (markdown-it-anchor). Keep the deep-link capability but
   hide the "#" until the heading is hovered or the link is keyboard-focused;
   reserving its slot means revealing it causes no layout shift. On touch
   devices (no hover) it's hidden outright rather than stuck on-screen. */
.heading-anchor {
  color: var(--color-muted);
  text-decoration: none;
  opacity: 0;
  transition: opacity 0.12s ease, color 0.12s ease;
}
:is(h1, h2, h3, h4, h5, h6):hover > .heading-anchor,
.heading-anchor:focus {
  opacity: 1;
}
.heading-anchor:hover { color: var(--color-accent-warm); }
@media (hover: none) {
  .heading-anchor { display: none; }
}

/* --- Site header + BBS-frame brand ------------------------------- */
body > header {
  border-bottom: 1px solid var(--color-rule);
  padding-bottom: 1rem;
  margin-bottom: 2rem;
}
body > header > p {
  margin: 0;
  font-size: var(--text-base);
  font-weight: normal;
  line-height: 1;
  letter-spacing: 0;
}
body > header > p svg {
  display: block;
  width: 100%;
  max-width: 26rem;
  height: auto;
  color: var(--color-accent);
  font-family: var(--font-mono);
  overflow: visible;
}
.brand-frame {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
}
.brand-cutout {
  fill: var(--color-bg);
}
.brand-name {
  font-size: 17px;
  font-weight: 500;
  fill: var(--color-accent-loud);
}
body > header > p svg a { cursor: pointer; }
body > header > p svg a:hover .brand-name,
body > header > p svg a:focus-visible .brand-name {
  text-decoration: underline;
}
.brand-tag {
  font-size: 14px;
  fill: var(--color-muted);
}

/* Condensed header (opt in via `condensedHeader` frontmatter) — slim one-row bar for
   immersive media pages (photos/videos). Reuses the same nav; swaps the SVG box for a wordmark. */
.header-condensed {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1.5rem;
  padding-bottom: 0.6rem;
  margin-bottom: 1.25rem;
}
.header-condensed .brand-mini {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: var(--text-md);
  color: var(--color-accent-loud);
  text-decoration: none;
}
.header-condensed .brand-mini:hover { text-decoration: underline; }
.header-condensed nav[aria-label="Site"] { margin-top: 0; }

/* --- Site nav (top header nav + theme toggle) -------------------- */
nav[aria-label="Site"] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 1.5rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  margin-top: 1rem;
}
nav[aria-label="Site"] .nav-menu {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 1.5rem;
}
nav[aria-label="Site"] ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
nav[aria-label="Site"] a,
nav[aria-label="Site"] button {
  color: var(--color-text);
  text-decoration: none;
  padding: 0.3rem 0;
  border-bottom: 1px dotted transparent;
}
nav[aria-label="Site"] a:hover,
nav[aria-label="Site"] button:hover {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}
nav[aria-label="Site"] button {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  background: transparent;
  border: 0;
  border-bottom: 1px dotted transparent;
  font: inherit;
  cursor: pointer;
  border-radius: 0;
}
nav[aria-label="Site"] kbd {
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
  font-size: inherit;
  color: var(--color-accent-warm);
  font-weight: 700;
}
nav[aria-label="Site"] svg[data-icon] {
  color: var(--color-accent-warm);
  flex: 0 0 auto;
}

/* --- Mobile menu (BBS frame) ------------------------------------- */
/* The toggle is a bracket control ([≡]/[×]) matching the [A]bout motif.
   Hidden on desktop; shown inside the mobile frame. The glyph swaps with
   the button's expanded state. */
nav[aria-label="Site"] .nav-toggle {
  display: none;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--color-accent-warm);
  border-bottom: 0;
}
nav[aria-label="Site"] .nav-toggle:hover {
  color: var(--color-accent-loud);
  border-bottom: 0;
}
.nav-toggle .nav-toggle-close { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle-open { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle-close { display: inline; }

/* Compact wordmark — only shown inside the mobile frame (media query below). */
.brand-compact { display: none; }

@media (max-width: 640px) {
  /* The compact frame wants to sit closer to the top than the desktop brand
     box does, so trim the page's top padding on mobile. */
  body { padding-top: 1.25rem; }
  body > header { position: relative; }

  /* Full header becomes a slim BBS frame: compact wordmark + tagline on the
     left, the bracket menu toggle on the right, all inside the accent border.
     The big SVG brand box is swapped out for the compact wordmark. */
  body > header:not(.header-condensed) {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    border: 1px solid var(--color-accent);
    border-radius: 2px;
    padding: 0.5rem 0.8rem;
    margin-bottom: 2rem;
  }
  body > header:not(.header-condensed) .brand-full { display: none; }

  .brand-compact {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    line-height: 1.2;
    text-decoration: none;
  }
  .brand-compact-name {
    font-family: var(--font-mono);
    font-weight: 600;
    font-size: 1.05rem;
    color: var(--color-accent-loud);
  }
  .brand-compact:hover .brand-compact-name { text-decoration: underline; }
  .brand-compact-tag {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--color-muted);
    white-space: nowrap;
  }

  nav[aria-label="Site"] {
    margin-top: 0;
    position: static;
  }
  nav[aria-label="Site"] .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.75rem;
    min-height: 2.75rem;
    margin-right: -0.4rem;
    padding: 0;
  }

  /* Open menu: a dropdown panel anchored just below the frame. */
  nav[aria-label="Site"] .nav-menu {
    display: none;
    position: absolute;
    top: calc(100% + 0.4rem);
    left: 0;
    right: 0;
    z-index: 50;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.15rem 0.9rem;
    background: var(--color-bg);
    border: 1px solid var(--color-accent);
    border-radius: 2px;
  }
  nav[aria-label="Site"] .nav-menu.is-open { display: flex; }
  nav[aria-label="Site"] .nav-menu ul {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    width: 100%;
  }
  nav[aria-label="Site"] .nav-menu li { width: 100%; }
  /* Each row is a full-width >=44px tap target (Apple HIG minimum), with the
     label vertically centred. */
  nav[aria-label="Site"] .nav-menu a,
  nav[aria-label="Site"] .nav-menu #theme-toggle {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 2.75rem;
    padding: 0.25rem 0;
  }
  /* Separate navigation from the theme control with a deliberate divider
     so the gap reads as intentional, not accidental. */
  nav[aria-label="Site"] .nav-menu #theme-toggle {
    margin-top: 0.3rem;
    border-top: 1px dotted var(--color-rule);
  }
}

/* Theme toggle: show the icon + label for the theme you can SWITCH TO. */
button [data-icon="sun"],
button [data-theme-label="light"] { display: none; }

:root[data-theme="dark"] button [data-icon="moon"],
:root[data-theme="dark"] button [data-theme-label="dark"] { display: none; }
:root[data-theme="dark"] button [data-icon="sun"],
:root[data-theme="dark"] button [data-theme-label="light"] { display: revert; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) button [data-icon="moon"],
  :root:not([data-theme="light"]) button [data-theme-label="dark"] { display: none; }
  :root:not([data-theme="light"]) button [data-icon="sun"],
  :root:not([data-theme="light"]) button [data-theme-label="light"] { display: revert; }
}

/* --- Sections nav (homepage main menu panel) --------------------- */
nav[aria-labelledby] {
  background: var(--color-bg-alt);
  padding: 1rem 1.25rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
nav[aria-labelledby] > ul {
  counter-reset: menu;
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.5rem;
}
nav[aria-labelledby] > ul > li {
  counter-increment: menu;
}
nav[aria-labelledby] a {
  color: var(--color-text);
  text-decoration: none;
  display: inline-block;
  padding: 0.3rem 0;
}
nav[aria-labelledby] a:hover {
  color: var(--color-accent);
}
nav[aria-labelledby] a::before {
  content: "[" counter(menu) "] ";
  color: var(--color-accent-warm);
  font-weight: 700;
}
nav[aria-labelledby] small {
  font-size: inherit;
  color: var(--color-muted);
  margin-left: 0.4rem;
}

/* --- Homepage: Main Menu / Recent Posts side by side ------------- */
/* Menu sits as a narrow rail on the left, recent posts take the wider
   column; both columns share a row height so the "All posts" link can pin
   to the bottom and line up with the menu panel. Collapses to one column on
   narrow screens. */
.home-cols {
  display: grid;
  grid-template-columns: minmax(0, 17rem) minmax(0, 1fr);
  gap: 2.5rem;
  align-items: stretch;
  margin-top: 1.25rem;
}
.home-cols > .home-menu > h2,
.home-cols > section > h2 { margin-top: 0; }
/* In the narrow rail each item's description drops to its own line, so every
   row is a deliberate two-line label + sub-label instead of ragged wrapping. */
.home-cols nav[aria-labelledby] small {
  display: block;
  margin-left: 0;
  margin-top: 0.1rem;
}
.home-cols > section { display: flex; flex-direction: column; }
.home-cols .home-allposts { margin: auto 0 0; text-align: right; }
/* The "All posts" CTA reuses the shared pill chrome + hover (see .react /
   .bubbles-vote / .like-btn); this just gives it its button shape. */
.home-cta {
  /* layout (inline-flex/center/gap) comes from .icon-link; this adds the pill skin */
  padding: 0.45rem 1.05rem;
  font-size: var(--text-sm);
  color: var(--color-accent);
  text-decoration: none;
}
.home-cta > svg { width: 1em; height: 1em; }
@media (max-width: 640px) {
  .home-cols { grid-template-columns: 1fr; gap: 1.75rem; }
}

/* --- Sidebar layout + widget (reusable) -------------------------- */
/* Wide content column + narrow right rail, with an optional full-width-of-the-
   content-column header row above the body. The rail sits on the body row, so
   it aligns with the content beneath the header (e.g. the books tabs) rather
   than the header itself. With no header element, row 1 collapses to zero and
   the rail aligns to the content top — so this degrades to a plain
   content+rail layout. The rail child is FIRST in source so that on mobile
   (single column) it stacks on top; explicit mobile areas pin the order:
   rail (widget) -> header (tabs) -> content. Mirrors the .home-cols breakpoint. */
.with-sidebar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 14rem);
  grid-template-areas:
    "header ."
    "content rail";
  column-gap: 2.5rem;
  row-gap: 1.5rem;
  align-items: start;
  margin-top: 1.5rem;
}
.with-sidebar > .with-sidebar__header { grid-area: header; margin-top: 0; }
.with-sidebar > .with-sidebar__content { grid-area: content; min-width: 0; }
.with-sidebar > aside,
.with-sidebar > .widget { grid-area: rail; }
/* First panel sits flush with the row top so it lines up with the rail widget. */
.with-sidebar__content > .shelf-panel:first-child { margin-top: 0; }
@media (max-width: 640px) {
  .with-sidebar {
    grid-template-columns: 1fr;
    grid-template-areas: "rail" "header" "content";
    row-gap: 1.75rem;
  }
}

/* Boxed sidebar widget: compact card skin for rail content. */
.widget {
  border: 1px solid var(--color-rule);
  border-radius: 0.5rem;
  padding: 1rem 1.1rem 1.15rem;
  background: var(--color-bg-alt);
}
.widget__title {
  margin: 0 0 0.6rem;
  font-size: var(--text-sm);
}
/* The widget's own boxed heading drops the full-width "──/rule" treatment of
   page-level h2s — it just needs a small mono label. */
.widget__title::before,
.widget__title::after { content: none; }

/* --- Archive title feed icon ------------------------------------- */
h1 a[aria-label*="feed"] > svg {
  width: 0.6em;
  height: 0.6em;
  vertical-align: 0.05em;
  margin-left: 0.15em;
}

/* --- Card list (homepage Recent Posts + archives) ---------------- */
.cards {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: 1rem;
}
.cards > li {
  position: relative;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-accent);
  padding: 1rem 1.25rem;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.cards > li:hover {
  border-color: var(--color-link-hover);
  box-shadow: 0 2px 0 var(--color-rule);
  transform: translateY(-1px);
}
.cards > li:hover :is(h2, h3) a {
  color: var(--color-link-hover);
}
.cards > li:has(:focus-visible) {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
.cards > li > :is(h2, h3) {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: normal;
  text-transform: none;
  color: var(--color-text);
  display: block;
  margin: 0;
}
.cards > li > :is(h2, h3)::before,
.cards > li > :is(h2, h3)::after {
  content: none;
}
.cards > li > :is(h2, h3) a {
  color: var(--color-accent);
  text-decoration: none;
}
.cards > li > :is(h2, h3) a::after {
  content: "";
  position: absolute;
  inset: 0;
}
.cards > li > p {
  margin: 0.35rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
.cards > li > p + p {
  margin-top: 0.5rem;
  font-family: var(--font-body);
  color: var(--color-text);
}
.cards > li > p > svg {
  vertical-align: -0.15em;
  margin-right: 0.25em;
}

/* --- Text content feed (posts + links): a stream, not cards ----- */
/* Shared by the text-primary content types. A leading marker
   (markers.<type>.web) is optional; when absent the body spans the row. */
.text-feed {
  list-style: none;
  padding: 0;
  margin: 0;
}
.text-feed > li {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.6rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--color-rule);
}
.text-feed > li:first-child {
  padding-top: 0.25rem;
}
.text-feed > li > .marker {
  grid-column: 1;
  margin-top: 0.3em;          /* nudge onto the serif title's first line */
  font-size: var(--text-md);  /* scale the icon with the title */
  opacity: 0.7;
}
.text-feed__body {
  grid-column: 2;
  min-width: 0;               /* let long titles wrap instead of overflowing */
}
.text-feed > li > .text-feed__body:first-child {
  grid-column: 1 / -1;        /* no marker → span the full row */
}
.text-feed :is(h2, h3) {
  font-family: var(--font-body);
  font-size: var(--text-md);
  font-weight: 600;
  line-height: 1.35;
  margin: 0;
  /* reset the global section-heading styling — these are list-item titles */
  display: block;
  text-transform: none;
  letter-spacing: normal;
  color: var(--color-text);
}
/* These are list-item titles, not section headings — drop the global
   "──"/"─" dash decoration and the trailing rule line. */
.text-feed :is(h2, h3)::before,
.text-feed :is(h2, h3)::after {
  content: none;
}
.text-feed :is(h2, h3) a {
  color: var(--color-link);
  text-decoration: none;
}
.text-feed :is(h2, h3) a:hover {
  color: var(--color-link-hover);
}
.text-feed__meta {
  margin: 0.3rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
.text-feed__meta .meta-icon {
  vertical-align: -0.15em;
  margin-right: 0.3em;
  opacity: 0.8;
}
.text-feed__meta .meta-icon--gap {
  margin-left: 0.85em;       /* space between the date and the reading-time group */
}
.text-feed .p-summary {
  margin: 0.4rem 0 0;
  font-family: var(--font-body);
  font-size: var(--text-base);   /* secondary to the title — was inheriting the larger body size */
  color: var(--color-muted);
  line-height: 1.5;
}

/* Posts register: a touch more air and a slightly larger title than the dense
   links/homepage stream. Add `text-feed--posts` to the <ul>. */
.text-feed--posts > li {
  padding: 1.45rem 0;
}
.text-feed--posts > li:first-child {
  padding-top: 0.25rem;
}
.text-feed--posts :is(h2, h3) {
  font-size: 1.25rem;
}

/* --- Media-object timeline (tag pages: mixed photos/posts/links) -- */
/* A chronological stream where every row shares the same fixed left
   "tile" — a photo thumbnail or a type glyph — so a mix of content
   types reads as one deliberate feed rather than a flattened list. */
.media-feed {
  list-style: none;
  padding: 0;
  margin: 0;
}
.media-feed > li {
  display: grid;
  grid-template-columns: 10rem 1fr;
  column-gap: 1.25rem;
  align-items: start;
  padding: 1rem 0;
  border-bottom: 1px solid var(--color-rule);
}
.media-feed > li:first-child {
  padding-top: 0.25rem;
}
/* The fixed square: holds a thumbnail (photos) or a centered glyph. */
.media-tile {
  grid-column: 1;
  width: 10rem;
  height: 10rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-rule);
  overflow: hidden;
  color: var(--color-accent);
}
.media-tile img,
.media-tile picture {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.media-tile > svg {
  width: 4rem;
  height: 4rem;
  opacity: 0.85;
}
.media-feed > li:has(h2 a:hover) .media-tile {
  border-color: var(--color-link-hover);
}
.media-feed__body {
  grid-column: 2;
  min-width: 0;
}
.media-feed__body > h2 {
  font-family: var(--font-body);
  font-size: var(--text-md);
  font-weight: 600;
  line-height: 1.35;
  margin: 0;
  /* reset the global section-heading styling */
  display: block;
  text-transform: none;
  letter-spacing: normal;
  color: var(--color-text);
}
.media-feed__body > h2::before,
.media-feed__body > h2::after { content: none; }
.media-feed__body > h2 a {
  color: var(--color-link);
  text-decoration: none;
}
.media-feed__body > h2 a:hover {
  color: var(--color-link-hover);
}
.media-feed__meta {
  margin: 0.3rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
.media-feed .p-summary {
  margin: 0.35rem 0 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--color-muted);
  line-height: 1.5;
}

/* --- Media grid: the frameless image/poster/cover grid shared by the photos,
       videos, watch-log and book archives. Tiles get a hairline edge, NOT the
       bordered text-card chrome of .cards. Column sizing and the photo square
       crop are layered per-archive below. --- */
.media-grid {
  list-style: none;
  margin: 1rem 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));
  gap: 0.75rem;
}
/* Videos render as wider YouTube-style cards — 3 across (vs the shared grid's
   ~10rem auto-fill), 2 on tablets, 1 on phones. Scoped to .video-feed so the
   books/watching listings keep the shared grid. */
.media-grid.video-feed { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 760px) { .media-grid.video-feed { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .media-grid.video-feed { grid-template-columns: 1fr; } }
.media-grid > li { margin: 0; }
.media-grid > li > a {
  display: block;
  text-decoration: none;
  color: inherit;
}
.media-grid > li > a img,
.media-grid > li > a picture {
  display: block;
  width: 100%;
  height: auto;
}
.media-grid > li > a img {
  box-sizing: border-box;
  border: 1px solid var(--color-rule);
  background: var(--color-bg-alt);
  transition: filter 0.15s ease;
}
/* Hover/focus is a subtle brightness lift; focus also gets a clear accent ring. */
.media-grid > li > a:hover img,
.media-grid > li > a:focus-visible img { filter: brightness(1.06); }
.media-grid > li > a:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.media-grid > li > p {
  margin: 0.4rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
.media-grid > li > p time { color: inherit; }
.media-grid > li > p strong { color: var(--color-text); font-weight: 600; }

/* Photos + videos: slightly wider tiles, tighter gap. */
.photo-feed {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
  gap: 0.6rem;
}
/* Photos only: square-cropped mosaic so the rows line up. */
.photo-feed-square > li > a img {
  aspect-ratio: 1;
  object-fit: cover;
}

/* Justified photo gallery (Flickr-style): consistent row height, variable width, true aspect,
   ~no crop. --ar = width/height, set per <li> at build via the aspectRatio filter. */
.photo-justified {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  list-style: none;
  padding: 0;
  margin: 1.25rem 0;
}
.photo-justified > li {
  /* Multiply the grow factor so it's always >> 1, keeping the row proportions
     intact while ensuring a lone portrait (aspect ratio < 1) still absorbs all
     the free space and fills the column. A bare var(--ar) leaves sub-1 factors
     short of full width when an item is alone on a row (single-column mobile). */
  flex-grow: calc(var(--ar, 1) * 100);
  flex-basis: calc(var(--ar, 1) * 13rem);
  margin: 0;
  min-width: 0;
}
.photo-justified > li > a { display: block; height: 100%; text-decoration: none; }
.photo-justified picture,
.photo-justified > li img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.photo-justified > li > a:hover img { filter: brightness(1.06); }
.photo-justified::after { content: ""; flex-grow: 999999; }
@media (max-width: 640px) {
  /* In a single column the trailing spacer would keep the last photo from
     filling the width, so drop it. */
  .photo-justified::after { content: none; }
}

/* Photo detail page — back-link matches the videos page; Flickr-style stage with prev/next */
.back-link { font-family: var(--font-mono); font-size: var(--text-sm); margin: 0 0 1rem; }
/* Utility: pair an icon with a text label, vertically centered. Use on any <a>/<button>. */
.icon-link { display: inline-flex; align-items: center; gap: 0.35em; }
.back-link a { color: var(--color-muted); text-decoration: none; }
.back-link a:hover { color: var(--color-link-hover); }
.photo-stage { position: relative; margin: 0.5rem 0 1.25rem; }
.photo-stage figure { margin: 0; }
.photo-stage figure picture { display: block; }
.photo-stage figure img {
  display: block;
  margin: 0 auto;
  max-width: 100%;
  max-height: 75vh;   /* fit within the viewport like Flickr; scales with window height */
  width: auto;
  height: auto;
}
.photo-nav {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  padding: 0 0.75rem;
  color: #fff;
  text-decoration: none;
  opacity: 0.6;
  transition: opacity 0.15s ease;
}
.photo-nav svg {
  width: 2.25rem;
  height: 2.25rem;
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.75));
}
.photo-nav:hover,
.photo-nav:focus-visible { opacity: 1; }
.photo-nav-prev { left: 0; }
.photo-nav-next { right: 0; }
.photo-detail > header { margin-top: 1rem; }
.photo-detail > header h1 { margin-bottom: 0.4rem; }
.photo-meta {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  margin: 0;
}
.photo-meta svg { opacity: 0.85; }
.photo-meta a { color: var(--color-muted); }
.photo-meta a:hover { color: var(--color-link-hover); }

/* --- Video embed (video detail page) ---------------------------- */
.video-embed {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--color-bg-alt);
  margin: 1.5rem 0;
  overflow: hidden;
}
.video-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
/* Self-hosted native <video> fills the same 16/9 stage; contain so portrait
   or oddly-sized clips letterbox instead of cropping. */
.video-embed video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

/* Video-first detail layout: player on top, title + meta below (our voice, not
   YouTube's chrome). Back-link reuses the shared .back-link/.icon-link. */
.video-detail > header { margin-top: 1rem; }
.video-detail > header h1 { margin-bottom: 0.4rem; }
.video-meta {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  margin: 0;
}
.video-meta svg { opacity: 0.85; }
.video-meta a { color: var(--color-muted); }
.video-meta a:hover { color: var(--color-link-hover); }
.video-alt-sources {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.6rem;
  margin: 0.6rem 0 1.4rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.video-alt-sources .video-alt-label { color: var(--color-muted); }
.video-alt-sources .video-alt-link {
  border: 1px solid var(--color-rule);
  border-radius: 4px;
  padding: 0.1rem 0.55rem;
  text-decoration: none;
  color: var(--color-link);
}
.video-alt-sources .video-alt-link::before { content: "\25b8\00a0"; color: var(--color-accent-warm); }
.video-alt-sources .video-alt-link:hover { border-color: var(--color-accent-warm); color: var(--color-link-hover); }

/* --- Star ratings + favorite heart ------------------------------- */
.icon-star,
.icon-star-half { color: var(--color-star); }
.icon-heart { color: var(--color-heart); margin-left: 0.25em; }
[aria-label*="out of 5 stars"] {
  font-size: 1.1rem;
  letter-spacing: 0.05em;
  line-height: 1;
  vertical-align: middle;
}

/* --- Book/watch cover grid (book archives + watch log) ----------- */
/* Poster tiles on the shared .media-grid base; only sizing + the no-cover
   placeholder are book-specific. */
.book-feed {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));
  gap: 1rem;
}
.book-no-cover {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 2 / 3;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-rule);
  padding: 1rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  text-align: center;
  color: var(--color-muted);
}

/* --- Watch log filter/sort controls (progressive enhancement) --- */
.list-controls {
  margin: 0 0 1.5rem;
}
.list-controls > summary {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  width: fit-content;
}
.list-controls[open] > .list-controls__row {
  margin-top: 0.85rem;
}
.list-controls__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: end;
}
.list-controls label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
.list-controls .list-controls__check {
  flex-direction: row;
  align-items: center;
  gap: 0.4rem;
}
.list-controls select,
.list-controls input[type="search"] {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-text);
  background: var(--color-bg-alt);
  border: 1px solid var(--color-accent);
  padding: 0.3rem 0.5rem;
}
.list-controls input[type="search"] {
  min-width: 12rem;
}
.list-controls button {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-accent);
  background: transparent;
  border: 1px solid var(--color-rule);
  padding: 0.35rem 0.75rem;
  cursor: pointer;
}
.list-controls button:hover {
  border-color: var(--color-link-hover);
  color: var(--color-link-hover);
}
.list-controls__count {
  margin: 0.75rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}

/* --- Minimal list (currently reading / want to read) ----------- */
/* Shelves nav: the three reading states as a pill menu (shares the pill chrome
   used by the homepage "All posts" CTA), so it reads as a real menu rather than
   a row of faint links. */
.shelf-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 2.5rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.shelf-nav a {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5ch;
  padding: 0.4rem 0.95rem;
  border: 1px solid var(--color-rule);
  border-radius: 999px;
  color: var(--color-text);
  text-decoration: none;
  transition: border-color 0.12s ease, color 0.12s ease;
}
.shelf-nav a:hover {
  border-color: var(--color-accent-warm);
  color: var(--color-accent-warm);
}
.shelf-nav__count {
  color: var(--color-muted);
}
/* Tab pattern (JS-enhanced): the active tab is filled with the warm accent;
   the count badge inherits so it stays legible on the filled pill. */
.shelf-nav a[role="tab"] {
  cursor: pointer;
}
.shelf-nav a[aria-selected="true"] {
  border-color: var(--color-accent-warm);
  background: var(--color-accent-warm);
  color: var(--color-bg);
}
.shelf-nav a[aria-selected="true"]:hover {
  color: var(--color-bg);
}
.shelf-nav a[aria-selected="true"] .shelf-nav__count {
  color: var(--color-bg);
  opacity: 0.75;
}
.shelf-panel {
  margin-top: 1.5rem;
}
/* The active tab already labels the panel, so tighten the (now somewhat
   redundant) leading heading's default top rhythm inside a panel. */
.shelf-panel > h2.section-major:first-child {
  margin-top: 0.5rem;
}
.shelf-panel:focus {
  outline: none;
}
.shelf-panel:focus-visible {
  outline: 2px solid var(--color-accent-warm);
  outline-offset: 4px;
}

/* Reading-challenge schedule status: quick green/amber read of where you stand. */
.reading-status {
  font-weight: 600;
}
.reading-status--ahead {
  color: var(--color-star); /* the rating-star green — reads as "good" */
}
.reading-status--behind {
  color: var(--color-accent-warm); /* amber — a nudge, not an alarm */
}

/* Reading-challenge progress meter: a two-tone solid block bar + bold percent,
   so it reads as a real bar instead of a thin sliver of text. */
.reading-bar {
  display: flex;
  align-items: center;
  gap: 0.6em;
  margin: 0.5rem 0 0;
  font-family: var(--font-mono);
}
.reading-bar__meter {
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
}
.reading-bar__fill {
  color: var(--color-star); /* the rating-star green */
}
.reading-bar__track {
  color: var(--color-rule);
}
.reading-bar__pct {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text);
}

/* Compact challenge widget body: count line, status line, then the bar. */
.reading-challenge__count {
  margin: 0;
  font-weight: 600;
}
.reading-challenge__status {
  margin: 0.15rem 0 0;
  font-size: var(--text-sm);
}

/* Primary section heading (the main Read log) — a clear step above the
   secondary widget headings (Challenge, Currently Reading) in the row above. */
h2.section-major {
  font-size: var(--text-lg);
  margin-top: 3.25rem;
}

.book-list {
  list-style: none;
  margin: 1rem 0;
  padding: 0;
}
.book-list > li {
  display: flex;
  gap: 0.85rem;
  align-items: center;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--color-rule);
}
.book-list > li:last-child { border-bottom: none; }
.book-list .cover {
  flex: 0 0 auto;
  width: 44px;
  text-decoration: none;
}
.book-list .cover img,
.book-list .cover picture {
  display: block;
  width: 44px;
  height: auto;
  border-radius: 2px;
  background: var(--color-bg-alt);
}
.book-list .cover::after { content: none; }
.book-list .cover .book-no-cover {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 2 / 3;
  width: 44px;
  background: var(--color-bg-alt);
  font-family: var(--font-mono);
  font-size: 0.55rem;
  text-align: center;
  color: var(--color-muted);
  padding: 0.2rem;
}
.book-list .meta { min-width: 0; }
.book-list .meta a.title {
  font-weight: 600;
  text-decoration: none;
  color: var(--color-text);
}
.book-list .meta a.title:hover { color: var(--color-link-hover); }
.book-list .meta a.title::after { content: none; }
.book-list .meta .byline {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
/* Keep a rating from splitting across lines (the narrower in-tab column can
   otherwise break a 5-star run as "★★★" / "★★"). */
.book-list .meta .byline [role="img"] {
  white-space: nowrap;
}

/* --- Book/watch detail page ------------------------------------- */
.book-detail-grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: minmax(0, 200px) 1fr;
  align-items: start;
  margin: 1rem 0 2rem;
}
@media (max-width: 32rem) {
  .book-detail-grid { grid-template-columns: 1fr; }
}
.book-detail-grid .book-cover {
  margin: 0;
  background: var(--color-bg-alt);
}
.book-detail-grid .book-cover img,
.book-detail-grid .book-cover picture {
  display: block;
  width: 100%;
  height: auto;
}
.book-detail-grid .book-info > header h1 {
  margin: 0 0 0.25rem;
}
.book-detail-grid .book-info > header p {
  margin: 0;
  color: var(--color-muted);
}

/* Subdued metadata rows (cert/date/genres/runtime, director credits) */
.book-info .meta {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  line-height: 1.5;
}
.book-info .meta a { color: var(--color-accent); }
.book-info .meta strong { color: var(--color-text); font-weight: 600; }

.book-info .tagline {
  color: var(--color-muted);
  font-size: var(--text-sm);
}

/* Synopsis / overview: serif body font, slightly de-emphasized */
.book-info .overview {
  color: color-mix(in srgb, var(--color-text) 70%, var(--color-muted));
  font-size: var(--text-sm);
  line-height: 1.55;
}

/* External-source attribution (TMDB logo, Open Library / Google Books) */
.book-info .attribution {
  margin-top: 1rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.book-info .attribution img {
  display: inline-block;
  vertical-align: middle;
  height: 0.9rem;
  width: auto;
}

/* Review section meta (date sits like an article header date) */
section[aria-label="Review"] > p {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
section[aria-label="Review"] > p svg {
  vertical-align: -0.15em;
  margin-right: 0.25em;
}

/* --- Breadcrumb -------------------------------------------------- */
nav[aria-label="Breadcrumb"] {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin-bottom: 1rem;
}
nav[aria-label="Breadcrumb"] a {
  color: var(--color-accent);
}
nav[aria-label="Breadcrumb"] svg {
  vertical-align: -0.12em;
  margin-right: 0.3em;
}
nav[aria-label="Breadcrumb"] [aria-current="page"] {
  color: var(--color-text);
}

/* --- Article figure (photo posts, inline article images) --------- */
article > figure,
article .e-content figure {
  margin: 1.5rem 0;
}
article > figure img,
article > figure picture,
article .e-content figure img,
article .e-content figure picture {
  display: block;
  width: 100%;
  height: auto;
}
article > figure figcaption,
article .e-content figcaption {
  margin-top: 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: color-mix(in srgb, var(--color-text) 78%, var(--color-muted));
  text-align: center;
}
/* The place/date metadata line under a photo caption: quieter than the
   commentary above it. Sits on its own line. */
.fig-meta {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.76rem;
  color: var(--color-muted);
  letter-spacing: 0.02em;
}
/* "All posts" link directly below the homepage feed list */
main > section > ul + p {
  margin-top: 1.5rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  text-align: right;
}
main > section > ul + p > a > svg {
  vertical-align: -0.15em;
  margin-left: 0.15em;
}

/* Collapse the Bubbles wrapper until/unless vote.js fills it in. */
.bubbles-wrap:has(.bubbles-vote:empty) { display: none; }

/* --- Code block copy button (JS in base.njk injects it) --------- */
article pre { position: relative; }
.copy-btn {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  background: transparent;
  border: 1px solid transparent;
  color: currentColor;
  padding: 0.25rem;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
  line-height: 0;
}
article pre:hover .copy-btn,
.copy-btn:focus-visible {
  opacity: 0.6;
}
.copy-btn:hover { opacity: 1; }

/* --- Lightbox dialog (JS in base.njk opens it for content images) */
.lightbox {
  border: none;
  padding: 0;
  background: transparent;
  max-width: 95vw;
  max-height: 95vh;
  width: auto;
  height: auto;
}
.lightbox::backdrop { background: rgba(0, 0, 0, 0.9); }
.lightbox img {
  display: block;
  max-width: 95vw;
  max-height: 90vh;
  width: auto;
  height: auto;
}
.lightbox-close {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  background: none;
  border: none;
  color: #fff;
  font-size: 1.5rem;
  cursor: pointer;
  padding: 0.25rem 0.5rem;
  line-height: 1;
  font-family: var(--font-mono);
}
.lightbox-close:hover { opacity: 0.7; }

/* --- Lede paragraph (intro / lead-in prose) --------------------- */
/* A calm lead-in: a step above body text on mobile, level with it on desktop,
   and kept below the h1 size so it doesn't compete with the page title. */
.lede {
  font-size: var(--text-lg);
  line-height: 1.45;
  color: var(--color-text);
  max-width: 60ch;
  margin: 0 0 1.5rem;
}

/* --- Changelog (post footer) ------------------------------------ */
#changelog + ul {
  list-style: none;
  padding: 0;
  margin: 0.75rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
#changelog + ul > li {
  display: grid;
  grid-template-columns: 11ch 1fr;
  gap: 0 1.5rem;
  padding: 0.5rem 0;
  border-bottom: 1px dotted var(--color-rule);
  align-items: baseline;
}
#changelog + ul > li:last-child { border-bottom: none; }
#changelog + ul > li > strong {
  color: var(--color-muted);
  font-weight: 500;
  white-space: nowrap;
}
@media (max-width: 500px) {
  #changelog + ul > li {
    grid-template-columns: 1fr;
    gap: 0.1rem;
  }
}

/* --- Forms (base styles for inputs, selects, textareas, buttons) - */
fieldset {
  border: 1px solid var(--color-rule);
  padding: 1rem 1.25rem;
  margin: 1.25rem 0;
}
legend {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  padding: 0 0.5rem;
}
label {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
input[type="text"],
input[type="email"],
input[type="url"],
input[type="password"],
input[type="search"],
input[type="tel"],
input[type="number"],
input[type="date"],
textarea,
select {
  font-family: var(--font-mono);
  font-size: var(--text-md);
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--color-rule);
  background: var(--color-bg-alt);
  color: var(--color-text);
  border-radius: 0;
  max-width: 100%;
}
textarea {
  min-height: 6rem;
  resize: vertical;
}
input:focus,
textarea:focus,
select:focus {
  outline: 2px solid var(--color-focus);
  outline-offset: 1px;
  border-color: var(--color-accent);
}
input[disabled],
textarea[disabled],
select[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
}
input[readonly],
textarea[readonly] {
  color: var(--color-muted);
}
input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--color-accent);
}
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  padding: 0.5rem 1.25rem;
  border: 1px solid var(--color-rule);
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
  border-radius: 0;
}
button:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
input[type="button"]:hover {
  background: var(--color-bg-alt);
  border-color: var(--color-accent);
  color: var(--color-accent);
}
button[disabled],
input[type="submit"][disabled],
input[type="reset"][disabled],
input[type="button"][disabled] {
  opacity: 0.55;
  cursor: not-allowed;
}

/* --- Footnotes (markdown-it-footnote) --------------------------- */
.footnotes-sep {
  margin: 3rem 0 1.5rem;
  border: 0;
  border-top: 1px solid var(--color-rule);
}
.footnotes {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
.footnotes ol {
  list-style: decimal;
  padding-left: 1.75rem;
  margin: 0.5rem 0;
}
.footnotes li + li { margin-top: 0.5rem; }
.footnotes li p { margin: 0; }
.footnotes a {
  color: var(--color-accent);
  text-decoration: none;
}
.footnotes a:hover {
  color: var(--color-link-hover);
  text-decoration: underline;
}
.footnote-ref a {
  color: var(--color-accent);
  text-decoration: none;
  padding: 0 0.15rem;
}
.footnote-ref a:hover { color: var(--color-link-hover); }
.footnote-backref {
  color: var(--color-accent);
  text-decoration: none;
  margin-left: 0.25rem;
}
.footnote-backref:hover { color: var(--color-link-hover); }

/* --- Update banner / inline callout ----------------------------- */
.update-banner {
  margin: 1.75rem 0;
  padding: 1rem 1.25rem;
  background: var(--color-bg-alt);
  border-left: 3px solid var(--color-accent-warm);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-text);
}
.update-banner p { margin: 0; }
.update-banner p + p { margin-top: 0.5rem; }
.update-banner p:first-child::before {
  content: "";
  display: inline-block;
  width: 1.1em;
  height: 1.1em;
  margin-right: 0.5em;
  vertical-align: -0.2em;
  background-color: var(--color-accent-warm);
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 16v-4'/%3E%3Cpath d='M12 8h.01'/%3E%3C/svg%3E");
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 16v-4'/%3E%3Cpath d='M12 8h.01'/%3E%3C/svg%3E");
  mask-size: contain;
  -webkit-mask-size: contain;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
}
.update-banner strong {
  color: var(--color-accent-warm);
  font-weight: 600;
}
.update-banner a {
  color: var(--color-accent);
  text-decoration: underline;
}
.update-banner a:hover { color: var(--color-link-hover); }

/* --- Blockquote (article body) ---------------------------------- */
.e-content blockquote {
  margin: 1.5rem 0;
  padding: 0.4rem 0 0.4rem 1rem;
  border-left: 3px solid var(--color-accent-warm);
  color: color-mix(in srgb, var(--color-text) 75%, var(--color-muted));
  font-style: italic;
}
.e-content blockquote > :first-child { margin-top: 0; }
.e-content blockquote > :last-child { margin-bottom: 0; }
.e-content blockquote cite {
  display: block;
  margin-top: 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-style: normal;
  color: var(--color-muted);
}
.e-content blockquote cite::before { content: "— "; }

/* --- Tables (article body) -------------------------------------- */
/* Mono + hairline grid, and horizontally scrollable so a wide table can't blow
   out the page width on mobile. display:block + width:max-content is the
   GitHub-style pattern: the grid stays intact, the table scrolls if it's too
   wide for the column, and small tables still size to their content. */
.e-content table {
  display: block;
  width: max-content;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  margin: 1.5rem 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.e-content th,
.e-content td {
  border: 1px solid var(--color-rule);
  padding: 0.4rem 0.65rem;
  text-align: left;
  vertical-align: top;
}
.e-content thead th {
  background: var(--color-bg-alt);
  font-weight: 600;
}

/* --- External link indicator (content body only) ---------------- */
.e-content a[href^="http"]:not([href*="michaelharley.net"]):not(.contact-card)::after,
.like-context a[href^="http"]:not([href*="michaelharley.net"])::after,
.like-about a[href^="http"]:not([href*="michaelharley.net"])::after {
  content: "";
  display: inline-block;
  width: 0.7em;
  height: 0.7em;
  margin-left: 0.15em;
  vertical-align: 0.05em;
  background-color: currentColor;
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 7h10v10'/%3E%3Cpath d='M7 17 17 7'/%3E%3C/svg%3E");
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 7h10v10'/%3E%3Cpath d='M7 17 17 7'/%3E%3C/svg%3E");
  mask-size: contain;
  -webkit-mask-size: contain;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
  opacity: 0.6;
}

/* --- Email obfuscation spam trap --------------------------------- */
.oe { display: none; }

/* --- Sitemap (slash pages directory) ---------------------------- */
.slash-list {
  list-style: none;
  padding: 0;
  margin: 1.5rem 0;
}
.slash-list li {
  display: grid;
  grid-template-columns: 16ch 1fr;
  gap: 0 1.5rem;
  padding: 0.5rem 0;
  border-bottom: 1px dotted var(--color-rule);
  align-items: baseline;
}
.slash-list li:last-child { border-bottom: none; }
.slash-name {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-accent);
  text-decoration: none;
  white-space: nowrap;
}
.slash-name:hover {
  color: var(--color-link-hover);
  text-decoration: underline;
}
.slash-desc {
  color: var(--color-muted);
  font-size: var(--text-sm);
}
@media (max-width: 500px) {
  .slash-list li {
    grid-template-columns: 1fr;
    gap: 0.1rem;
  }
}

/* --- Listening page (Last.fm recent tracks + top artists) -------- */
.recent-tracks {
  list-style: none;
  padding: 0;
  margin: 0.75rem 0;
}
.recent-tracks li {
  display: grid;
  grid-template-columns: 11ch 1fr;
  gap: 0 1.5rem;
  padding: 0.5rem 0;
  border-bottom: 1px dotted var(--color-rule);
  align-items: baseline;
}
.recent-tracks li:last-child { border-bottom: none; }
.recent-tracks time {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  white-space: nowrap;
}
.recent-tracks .artist {
  color: var(--color-muted);
  font-size: var(--text-sm);
  margin-left: 0.5em;
}

.listening-toggle {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1rem 0;
}
.listening-toggle button[aria-selected="true"] {
  background: var(--color-bg-alt);
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.artist-list {
  padding-left: 2.5rem;
  margin: 0.75rem 0;
}
.artist-list li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 1rem;
  padding: 0.5rem 0;
  border-bottom: 1px dotted var(--color-rule);
  align-items: baseline;
}
.artist-list li:last-child { border-bottom: none; }
.artist-list .playcount {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  white-space: nowrap;
}

@media (max-width: 500px) {
  .recent-tracks li {
    grid-template-columns: 1fr;
    gap: 0.1rem;
  }
  .recent-tracks .artist {
    margin-left: 0;
  }
}

/* --- 404 cat ----------------------------------------------------- */
.four-oh-four-cat {
  display: block;
  margin: 1rem auto;
}

/* --- Contact list (contact page) -------------------------------- */
/* Contact cards — each method is a whole-card link; the [E]/[M]/[B] key
   echoes the [A]bout / [1] Books bracket motif, the arrow signals "open". */
.contact-cards {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 1.5rem 0;
  max-width: 34em;
  font-family: var(--font-mono);
}
.contact-card {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--color-rule);
  border-radius: 4px;
  text-decoration: none;
  color: var(--color-text);
}
.contact-card:hover {
  border-color: var(--color-accent);
  background: var(--color-bg-alt);
}
.cc-key {
  flex: 0 0 auto;
  color: var(--color-accent-warm);
  font-weight: 700;
}
.cc-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.cc-name { color: var(--color-text); }
.cc-handle {
  color: var(--color-muted);
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}
.cc-arrow {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  color: var(--color-accent);
  font-size: var(--text-md);
}
@media (max-width: 500px) {
  /* Tighten so the longest handle (@user@instance) fits on one line. */
  .contact-card { gap: 0.6rem; padding: 0.65rem 0.75rem; }
  .cc-handle { font-size: var(--text-xs); }
}

/* --- Subscribe form (subscribe-email page) --------------------- */
.subscribe-form {
  margin: 1.5rem 0;
  max-width: 32em;
  background: var(--color-bg-alt);
  padding: 1.25rem;
}
.subscribe-field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 1rem;
}
/* In-panel overrides: input bg + button-hover bg use page color so they
   pop from the surrounding bg-alt panel (base values would blend). */
.subscribe-form input { background: var(--color-bg); }
.subscribe-form button:hover { background: var(--color-bg); }
.subscribe-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
/* Email + RSS live in one panel, each an input-then-button row. */
.sub-block { margin-bottom: 1.5rem; }
.sub-block:last-child { margin-bottom: 0; }
.sub-block h2 { margin-top: 0; }
.sub-block p { margin: 0.25rem 0 0.75rem; }
.sub-row {
  display: grid;
  /* Fixed button column so Subscribe + Copy (and their input/url fields) line
     up across both rows. */
  grid-template-columns: 1fr 10rem;
  gap: 0.5rem;
  align-items: stretch;
}
.sub-row input { min-width: 0; width: 100%; box-sizing: border-box; }
.sub-row button { margin-top: 0; white-space: nowrap; box-sizing: border-box; }
/* Read-only URL shown as a styled box (a code element shrinks where a form
   control's intrinsic width would not). */
.sub-url {
  min-width: 0;
  overflow-x: auto;
  white-space: nowrap;
  display: flex;
  align-items: center;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--color-rule);
  background: var(--color-bg);
  color: var(--color-muted);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  box-sizing: border-box;
}

/* --- Webmention-send AJAX status (JS in base.njk inserts this) -- */
.wm-send-status {
  margin: 0.75rem 0 0;
  padding: 0.6rem 0.8rem;
  background: var(--color-bg);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  border-left: 3px solid var(--color-accent);
}
.wm-send-status.wm-send-error { border-left-color: var(--color-accent-loud); }
.wm-send-status strong {
  color: var(--color-accent-warm);
  margin-right: 0.3em;
}

/* --- Meta-zone panels (Signal, Comments) ------------------------- */
section[aria-labelledby] {
  margin: 0.5rem 0 1rem;
  background: var(--color-bg-alt);
  padding: 1rem 1.25rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  display: grid;
  gap: 0.5rem;
}

/* --- Signal facepile (likes / boosts / mentions) ---------------- */
.wm-faces {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.wm-faces li {
  margin: 0;
  padding: 0;
}
.wm-faces img {
  display: block;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
}
.wm-no-photo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-bg-alt);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: bold;
  color: var(--color-muted);
}
.wm-name-list {
  list-style: none;
  padding: 0;
  margin: 0.35rem 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.wm-name-list li {
  margin: 0 0 0.15rem;
}

/* --- Webmention-send form (panel chrome details) ----------------- */
main > details {
  margin: 0.5rem 0 1rem;
  background: var(--color-bg-alt);
  padding: 1rem 1.25rem;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}

/* --- Shared details marker treatment (BBS [+]/[-]) --------------- */
details > summary {
  cursor: pointer;
  color: var(--color-text);
  list-style: none;
  padding: 0.2rem 0;
}
details > summary::-webkit-details-marker { display: none; }
details > summary::before {
  content: "[+] ";
  color: var(--color-accent-warm);
  font-weight: 700;
}
details[open] > summary::before {
  content: "[-] ";
}
details > summary:hover {
  color: var(--color-accent);
}

/* --- Comments article (Signal/Comments section content) ---------- */
section[aria-labelledby] > article > p:first-child {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0 0 0.5rem;
  line-height: 1.6;
}
section[aria-labelledby] > article > p:last-child {
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--color-text);
  margin: 0;
}
section[aria-labelledby] > article + article {
  margin-top: 1.5rem;
  border-top: 1px solid var(--color-rule);
  padding-top: 1.5rem;
}
main > details > form {
  margin-top: 0.75rem;
  padding-left: 2ch;
  display: grid;
  gap: 0.75rem;
}
main > details > form > p {
  color: var(--color-muted);
  margin: 0;
}
main > details > form > label {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  color: var(--color-muted);
}
main > details > form input[type="url"] {
  font: inherit;
  font-size: var(--text-base);
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--color-accent);
  background: var(--color-bg-alt);
  color: var(--color-text);
  max-width: 32em;
}
main > details > form input[type="url"]:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
main > details > form button {
  font: inherit;
  padding: 0.5rem 1.25rem;
  border: 1px solid var(--color-accent);
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
  justify-self: start;
}
main > details > form button:hover {
  background: var(--color-bg);
  border-color: var(--color-accent-loud);
  color: var(--color-accent-loud);
}

/* --- Footer ------------------------------------------------------- */
footer {
  margin-top: 3.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-rule);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-muted);
}
footer p {
  margin: 0.35rem 0;
}
footer a {
  color: inherit;
  text-decoration: none;
}
footer a:hover {
  color: var(--color-accent);
}
footer nav ul {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.5rem;
}
/* Taller hit area for the footer nav links (touch target). */
footer nav a {
  display: inline-block;
  padding: 0.3rem 0;
}
footer nav svg {
  vertical-align: -0.15em;
  margin-right: 0.25em;
}

/* ===== Unified conversation footer ============================== */
/* Reactions render in one horizontal bar, by type, regardless of   */
/* whether the signal came from the site, a webmention, or bubbles. */
.reactions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}

/* Pill chrome shared by all three reaction controls: the native like button,
   the facepile expanders, and the bubbles link. Each sets its own display,
   padding and font-size below. */
.react,
.bubbles-vote,
.like-btn,
.home-cta {
  background: var(--color-bg);
  border: 1px solid var(--color-rule);
  border-radius: 999px;
  font-family: var(--font-mono);
  color: var(--color-text);
  transition: border-color 0.12s ease, color 0.12s ease;
}
/* One shared hover/active treatment for all three pills: the amber engagement
   accent (matching the [+] markers, the signal icons and the bubbles chip). */
.react:hover,
.bubbles-vote:hover,
.like-btn:hover,
.like-btn[aria-pressed="true"],
.home-cta:hover {
  border-color: var(--color-accent-warm);
  color: var(--color-accent-warm);
}
/* The facepile summary has its own colour (and the global details:hover tints
   it cyan), so steer it to the same amber on hover. */
.react:hover > summary { color: var(--color-accent-warm); }
/* Facepile expander — a <details> whose <summary> fills the whole pill, so the
   entire row toggles (matching the bubbles link). The padding lives on the
   summary (the click target), not the pill, so clicking anywhere toggles. */
.react {
  display: block;
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.4;
}
.react > summary {
  list-style: none;
  cursor: pointer;
  color: var(--color-text);
  padding: 0.3rem 0.6rem;
  transition: color 0.12s ease;
}
.react > summary::-webkit-details-marker { display: none; }
.react[open] { border-radius: 0.75rem; }
.react[open] > summary { padding-bottom: 0.2rem; }
/* When open, the avatars align under the summary text and carry the pill's
   bottom padding (the pill itself has none now). */
.react .wm-faces,
.react .wm-name-list {
  margin-top: 0;
  padding: 0 0.6rem 0.4rem;
}

/* Like control — the button is also the count display. */
/* Native "like this post" button — its own control under the post tags. */
.post-like { margin: 1.75rem 0 1.25rem; }

/* bubbles.town upvote — a score chip + CTA link; pill chrome shared above. */
.bubbles-vote {
  display: inline-block;
  padding: 0.3rem 0.6rem;
  font-size: var(--text-sm);
  text-decoration: none;
}
/* Amber upvote arrow, then "15 ▲ on Bubbles" + the 🫧. Spacing is plain mono
   whitespace between the inline elements — no flex gaps, no alignment margins.
   The arrow is padded out to a 3ch box (the width of the "[+]" markers on the
   facepile rows) with the glyph centred, so it lands under the "+" and the
   trailing mono space carries the count into the facepile number column. */
.bubbles-vote .bubbles-arw { width: 0.95em; height: 0.95em; box-sizing: content-box; padding: 0 calc((3ch - 0.95em) / 2); vertical-align: -0.14em; fill: none; stroke: var(--color-accent-warm); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.bubbles-vote .bubbles-count { font-variant-numeric: tabular-nums; }
.bubbles-vote .bubbles-bub { line-height: 1; }
/* Type-icon trailing each facepile summary, separated by a plain mono space.
   Tinted amber to match the [+] markers (the site's signal accent). */
.react > summary svg.sig-ico { width: 0.95em; height: 0.95em; vertical-align: -0.14em; stroke: var(--color-accent-warm); }
.like-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.4rem 0.9rem;
  font-size: var(--text-base);
  /* Filled rather than relying on the hairline border, so it reads as a control
     in both the warm-paper light theme and dark. */
  background: var(--color-bg-alt);
  cursor: pointer;
}
/* The thumb is a small trailing accent (matching the Signal rows' sig-icons),
   not a leading glyph — keeps the button in the site's mono/bracket voice. */
.like-btn .sig-ico { width: 0.95em; height: 0.95em; fill: none; stroke: var(--color-accent-warm); vertical-align: -0.06em; }
/* Hover + pressed colours come from the shared pill rule above; once liked,
   the thumb fills with the current (amber) colour. */
.like-btn[aria-pressed="true"] svg { fill: currentColor; }
.like-count { font-variant-numeric: tabular-nums; }

/* Comments — merged native + webmention thread. */
.comments { gap: 1rem; }
.comment {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
}
.comment-avatar img,
.comment-avatar .wm-no-photo {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.comment-body { flex: 1; min-width: 0; }
.comment-meta {
  margin: 0 0 0.25rem;
  font-size: var(--text-xs);
  color: var(--color-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0.4em;
  align-items: baseline;
}
.comment-name { font-weight: bold; color: var(--color-text); }
a.comment-name { color: var(--color-link); }
.comment-via { color: var(--color-muted); }
.comment-content { font-size: var(--text-sm); }
.comment-content :first-child { margin-top: 0; }
.comment-content :last-child { margin-bottom: 0; }
/* Quoted text in comments — same language as post blockquotes, scaled down. */
.comment-content blockquote {
  margin: 0.5rem 0;
  padding: 0.1rem 0 0.1rem 0.75rem;
  border-left: 2px solid var(--color-accent-warm);
  color: color-mix(in srgb, var(--color-text) 70%, var(--color-muted));
  font-style: italic;
}
.comment-content blockquote > :first-child { margin-top: 0; }
.comment-content blockquote > :last-child { margin-bottom: 0; }

/* Comment form. */
/* Both conversation forms (comment + webmention) share one compact style. */
.comment-form,
.wm-send-form { display: grid; gap: 0.6rem; }
.comment-form label,
.wm-send-form label { display: grid; gap: 0.25rem; }
.comment-form input,
.comment-form textarea,
.wm-send-form input,
.wm-send-form textarea {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  padding: 0.4rem 0.5rem;
  background: var(--color-bg);
  border: 1px solid var(--color-rule);
  color: var(--color-text);
}
.comment-form textarea,
.wm-send-form textarea { resize: vertical; }
/* Keep both submit buttons left-aligned at their natural width, not stretched
   across the grid. */
.comment-form button,
.wm-send-form button { justify-self: start; }
.form-intro { margin: 0 0 0.25rem; color: var(--color-muted); }
.form-hint { color: var(--color-muted); font-weight: normal; }
.req { color: var(--color-accent-loud); }

/* Conversation menu — BBS-style: numbered direct channels, [+] form toggles. */
.convo-menu {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: convo;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.convo-menu > li { margin: 0; }
.convo-menu > li.menu-link {
  counter-increment: convo;
}
/* Match the site-nav pattern: no persistent underline (which would run under
   the [n] key too); the underline is a hover-only dotted border instead. */
.convo-menu > li.menu-link > a {
  color: var(--color-link);
  text-decoration: none;
  border-bottom: 1px dotted transparent;
  display: inline-block;
  padding: 0.3rem 0;
}
.convo-menu > li.menu-link > a:hover {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}
.convo-menu > li.menu-link > a::before {
  content: "[" counter(convo) "] ";
  color: var(--color-accent-warm);
  font-weight: 700;
}
/* When a form is expanded, give it breathing room before the next menu row. */
.convo-menu .menu-form details[open] { margin-bottom: 1.25rem; }

/* Honeypot — visually and assistively hidden, but present for bots. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* === Doxipedia landing (Power Platform knowledge-base hub) ========= */
.dox-hero {
  position: relative;
  border: 1px solid var(--color-text);
  background: var(--color-bg-alt);
  padding: 1.5rem 1.6rem 1.25rem;
  margin: 0 0 1.4rem;
}
.dox-hero::after {
  content: "";
  position: absolute;
  inset: 4px;
  border: 1px solid var(--color-rule);
  pointer-events: none;
}
.dox-hero__label {
  position: absolute;
  top: -0.62rem;
  left: 1.3rem;
  background: var(--color-bg);
  padding: 0 0.5rem;
  font-size: var(--text-xs);
  letter-spacing: 0.2em;
  color: var(--color-accent-warm);
  font-weight: 600;
}
.dox-hero h1 {
  display: block;
  font-size: 2.3rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  line-height: 1;
  margin: 0;
}
.dox-hero h1::before,
.dox-hero h1::after { content: none; }
.dox-hero__tag {
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0.75rem 0 0;
}
.dox-lede { max-width: 64ch; margin: 0 0 1rem; }
.dox-prompt {
  font-size: var(--text-sm);
  color: var(--color-muted);
  letter-spacing: 0.03em;
  margin: 0 0 0.9rem;
}
.dox-prompt b { color: var(--color-accent); font-weight: 600; }
.dox-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.9rem;
}
@media (max-width: 640px) { .dox-grid { grid-template-columns: 1fr; } }
.dox-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-rule);
  background: var(--color-bg-alt);
  padding: 0.95rem 1rem 0.9rem;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.dox-card:hover,
.dox-card:focus-within {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}
.dox-card__top { display: flex; align-items: baseline; gap: 0.55rem; }
.dox-key {
  flex: 0 0 auto;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--color-bg);
  background: var(--color-text);
  padding: 0.05rem 0.4rem;
  letter-spacing: 0.05em;
}
.dox-card h2 {
  display: inline;
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin: 0;
}
.dox-card h2::before,
.dox-card h2::after { content: none; }
.dox-count {
  margin-left: auto;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-accent-warm);
  white-space: nowrap;
}
.dox-rule { border: 0; border-top: 1px solid var(--color-rule); margin: 0.55rem 0; }
.dox-desc { font-size: var(--text-sm); color: var(--color-muted); margin: 0 0 0.65rem; }
.dox-items { list-style: none; padding: 0; margin: 0; flex: 1; font-size: var(--text-sm); }
.dox-items li { padding: 0.1rem 0; }
.dox-items a { text-decoration: none; color: var(--color-text); }
.dox-items a::before { content: "\203a\00a0"; color: var(--color-accent); font-weight: 700; }
.dox-items a:hover { color: var(--color-accent); text-decoration: underline; }
.dox-card__foot { margin: 0.7rem 0 0; font-size: var(--text-xs); color: var(--color-muted); }
.dox-card__foot b { color: var(--color-accent); font-weight: 500; }
.dox-card--about { border-style: dashed; }
.dox-card--about .dox-key { background: var(--color-accent-warm); }
.dox-card--about p { font-size: var(--text-sm); color: var(--color-muted); line-height: 1.5; margin: 0 0 0.5rem; }
.dox-card--about a { color: var(--color-accent); }

/* === Doxipedia reference pages (naming conventions, recipes) ======= */
.docref-crumb { font-size: var(--text-sm); color: var(--color-muted); letter-spacing: 0.03em; margin-bottom: 1.1rem; }
.docref-crumb a { color: var(--color-muted); }
.docref-eyebrow { font-size: var(--text-xs); letter-spacing: 0.2em; color: var(--color-accent-warm); font-weight: 600; margin: 0 0 0.5rem; }
.docref-epi {
  font-family: var(--font-body); font-style: italic; font-size: var(--text-md); color: var(--color-text);
  border-left: 2px solid var(--color-accent-warm); padding: 0.25rem 0 0.25rem 1rem; margin: 1.2rem 0 0.4rem;
}
.docref-epi cite { display: block; font-style: normal; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-muted); margin-top: 0.4rem; }
.docref-toc {
  display: flex; flex-wrap: wrap; gap: 0.45rem; align-items: center; margin: 1.4rem 0 0.5rem;
  padding: 0.8rem 0; border-top: 1px solid var(--color-rule); border-bottom: 1px solid var(--color-rule);
}
.docref-toc > span { font-size: var(--text-xs); color: var(--color-muted); letter-spacing: 0.04em; margin-right: 0.25rem; }
.docref-toc a { font-size: var(--text-sm); text-decoration: none; color: var(--color-text); border: 1px solid var(--color-rule); padding: 0.15rem 0.6rem; background: var(--color-bg-alt); }
.docref-toc a:hover { border-color: var(--color-accent); color: var(--color-accent); }
.docref-kicker { font-size: var(--text-xs); letter-spacing: 0.16em; text-transform: uppercase; color: var(--color-muted); margin: 1.1rem 0 0.5rem; }
.docref-pattern { display: inline-block; font-size: var(--text-md); background: var(--color-bg-alt); border: 1px solid var(--color-rule); padding: 0.5rem 0.85rem; margin-bottom: 1rem; }
.docref-pattern .ph { color: var(--color-accent); }
.docref-pattern .ph-b { color: var(--color-accent-warm); }
.docref-pattern .sep { color: var(--color-muted); }
.docref-anat { display: flex; flex-wrap: wrap; align-items: flex-start; font-size: 1.55rem; font-weight: 600; margin: 0.4rem 0; }
.docref-seg { display: flex; flex-direction: column; align-items: center; }
.docref-seg .lab { font-size: 0.62rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; margin-top: 0.55rem; padding-top: 0.4rem; border-top: 1.5px solid currentColor; width: 100%; text-align: center; line-height: 1.3; }
.docref-seg.is-type .tok, .docref-seg.is-type .lab { color: var(--color-accent); }
.docref-seg.is-desc .tok { color: var(--color-text); }
.docref-seg.is-desc .lab { color: var(--color-muted); border-color: var(--color-rule); }
.docref-seg.is-scope .tok, .docref-seg.is-scope .lab { color: var(--color-accent-warm); }
.docref-usep { color: var(--color-muted); font-weight: 400; padding: 0 0.12rem; align-self: flex-start; }
.docref-gloss { font-size: var(--text-sm); color: var(--color-muted); margin: 0 0 0.3rem; }
.docref-gloss b { color: var(--color-text); font-weight: 500; }
.docref-abbr { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1px; background: var(--color-rule); border: 1px solid var(--color-rule); margin: 0.3rem 0 0.5rem; }
.docref-abbr div { background: var(--color-bg-alt); padding: 0.35rem 0.6rem; font-size: var(--text-sm); display: flex; gap: 0.5rem; align-items: baseline; }
.docref-abbr b { color: var(--color-accent); font-weight: 700; min-width: 2rem; }
.docref-abbr span { color: var(--color-muted); }
.docref-examples { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.3rem 0 0.5rem; }
.docref-examples span { font-size: var(--text-sm); background: var(--color-bg-alt); border: 1px solid var(--color-rule); padding: 0.2rem 0.6rem; }
.docref-foot { margin-top: 2.4rem; font-size: var(--text-xs); color: var(--color-muted); border-top: 1px dashed var(--color-rule); padding-top: 0.8rem; }
.docref-note { font-size: var(--text-sm); color: var(--color-muted); background: var(--color-bg-alt); border-left: 2px solid var(--color-accent); padding: 0.6rem 0.9rem; margin: 1rem 0 1.4rem; }
.docref-note b, .docref-note code { color: var(--color-text); }
.docref-abbr--wide { grid-template-columns: repeat(auto-fill, minmax(255px, 1fr)); }
.docref-abbr--wide div { display: block; }
.docref-abbr--wide b { display: inline-block; margin-right: 0.25rem; }
.docref-vargrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(225px, 1fr)); gap: 0.7rem; margin: 0.4rem 0 1.1rem; }
.docref-vargrid > div { border: 1px solid var(--color-rule); background: var(--color-bg-alt); padding: 0.7rem 0.85rem; }
.docref-vargrid b { display: block; color: var(--color-accent); font-weight: 700; font-size: var(--text-md); }
.docref-vargrid p { font-size: var(--text-sm); color: var(--color-muted); margin: 0.3rem 0 0; }
.docref-vargrid code { color: var(--color-accent-warm); }
.docref-fix { display: flex; flex-direction: column; gap: 0.5rem; margin: 0.5rem 0 0.6rem; }
.docref-fix > div { border: 1px solid var(--color-rule); background: var(--color-bg-alt); padding: 0.6rem 0.85rem; }
.docref-fix .swap { font-size: var(--text-md); }
.docref-fix .dep { color: var(--color-accent-loud); text-decoration: line-through; }
.docref-fix .can { color: var(--color-accent); font-weight: 600; }
.docref-fix .arrow { color: var(--color-muted); padding: 0 0.4rem; }
.docref-fix p { font-size: var(--text-sm); color: var(--color-muted); margin: 0.35rem 0 0; }
.docref-sub { font-size: var(--text-md); font-weight: 600; color: var(--color-text); margin: 1.4rem 0 0.6rem; }
.docref-sub::before { content: "\2500\00a0"; color: var(--color-rule); }
.docref-body p { max-width: 68ch; }
.docref-body ul { max-width: 68ch; }
