:root {
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-serif: 'Source Serif 4', Georgia, 'Times New Roman', serif;

  --fg: #1a1a1a;
  --bg: #fdfdfb;
  --muted: #6b6b6b;
  --muted-light: #928f89;
  --accent: #a3402f;
  --border: #e4e0da;

  /* Reference only — topic-title-glitch.js holds the source of truth and
     sets colors directly. Hues measured from public/images/ancient-lakes-2019.jpg
     (the why page photo), tuned to a consistent vividness. */
  --glitch-rust: #ae6a29;
  --glitch-mustard: #ae8f29;
  --glitch-olive: #a2ae29;
  --glitch-sky: #296fae;
  --glitch-mauve: #ae293d;

  /* Baseline grid: every spacing, margin, and leading value below is a
     multiple of this unit. */
  --grid-unit: 8px;

  /* Modular type scale — Perfect Fourth (1.333), base 16px. No font-size
     anywhere in this file should use a value outside this set. */
  --scale-small: 0.75rem;     /* 12px — metadata, timestamps, captions */
  --scale-body: 1rem;         /* 16px — paragraph text */
  --scale-h3: 1.3125rem;      /* 21px — sub-headers */
  --scale-h2: 1.75rem;        /* 28px — section headers */
  --scale-h1: 2.375rem;       /* 38px — post titles */
  --scale-display: 3.125rem;  /* 50px — homepage/hero only */

  /* Leading, grid-locked to the nearest 8px multiple for each scale step */
  --leading-small: 16px;    /* 12px type, ~1.4x */
  --leading-body: 24px;     /* 16px type, 1.5x */
  --leading-h3: 24px;       /* 21px type, ~1.15x */
  --leading-h2: 32px;       /* 28px type, ~1.15x */
  --leading-h1: 48px;       /* 38px type, ~1.25x */
  --leading-display: 56px;  /* 50px type, ~1.12x */

  /* 8px spacing scale */
  --space-1: 0.5rem;   /* 8px */
  --space-2: 1rem;     /* 16px */
  --space-3: 1.5rem;   /* 24px */
  --space-4: 2rem;     /* 32px */
  --space-5: 3rem;     /* 48px */
  --space-6: 4rem;     /* 64px */
  --space-7: 6rem;     /* 96px */

  /* Paragraph breaks read as a new block, not "one extra line". Originally
     2x body leading (48px); tightened ~15% to 40px (still a clean 5x8px
     grid step) since 48px read as too much air between paragraphs. */
  --paragraph-gap: 1.25rem; /* 20px */
}

@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Variable.ttf') format('truetype-variations'),
       url('/fonts/Inter-Variable.ttf') format('truetype');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Source Serif 4';
  src: url('/fonts/SourceSerif4-Variable.ttf') format('truetype-variations'),
       url('/fonts/SourceSerif4-Variable.ttf') format('truetype');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

* { box-sizing: border-box; }

body {
  font-family: var(--font-serif);
  font-size: var(--scale-body);
  font-weight: 400;
  line-height: var(--leading-body);
  color: var(--fg);
  background: var(--bg);
  max-width: 760px;
  margin: 0 auto;
  padding: 0 var(--space-3) var(--space-7);
}

/* ---- Navigation: quiet, understated ---- */
.site-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-6);
  font-family: var(--font-sans);
}

.brand-block { display: flex; flex-direction: column; gap: 0; }

.brand-row { display: flex; align-items: center; gap: var(--space-1); }
/* Decorative -- the adjacent .brand text link is the real "go home"
   control, this just gives the icon a matching hit target without a
   second, redundant tab stop (see aria-hidden/tabindex in _header.ejs). */
.brand-icon-link { display: block; line-height: 0; }
.brand-icon { width: 36px; height: 36px; display: block; }

.brand {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--scale-h3);
  line-height: var(--leading-h3);
  text-decoration: none;
  color: var(--fg);
  letter-spacing: -0.01em;
}

.brand-why {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  line-height: var(--leading-small);
  text-decoration: none;
  color: var(--muted);
  letter-spacing: 0.01em;
}
.brand-why:hover { color: var(--fg); }

