/* things — an index to twelve years of a newsletter.
 *
 * The visual system borrows from the newsletter's own vernacular: everything
 * here is numbered (s21e16, section 1.1), so numbering does the structural
 * work. Codes, dates and counts are set in monospace and treated as ledger
 * data; prose is set in a serif, because it is reading matter.
 */

:root {
  --paper:   #f4f2ec;
  --paper-2: #eae7de;
  --paper-3: #dedacd;
  --ink:     #191a1d;
  --ink-2:   #61605a;
  --rule:    #d6d2c6;
  --stamp:   #8c2f39;  /* oxblood: actions and links */
  --ledger:  #2e4a6d;  /* ledger blue: codes and data */
  --mark:    #f6e08c;
  --bar:     #b3ac98;

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
           Georgia, ui-serif, serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, "Cascadia Mono",
          "Roboto Mono", monospace;

  --measure: 34rem;
  --gutter: clamp(1rem, 4vw, 2.5rem);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:   #16171a;
    --paper-2: #1d1f23;
    --paper-3: #282b30;
    --ink:     #e7e4db;
    --ink-2:   #99968c;
    --rule:    #34363b;
    --stamp:   #dd8089;
    --ledger:  #90b6e0;
    --mark:    #574717;
    --bar:     #4d525a;
  }
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.55;
  text-rendering: optimizeLegibility;
}

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

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

.wrap { max-width: 62rem; margin: 0 auto; padding: 0 var(--gutter); }

/* --- masthead ---------------------------------------------------------- */

.masthead {
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  position: sticky;
  top: 0;
  z-index: 10;
}

.masthead .wrap {
  display: flex;
  flex-wrap: nowrap;
  align-items: baseline;
  gap: 0.4rem 1.1rem;
  padding-block: 0.7rem;
}

.wordmark {
  font-family: var(--mono);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
  flex: none;
}
.wordmark::before {
  content: "▍";
  color: var(--stamp);
  margin-right: 0.35em;
}

/* Swipeable, not wrapping: on a narrow viewport there are more entries
   than fit on one line, and wrapping them pushes the page content down
   awkwardly (or, without wrapping, forces the whole page to scroll
   sideways). Letting just this row scroll horizontally keeps the header
   one line tall and the extra entries a swipe away, at the cost of not
   being able to see all of them at a glance -- a plain, JS-free fix for
   now; a hamburger/overflow menu is a bigger redesign for later. */
.masthead nav {
  display: flex;
  flex-wrap: nowrap;
  gap: 1.1rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  min-width: 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.masthead nav::-webkit-scrollbar { display: none; }
.masthead nav a {
  color: var(--ink-2);
  text-decoration: none;
  flex: none;
}
.masthead nav a:hover,
.masthead nav a[aria-current="page"] { color: var(--stamp); text-decoration: underline; }

/* --- page furniture ---------------------------------------------------- */

main { padding-block: 2rem 4rem; }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0 0 0.5rem;
}

h1 {
  font-size: clamp(1.65rem, 5vw, 2.4rem);
  line-height: 1.15;
  font-weight: 600;
  margin: 0 0 0.6rem;
  letter-spacing: -0.01em;
}
h2 { font-size: 1.25rem; font-weight: 600; margin: 2.4rem 0 0.8rem; }
h3 { font-size: 1.05rem; font-weight: 600; margin: 1.6rem 0 0.5rem; }

.lede { color: var(--ink-2); max-width: var(--measure); margin: 0 0 1.6rem; }

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

/* --- the run: a bar per month across the whole archive ----------------- */

.run {
  display: flex;
  align-items: flex-end;
  gap: 1px;
  height: 56px;
  margin: 1.5rem 0 0.4rem;
  overflow-x: auto;
  padding-bottom: 2px;
  scrollbar-width: thin;
}
.run-bar {
  flex: 1 0 4px;
  min-width: 4px;
  background: var(--bar);
  display: block;
  border: 0;
  padding: 0;
  border-radius: 1px 1px 0 0;
  transition: background 120ms ease;
}
.run-bar[data-count="0"] { height: 2px !important; background: var(--rule); }
.run-bar:hover, .run-bar:focus-visible { background: var(--stamp); }
.run-bar[aria-current="true"] { background: var(--ledger); }

.run-axis {
  display: flex;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-2);
  border-top: 1px solid var(--rule);
  padding-top: 0.35rem;
}

/* --- search ------------------------------------------------------------ */

