:root {
  --ink: #1b1b1f;
  --muted: #6b6b76;
  --line: #e3e3e8;
  --accent: #2952e3;
  --accent-soft: #eef1fd;
  --bg: #fafafa;
  --card: #ffffff;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--ink);
  line-height: 1.5;
}

.wrap {
  max-width: 860px;
  margin: 0 auto;
  padding: 32px 24px 80px;
}
/* An item's reading page needs much more width than a plain text column — up to two 300px side
   panels (General Comments, Inline Comments) plus the reader itself, which should stay the
   biggest thing on screen regardless of whether either panel is present. Centered like the
   default .wrap (not left-aligned — that was tried and reverted, since flush-left read as
   asymmetric/off), but with a much higher cap than .wrap's 860px: 1900px means centering only
   actually produces a visible gap on genuinely ultra-wide windows (beyond roughly sidebar + 1900px
   content + padding ≈ 2190px) — on ordinary/maximized windows the content simply fills the
   available width edge-to-edge, so there's nothing to center *away from*. */
.wrap-reader { max-width: 1900px; }

header.top {
  border-bottom: 1px solid var(--line);
  background: var(--card);
}

header.top .wrap {
  max-width: none;
  margin: 0;
  padding: 18px 24px;
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
}

header.top a.brand {
  font-weight: 700;
  font-size: 18px;
  color: var(--ink);
  text-decoration: none;
}

.breadcrumb {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 20px;
}
.breadcrumb a { color: var(--muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--accent); text-decoration: underline; }
.breadcrumb .sep { margin: 0 6px; }

h1 { font-size: 26px; margin: 0 0 6px; }
h2 { font-size: 18px; margin: 32px 0 12px; }
.sub { color: var(--muted); font-size: 14px; margin-bottom: 28px; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 20px;
  margin-bottom: 16px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
  margin-bottom: 8px;
}

.tile {
  display: block;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 16px;
  text-decoration: none;
  color: var(--ink);
  transition: border-color .12s ease;
}
.tile:hover { border-color: var(--accent); }
.tile .tile-title { font-weight: 600; font-size: 15px; margin-bottom: 4px; }
.tile .tile-meta { font-size: 12px; color: var(--muted); }

.badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 2px 8px;
  margin-top: 8px;
}

.item-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
}
.item-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 16px;
}
.item-row.dragging { opacity: 0.4; }
.item-row .drag-handle {
  cursor: grab;
  color: var(--muted);
  font-size: 16px;
  line-height: 1;
  user-select: none;
  padding: 4px;
}
.item-row .drag-handle:active { cursor: grabbing; }
.item-row a.item-link {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  text-decoration: none;
  color: var(--ink);
}
.item-row .item-title { font-weight: 600; font-size: 15px; }
.item-row .item-meta { font-size: 12px; color: var(--muted); }

form.inline-form {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

input[type=text], input[type=file], select, textarea {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
}

button, input[type=submit] {
  font: inherit;
  padding: 8px 14px;
  border-radius: 6px;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
}
button.secondary {
  background: #fff;
  color: var(--accent);
}
button.small, .btn-small {
  padding: 4px 10px;
  font-size: 12px;
}

label { font-size: 13px; color: var(--muted); }

.version-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.version-row:last-child { border-bottom: none; }
.version-row .live-tag {
  color: var(--accent);
  font-weight: 600;
  font-size: 12px;
  margin-left: 8px;
}

/* Reader row: optional Author's Note (left) + reader (center, flexes to fill) + optional
   General Comments (right). Either side panel is absent from the DOM entirely when it has
   nothing to show, so the reader is centered/full-width rather than leaving dead space. */
.reader-layout {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  margin-bottom: 20px;
}
.reader-col {
  flex: 1 1 auto;
  /* Guarantees the reader never gets squeezed down to near-nothing when both side panels (General
     Comments + Inline Comments, 300px each) are present at once — if the window genuinely isn't
     wide enough for min-width plus both panels, the row overflows/scrolls instead of the reader
     silently shrinking into unreadability, which is the wrong tradeoff for the page's main content. */
  min-width: 640px;
}

/* General Comments lives here, on the left of the reader. Author's Note is a full-width banner
   above .reader-layout instead (see .author-note-banner) — this stack exists for whatever else
   ends up on the left, not just General Comments specifically. */
.reader-left-stack {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 0 0 auto;
}

/* Author's Note as a full-width banner above the reader, not a side panel — reuses .side-panel
   for its border/collapse styling but overrides the fixed 300px width. */
.side-panel.author-note-banner {
  width: auto;
  margin-bottom: 20px;
}

/* Minimal, auto-width slot for "+ Add general comment" when there are no comments yet — doesn't
   reserve a full 300px column for an empty state. */
.reader-side-add { flex: 0 0 auto; align-self: flex-start; }
.reader-side-add .details-toggle summary { margin-top: 0; }

.side-panel {
  /* flex-basis left at auto (not a fixed length) on purpose — a fixed-length flex-basis applies
     to the main axis, which is vertical once nested inside .reader-left-stack's column layout;
     `width` alone is direction-safe and does the actual sizing here. */
  flex: 0 0 auto;
  width: 300px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  padding: 16px;
  align-self: flex-start;
}
.side-panel.is-collapsed {
  flex: 0 0 auto;
  width: auto;
  padding: 10px 14px;
}
.side-panel.is-collapsed .side-panel-body { display: none; }

.side-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.side-panel.is-collapsed .side-panel-head { justify-content: flex-start; }
.side-panel-head h2 { margin: 0; font-size: 15px; white-space: nowrap; }

.side-panel-toggle {
  font: inherit;
  font-size: 12px;
  color: var(--muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 4px 8px;
  cursor: pointer;
  white-space: nowrap;
}
.side-panel-toggle:hover { color: var(--accent); border-color: var(--accent); }

.side-panel-body { margin-top: 14px; }

.author-note-text {
  font-size: 14px;
  white-space: pre-wrap;
  word-wrap: break-word;
  margin: 0 0 10px;
}

.reader {
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 20px;
}
.reader-layout .reader { margin-bottom: 0; }

.pdf-reader {
  display: flex;
  flex-direction: column;
  max-height: 85vh;
}
.pdf-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--card);
  flex-shrink: 0;
}
.pdf-toolbar button {
  font: inherit;
  font-size: 13px;
  padding: 5px 10px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink);
  cursor: pointer;
}
.pdf-toolbar button:hover { border-color: var(--accent); color: var(--accent); }
.pdf-toolbar button:disabled {
  opacity: 0.4;
  cursor: default;
  border-color: var(--line);
  color: var(--ink);
}
.pdf-zoom-level {
  font-size: 13px;
  color: var(--muted);
  min-width: 42px;
  text-align: center;
  user-select: none;
}
#pdf-comment-mode.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
#pdf-diff-toggle.active {
  background: #2f9e4f;
  color: #fff;
  border-color: #2f9e4f;
}
/* Explains the on-page "***" removal markers once, instead of spelling it out at every single
   one — a sibling of .pdf-pages (not inside it), so it's outside .pdf-pages' own internal scroll
   and stays visible the whole time diff mode is showing removals, no matter how far down the
   document you've scrolled. Shown/hidden by public/js/pdf-viewer.js alongside the markers
   themselves — only worth showing when there's at least one "***" on the page to explain. */