.nav-menu { position: relative; display: flex; align-items: center; gap: var(--space-2); }

.hamburger-btn {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  width: 16px;
  height: 16px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}
.hamburger-bar { display: block; width: 100%; height: 2px; background: var(--fg); }
.hamburger-btn:hover .hamburger-bar { background: var(--muted); }
@media (hover: none), (pointer: coarse) {
  .hamburger-btn { width: 24px; height: 24px; }
}

.who {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  font-weight: 500;
  line-height: var(--leading-small);
  color: var(--muted);
  letter-spacing: 0.02em;
}

.nav-menu-dropdown {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 0;
  min-width: 184px;
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  z-index: 20;
  display: flex;
  flex-direction: column;
  padding: var(--space-1) 0;
}
.nav-menu-dropdown[hidden] { display: none; }
.nav-menu-form { margin: 0; }
.nav-menu-item {
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  font-weight: 600;
  line-height: var(--leading-small);
  letter-spacing: 0.02em;
  color: var(--fg);
  text-decoration: none;
  background: none;
  border: none;
  text-align: left;
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  appearance: none;
}
.nav-menu-item:hover { background: var(--border); }
@media (hover: none), (pointer: coarse) {
  .nav-menu-item { padding: var(--space-2) var(--space-3); }
}

/* ---- Headings ---- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-sans);
  color: var(--fg);
  margin: 0;
}

.page-title {
  font-size: var(--scale-h1);
  font-weight: 700;
  line-height: var(--leading-h1);
  letter-spacing: -0.03em;
  margin-bottom: var(--space-2);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.entry-subtitle {
  font-family: var(--font-sans);
  font-size: var(--scale-h2);
  line-height: var(--leading-h2);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-top: var(--space-2);
}

/* ---- Buttons ---- */
button {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--scale-small);
  line-height: var(--leading-small);
}

button[type=submit], .back-link {
  padding: var(--space-1) var(--space-2);
  border: none;
  border-radius: 0;
  background: var(--fg);
  color: #fff;
  cursor: pointer;
}
button[type=submit]:hover, .back-link:hover { background: var(--muted); }

/* Fingers are less precise than a mouse cursor — give tappable buttons more room */
@media (hover: none), (pointer: coarse) {
  button[type=submit], .back-link { padding: var(--space-2); }
}

.back-link {
  display: inline-block;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--scale-small);
  line-height: var(--leading-small);
  text-decoration: none;
}
.back-link:hover { color: #fff; }

/* ---- Metadata / labels ---- */
.date {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--scale-small);
  line-height: var(--leading-small);
  letter-spacing: 0.03em;
  color: var(--muted-light);
  display: block;
}

.excerpt {
  font-family: var(--font-serif);
  font-size: var(--scale-body);
  line-height: var(--leading-body);
  color: var(--muted);
  margin: 0;
}

/* ---- Manage invites ---- */
.section-title {
  font-size: var(--scale-h3);
  line-height: var(--leading-h3);
  font-weight: 650;
  margin: var(--space-6) 0 var(--space-3);
}
.invite-list { list-style: none; padding: 0; margin: var(--space-3) 0 0; }
.invite-list li { margin-bottom: var(--space-4); }
.invite-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.invite-item-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
}
.invitee-name { font-family: var(--font-sans); font-weight: 600; }
.invitee-name-input {
  width: auto;
  max-width: 220px;
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--scale-body);
}
.access-form { display: flex; flex-direction: column; gap: var(--space-2); }
.checkbox-field label {
  font-family: var(--font-serif);
  font-size: var(--scale-body);
  color: var(--fg);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.checkbox-field input[type=checkbox] { width: auto; }

.radio-field { display: flex; gap: var(--space-3); }
.radio-field label {
  font-family: var(--font-serif);
  font-size: var(--scale-body);
  color: var(--fg);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.radio-field input[type=radio] { width: auto; }

.topic-select-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-3);
  margin-left: var(--space-2);
  border-left: 2px solid var(--border);
}
.topic-select-list[hidden] { display: none; }
.topic-checkbox {
  font-family: var(--font-serif);
  font-size: var(--scale-body);
  color: var(--fg);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.topic-checkbox input[type=checkbox] { width: auto; }
.save-access-btn { align-self: flex-start; }

.hint {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  color: var(--muted-light);
}

/* ---- Site statistics ---- */
.stats-subhead {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: var(--space-5) 0 var(--space-2);
}

.stats-range-selector,
.admin-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  font-weight: 600;
}
.stats-range-selector a, .admin-tabs a { color: var(--muted-light); text-decoration: none; }
.stats-range-selector a:hover, .admin-tabs a:hover { color: var(--fg); }
.stats-range-selector a.active, .admin-tabs a.active { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; }