.searchbar { display: flex; gap: 0.5rem; flex-wrap: wrap; margin: 1.2rem 0; }
.searchbar input[type="search"] {
  flex: 1 1 16rem;
  font: inherit;
  padding: 0.6rem 0.75rem;
  background: var(--paper-2);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 2px;
  min-width: 0;
}
.searchbar input[type="number"] {
  width: 5em;
  font: inherit;
  padding: 0.6rem 0.75rem;
  background: var(--paper-2);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 2px;
}
.searchbar button, .btn {
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.6rem 0.9rem;
  background: var(--stamp);
  color: var(--paper);
  border: 0;
  border-radius: 2px;
  cursor: pointer;
  text-decoration: none;
}
.btn.ghost { background: transparent; color: var(--ink-2); border: 1px solid var(--rule); }

mark { background: var(--mark); color: inherit; padding: 0 0.1em; }

/* --- toggles / filter chips ------------------------------------------- */

.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.8rem 0 1.4rem; padding: 0; list-style: none; }
.chip {
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  padding: 0.25rem 0.55rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
}
.chip:hover { border-color: var(--stamp); color: var(--stamp); }
.chip[aria-current="page"], .chip.on {
  background: var(--ledger); border-color: var(--ledger); color: var(--paper);
}

/* --- the episode list: a ledger -------------------------------------- */

.ledger { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.ledger li { border-bottom: 1px solid var(--rule); }

.entry {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.15rem 1.2rem;
  padding: 0.85rem 0;
  text-decoration: none;
  color: inherit;
}
.entry:hover .entry-title { color: var(--stamp); text-decoration: underline; }

.entry-meta {
  font-family: var(--mono);
  font-size: 0.74rem;
  color: var(--ink-2);
  display: flex;
  gap: 0.7rem;
  flex-wrap: wrap;
}
.entry-code { color: var(--ledger); font-weight: 600; }
.entry-title { font-size: 1.02rem; line-height: 1.35; }
.entry-snippet { color: var(--ink-2); font-size: 0.94rem; margin-top: 0.25rem; }

@media (min-width: 46rem) {
  .entry { grid-template-columns: 9.5rem 1fr; }
  .entry-meta { flex-direction: column; gap: 0.15rem; }
}

.entry-row { display: flex; align-items: center; gap: 0.1rem; }
.entry-row .entry { flex: 1 1 auto; min-width: 0; }

/* A checkbox this small needs a tap target well beyond its own box —
   44px square is the usual touch-target floor. */
.select-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  flex-shrink: 0;
  cursor: pointer;
}
.select-toggle input[type="checkbox"] {
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--stamp);
}

.select-all-row { margin: 0.6rem 0; }
.select-all {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-2);
  cursor: pointer;
  padding: 0.5rem 0.2rem;
}
.select-all input[type="checkbox"] {
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--stamp);
}

/* --- add-to-playlist picker -------------------------------------------- */