/* Diff-mode banner title (2026-07-19) — names the revision color ("Green Revisions"), sitting
   directly above the removal legend. Same sibling-of-.pdf-pages placement, so it also stays put
   through any internal scrolling. The color here is the same revision green the marks use; when
   per-Version revision colors land, this (and the title's text) follow the Version's color. */
.pdf-diff-title {
  padding: 5px 12px 3px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: #2f9e4f;
  background: rgba(47, 158, 79, 0.12);
  flex-shrink: 0;
}
.pdf-diff-legend {
  padding: 4px 12px;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  background: rgba(47, 158, 79, 0.9);
  flex-shrink: 0;
}
.pdf-page-count {
  font-size: 12px;
  color: var(--muted);
  margin-left: auto;
  white-space: nowrap;
}
.pdf-pages {
  overflow: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  background: #f2f2f4;
}
/* No max-width here on purpose — the wrapper's inline width (set in JS to match the PDF page's
   actual rendered pixel size, public/js/pdf-viewer.js) needs to be able to genuinely exceed the
   container once zoomed in past "fit," so .pdf-pages' own overflow:auto can scroll to it. A
   max-width: 100% here silently caps the *displayed* size at the container's width regardless of
   how far you've "zoomed in" — the percentage keeps climbing but the page visually stops growing,
   which is exactly the bug this comment is here to prevent reintroducing. */
.pdf-page-wrap {
  position: relative;
  /* Adapted from pdfjs-dist's own web/pdf_viewer.css (.pdfViewer .page) — the piece that was
     missing the first time the text layer was attempted: pdf.js's TextLayer class positions
     spans using --total-scale-factor but never sets it itself, expecting the caller to. Default
     of 1 here; public/js/pdf-viewer.js sets --scale-factor on each wrapper to match its actual
     render scale, and --total-scale-factor derives from that automatically via calc(). */
  --scale-factor: 1;
  --user-unit: 1;
  --total-scale-factor: calc(var(--scale-factor) * var(--user-unit));
  --scale-round-x: 1px;
  --scale-round-y: 1px;
}
.pdf-pages.comment-mode .pdf-page-wrap { cursor: crosshair; }
.pdf-page {
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
  display: block;
}

/* Invisible, selectable text overlaid on the canvas — adapted (minimal subset) from pdf.js's own
   .textLayer rule in web/pdf_viewer.css. This is what makes click-and-drag text selection (for a
   highlight comment) possible at all; without it the canvas is just pixels, nothing to select. */
.pdf-text-layer {
  position: absolute;
  inset: 0;
  overflow: clip;
  opacity: 1;
  line-height: 1;
  text-align: initial;
  letter-spacing: normal;
  word-spacing: normal;
  transform-origin: 0 0;
  z-index: 1;
  --min-font-size: 1;
  --text-scale-factor: calc(var(--total-scale-factor) * var(--min-font-size));
  --min-font-size-inv: calc(1 / var(--min-font-size));
}
.pdf-text-layer span,
.pdf-text-layer br {
  color: transparent;
  position: absolute;
  white-space: pre;
  cursor: text;
  transform-origin: 0% 0%;
  user-select: text;
}
.pdf-text-layer > :not(.markedContent),
.pdf-text-layer .markedContent span:not(.markedContent) {
  --font-height: 0;
  font-size: calc(var(--text-scale-factor) * var(--font-height));
  --scale-x: 1;
  --rotate: 0deg;
  transform: rotate(var(--rotate)) scaleX(var(--scale-x)) scale(var(--min-font-size-inv));
}
.pdf-text-layer .markedContent { display: contents; }
.pdf-text-layer ::selection { background: rgba(41, 82, 227, 0.3); }