.stats-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(120px, 1fr));
  gap: var(--space-3);
  max-width: 400px;
}
.stat-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3);
  border: 1px solid var(--border);
}
.stat-value {
  font-family: var(--font-sans);
  font-size: var(--scale-h1);
  font-weight: 700;
  line-height: var(--leading-h1);
  letter-spacing: -0.02em;
  color: var(--fg);
}
.stat-label {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  color: var(--muted);
  letter-spacing: 0.02em;
}

.day-nav {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
  font-family: var(--font-sans);
  font-size: var(--scale-small);
}
.day-nav a { color: var(--muted); text-decoration: none; }
.day-nav a:hover { color: var(--fg); }

.stats-chart { display: block; width: 100%; max-width: 700px; height: 140px; }
.chart-bar-pageviews { fill: var(--fg); }
.chart-bar-visitors { fill: var(--accent); }
.chart-range-labels {
  display: flex;
  justify-content: space-between;
  max-width: 700px;
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  color: var(--muted-light);
  margin-top: var(--space-1);
}
.chart-legend {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  color: var(--muted);
}
.legend-item { display: flex; align-items: center; gap: var(--space-1); }
.legend-swatch { width: 10px; height: 10px; display: inline-block; flex-shrink: 0; }
.legend-swatch-pageviews { background: var(--fg); }
.legend-swatch-visitors { background: var(--accent); }

.people-list { list-style: none; padding: 0; margin: var(--space-3) 0 0; max-width: 700px; }
.person-item { border-bottom: 1px solid var(--border); }
.person-item:last-child { border-bottom: none; }
.person-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  cursor: pointer;
}
.person-summary-empty { cursor: default; }
.person-name { font-family: var(--font-sans); font-weight: 600; color: var(--fg); }
.person-meta { font-family: var(--font-sans); font-size: var(--scale-small); color: var(--muted-light); }
.person-error-flag { color: var(--accent); }

.person-detail { padding: 0 0 var(--space-3); }
.person-visit-list, .person-error-list {
  list-style: none;
  padding: 0;
  margin: var(--space-2) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.person-visit-list li, .person-error-list li {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  color: var(--muted);
}
.visit-label { color: var(--fg); min-width: 140px; }
.visit-duration { color: var(--muted-light); margin-left: auto; }
.person-error-heading {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  margin: var(--space-3) 0 0;
}

@media (max-width: 420px) {
  .stats-grid { grid-template-columns: 1fr 1fr; max-width: none; }
  .stat-value { font-size: var(--scale-h2); line-height: var(--leading-h2); }
}

/* ---- Topic list (homepage) ----
   .post-list itself is the grid, not each .post-item -- .post-item is
   display:contents so its two children (thumb, post-info) become direct
   grid items sharing ONE set of column tracks across every row. That's
   what makes every row's title start at the same x: the "auto" first
   column is sized once, from the widest thumb needed anywhere in the
   list, rather than independently per row (which is what happened when
   each .post-item was its own grid). */
.post-list {
  list-style: none;
  padding: 0;
  margin: var(--space-6) 0 0;
  display: grid;
  grid-template-columns: auto 1fr;
  row-gap: var(--space-3);
  column-gap: var(--space-3);
}
.post-item { display: contents; }
.thumb { width: 56px; height: 56px; object-fit: cover; border-radius: 0; }
img.thumb { border-radius: 3px; }
/* Square, sized in JS (topic-thumb-size.js) to match its own row's
   post-info height exactly -- the height of that post's own title,
   subtitle, and date, whatever that comes out to at whatever text/zoom
   size the visitor's browser is actually using. The 56px here is only
   the fallback for the instant before that script runs. align-self:
   start keeps the top of the square level with the top of the title
   text beside it. Both are links to the topic, so they share this sizing
   with .thumb-icon below -- same container, same behavior. */
.thumb-frame, .thumb-icon {
  display: block;
  position: relative;
  align-self: start;
  width: 56px;
  height: 56px;
  flex-shrink: 0;
}
/* The inner <img> has to be absolutely positioned inside .thumb-frame
   rather than sized directly: a replaced element's own intrinsic size
   otherwise overrides explicit sizing entirely. */
.thumb-frame .thumb { position: absolute; inset: 0; width: 100%; height: 100%; }
/* The icon itself stays a small fixed size and centers inside whatever
   size the container above ends up being -- unlike the photo, it
   doesn't grow to fill it. */
.thumb-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--fg);
}
.thumb-icon svg { width: 48px; height: 48px; flex-shrink: 0; }
.post-info { align-self: start; display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }

