/* CleanLinguistList — editorial treatment.
   Concept: postings read like dictionary/bibliography entries; category
   groups read like a journal's table of contents; the browse view's result
   cards read like library catalog cards. Ported from a plain form/card UI —
   see git history for the prior version.

   Type system: Archivo (a confident, current grotesque) for headlines and
   entry titles, IBM Plex Sans/Mono for body copy and labels — deliberately
   sans-only, no serif, to read as a clean break from LINGUIST List's own
   dated styling rather than another vintage-journal pastiche. */

@import url("https://fonts.googleapis.com/css2?family=Archivo:wght@500;600;700;800&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500;600&display=swap");

:root {
  --paper: #f1ece2;
  --surface: #f7f3ea;
  --ink: #211f1a;
  --ink-muted: #6b675e;
  --rule: #e0d9cc;
  --rule-strong: #bdb3a0;
  --accent: #3f6e75;
  --accent-soft: #e5ebe8;
  --accent-contrast: #fbf9f4;
  --danger: #9c4a3d;

  --font-display: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-body: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", "SF Mono", Consolas, monospace;
}

/* Theme resolution order: system preference by default; an explicit
   data-theme (set by the toggle in app.js, persisted in localStorage) wins
   either direction. See app.js's initThemeToggle(). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #1c1a17;
    --surface: #211e1a;
    --ink: #ece7de;
    --ink-muted: #a39c8d;
    --rule: #3a362f;
    --rule-strong: #4d473d;
    --accent: #7fb0b3;
    --accent-soft: #253634;
    --accent-contrast: #14201f;
    --danger: #d98a76;
  }
}

:root[data-theme="dark"] {
  --paper: #1c1a17;
  --surface: #211e1a;
  --ink: #ece7de;
  --ink-muted: #a39c8d;
  --rule: #3a362f;
  --rule-strong: #4d473d;
  --accent: #7fb0b3;
  --accent-soft: #253634;
  --accent-contrast: #14201f;
  --danger: #d98a76;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
}

a {
  color: var(--accent);
}

.page {
  max-width: 700px;
  margin: 0 auto;
  padding: 40px 20px 90px;
}

.page-browse {
  max-width: 1020px;
}

/* ---------- Browse layout: results primary, sidebar (jump-to + picker) tucked to one side ---------- */

.browse-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  align-items: start;
}

.sidebar {
  /* Narrow screens: full width (matching the result cards), stacked above
     the results (order: -1) — both accordions below default to closed
     (see .controls-panel), so this doesn't push the digest itself down. */
  order: -1;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.controls-panel {
  /* Without this, flexbox shrinks an open panel to fit .sidebar's capped
     max-height (see that rule) — and since this element's own overflow is
     hidden (just below, for the border-radius), the excess content is
     silently clipped away instead of making the PARENT scroll. Keeping its
     natural height forces the parent to be the one that overflows. */
  flex-shrink: 0;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--surface);
  overflow: hidden;
}

/* NOTE: this media query must come AFTER the base .sidebar rule above —
   equal-specificity rules resolve by source order, so an override placed
   before its base would silently lose at the very widths it's meant to
   apply to. */
@media (min-width: 860px) {
  .browse-layout {
    grid-template-columns: 1fr 280px;
    grid-template-rows: auto;
    gap: 28px;
  }

  .results {
    grid-column: 1;
    grid-row: 1;
  }

  .sidebar {
    grid-column: 2;
    grid-row: 1;
    order: 0;
    position: sticky;
    top: 24px;
    /* A sticky element taller than the viewport traps scroll: once stuck,
       its overflow past the viewport bottom is only reachable by scrolling
       the whole page until the sticky container's natural (unstuck) bottom
       comes into view. Capping its height and scrolling it internally
       avoids that — e.g. with both panels open, the full picker can run
       well past one screen's height. */
    max-height: calc(100vh - 48px);
    overflow-y: auto;
    /* A grid item's default min-height is auto, i.e. "at least as tall as
       my content" — that silently overrides max-height (the item just
       grows past it instead of clipping/scrolling), which is exactly what
       was happening here. min-height: 0 lets max-height actually apply. */
    min-height: 0;
  }
}