/* Existing highlight comments — semi-transparent marks over the anchored quads, plus one numbered
   badge per highlight (positioned at the first quad, matching how a pin's badge sits at its
   point). Unlike a pin, a highlight can span multiple quads (one per line the selection crossed). */
.pdf-highlight-mark {
  position: absolute;
  background: rgba(255, 196, 0, 0.35);
  border-radius: 2px;
  pointer-events: none;
  z-index: 2;
}

/* Version-diff marks ("show changes since v<N-1>," public/js/pdf-viewer.js's applyDiffMarksForPage)
   — a thick colored underline, not a background fill (2026-07-17, was a translucent green box
   before) — deliberately a different *shape* of mark from the yellow comment-highlight below, not
   just a different hue, so the two stay visually distinguishable even if a future per-Person
   comment color and a future per-Version diff color ever happened to land on similar hues (the
   tension flagged in Section 9.6's roadmap entry). No `background` at all now — solid, fully
   opaque border color (not translucent, unlike the highlight below) so it reads clearly at a
   glance. Higher `z-index` than `.pdf-highlight-mark` so the underline stays visible on top if a
   comment highlight and a diff addition ever land on the same span of text, rather than the two
   blending or the highlight's fill obscuring it. */
.pdf-diff-mark {
  position: absolute;
  border-bottom: 5px solid #2f9e4f;
  pointer-events: none;
  z-index: 4;
}

/* Removal marker — a small "***" badge, vertically aligned with the exact line in the *current*
   page where text used to sit (public/js/pdf-viewer.js's applyRemovedMarksForPage). Two-level
   structure, not one absolutely-positioned element (2026-07-17 — a single `left: 100%` element
   anchored to the *page's* right edge worked fine at "fit" zoom, but scrolled out of view once
   zoomed in past it and the page became wider than the visible .pdf-pages viewport; a real report,
   not a hypothetical):
     .pdf-diff-removed-row — zero-height, spans the *full page width* (`left/right: 0`), absolutely
       positioned only vertically, at the removal's line. Exists purely to give the sticky child
       below room to track across the whole page width, however much of it is currently off-screen.
     .pdf-diff-removed-mark — position: sticky; right: 8px *inside* that row, so it hovers at the
       right edge of whatever's currently visible in .pdf-pages (verified in isolation before
       wiring in — a standalone sticky-in-a-wide-absolutely-positioned-row test, scrolled and
       measured/screenshotted, confirmed the marker's screen position stays fixed relative to the
       viewport regardless of scroll position), not the page's own right edge.
   The actual removed words are still never shown inline, only via this element's title tooltip.
   Same green family as an addition mark (not a contrasting red) — both describe "this changed
   since last version," just in different directions, so they read as one family rather than two
   unrelated systems. pointer-events left enabled on the mark (unlike .pdf-diff-mark) specifically
   so the tooltip is reachable on hover; the row itself has none, so it never intercepts clicks
   meant for the page underneath it. */
.pdf-diff-removed-row {
  position: absolute;
  left: 0;
  right: 0;
  width: 100%;
  height: 0;
  pointer-events: none;
}
.pdf-diff-removed-mark {
  position: sticky;
  right: 8px;
  display: inline-block;
  float: right;
  transform: translateY(-50%);
  font-size: 13px;
  font-weight: 700;
  color: #fff;
  background: rgba(47, 158, 79, 0.9);
  border-radius: 3px;
  padding: 1px 5px;
  cursor: default;
  pointer-events: auto;
  z-index: 3;
}

.pdf-pin-marker {
  position: absolute;
  transform: translate(-50%, -50%);
  /* min-width + border-radius as a fixed pixel value (not 50%, which distorts into an ellipse
     once width > height) — 2026-07-19: the badge now shows "initial + page number" (e.g. "M3"),
     not a single-digit count, so it needs to grow past a strict circle for 2+ characters while
     still reading as a rounded "pill" badge, not a stretched oval. */
  min-width: 22px;
  height: 22px;
  padding: 0 5px;
  border-radius: 11px;
  background: var(--accent);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  cursor: default;
  z-index: 5;
}

.pdf-pin-popover {
  /* Fixed (viewport-relative), not absolute within the scrollable .pdf-pages — otherwise a click
     near the edge of the visible area can place the popover partly or fully outside the visible,
     scrolled viewport of that container, effectively making it disappear. Position is computed
     and clamped in JS from the click's viewport coordinates. */
  position: fixed;
  z-index: 30;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
  padding: 12px;
  width: 260px;
  visibility: hidden;
}
.pdf-pin-popover.is-positioned { visibility: visible; }
.pdf-pin-popover .inline-form {
  flex-direction: column;
  align-items: stretch;
}
.pdf-pin-popover textarea { min-height: 60px; }
.pdf-pin-error { color: #b3261e; font-size: 12px; }

@keyframes comment-flash-pulse {
  0%, 100% { background-color: var(--card); }
  30% { background-color: var(--accent-soft); }
}
.comment-thread.comment-flash .comment-row { animation: comment-flash-pulse 1.2s ease; }

@keyframes pin-flash-pulse {
  0%, 100% { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35); }
  30% { box-shadow: 0 0 0 6px var(--accent-soft), 0 1px 3px rgba(0, 0, 0, 0.35); }
}
.pdf-pin-marker.pin-flash { animation: pin-flash-pulse 1.2s ease; }