.topic-meta { display: flex; align-items: center; gap: var(--space-1); }

/* Sits in normal flow right next to the date -- the last line of the
   post's own text -- rather than absolutely positioned below it, so it
   can never drift into the row below regardless of how tall the thumbnail
   ends up being relative to the text. */
.topic-edit-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  color: var(--muted-light);
  opacity: 0;
  transition: opacity 0.15s ease, color 0.15s ease;
}
.topic-edit-btn svg { width: 16px; height: 16px; }
.topic-edit-btn:hover { color: var(--fg); }
.post-item:hover .topic-edit-btn,
.topic-edit-btn:focus-visible {
  opacity: 1;
}
@media (hover: none), (pointer: coarse) {
  .topic-edit-btn { opacity: 1; }
}
.post-list a {
  font-family: var(--font-sans);
  font-size: var(--scale-h2);
  line-height: var(--leading-h2);
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--fg);
  text-decoration: none;
}

/* ---- Search results: grouped by topic ---- */
.search-group { margin-bottom: var(--space-6); }
.search-group-header { display: flex; gap: var(--space-3); align-items: center; margin-bottom: var(--space-3); }

.search-entries {
  list-style: none;
  padding: 0;
  margin: 0 0 0 calc(56px + var(--space-3));
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.search-entry { display: flex; gap: var(--space-2); align-items: center; }
.search-entry .thumb { width: 40px; height: 40px; }
.search-entry-info { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.search-entry-title {
  font-family: var(--font-sans);
  font-size: var(--scale-h3);
  line-height: var(--leading-h3);
  font-weight: 650;
  color: var(--fg);
  text-decoration: none;
}
.search-entry-title:hover { color: var(--accent); }

@media (max-width: 420px) {
  .search-entries { margin-left: calc(40px + var(--space-2)); }
}

/* ---- Title hover glitch: shared structural bits ----
   Both the topic titles and the "scab.land" wordmark use the same effect
   (topic-title-glitch.js); each keeps its own font rules above/in .brand,
   this just wires up the color layers and gives them defaults so both are
   inert and exactly at rest until a hover ever begins. */
.post-list a, .brand {
  position: relative;
  isolation: isolate; /* keep the hover color layers from bleeding into siblings */
  --ch-a-opacity: 0;
  --ch-a-x: 0px;
  --ch-a-y: 0px;
  --ch-a-color: var(--fg);
  --ch-b-opacity: 0;
  --ch-b-x: 0px;
  --ch-b-y: 0px;
  --ch-b-color: var(--fg);
  --main-x: 0px;
  --main-y: 0px;
  --main-color: var(--fg);
  --main-clip: inset(0 0 0 0);
}

/* ---- Topic title hover: analog color glitch ----
   topic-title-glitch.js drives the ch-a, ch-b, and main custom properties
   above every frame while hovered. This block only wires those properties
   to visible output; it never sets font-family/size itself, so the title
   keeps the site's own type exactly as declared above. */
.glitch-text {
  position: relative;
  display: inline-block;
  color: var(--main-color);
  transform: translate(var(--main-x), var(--main-y));
  clip-path: var(--main-clip, inset(0 0 0 0));
}
.post-list a::before,
.post-list a::after,
.brand::before,
.brand::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  pointer-events: none;
  white-space: nowrap;
}
.post-list a::before,
.brand::before {
  opacity: var(--ch-a-opacity);
  color: var(--ch-a-color);
  transform: translate(var(--ch-a-x), var(--ch-a-y));
}
.post-list a::after,
.brand::after {
  opacity: var(--ch-b-opacity);
  color: var(--ch-b-color);
  transform: translate(var(--ch-b-x), var(--ch-b-y));
}
@media (prefers-reduced-motion: reduce) {
  .glitch-text,
  .post-list a::before,
  .post-list a::after,
  .brand::before,
  .brand::after {
    transition: color 0.5s ease, opacity 0.5s ease;
  }
}

/* ---- Entries / article body ---- */
.entry { padding: var(--space-6) 0 var(--space-4); border-bottom: 1px solid var(--border); }
.entry:first-of-type { padding-top: 0; }

.post-body {
  font-family: var(--font-serif);
  font-size: var(--scale-body);
  line-height: var(--leading-body);
  max-width: 65ch;
  margin-top: var(--space-3);
}
.post-body a[href^="/search?q="] {
  color: var(--accent);
  text-decoration: none;
  font-family: var(--font-sans);
  font-size: var(--scale-small);
}
.post-body a[href^="/search?q="]:hover { text-decoration: underline; }
.post-body p { margin: 0 0 var(--paragraph-gap); }
.post-body p:last-child { margin-bottom: 0; }
.post-body ul, .post-body ol { margin: 0 0 var(--paragraph-gap); padding-left: 1.4em; }
.post-body li { margin-bottom: var(--space-1); }
.post-body li:last-child { margin-bottom: 0; }
.post-body img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 4px;
  margin: var(--space-4) 0;
  cursor: pointer;
}