.controls-panel[open] {
  padding-bottom: 18px;
}

/* Narrow screens stack both accordions above the results (see .sidebar) —
   tightened here rather than switching to a side-by-side row, which would
   leave an OPEN panel squeezed into half-width (cramped for the journal
   checkbox list in particular). */
@media (max-width: 859px) {
  .sidebar {
    gap: 10px;
  }

  .controls-summary-label {
    padding: 9px 14px;
  }

  .controls-summary-indicator {
    width: 32px;
  }

  .controls-panel[open] {
    padding-bottom: 12px;
  }
}

.controls-summary {
  list-style: none;
  cursor: pointer;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
  display: flex;
  align-items: stretch;
  justify-content: space-between;
}

.controls-summary::-webkit-details-marker {
  display: none;
}

.controls-summary-label {
  display: flex;
  align-items: center;
  padding: 13px 16px;
}

.controls-summary-indicator {
  width: 38px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  color: var(--accent);
  background: var(--accent-soft);
}

.controls-summary-indicator::before {
  content: "+";
}

.controls-panel[open] .controls-summary-indicator::before {
  content: "\2212";
}

.controls-panel[open] .controls-summary {
  border-bottom: 1px solid var(--rule);
  margin-bottom: 16px;
}

.controls-summary:hover .controls-summary-label {
  color: var(--accent);
}

.controls-summary:hover .controls-summary-indicator {
  background: var(--accent);
  color: var(--accent-contrast);
}

.controls-body {
  padding: 0 16px;
}

.jumpto-list {
  display: flex;
  flex-direction: column;
  padding: 4px 0;
}

.jumpto-list a {
  font-size: 13.5px;
  color: var(--ink);
  text-decoration: none;
  padding: 7px 0;
  border-top: 1px solid var(--rule);
}

.jumpto-list a:first-child {
  border-top: none;
}

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

.jumpto-count {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-muted);
  margin-left: 6px;
}

/* ---------- Masthead ---------- */

.masthead {
  border-top: 3px solid var(--accent);
  border-bottom: 1px solid var(--rule);
  padding: 16px 0 20px;
  margin-bottom: 28px;
}

.masthead-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

h1.masthead-heading {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 27px;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: 0 0 5px;
}

h1.masthead-heading a {
  color: var(--ink);
  text-decoration: none;
}

h1.masthead-heading a:hover {
  color: var(--accent);
}

.masthead-dek {
  margin: 0 0 4px;
  color: var(--ink-muted);
  font-size: 14.5px;
  /* Wide enough that the current subtitle fits on one line at normal page
     widths — it still wraps naturally on narrow screens via the page's own
     max-width, this just stops it wrapping needlessly on wide ones. */
  max-width: 70ch;
}

.masthead-cta {
  margin: 0;
  font-size: 13.5px;
}

.masthead-cta a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}

.masthead-cta a:hover {
  text-decoration: underline;
}

.page-context {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  margin: 0 0 28px;
}

/* ---------- Theme toggle ---------- */

.theme-toggle {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  margin-top: 2px;
  border-radius: 999px;
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  cursor: pointer;
}

.theme-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.theme-toggle-btn {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.theme-toggle:hover .theme-toggle-btn:not(.active) {
  color: var(--accent);
}

.theme-toggle-btn.active {
  background: var(--accent);
  color: var(--accent-contrast);
}

.theme-toggle-btn svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- Nav ---------- */

.nav-links {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.03em;
  color: var(--ink-muted);
  margin-bottom: 32px;
}

.nav-links a {
  color: var(--ink-muted);
  text-decoration: underline;
  text-decoration-color: var(--rule-strong);
  text-underline-offset: 3px;
  margin-right: 18px;
}

.nav-links a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

/* ---------- Flat content sheet (replaces the old boxed "card") ---------- */

.card {
  margin-bottom: 28px;
}

.section-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 14px;
}

/* ---------- View toggle (index.html) ---------- */

.toggle-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 10px 24px;
  margin-bottom: 22px;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 8px;
}