.picker { margin: 1.6rem 0; padding-top: 1.2rem; border-top: 1px solid var(--rule); }
.picker-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-top: 0.6rem; }
.picker-row select, .picker-row input[type="text"] {
  font: inherit;
  font-size: 0.92rem;
  padding: 0.55rem 0.7rem;
  background: var(--paper-2);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 2px;
}
.picker-row input[type="text"] { flex: 1 1 14rem; min-width: 0; }
.picker-or {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* --- data tables ------------------------------------------------------- */

/* Only for non-table wide content now (cluster.html's canonical-links
   <pre> block) — NOT used by any <table> here anymore. overflow-x: auto
   on a sticky header's ancestor forces overflow-y to compute as 'auto'
   too (CSS Overflow spec: a non-visible value on one axis forces the
   other off 'visible'), which makes that div the sticky element's
   scrolling ancestor *instead of* the page. Since the div never
   actually scrolls internally (it just grows to fit its content),
   sticky then does nothing at all — not "wrong position", just never
   active — identically in every spec-compliant browser, which is why
   it silently failed the same way in both Safari and Chrome. None of
   this app's tables are wide enough to need horizontal scroll in
   practice, so the fix was removing the wrapper for all three rather
   than finding a CSS-only way to have both. */
.table-scroll { overflow-x: auto; }
/* separate + zero spacing, not collapse: position: sticky on a table
   cell is unreliable across browsers when border-collapse: collapse is
   in effect (a long-documented WebKit/Safari bug) — this renders
   identically to collapse since every bordered edge here is a single
   shared border-bottom, not a full box per cell. */
table { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 0.94rem; }
th, td { text-align: left; padding: 0.5rem 0.9rem 0.5rem 0; border-bottom: 1px solid var(--rule); }
th {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  font-weight: 500;
  white-space: nowrap;
  padding: 0;
  border-bottom: none;
}
/* Sticky lives on a block-level span wrapping the header cell's content
   rather than directly on <th> — a plain block element is a more
   consistently-supported sticky target across browsers than a table
   cell. Same stacking as .az-nav below: stick under the sticky masthead
   (4.2rem tall, z-index 10), not over it. An opaque background is
   required — sticky's own box is transparent by default, so rows
   scrolling underneath would otherwise show through the header. */
th > .th-sticky {
  display: block;
  padding: 0.5rem 0.9rem 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  position: sticky;
  top: 4.2rem;
  z-index: 5;
  background: var(--paper);
}
td.num, th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
td.mono { font-family: var(--mono); font-size: 0.85rem; white-space: nowrap; }
td.type-action, th.type-action { text-align: center; }
td.type-action .inline-form { justify-content: center; }

/* --- stat row ---------------------------------------------------------- */

.stats { display: flex; flex-wrap: wrap; gap: 1.4rem 2.2rem; margin: 1.2rem 0; padding: 0; list-style: none; }
.stats div { display: flex; flex-direction: column; }
.stats b {
  font-family: var(--mono);
  font-size: 1.25rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ledger);
}
.stats span {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* --- episode page ------------------------------------------------------ */

.episode-head { border-bottom: 1px solid var(--rule); padding-bottom: 1.2rem; margin-bottom: 1.8rem; }

.prose { max-width: var(--measure); font-size: 1.06rem; line-height: 1.65; overflow-wrap: break-word; }
.prose h1 { font-size: 1.3rem; margin: 2.4rem 0 0.5rem; }
.prose h2 { font-size: 1.12rem; margin: 2rem 0 0.4rem; }
.prose h3 { font-size: 1rem; }
.prose img, .prose iframe { max-width: 100%; height: auto; }
.prose blockquote {
  margin: 1.2rem 0;
  padding-left: 1rem;
  border-left: 2px solid var(--paper-3);
  color: var(--ink-2);
}
.prose pre { overflow-x: auto; background: var(--paper-2); padding: 0.8rem; font-size: 0.85rem; }
.prose hr { border: 0; border-top: 1px solid var(--rule); margin: 2rem 0; }

.sidenote {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-2);
}

.cols { display: grid; gap: 2.5rem; }
@media (min-width: 60rem) {
  .cols { grid-template-columns: minmax(0, 1fr) 17rem; align-items: start; }
  .cols aside { position: sticky; top: 4.2rem; }
}

.linklist { list-style: none; margin: 0; padding: 0; font-size: 0.9rem; }
.linklist li { padding: 0.45rem 0; border-bottom: 1px solid var(--rule); overflow-wrap: anywhere; }
.linklist .host { font-family: var(--mono); font-size: 0.74rem; color: var(--ledger); }

.aside-group {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ledger);
  margin: 1rem 0 0.3rem;
}
.aside-group:first-of-type { margin-top: 0.6rem; }

.aside-more { margin: 0; }
.aside-more > summary {
  padding: 0.45rem 0;
  font-size: 0.82rem;
  color: var(--ink-2);
  cursor: pointer;
}
.aside-more > summary:hover { color: var(--stamp); }
.aside-more[open] > summary { border-bottom: 1px solid var(--rule); }
.aside-more .linklist { margin-top: 0; }

.tag {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0 0.3em;
}

/* --- index --------------------------------------------------------------- */

.az-nav {
  position: sticky;
  top: 4.2rem;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  gap: 0.05rem 0.5rem;
  padding: 0.55rem var(--gutter);
  margin: 0 calc(var(--gutter) * -1) 1.4rem;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.02em;
}
.az-nav a { color: var(--ink-2); text-decoration: none; }
.az-nav a:hover { color: var(--stamp); text-decoration: underline; }
.az-nav span { color: var(--rule); }

.index-group { margin: 1.8rem 0; }
.index-group h2 {
  font-family: var(--mono);
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  color: var(--ledger);
  border-bottom: 1px solid var(--rule);
  margin: 0 0 0.5rem;
  padding-bottom: 0.2rem;
}
.index-list { list-style: none; margin: 0; padding: 0; }
.index-list li {
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--rule);
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.index-list a { font-size: 1rem; }
.index-list li.alias { color: var(--ink-2); }
.index-list .alias-name { font-style: italic; }
.index-list .see {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* --- admin: entities ---------------------------------------------------- */

.error {
  color: var(--stamp);
  font-family: var(--mono);
  font-size: 0.85rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--stamp);
  border-radius: 2px;
  margin: 1rem 0;
}