/* Wraps a standalone photo (see photo-captions.js) so its caption bar can be
   positioned against it, same as .carousel-slide already allows below. */
.photo-frame { position: relative; }

/* ---- Video thumbnail (cropped poster still + play icon, in the feed and
   carousel) -- the actual <video> only ever plays in the lightbox. ---- */
.video-thumb { position: relative; display: block; }
.video-thumb svg {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 56px;
  height: 56px;
  color: #fff;
  filter: drop-shadow(0 1px 6px rgba(0, 0, 0, 0.5));
  /* Otherwise a click aimed at the icon (the obvious thing to click) lands
     on the icon itself instead of the underlying <img> that actually opens
     the lightbox. */
  pointer-events: none;
}

/* ---- Photo caption (hover-reveal bar over the bottom of a photo) ---- */
.photo-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  box-sizing: border-box;
  background: rgba(26, 26, 26, 0.82);
  color: #fff;
  font-family: var(--font-serif);
  font-size: var(--scale-small);
  line-height: var(--leading-small);
  padding: var(--space-1) var(--space-2);
  min-height: calc((var(--leading-small) * 2) + (var(--space-1) * 2));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.photo-caption a { color: inherit; }
.photo-frame:hover .photo-caption,
.carousel-slide:hover .photo-caption {
  opacity: 1;
  pointer-events: auto;
}
@media (hover: none), (pointer: coarse) {
  .photo-caption { opacity: 1; pointer-events: auto; }
}

/* ---- Photo carousel ---- */
.carousel { position: relative; margin: var(--space-4) 0; overflow: hidden; border-radius: 4px; }
.carousel-slide { position: relative; display: none; }
.carousel-slide.active { display: block; }
.carousel-slide img { aspect-ratio: 1 / 1; object-fit: cover; margin: 0; border-radius: 0; cursor: pointer; }