.toggle-tabs {
  display: flex;
  align-items: center;
  gap: 24px;
}

.toggle-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.days-select {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink-muted);
  padding: 5px 6px;
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  background: var(--surface);
}

.days-select:disabled,
.icon-btn:disabled {
  opacity: 0.5;
  cursor: default;
}

.icon-btn {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  color: var(--ink-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

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

.icon-btn svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Spins the refresh icon while a digest fetch is in flight — explicit,
   speed-independent feedback (a brief opacity dim reads as a flicker on a
   fast response; a ~0.4s-per-turn spin reads as "working" either way). */
.icon-btn.is-loading svg {
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.toggle-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 0 0 10px;
  margin-bottom: -1px;
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink-muted);
  cursor: pointer;
}

.toggle-btn:hover {
  color: var(--ink);
}

.toggle-btn.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ---------- Form fields ---------- */

.field-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 14px;
  margin-bottom: 18px;
  font-size: 14.5px;
}

.field-row label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}

.field-row input[type="checkbox"] {
  accent-color: var(--accent);
  margin-right: 2px;
}

.field-email {
  flex: 1 1 auto;
  min-width: 220px;
}

.field-row .field-inline-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 400;
  color: var(--ink);
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
}

select,
input[type="email"],
input[type="text"] {
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ink);
  padding: 5px 2px;
  border: none;
  border-bottom: 1px solid var(--rule-strong);
  background: transparent;
  border-radius: 0;
}

select:focus-visible,
input:focus-visible {
  outline: none;
  border-bottom-color: var(--accent);
}

input[type="email"] {
  width: 100%;
}

.picker-note {
  font-size: 13.5px;
  color: var(--ink-muted);
  margin: 0 0 16px;
  max-width: 56ch;
}

/* ---------- Category picker (group-block, generated by app.js) ---------- */

.group-block {
  border-top: 1px solid var(--rule);
  padding: 12px 0 16px;
}

/* The first group-block sits right after .picker-toolbar, which already
   draws its own (thicker) divider below itself — an adjacent-sibling
   selector is used here rather than :first-of-type, since picker-toolbar
   is also a <div> and would otherwise count as the "first div", leaving
   this rule never actually matching and producing a doubled line. */
.picker-toolbar + .group-block {
  border-top: none;
  padding-top: 0;
}

/* A solo-group picker (e.g. "Journals only") skips the toolbar entirely, so
   its one group-block is the container's actual first child — the sibling
   rule above never matches that case, so this covers it separately. */
.group-block:first-child {
  border-top: none;
  padding-top: 0;
}

.group-header {
  margin-bottom: 10px;
}

.group-title {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15.5px;
  letter-spacing: -0.005em;
  margin-bottom: 8px;
}

.group-header-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Pushes the check-all button to the right, whether or not the reorder
   arrows are present before it (they aren't on non-reorderable pickers). */
.group-header-controls .toggle-all-btn {
  margin-left: auto;
}

/* The solo-group case (see app.js) has nothing else on this row to push
   against — left-aligned like any other lone control, not stranded on
   the right with empty space to its left. */
.group-header-controls-solo {
  margin-bottom: 10px;
}

.group-header-controls-solo .toggle-all-btn {
  margin-left: 0;
}

.arrow-btn,
.toggle-all-btn {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.03em;
  padding: 3px 8px;
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  color: var(--ink-muted);
  border-radius: 3px;
  cursor: pointer;
}

.arrow-btn:hover,
.toggle-all-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.arrow-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

.arrow-btn:disabled:hover {
  color: var(--ink-muted);
  border-color: var(--rule-strong);
}

.picker-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
  padding-bottom: 14px;
  border-bottom: 2px solid var(--rule-strong);
}

.picker-toolbar-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15.5px;
  letter-spacing: -0.005em;
}

.category-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-left: 2px;
}