/* Highlight badges reuse .pdf-pin-marker's shape/position/click behavior wholesale — only the
   color differs, so a glance at the page tells a highlight comment apart from a plain pin. */
.pdf-highlight-badge { background: #b8860b; }

/* Inline Comments' per-commenter tabs (comment-tabs.ejs) also filter which pins/highlights show
   on the page itself, not just the panel rows — public/js/pdf-viewer.js toggles this on a pin
   marker, a highlight badge, or a highlight's own fill rect(s) to match the selected tab. */
.pdf-anchor-hidden { display: none !important; }

/* Floating card for viewing an existing Inline Comment (2026-07-18) — reuses .pdf-pin-popover's
   positioning/clamp/visibility rules wholesale (public/js/pdf-viewer.js applies both classes to
   the same wrapper), only overriding size and adding scroll for a long thread. */
.pdf-comment-card {
  width: 360px;
  max-height: 70vh;
  overflow-y: auto;
}
.pdf-comment-card .comment-list { margin: 0; }
.pdf-comment-card-close {
  float: right;
  background: none;
  border: none;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  color: var(--muted);
  padding: 0 0 6px 8px;
}
.pdf-comment-card-close:hover { color: var(--accent); }

/* Compact nav row (comment-nav-row.ejs) — the Inline Comments panel is navigation-only now: badge,
   author, short preview, reply count, resolved tag — no body/replies/reply-form/delete/resolve
   here, only in the floating card above. Border/background match .comment-row's own bordered-card
   treatment (just more compact padding) specifically so the per-Person border-left-color override
   (2026-07-18, comment-nav-row.ejs) has a border to actually color — .comment-nav-row previously
   had no border of its own at all. */
.comment-nav-row {
  background: var(--card);
  border: 1px solid var(--line);
  border-left-width: 4px;
  border-left-color: var(--person-color, var(--line));
  border-radius: 8px;
  padding: 8px 10px;
}
.comment-nav-row-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  font: inherit;
  cursor: pointer;
  padding: 0;
}
.comment-nav-row-btn:hover { color: var(--accent); }
.comment-nav-preview {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
  font-size: 12px;
}

/* Narrower than the shared 300px .side-panel default — the nav-only redesign no longer needs room
   for full comment bodies, directly addressing the long-flagged "panel stretches the reader too
   much" complaint (CLAUDE.md Section 10). */
.side-panel.inline-comments-col { width: 240px; }

.reader pre {
  white-space: pre-wrap;
  word-wrap: break-word;
  padding: 24px;
  margin: 0;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 15px;
  max-height: 75vh;
  overflow-y: auto;
}

.empty {
  color: var(--muted);
  font-size: 14px;
  padding: 20px 0;
}

/* First-run orientation on the empty home page (2026-07-26) — a friendly callout instead of a bare
   "No Tables yet" line, so a brand-new tester (esp. one who arrived expecting to be on a Table)
   isn't dropped onto an empty page with no context. */
.onboard-callout {
  background: var(--accent-soft);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 20px 24px;
  max-width: 640px;
  margin-top: 8px;
}
.onboard-callout h2 { margin: 0 0 10px; font-size: 20px; }
.onboard-callout p { margin: 0 0 10px; color: var(--ink); line-height: 1.5; }
.onboard-callout .onboard-next { margin-top: 4px; }
.onboard-callout ul { margin: 0; padding-left: 20px; color: var(--ink); line-height: 1.5; }
.onboard-callout li { margin-bottom: 6px; }

/* position: relative so a .page-actions popover card (position: absolute, 2026-07-21) has
   something to anchor to — without this, an absolutely-positioned child falls back to the nearest
   *actually* positioned ancestor further up the tree, which reads as "nothing opens" (the details
   really does toggle open, its card just renders detached from the button, off in some unrelated
   spot). Harmless everywhere else .details-toggle is used (plain in-flow .card content, like
   "+ Add Reading") since relative positioning with no offset behaves exactly like static layout. */
/* .section-panel (2026-07-22) — visually identical to .details-toggle's summary but deliberately
   NOT in flyouts.js's auto-close selector: for a page section meant to just sit open by default
   (the Table page's "Loose Pieces" list), not a click-to-reveal popover that should vanish the
   moment you click elsewhere. */
.section-panel summary {
  cursor: pointer;
  font-size: 14px;
  color: var(--accent);
  margin: 20px 0 8px;
}

.details-toggle { position: relative; }
.details-toggle summary {
  cursor: pointer;
  font-size: 14px;
  color: var(--accent);
  margin: 20px 0 8px;
}

.details-toggle.primary summary {
  display: inline-block;
  list-style: none;
  color: #fff;
  background: var(--accent);
  padding: 10px 18px;
  border-radius: 6px;
  font-weight: 600;
  margin: 20px 0 8px;
}
.details-toggle.primary summary::-webkit-details-marker { display: none; }
.details-toggle.primary[open] summary {
  border-radius: 6px 6px 0 0;
  margin-bottom: 0;
}

.details-toggle.primary.compact summary {
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 500;
}

.siblings-zone {
  margin-top: 36px;
  padding-top: 20px;
  border-top: 2px dashed var(--line);
}
.siblings-zone h2 {
  margin-top: 0;
}

.pill-row { display: flex; gap: 8px; align-items: center; }