.carousel-prev, .carousel-next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: rgba(26, 26, 26, 0.55);
  color: #fff;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, background-color 0.15s ease;
}
.carousel-prev svg, .carousel-next svg { width: 24px; height: 24px; }
.carousel-prev { left: var(--space-2); }
.carousel-next { right: var(--space-2); }
.carousel:hover .carousel-prev,
.carousel:hover .carousel-next,
.carousel-prev:focus-visible,
.carousel-next:focus-visible {
  opacity: 1;
}
.carousel-prev:hover, .carousel-next:hover { background: var(--fg); }

/* Touchscreens have no :hover, so the arrows must be visible (and easy to tap) by default */
@media (hover: none), (pointer: coarse) {
  .carousel-prev, .carousel-next { opacity: 1; width: 48px; height: 48px; }
}

/* ---- Photo lightbox ---- */
.lightbox {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.9);
  z-index: 1000;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  box-sizing: border-box;
}
.lightbox.open { display: flex; }
.lightbox-photo {
  position: relative;
  z-index: 1;
  display: inline-block;
  line-height: 0;
  border: 2px solid rgba(255, 255, 255, 0.2);
  box-sizing: border-box;
}
.lightbox-img,
.lightbox-video {
  display: block;
  width: auto;
  height: auto;
  max-width: calc(100vw - (var(--space-4) * 2) - 4px);
  max-height: calc(100vh - (var(--space-4) * 2) - 4px);
  object-fit: contain;
}
/* An iframe has no intrinsic size to shrink-to-fit the way an img/video
   does, so its width is computed directly from the viewport instead --
   whichever of the width cap, the height cap converted through the 16:9
   ratio, or a flat max is smallest, so it never overflows either axis. */
.lightbox-youtube {
  display: block;
  width: min(calc(100vw - (var(--space-4) * 2) - 4px), calc((100vh - (var(--space-4) * 2) - 4px) * 16 / 9), 960px);
  aspect-ratio: 16 / 9;
  border: none;
}
/* The [hidden] attribute alone loses to the display:block rule above
   (a class selector beats the UA stylesheet's attribute-implicit style),
   so it has to be restated explicitly to actually hide either element. */
.lightbox-img[hidden],
.lightbox-video[hidden],
.lightbox-youtube[hidden] {
  display: none;
}
.lightbox-photo:hover .lightbox-caption { opacity: 1; pointer-events: auto; }
.lightbox-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  box-sizing: border-box;
  background: rgba(26, 26, 26, 0.82);
  color: #fff;
  font-family: var(--font-serif);
  font-size: var(--scale-small);
  line-height: var(--leading-small);
  padding: var(--space-1) var(--space-2);
  min-height: calc((var(--leading-small) * 2) + (var(--space-1) * 2));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.lightbox-caption a { color: inherit; }
.lightbox-caption:empty { display: none; }
@media (hover: none), (pointer: coarse) {
  .lightbox-caption { opacity: 1; pointer-events: auto; }
}
.lightbox-close,
.lightbox-prev,
.lightbox-next {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.lightbox-close:hover,
.lightbox-prev:hover,
.lightbox-next:hover {
  background: rgba(255, 255, 255, 0.28);
}
.lightbox-close svg, .lightbox-prev svg, .lightbox-next svg { width: 24px; height: 24px; }
.lightbox-close { top: var(--space-3); right: var(--space-3); }
.lightbox-prev { left: var(--space-3); top: 50%; transform: translateY(-50%); }
.lightbox-next { right: var(--space-3); top: 50%; transform: translateY(-50%); }

.post-body blockquote {
  margin: var(--space-4) 0;
  padding-left: var(--space-3);
  border-left: 3px solid var(--border);
  font-style: italic;
  color: var(--muted);
}
.post-body h2 { font-size: var(--scale-h3); line-height: var(--leading-h3); font-weight: 650; margin: var(--space-5) 0 var(--space-2); }
.post-body h3 { font-size: var(--scale-h3); line-height: var(--leading-h3); font-weight: 600; margin: var(--space-4) 0 var(--space-2); }

/* ---- Engagement (like/comment icons, Facebook-minimal) ---- */
.engagement { margin-top: var(--space-4); display: flex; align-items: center; gap: var(--space-4); }
.engagement-item { display: flex; align-items: center; gap: var(--space-1); }
.engagement-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.engagement-btn svg { width: 20px; height: 20px; }
.engagement-btn:hover { color: var(--fg); }
.engagement-btn.liked { color: var(--accent); }
.engagement-btn.liked svg { fill: currentColor; }
.engagement-btn[aria-expanded=true] { color: var(--fg); }
.engagement-count {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  line-height: var(--leading-small);
  font-weight: 500;
  color: var(--muted);
}

.likes-count { position: relative; }
.likes-count-toggle {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: transparent;
}
.likes-count-toggle:hover { text-decoration-color: var(--muted); }
.likes-dropdown {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  min-width: 140px;
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-2);
}
.likes-dropdown[hidden] { display: none; }
.likes-dropdown-name {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  line-height: var(--leading-small);
  color: var(--fg);
}