.admin-search { display: flex; gap: 0.5rem; margin: 1rem 0 1.6rem; max-width: 28rem; }
.admin-search input[type="text"] { flex: 1 1 auto; min-width: 0; }

.admin-entity {
  padding: 1rem 0;
  border-bottom: 1px solid var(--rule);
}
.admin-entity h2 {
  font-family: var(--serif);
  font-size: 1.1rem;
  font-weight: normal;
  margin: 0 0 0.5rem;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.admin-aliases { list-style: none; margin: 0 0 0.7rem; padding: 0; }
.admin-aliases li {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  padding: 0.25rem 0;
}

.admin-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; }

.inline-form { display: flex; gap: 0.4rem; align-items: center; }
.inline-form input[type="text"] {
  font: inherit;
  font-size: 0.88rem;
  padding: 0.4rem 0.6rem;
  background: var(--paper-2);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 2px;
  width: 12rem;
  max-width: 40vw;
}

/* --- clusters ---------------------------------------------------------- */

.cluster-grid { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
@media (min-width: 44rem) { .cluster-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 70rem) { .cluster-grid { grid-template-columns: repeat(3, 1fr); } }

.cluster {
  background: var(--paper);
  padding: 1rem 1.1rem 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.cluster h3 { margin: 0; font-size: 1rem; }
.cluster h3 a { color: inherit; text-decoration: none; }
.cluster h3 a:hover { color: var(--stamp); text-decoration: underline; }
.cluster ul { list-style: none; margin: 0; padding: 0; font-size: 0.88rem; }
.cluster li { padding: 0.2rem 0; }
.cluster .size {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* --- playlists ----------------------------------------------------------- */

.playlist-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
}
.playlist-row .entry { flex: 1 1 auto; min-width: 0; }
.playlist-actions { display: flex; gap: 0.3rem; flex-shrink: 0; }
.playlist-actions form { display: contents; }
.playlist-actions button {
  padding: 0.35rem 0.55rem;
  font-size: 0.7rem;
}
.playlist-actions button:disabled { opacity: 0.35; cursor: default; }

.playlist-row[draggable="true"] { cursor: grab; }
.playlist-row[draggable="true"].dragging { cursor: grabbing; opacity: 0.4; }
.drag-handle {
  flex-shrink: 0;
  color: var(--ink-2);
  font-size: 1.1rem;
  line-height: 1;
  padding: 0.6rem 0.2rem;
  touch-action: none;
}

/* --- pagination and footer -------------------------------------------- */

.pager { display: flex; gap: 0.6rem; align-items: center; margin: 2rem 0 0; font-family: var(--mono); font-size: 0.78rem; }
.pager span { color: var(--ink-2); }

footer {
  border-top: 1px solid var(--rule);
  padding-block: 1.4rem 3rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-2);
}
footer a { color: var(--ink-2); }
footer .inline-form { display: inline-flex; }
.linklike {
  background: none; border: none; padding: 0; margin: 0;
  font: inherit; color: inherit; text-decoration: underline; cursor: pointer;
}

.empty { color: var(--ink-2); padding: 2rem 0; max-width: var(--measure); }

/* --- SIP ----------------------------------------------------------------- */

.sip-phrase {
  font-family: var(--serif);
  font-size: clamp(2rem, 7vw, 3.4rem);
  line-height: 1.15;
  margin: 1.2rem 0 1.6rem;
  max-width: 40rem;
}
.sip-phrase a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 3px solid var(--stamp);
}
.sip-phrase a:hover { color: var(--stamp); }

.sip-meta { font-size: 1.05rem; margin: 0 0 1.6rem; }
.sip-meta .sidenote { display: inline; }

.sip-actions { display: flex; gap: 0.8rem; flex-wrap: wrap; align-items: center; margin-bottom: 2.6rem; }

.sip-explainer {
  border-top: 1px solid var(--rule);
  padding-top: 1.6rem;
  margin-top: 1.6rem;
}
.sip-explainer h2 { font-size: 1.05rem; margin: 0 0 0.8rem; }
.sip-explainer .prose { font-size: 0.98rem; margin-bottom: 1rem; }

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