/* Upper-right settings affordance, used on Table/Read/Item pages alike. Settings content itself
   is expected to grow a lot (Section 2 of CLAUDE.md) — this is just a consistent place to put
   whatever settings exist for the current page's level, not a finished settings design. */
.page-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 20px;
}
.page-head h1 { margin: 0; }

.page-settings {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
  padding-top: 2px;
}

.settings-toggle { position: relative; }
.settings-toggle summary {
  cursor: pointer;
  list-style: none;
  font-size: 13px;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px 12px;
  background: var(--card);
  white-space: nowrap;
}
.settings-toggle summary::-webkit-details-marker { display: none; }
.settings-toggle summary:hover { color: var(--accent); border-color: var(--accent); }
.settings-toggle[open] summary { color: var(--accent); border-color: var(--accent); }

/* Link to the comment checklist page (Roadmap 9.4, 2026-07-18) — same visual weight as a
   .settings-toggle summary, so it sits comfortably alongside "⚙ Settings" in .page-settings. */
.export-comments-link {
  font-size: 13px;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px 12px;
  background: var(--card);
  white-space: nowrap;
  text-decoration: none;
}
.export-comments-link:hover { color: var(--accent); border-color: var(--accent); }

/* Checklist checkbox (independent of Resolve — see comment-thread-body.ejs) on the comment
   checklist page. Checked entries dim and strike through for a quick sense of progress. */
.checklist-checkbox { margin-right: 8px; width: 16px; height: 16px; vertical-align: middle; }
.comment-row.is-checked { opacity: 0.55; }
.comment-row.is-checked .comment-body { text-decoration: line-through; }

/* Comment Checklist page (2026-07-18) — deliberately smaller/denser than the reader's own comment
   rendering: this page is meant to be scanned and clicked through quickly, not read leisurely, and
   every row on it is guaranteed non-collapsible (comment-thread.ejs's noCollapse), so there's no
   risk of a compact row hiding something important behind a toggle. Scoped under .checklist-page
   (set on comment-checklist.ejs's own .wrap) so none of this leaks into the reader page, which
   still uses the full-size .comment-row/.comment-list/h2 styling. */
.checklist-page h2 {
  font-size: 15px;
  margin: 18px 0 8px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.checklist-page .comment-list { gap: 6px; }
.checklist-page .comment-row {
  padding: 6px 10px;
  border-radius: 6px;
}
.checklist-page .comment-meta { font-size: 12px; margin-bottom: 2px; }
.checklist-page .comment-body { font-size: 13px; }
.checklist-page .comment-replies {
  margin: 4px 0 0 14px;
  padding-left: 8px;
  gap: 4px;
}
.checklist-page .comment-reply { padding: 4px 8px; }
.checklist-page .details-toggle summary { font-size: 12px; margin: 4px 0; }
.checklist-page .comment-delete,
.checklist-page .comment-resolve-form { font-size: 11px; }
.checklist-page .comment-edit summary { font-size: 11px; }

/* Signed-in indicator + logout in every page header (2026-07-19, real accounts). header.top's
   .wrap deliberately doesn't use the centered column (see the Change Log on left-justifying the
   brand), so this just floats the menu to the row's right edge. */
header.top .wrap { display: flex; align-items: center; justify-content: space-between; }
.user-menu { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.user-menu-name { color: var(--muted); }
.user-menu-logout { display: inline; margin: 0; }
.user-menu-logout .link-button { font-size: 13px; }
/* Account Settings + Admin flyouts, inline in the user-menu (2026-07-21 — replaces the old
   standalone pages and the plain admin-badge link). The user-menu name itself always shows the
   EFFECTIVE identity (e.g. "Marc," even while admin is viewing as them); this toggle is the one
   thing that stays admin-labeled regardless of impersonation, so it's the one place admin can
   always reach the impersonation switcher, even while deep in someone else's view. */
.settings-toggle.admin-toggle summary {
  color: #a65d00;
  border-color: #d9a15c;
}
.settings-toggle.admin-toggle summary:hover,
.settings-toggle.admin-toggle[open] summary { color: #8a4d00; border-color: #8a4d00; }

/* Login / signup page (2026-07-19) — the one surface that renders with no sidebar/session. */
.login-page { display: flex; justify-content: center; padding: 60px 20px; }
.login-card { width: 100%; max-width: 380px; padding: 24px; }
.login-card h1 { font-size: 20px; margin: 0 0 16px; }
.login-form { display: flex; flex-direction: column; gap: 12px; }
.login-form label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--muted); }
.login-form input { width: 100%; }
.login-error { color: #b3261e; font-size: 13px; margin: 0 0 12px; }
.login-switch { margin: 14px 0 0; }

.acting-as-note { font-size: 13px; color: var(--muted); }
.acting-as-note strong { color: var(--ink); }
.link-button {
  background: none;
  border: none;
  padding: 0;
  color: var(--muted);
  font-size: 12px;
  text-decoration: underline;
  cursor: pointer;
}
.link-button:hover { color: var(--accent); }

.settings-toggle .card {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 300px;
  z-index: 30;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}
.settings-toggle .card form.inline-form {
  flex-direction: column;
  align-items: stretch;
}
.settings-toggle .card input[type=text],
.settings-toggle .card select {
  width: 100%;
}

.settings-section + .settings-section {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
/* Per-Person color picker (Table Settings → People, 2026-07-17) — a row of small clickable
   swatches from the curated palette (db.js's PERSON_COLORS), submitted together with the rest of
   that Person's row (name/role) rather than auto-submitting on click, consistent with how those
   fields already work. The actual <input type="radio"> is invisible (opacity: 0) but still real
   and clickable, filling the swatch; :has() drives the "selected" ring so no JS is needed to keep
   the visual state in sync with which radio is actually checked. */
.color-swatch-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  align-items: center;
}
.color-swatch {
  position: relative;
  display: inline-block;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid transparent;
}
.color-swatch input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}
.color-swatch:has(input:checked) {
  border-color: var(--ink);
  box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--ink);
}
/* Read-only color dot on a People roster row (Table Settings, 2026-07-20) — color itself is now
   set from each account's own Account Settings, not editable here, so this is just a glance-able
   indicator rather than a picker like .color-swatch above. */