/* ---- Comments ---- */
.comments { margin-top: var(--space-3); }
.comments > .comment-form { margin-top: 0; }
.comment { margin-bottom: var(--space-2); max-width: 65ch; }
.comment strong {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--scale-small);
}
.comment .date { display: inline; margin-left: var(--space-2); }
.comment p {
  font-family: var(--font-serif);
  font-size: var(--scale-small);
  line-height: var(--leading-small);
  margin: var(--space-1) 0 0;
}

.comment-form, .login-page form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
  max-width: 65ch;
}
textarea, input[type=email], input[type=text], input[type=datetime-local], select {
  font-family: var(--font-serif);
  font-size: var(--scale-body);
  padding: var(--space-2);
  border: 1px solid var(--border);
  border-radius: 0;
  background: #fff;
  width: 100%;
  /* Without this, some browsers layer their own native control border on
     top of ours, making inputs look thicker than a plain textarea. */
  appearance: none;
  -webkit-appearance: none;
}
/* The browser's native focus ring stacks on top of our border and reads as
   a much thicker box. Replace it with just a color change, same 1px width. */
textarea:focus, input[type=email]:focus, input[type=text]:focus, input[type=datetime-local]:focus, select:focus {
  outline: none;
  border-color: var(--fg);
}

/* ---- Subtle underline input (search field, sign-in email field) ---- */
.search-form { max-width: 400px; margin: var(--space-3) 0 var(--space-6); }
input.underline-input {
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  padding: var(--space-1) 0;
}
input.underline-input::placeholder { color: var(--muted-light); }
/* A full-black underline reads much heavier here than the same color does
   on a boxed input's thin 1px border all the way around -- a lone dark
   line spanning the full width draws more visual weight. A mid-gray focus
   color keeps a visible cue without that heaviness. */
input.underline-input:focus { outline: none; border-color: var(--muted); }
textarea { min-height: 72px; resize: vertical; }
/* Comments start as a single line — tall enough for the text plus padding,
   not a paragraph-sized box — but keep the drag handle to expand. */
.comment-form textarea { min-height: 56px; }
.comment-form button[type=submit],
.login-page form button[type=submit] {
  align-self: flex-start;
  display: none;
}

/* ---- New post form ---- */
.post-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 65ch;
  margin-top: var(--space-3);
}
.field { display: flex; flex-direction: column; gap: var(--space-1); }
/* The [hidden] attribute alone loses to display:flex above (a class
   selector beats the UA stylesheet's attribute-implicit style), so it
   has to be restated explicitly to actually hide the field. */
.field[hidden] { display: none; }
.field label {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.02em;
}
.field .hint {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  color: var(--muted-light);
}
.field .hint a { color: inherit; }