.category-checkbox {
  font-size: 14.5px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.category-checkbox input {
  accent-color: var(--accent);
}

/* ---------- Buttons & status ---------- */

.submit-btn {
  background: var(--accent);
  color: var(--accent-contrast);
  border: none;
  border-radius: 3px;
  padding: 11px 24px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.submit-btn:hover {
  opacity: 0.88;
}

.status-message {
  margin-top: 14px;
  font-size: 14px;
}

.status-message.error {
  color: var(--danger);
}

.status-message.success {
  color: var(--accent);
}

.link-danger {
  color: var(--danger);
}

/* ---------- Results: group sections + index cards ---------- */

.results {
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition: opacity 0.15s ease;
}

/* While a new digest is loading, dim the CURRENT content instead of wiping
   it to a blank "Loading…" state first — the destroy-then-recreate cycle
   is what reads as a flicker, especially when the fetch resolves quickly. */
.results.is-loading {
  opacity: 0.45;
}

/* One group-section per top-level group (e.g. "Journal Publications") — a
   <details> itself, so collapsing it hides every card inside at once, the
   same native mechanism each entry-card below already uses one level down.
   The rule sits on the BOTTOM of each section, not the top: a top rule on
   the first section would double up against .toggle-row's own bottom
   border right above it. The last section skips its rule too, for the same
   reason against the footer's top border below it. */
.group-section {
  border-bottom: 3px solid var(--accent);
  padding-bottom: 20px;
}

.group-section:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.group-section-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 2px 10px;
  cursor: pointer;
  list-style: none;
}

.group-section-header::-webkit-details-marker {
  display: none;
}

.group-section-title {
  flex: 1;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 19px;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.group-section-count {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-muted);
  flex-shrink: 0;
}

.group-section-indicator {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--rule-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--accent);
}

.group-section-header:hover .group-section-indicator {
  background: var(--accent);
  color: var(--accent-contrast);
  border-color: var(--accent);
}

.group-section-indicator::before {
  content: "\2212";
}

.group-section:not([open]) .group-section-indicator::before {
  content: "+";
}

.group-section-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 2px 0 26px;
}

.entry-card {
  background: var(--surface);
  border: 1.5px solid var(--rule-strong);
  border-radius: 5px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}

.entry-card-header {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  padding: 0;
  background: var(--accent-soft);
  cursor: pointer;
  list-style: none;
}

.entry-card-header::-webkit-details-marker {
  display: none;
}

.entry-card[open] > .entry-card-header {
  border-bottom: 1px solid var(--rule);
}

.entry-card-header-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: 1;
  min-width: 0;
  gap: 10px;
  padding: 10px 16px;
}

.entry-card-label {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--accent);
}

.entry-card-count {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-muted);
  flex-shrink: 0;
}

.entry-card-indicator {
  width: 38px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 15px;
  color: var(--accent);
  background: var(--surface);
}

.entry-card-header:hover .entry-card-indicator {
  background: var(--accent);
  color: var(--accent-contrast);
}

.entry-card-indicator::before {
  content: "\2212";
}

.entry-card:not([open]) .entry-card-indicator::before {
  content: "+";
}

.entry-list {
  list-style: none;
  margin: 0;
  padding: 4px 16px;
  max-height: 420px;
  overflow-y: auto;
}

.entry {
  padding: 12px 0;
  border-top: 1px solid var(--rule);
}

.entry:first-child {
  border-top: none;
}

.entry-date {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-muted);
  letter-spacing: 0.02em;
  margin-right: 8px;
}

.entry-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: -0.005em;
  color: var(--ink);
  text-decoration: none;
}

.entry-title:hover {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--rule-strong);
}

.entry-desc {
  margin: 5px 0 0;
  font-size: 13.5px;
  color: var(--ink-muted);
  line-height: 1.5;
}

.entry-from {
  display: block;
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-muted);
  opacity: 0.85;
}

.empty-state {
  color: var(--ink-muted);
  font-size: 14.5px;
  padding: 24px 0;
  text-align: center;
  font-style: italic;
}

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

footer.site-footer {
  margin-top: 48px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.03em;
  line-height: 1.7;
  color: var(--ink-muted);
}

footer.site-footer a {
  color: var(--ink-muted);
  text-decoration: underline;
}

footer.site-footer a:hover {
  color: var(--accent);
}