.color-swatch-static {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  flex-shrink: 0;
}
.comment-tabs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.comment-tab {
  font: inherit;
  font-size: 13px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--muted);
  cursor: pointer;
}
.comment-tab:hover { border-color: var(--accent); color: var(--accent); }
.comment-tab.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.comment-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 8px;
}
.comment-thread.comment-hidden { display: none; }
.comment-row {
  background: var(--card);
  border: 1px solid var(--line);
  /* Per-Person color accent (2026-07-17, moved to Account Settings 2026-07-20) — a thicker left
     border, driven by the --person-color custom property set per-row via inline style
     (views/partials/comment-thread-body.ejs etc.) from that comment's author's account color.
     Reading it through a custom property (not a direct border-left-color override) is what lets
     public/js/live-color.js recolor an already-rendered row in place when you change your color,
     with no reload. Falls back to the ordinary border color when there's no linked Person (a rare
     edge case) rather than leaving a hard-coded default color that would look like everyone's. */
  border-left-width: 4px;
  border-left-color: var(--person-color, var(--line));
  border-radius: 10px;
  padding: 12px 16px;
}
/* Inline Comment rows (has a pin) are clickable anywhere on them to jump to the pin on the page
   — see the [data-goto-pin] handler in public/js/pdf-viewer.js. General Comment rows and replies
   don't get this attribute, so they stay non-interactive as plain cards. */
.comment-row[data-goto-pin] { cursor: pointer; }
.comment-row[data-goto-pin]:hover { border-color: var(--accent); }
.comment-meta { font-size: 13px; margin-bottom: 4px; }
.comment-meta .comment-date { color: var(--muted); font-size: 12px; margin-left: 6px; }
.comment-body { font-size: 14px; white-space: pre-wrap; word-wrap: break-word; }

/* Pin badge on an Inline Comment's list entry — matches the marker drawn on the PDF page itself
   (public/js/pdf-viewer.js), so the two are visually tied together. Shows the commenter's initial
   + page number (2026-07-19, e.g. "M3") in that Person's own color (set inline per-badge by
   whichever partial renders it — comment-thread-body.ejs, comment-thread.ejs, comment-nav-row.ejs
   — falling back to this rule's plain --accent blue for the rare comment with no linked Person).
   min-width + a fixed-pixel border-radius (not 50%, which distorts into an ellipse once
   width > height) keeps it reading as a rounded "pill" for 2+ characters instead of a circle that
   would clip them. */
.pin-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--person-color, var(--accent));
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  margin-right: 2px;
  white-space: nowrap;
}
.comment-page-badge { font-size: 11px; color: var(--muted); margin-left: 6px; }

.thread-toggle {
  font: inherit;
  font-size: 12px;
  color: var(--muted);
  background: none;
  border: none;
  padding: 8px 0 0;
  margin-left: 4px;
  cursor: pointer;
  display: block;
}
.thread-toggle:hover { color: var(--accent); }

.comment-replies {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 10px 0 0 18px;
  padding-left: 12px;
  border-left: 2px solid var(--line);
}
.comment-replies.is-collapsed { display: none; }
.comment-reply { padding: 10px 12px; }

/* Resolve state (Roadmap 9.4) — the badge shown both on an un-collapsed resolved comment (its own
   poster's view) and inside the collapsed summary below (everyone else's view). */
.resolved-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  color: #2f9e4f;
  background: #eafaf0;
  border: 1px solid #bfe8cd;
  border-radius: 999px;
  padding: 1px 8px;
  margin-left: 6px;
  vertical-align: middle;
}
.comment-resolve-form { display: inline-block; margin-left: 10px; }

/* A resolved thread collapses to this compact, clickable/expandable summary for everyone except
   the person who posted it (views/partials/comment-thread.ejs) — the full row/replies markup
   (comment-thread-body.ejs) only renders once the <details> is opened. */