/* ---- Icon picker (replaces the native <datalist>, see icon-picker.js) ---- */
.icon-picker { position: relative; }
.icon-picker-results {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  right: 0;
  max-height: 280px;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  z-index: 20;
  display: flex;
  flex-direction: column;
  padding: var(--space-1) 0;
}
.icon-picker-results[hidden] { display: none; }
.icon-picker-result {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  box-sizing: border-box;
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  color: var(--fg);
  background: none;
  border: none;
  text-align: left;
  padding: var(--space-1) var(--space-3);
  cursor: pointer;
}
.icon-picker-result img { flex-shrink: 0; }
.icon-picker-result:hover, .icon-picker-result.active { background: var(--border); }
.post-form input[type=file] {
  font-family: var(--font-sans);
  font-size: var(--scale-body);
}
.post-form textarea { min-height: 144px; }
.post-form button[type=submit] { align-self: flex-start; }
#photoCaptionFields { display: flex; flex-direction: column; gap: var(--space-3); }
#photoCaptionFields:empty { display: none; }
#youtubeUrls { min-height: 56px; }
.youtube-preview { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.youtube-preview:empty { display: none; }
.youtube-preview-thumb { width: 64px; height: 64px; object-fit: cover; border-radius: 0; display: block; }

.existing-photos { display: flex; flex-direction: column; gap: var(--space-3); }
.existing-photo { display: flex; align-items: flex-start; gap: var(--space-2); }
.existing-photo-thumb-wrap { position: relative; flex-shrink: 0; }
.existing-photo-thumb { width: 64px; height: 64px; object-fit: cover; border-radius: 0; display: block; }
.existing-photo-video-badge {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  box-sizing: border-box;
  background: rgba(26, 26, 26, 0.82);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  padding: 2px 0;
  pointer-events: none;
}
.existing-photo input[type=text] { flex: 1; }
.existing-photo-remove {
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: var(--space-1);
  white-space: nowrap;
  align-self: center;
}
.existing-photo-remove input[type=checkbox] { width: auto; }
.existing-photo.is-removed { opacity: 0.4; }

.existing-photo-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 64px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  color: var(--muted-light);
  cursor: grab;
  flex-shrink: 0;
  /* Without this, touch-dragging the handle also scrolls the page on
     mobile instead of just reordering. */
  touch-action: none;
}
.existing-photo-handle svg { width: 18px; height: 18px; }
.existing-photo-handle:hover { color: var(--muted); }
.existing-photo-dragging {
  opacity: 0.6;
  background: var(--bg);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}
.existing-photo-dragging .existing-photo-handle { cursor: grabbing; }

.post-form-actions { display: flex; align-items: center; gap: var(--space-3); }
.delete-post-btn {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--scale-small);
  color: var(--accent);
  cursor: pointer;
}
.delete-post-btn:hover { text-decoration: underline; }

/* ---- Delete confirmation modal ---- */
.modal {
  display: flex;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 1000;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}
.modal[hidden] { display: none; }
.modal-dialog {
  background: var(--bg);
  border: 1px solid var(--border);
  padding: var(--space-4);
  max-width: 360px;
  width: 100%;
}
.modal-dialog p {
  font-family: var(--font-sans);
  font-size: var(--scale-body);
  margin: 0 0 var(--space-3);
}
.modal-actions { display: flex; gap: var(--space-2); justify-content: flex-end; }
.modal-actions form { margin: 0; }
.modal-cancel {
  background: none;
  border: 1px solid var(--border);
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--scale-small);
  cursor: pointer;
}
.modal-confirm-delete {
  background: var(--accent);
  color: #fff;
  border: none;
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--scale-small);
  cursor: pointer;
}
.modal-confirm-delete:hover { background: #8a3324; }

.login-page p { max-width: 65ch; margin: 0 0 var(--space-3); }
.login-page .subtitle {
  font-family: var(--font-sans);
  font-size: var(--scale-h3);
  line-height: var(--leading-h3);
  font-weight: 600;
  color: var(--fg);
}
.error { color: var(--accent); font-family: var(--font-sans); font-size: var(--scale-body); }
.notice { color: var(--fg); font-family: var(--font-sans); font-size: var(--scale-body); }

.draft-badge {
  display: inline-block;
  vertical-align: middle;
  font-family: var(--font-sans);
  font-size: var(--scale-small);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 2px 8px;
  margin-left: var(--space-2);
}

/* ---- Narrow screens ---- */
@media (max-width: 420px) {
  .page-title { font-size: var(--scale-h2); line-height: var(--leading-h2); }
  .post-list a { font-size: var(--scale-h3); line-height: var(--leading-h3); }
}