.comment-collapsed summary {
  cursor: pointer;
  list-style: none;
  font-size: 13px;
  color: var(--muted);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px 12px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.comment-collapsed summary::-webkit-details-marker { display: none; }
.comment-collapsed summary:hover { border-color: var(--accent); }
.comment-collapsed[open] summary { border-radius: 10px 10px 0 0; border-bottom-color: transparent; }
.comment-collapsed-preview {
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1 1 auto;
}
.comment-collapsed-replies { font-size: 11px; color: var(--muted); flex-shrink: 0; }
.comment-collapsed .comment-row { border-radius: 0 0 10px 10px; border-top: none; }

.reply-toggle { display: inline-block; }
.reply-toggle summary { font-size: 12px; margin: 8px 0 0; }
.comment-edit { display: inline-block; margin-left: 12px; }
.comment-edit summary { font-size: 12px; margin: 8px 0 0; }
.comment-edit .comment-edit-form { margin-top: 6px; }
.comment-delete { display: inline-block; margin: 8px 0 0 12px; }
.comment-delete .link-button { font-size: 12px; }
.comment-edited { color: var(--muted); font-size: 12px; font-style: italic; margin-left: 4px; }

.child-label-custom-wrap { display: block; }
.child-label-custom-wrap.is-hidden { display: none; }
.child-label-custom-wrap input[type=text] { margin-top: 6px; }

.settings-section h3 {
  margin: 0 0 8px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
}

.layout {
  display: flex;
  align-items: flex-start;
}
.layout > .wrap {
  flex: 1 1 auto;
  min-width: 0;
}
.sidebar {
  width: 240px;
  flex-shrink: 0;
  border-right: 1px solid var(--line);
  background: var(--card);
  min-height: calc(100vh - 60px);
  padding: 20px 14px;
}
.sidebar-table {
  margin-bottom: 4px;
}
.sidebar-table summary {
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  padding: 6px 4px;
  border-radius: 6px;
  list-style: none;
}
.sidebar-table summary::-webkit-details-marker { display: none; }
.sidebar-table summary::before {
  content: "▸ ";
  color: var(--muted);
  font-size: 11px;
}
.sidebar-table[open] > summary::before {
  content: "▾ ";
}
.sidebar-table summary:hover { background: var(--accent-soft); }
.sidebar-table summary.current { color: var(--accent); }

.sidebar-table summary a,
.sidebar-read-details summary a {
  color: inherit;
  text-decoration: none;
}
.sidebar-table summary a:hover,
.sidebar-read-details summary a:hover {
  text-decoration: underline;
}

.sidebar-reads {
  display: flex;
  flex-direction: column;
  padding: 2px 0 6px 16px;
}

.sidebar-read-details {
  margin-bottom: 2px;
}
.sidebar-read-details summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  padding: 5px 4px;
  border-radius: 6px;
  list-style: none;
}
.sidebar-read-details summary::-webkit-details-marker { display: none; }
.sidebar-read-details summary::before {
  content: "▸ ";
  color: var(--muted);
  font-size: 10px;
}
.sidebar-read-details[open] > summary::before {
  content: "▾ ";
}
.sidebar-read-details summary:hover { background: var(--accent-soft); }
.sidebar-read-details summary.current { color: var(--accent); }

.sidebar-items {
  display: flex;
  flex-direction: column;
  padding: 2px 0 6px 18px;
}
.sidebar-items a.sidebar-item {
  display: block;
  font-size: 12px;
  color: var(--muted);
  text-decoration: none;
  padding: 4px;
  border-radius: 6px;
}
.sidebar-items a.sidebar-item:hover { background: var(--accent-soft); color: var(--ink); }
.sidebar-items a.sidebar-item.current { color: var(--accent); font-weight: 600; background: var(--accent-soft); }

/* ==========================================================================
   2026-07-21 redesign pass: Tables/Readings visual hierarchy, tabbed
   Settings, flyouts everywhere, inline-editable titles/notes, sidebar
   reorder + persistent expand state. Placeholder colors — explicitly called
   out as temporary by the user, real palette to follow later.
   ========================================================================== */

:root {
  --table-brown: #6b4a34;
  --reading-teal: #cfe9e4;
  --reading-teal-ink: #1d4a44;
}

/* Small subheading under a page title ("Readings" / "Scripts" etc., 2026-07-21) — deliberately
   lighter than the default h2 (used for General/Inline Comments panel headers etc.), since this
   one's job is just labeling the list right below it, not introducing a new visual section. */
.section-subheading {
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  margin: 18px 0 8px;
}

/* ---- Table tiles (home page) — the biggest element on the page, big square brown buttons ---- */
.tile-table-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 16px;
  margin: 20px 0;
}
.tile-table {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  background: var(--table-brown);
  color: #fff;
  border: none;
  border-radius: 12px;
  padding: 14px;
  text-decoration: none;
  font-weight: 700;
  font-size: 16px;
  text-align: center;
  word-break: break-word;
  transition: opacity .12s ease;
}
.tile-table:hover { opacity: .88; }
.tile-table.dragging { opacity: .4; }

/* ---- Reading tiles (Table view) — rectangles taller than wide, pale teal ---- */
.tile-reading-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 14px;
  margin-bottom: 8px;
}
.tile-reading {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 130px;
  background: var(--reading-teal);
  color: var(--reading-teal-ink);
  border: none;
  border-radius: 10px;
  padding: 16px 14px;
  text-decoration: none;
  transition: opacity .12s ease;
}
.tile-reading:hover { opacity: .85; }
.tile-reading.dragging { opacity: .4; }
.tile-reading.drop-target { outline: 3px solid var(--accent); outline-offset: 2px; }
.tile-reading .tile-title { font-weight: 700; font-size: 15px; margin-bottom: 4px; color: inherit; }
.tile-reading .tile-meta { font-size: 12px; color: inherit; opacity: .85; }

/* ---- Page-level header button row (Invite / Manage Members / Leave Table, etc.) ---- */
.page-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 10px 0 18px;
}
.page-actions .settings-toggle summary,
.page-actions .details-toggle summary {
  font-size: 13px;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px 12px;
  cursor: pointer;
  list-style: none;
  background: var(--card);
  /* Zero the base `.details-toggle summary { margin: 20px 0 8px }` here (2026-07-26). In the
     .page-actions button row that asymmetric margin made each summary's box 62px tall with the
     visible pill sitting 6px below its box center — so the Invite/Manage Members pills didn't line
     up with the Leave Table button (which has no such margin) even with align-items:center, since
     centering aligns the boxes, not the margin-offset content inside them. */
  margin: 0;
}
.page-actions .settings-toggle summary::-webkit-details-marker,
.page-actions .details-toggle summary::-webkit-details-marker { display: none; }
.page-actions .settings-toggle summary:hover,
.page-actions .details-toggle summary:hover { color: var(--accent); border-color: var(--accent); }
.page-actions .settings-toggle .card,
.page-actions .details-toggle .card {
  position: absolute;
  top: calc(100% + 6px);
  width: 280px;
  z-index: 30;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}
.page-actions form.leave-table-form { display: inline; }
/* "Leave Table" is a real <button>, so without an explicit background it inherited the base
   button's blue primary fill — giving unreadable red-on-blue (caught in a 2026-07-26 browser
   dry-run). It's a destructive-but-secondary action, so style it like the Invite/Manage Members
   pills next to it: white fill, red text + border. */
.page-actions .small.danger {
  background: var(--card);
  color: #b3261e;
  border-color: #e3bcb6;
}
.page-actions .small.danger:hover { background: #fdf1ef; }

/* Manage Members roster rows — reuses the comment-row-ish card look for consistency. */
.member-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.member-row:last-child { border-bottom: none; }
/* min-width: 0 is required, not decorative — a flex item with flex-basis: auto refuses to shrink
   below its own content's natural width by default, which is exactly what was pushing the Remove
   button out past the flyout's edge for a long name/email (2026-07-22 bug report: "buttons
   bleeding off the side"). With it, long text wraps instead of forcing the row wider. */
.member-row .member-name { flex: 1 1 auto; min-width: 0; word-break: break-word; }
.member-row .owner-badge {
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  background: var(--table-brown);
  border-radius: 8px;
  padding: 1px 6px;
}

/* ---- Tabbed Settings panel (views/partials/settings-panel.ejs) ---- */
.settings-tabs {
  display: flex;
  gap: 2px;
  margin: -4px -4px 12px;
  border-bottom: 1px solid var(--line);
}
.settings-tab-btn {
  font: inherit;
  font-size: 13px;
  padding: 6px 10px;
  border: none;
  background: none;
  color: var(--muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.settings-tab-btn:hover { color: var(--accent); }
.settings-tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.settings-tab-panel { display: none; }
.settings-tab-panel.active { display: block; }
.settings-subsection { margin-top: 4px; }
.settings-subsection summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  list-style: none;
  padding: 4px 0;
}
.settings-subsection summary::-webkit-details-marker { display: none; }
.settings-subsection summary::before { content: "▸ "; color: var(--muted); font-size: 10px; }
.settings-subsection[open] summary::before { content: "▾ "; }
.archive-placeholder {
  font-size: 12px;
  color: var(--muted);
  border: 1px dashed var(--line);
  border-radius: 6px;
  padding: 8px 10px;
}

/* ---- Inline-editable title / Author's Note (page itself, not Settings) ---- */
.inline-editable-display {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.inline-edit-icon {
  background: none;
  border: none;
  padding: 2px;
  font-size: 14px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
}
.inline-edit-icon:hover { color: var(--accent); }
.inline-edit-form { display: none; }
.inline-editable.is-editing .inline-editable-display { display: none; }
.inline-editable.is-editing .inline-edit-form {
  display: flex;
  gap: 6px;
  align-items: flex-start;
  flex-wrap: wrap;
  margin: 4px 0 12px;
}
.inline-editable.is-editing .inline-edit-form input[type=text] { flex: 1 1 260px; }
.inline-editable.is-editing .inline-edit-form textarea { flex: 1 1 100%; min-height: 60px; }

/* ---- Sidebar: separation between Tables, reorder handle, color-by-level ----
   Colors reuse the same brown/teal placeholders as the Table/Reading tiles above (per explicit
   request, "for ease of use now" — a real palette is still to come). The item/leaf level is
   deliberately left neutral rather than given a third loud color, since it's both the most
   numerous level and the one least in need of extra visual weight.
   .sidebar-table-row is the actual drag source (2026-07-21) — draggable is deliberately NOT on
   the <details> itself, so a drag gesture starting on the row can't be confused with a click on
   its <summary> (which needs to keep toggling normally); the small ⠿ handle is just a visual cue,
   the whole row is what's grabbable, same pattern read.ejs's own item reorder already uses. */
.sidebar-table-row {
  display: flex;
  align-items: flex-start;
  gap: 2px;
  border-left: 3px solid var(--table-brown);
  padding-left: 4px;
  margin-bottom: 10px;
  border-radius: 0 6px 6px 0;
}
.sidebar-table-row + .sidebar-table-row { margin-top: 6px; }
.sidebar-table-row.dragging { opacity: .5; }
.sidebar-table-row .sidebar-table { flex: 1 1 auto; min-width: 0; }
.sidebar-drag-handle {
  cursor: grab;
  color: var(--muted);
  font-size: 12px;
  padding: 6px 0 0 2px;
  user-select: none;
  flex-shrink: 0;
}
.sidebar-read-details {
  border-left: 3px solid var(--reading-teal);
  padding-left: 6px;
}

.sidebar-empty { font-size: 12px; color: var(--muted); padding: 4px; }
