/* ============================================================================
   cursory_helper — UI. Mobile-first; min-width media queries layer on the
   desktop refinements. The document viewer is the hero: the scanned image owns
   the main column and the workspace tools dock as a sidebar on wide screens
   (the same .slideover markup becomes an overlay drawer on mobile).
   ============================================================================ */

:root {
  --bg: #eef1f5;
  --surface: #ffffff;
  --surface-2: #f6f8fb;
  --fg: #161a22;
  --muted: #5b6472;
  --accent: #2563a8;
  --accent-strong: #1c4d85;
  --accent-soft: #e8f0fa;
  --border: #dde2ea;
  --border-strong: #c7cedb;
  --ring: rgba(37, 99, 168, 0.35);
  --error-bg: #fdecea;
  --error-fg: #8a1c12;
  --info-bg: #e8f1fb;
  --info-fg: #1c4f8a;
  --ok-bg: #e6f4ea;
  --ok-fg: #1a7f37;
  /* Book-coverage strip palette. Cached = calm green; gap = a soft amber that
     reads as "to do" without the alarm of red (a book with hundreds of tiny
     holes must not scream); dead = a muted, hatched grey for confirmed
     permanently-missing pages, deliberately NOT counted as a gap. */
  --cov-cached: #3a9d63;
  --cov-cached-rail: #d8ede0;
  --cov-gap: #e3b34e;
  --cov-dead: #b7bcc6;
  --cov-strip-rail: #e9edf3;
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.08);
  --shadow-md: 0 4px 12px rgba(16, 24, 40, 0.10);
  --shadow-lg: -2px 0 24px rgba(16, 24, 40, 0.18);
  --radius: 10px;
  --radius-sm: 7px;
  --nav-h: 56px;
  --maxw: 1500px;
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--fg);
  background: var(--bg);
  line-height: 1.55;
  font-size: 16px;
}

h1 { font-size: 1.5rem; line-height: 1.25; margin: 0 0 0.5rem; }
h2 { font-size: 1.15rem; margin: 0 0 0.6rem; }
h3 { font-size: 1rem; margin: 0 0 0.5rem; }

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

/* ---- Top navigation -------------------------------------------------- */

.topnav {
  position: sticky;
  top: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: var(--nav-h);
  padding: 0 1rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}

.topnav .brand {
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--fg);
  white-space: nowrap;
  margin-right: auto;
}

.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 40px;
  height: 38px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  width: 18px;
  height: 2px;
  margin: 0 auto;
  background: var(--fg);
  border-radius: 2px;
}

.navlinks {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  align-items: stretch;
}
/* Mobile: links collapse into a dropdown panel under the bar. */
.navlinks {
  position: absolute;
  top: var(--nav-h);
  left: 0;
  right: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  padding: 0.5rem 1rem 0.85rem;
  max-height: 0;
  overflow: hidden;
  padding-top: 0;
  padding-bottom: 0;
  opacity: 0;
  pointer-events: none;
  transition: max-height 0.2s ease, opacity 0.15s ease, padding 0.2s ease;
}
.topnav.nav-open .navlinks {
  max-height: 80vh;
  opacity: 1;
  pointer-events: auto;
  padding-top: 0.5rem;
  padding-bottom: 0.85rem;
  overflow-y: auto;
}

.navlinks a,
.navlinks .navlink-btn {
  display: block;
  padding: 0.6rem 0.5rem;
  color: var(--accent);
  text-decoration: none;
  border-radius: var(--radius-sm);
  font-size: 1rem;
  text-align: left;
  width: 100%;
}
.navlinks a:hover,
.navlinks .navlink-btn:hover { background: var(--accent-soft); }

.navlink-btn {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  font: inherit;
}

.user-email {
  color: var(--muted);
  font-size: 0.85rem;
  white-space: nowrap;          /* never character-stack a long email */
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;                 /* flex-item: allow shrinking so ellipsis works
                                   (min-width:auto would force the whole nav wider
                                   than a narrow portrait viewport). */
  max-width: 13rem;
}
/* The Account toggle + the collapsed mobile menu must never exceed the viewport. */
.nav-account .nav-dropdown-toggle { min-width: 0; }
/* Account ▾ — the email + Log out folded into a right-aligned dropdown so the
   nav row stays compact. Reuses the .nav-dropdown component (JS + menu styles). */
.nav-account { margin-left: auto; }
.nav-account .nav-dropdown-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  max-width: 100%;
}
.nav-account .logout-form button { width: 100%; text-align: left; border: none; }
.logout-form { margin: 0; }
.logout-form button {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--border-strong);
  width: 100%;
}

/* Webmap title-bar icon (replaces the staff "Map" nav link). Sits right after
   the brand; an unobtrusive muted glyph that brightens to the accent on hover. */
.brand-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  text-decoration: none;
  font-size: 1.2rem;
  line-height: 1;
  padding: 0.2rem;
  border-radius: var(--radius-sm);
  margin-right: 0.25rem;
}
.brand-icon:hover { color: var(--accent); background: var(--accent-soft); }

/* ---- Landman ▾ nav dropdown ------------------------------------------ */
/* MOBILE-FIRST (default): the dropdown lives inside the collapsed .navlinks
   column, so the menu expands INLINE as an indented sub-list (no floating
   popover that would clip off-screen). Desktop overrides to a floating menu
   in the 768px breakpoint below. */
.nav-dropdown { width: 100%; }
.nav-dropdown-toggle {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}
.nav-dropdown-caret { transition: transform 0.15s ease; flex: none; }
.nav-dropdown.open > .nav-dropdown-toggle .nav-dropdown-caret {
  transform: rotate(180deg);
}
.nav-dropdown-menu {
  display: none;
  flex-direction: column;
  padding-left: 0.75rem;     /* indent the sub-list on mobile */
}
.nav-dropdown.open > .nav-dropdown-menu { display: flex; }
.nav-dropdown-menu a {
  display: block;
  padding: 0.55rem 0.5rem;
  color: var(--accent);
  text-decoration: none;
  border-radius: var(--radius-sm);
  font-size: 1rem;
}
.nav-dropdown-menu a:hover { background: var(--accent-soft); }

/* ---- Buttons --------------------------------------------------------- */

button,
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  cursor: pointer;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.95rem;
  font-size: 0.95rem;
  font-family: inherit;
  text-decoration: none;
  line-height: 1.2;
  min-height: 40px;
  transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
button:hover,
.button:hover { background: var(--accent-strong); border-color: var(--accent-strong); }
button:focus-visible,
.button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
}

button.secondary,
.button.secondary {
  background: var(--surface);
  color: var(--accent);
  border-color: var(--border-strong);
}
button.secondary:hover,
.button.secondary:hover { background: var(--surface-2); border-color: var(--accent); }

.button.disabled,
.button[aria-disabled="true"] {
  background: var(--surface-2);
  color: var(--muted);
  border-color: var(--border);
  cursor: default;
  pointer-events: none;
}

.link-btn {
  background: none;
  border: none;
  color: var(--accent);
  padding: 0.35rem 0.4rem;
  min-height: 0;
  font: inherit;
  cursor: pointer;
  text-decoration: none;
}
.link-btn:hover { background: transparent; text-decoration: underline; color: var(--accent-strong); }
.link-btn-danger { color: var(--error-fg); }

/* ---- Layout ---------------------------------------------------------- */

.content {
  max-width: var(--maxw);
  margin: 1.25rem auto;
  padding: 0 1rem;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.1rem 1.15rem;
  box-shadow: var(--shadow-sm);
  margin-bottom: 1rem;
}
.card > h2:first-child,
.card > h3:first-child { margin-top: 0; }

.auth-card { max-width: 420px; margin: 3rem auto; }
.auth-form { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 1rem; }
.auth-form input {
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 1rem;
}
.auth-form button { margin-top: 0.5rem; }

.muted { color: var(--muted); font-size: 0.9rem; }
.muted.small { font-size: 0.8rem; }

/* ---- Forms ----------------------------------------------------------- */

.field { margin-bottom: 0.75rem; }
.field label,
.field > .label,
label.field,
.index-fields label,
.parcel-form label,
.opendoc-form .field label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 0.25rem;
}
label.inline { display: inline-flex; align-items: center; gap: 0.35rem; font-weight: 400; }

input[type="text"],
input[type="email"],
input[type="number"],
input[type="date"],
input[type="search"],
select,
textarea {
  width: 100%;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 1rem;
  font-family: inherit;
  background: var(--surface);
  color: var(--fg);
}
textarea { resize: vertical; }

.field-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

.search-form,
.parcel-form,
.opendoc-form,
.auth-form,
.find-form,
.export-form,
.export-filter,
.link-search,
.link-by-id { max-width: 640px; }

/* The workspace panel (docked sidebar on desktop, drawer on mobile) is narrow, so
   multi-column field rows squish there regardless of viewport width — keep them
   single-column inside the panel. */
.slideover-panel .field-row,
.slideover-panel .index-fields-row { grid-template-columns: 1fr; }

/* Parcel assessor enrichment: provenance badge + fetch button row, and the
   "review before overwrite" preview block. */
.parcel-provenance {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}
.assessor-note { margin: 0.25rem 0 0.6rem; }
.assessor-preview {
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  padding: 0.6rem 0.85rem;
  margin-bottom: 0.85rem;
}

/* On-demand Harrison card refresh: panel-local polling always keeps the prior
   card visible. The structured current snapshot is visually distinct from the
   OCR/historical transfer rows below it. */
.taxcard-refresh-control {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.65rem;
  margin-bottom: 0.85rem;
}
.taxcard-refresh-control form,
.taxcard-refresh-status { margin: 0; }
.taxcard-refresh-status { color: var(--muted); }
.taxcard-refresh-failed,
.taxcard-refresh-unavailable,
.taxcard-refresh-not_found { color: var(--error-fg); }
.taxcard-current-assessment {
  margin: 0.65rem 0 0.9rem;
  padding: 0.7rem 0.85rem;
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.taxcard-current-assessment h3 { margin: 0 0 0.5rem; }
.taxcard-current-assessment dl {
  display: grid;
  grid-template-columns: minmax(7rem, max-content) 1fr;
  gap: 0.25rem 0.75rem;
  margin: 0;
}
.taxcard-current-assessment dt { color: var(--muted); font-weight: 600; }
.taxcard-current-assessment dd { margin: 0; }
.taxcard-capture-status {
  margin: 0.65rem 0 0.9rem;
  padding: 0.65rem 0.8rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--info-bg);
  color: var(--info-fg);
}
.taxcard-capture-status strong { display: block; }
.taxcard-prior-capture {
  margin: 0.45rem 0 0.65rem;
  color: var(--muted);
}

.search-scope .label,
.field > .label { display: block; font-size: 0.85rem; font-weight: 600; color: var(--muted); margin-bottom: 0.25rem; }

.actions,
.export-actions,
.doc-index-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
  margin-top: 0.5rem;
}

fieldset.bounded,
fieldset.runsheet-header {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.75rem 0.85rem;
  margin: 0.5rem 0;
}
fieldset legend { font-weight: 600; font-size: 0.85rem; color: var(--muted); padding: 0 0.3rem; }
fieldset.bounded { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; }
fieldset.bounded label { display: flex; align-items: center; gap: 0.4rem; }
fieldset.bounded input { width: 100%; }

/* ---- Flash / messages ------------------------------------------------ */

.flash {
  max-width: var(--maxw);
  margin: 0.75rem auto 0;
  padding: 0.7rem 1rem;
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
}
.flash-error { background: var(--error-bg); color: var(--error-fg); }
.flash-info { background: var(--info-bg); color: var(--info-fg); }
.error { color: var(--error-fg); }

/* Global htmx error toast (base.html chErrToast) — surfaces the 4xx/5xx detail
   htmx would otherwise swallow. Fixed, stacked bottom-right, above the slideovers
   and lightbox. */
.ch-toasts {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 3000;
  display: flex; flex-direction: column; gap: 0.5rem;
  max-width: min(360px, calc(100vw - 2rem));
}
.ch-toast {
  display: flex; align-items: flex-start; gap: 0.6rem;
  background: var(--error-bg); color: var(--error-fg);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-md); padding: 0.7rem 0.85rem; font-size: 0.92rem;
}
.ch-toast-msg { flex: 1; }
.ch-toast-close {
  flex: none; background: none; border: 0; color: inherit; cursor: pointer;
  padding: 0.1rem; line-height: 1; display: inline-flex; opacity: 0.75;
}
.ch-toast-close:hover { opacity: 1; }

/* ---- Dashboard tiles ------------------------------------------------- */

.tile-grid {
  list-style: none;
  padding: 0;
  margin: 1.25rem 0 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.85rem;
}
.tile a {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
  text-decoration: none;
  color: var(--fg);
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}
.tile a:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.tile strong { display: block; color: var(--accent); font-size: 1.02rem; }
.tile span { display: block; color: var(--muted); font-size: 0.88rem; margin-top: 0.25rem; }

.recent-widget .recent-list { list-style: none; margin: 0; padding: 0; }
.recent-widget .recent-list li { padding: 0.55rem 0; border-bottom: 1px solid var(--border); }
.recent-widget .recent-list li:last-child { border-bottom: none; }

/* ---- Tables (responsive: scroll-in-container on small screens) ------- */

.data-table,
.results-table,
.admin-table,
.history-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}
.data-table th, .data-table td,
.results-table th, .results-table td,
.admin-table th, .admin-table td,
.history-table th, .history-table td {
  text-align: left;
  padding: 0.55rem 0.7rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.data-table th, .results-table th, .admin-table th, .history-table th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  background: var(--surface-2);
  white-space: nowrap;
}
.data-table tbody tr:hover,
.results-table tbody tr:hover,
.history-table tbody tr:hover { background: var(--surface-2); }

/* Visited rows: documents the current user has already opened in the viewer,
   styled like a visited link so a list of results shows what's been reviewed.
   A left marker + a softer row + a "viewed" link color on the instrument #. */
.results-table tbody tr.result-row.visited { background: #faf7fd; }
.results-table tbody tr.result-row.visited > td:first-child {
  box-shadow: inset 3px 0 0 #7c5cbf;
}
.results-table a.doc-open.visited { color: #6f4fb0; }
.results-table a.doc-open.visited::after {
  content: " ✓";
  color: #6f4fb0;
  font-size: 0.85em;
}

/* "Back to results" control in the viewer toolbar — visually distinct (accent
   fill) so the return path is obvious. */
.viewer-nav .back-to-results { font-weight: 600; }
.data-table form, .results-table form, .history-table form, .admin-table form { margin: 0; }

/* Wrap any table in a horizontally scrollable shell on narrow screens. */
.table-scroll,
.results-block,
.linked,
.link-control,
.parcels .card,
.history-page,
.admin {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.results-block {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 0;
  margin-top: 1rem;
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.results-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 0.75rem 1rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.results-count { font-weight: 600; }
.refetch-inline { margin: 0 0 0 auto; }
.search-results { margin-top: 0.5rem; }

/* ---- Results pager --------------------------------------------------- */
.results-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.pager-btn {
  padding: 0.3rem 0.7rem;
  font-size: 0.9rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
}
.pager-btn:hover:not(:disabled) { background: var(--surface-2); }
.pager-btn:disabled { opacity: 0.45; cursor: default; }
.pager-status { margin: 0 0.6rem; font-weight: 600; color: var(--muted); }

/* ---- Sortable results table ----------------------------------------- */
/* The full-column table is wide; scroll it horizontally inside the block
   (which is overflow:hidden for its rounded corners) so header + pager stay put. */
.results-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.results-scroll .results-table { min-width: 1000px; }
.col-image { text-align: center; }
.col-parties { max-width: 18rem; }
.col-desc { max-width: 22rem; }
/* Clickable column headers. The <button> fills the cell and inherits the th look. */
.results-table th.sortable { padding: 0; }
.results-table th.sortable .th-sort {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.55rem 0.7rem;
  background: transparent;
  border: 0;
  font: inherit;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  white-space: nowrap;
  cursor: pointer;
}
.results-table th.sortable .th-sort:hover { background: var(--surface); color: var(--text); }
.results-table th.sorted .th-sort { color: var(--accent); }
.sort-ind { font-size: 0.7em; }
.search-loading { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--muted); }
/* Local-table headers sort client-side (the set is small + fully in the DOM); the
   button look matches the server-sorted county headers. */
.results-table th.sortable .th-sort { font: inherit; }

/* ---- Detail column: flag dot + ✓ + cross-refs chip + expandable sub-row --- */

/* COTT IDX cross-ref / notation flag — small colored dot beside the Fetch
   button. Colors mirror the live grid (blue=xref, orange=notation, red=both). */
.flag-dot {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  margin-right: 0.35rem;
  vertical-align: middle;
  border: 1px solid rgba(0, 0, 0, 0.25);
}
.flag-blue   { background: #2c7be5; }
.flag-orange { background: #f5a623; }
.flag-red    { background: #d9534f; }


/* The compact chip beside the ✓ — opens the cross-refs sub-row in place. */
.xref-toggle {
  margin-left: 0.4rem;
  font-size: 0.78rem;
  color: var(--muted);
}
.xref-toggle:hover { color: var(--accent-strong); }
.xref-toggle[aria-expanded="true"] { color: var(--accent); }
.xref-toggle .xref-count {
  display: inline-block;
  min-width: 1.1rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-strong);
  font-weight: 600;
  text-align: center;
}

/* Sub-row dropped directly under the instrument row. The colspan spans the
   full table width; the inner mini-table renders the cross-refs. */
.xref-row > td {
  padding: 0 !important;
  background: var(--surface);
  border-top: 0;
}
.xref-wrap {
  margin: 0.25rem 0.5rem 0.6rem 2.5rem;
  padding: 0.5rem 0.7rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.xref-header {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  margin-bottom: 0.35rem;
  font-size: 0.85rem;
}
.xref-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}
.xref-table th, .xref-table td {
  padding: 0.25rem 0.6rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
}
.xref-table tr:last-child td { border-bottom: 0; }
.xref-table th { color: var(--muted); font-weight: 600; }

/* ---- Badges ---------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 600;
  line-height: 1.4;
  background: var(--surface-2);
  color: var(--muted);
  border: 1px solid var(--border);
}
.badge.cached, .badge-cached, .badge.cleaned { background: var(--ok-bg); color: var(--ok-fg); border-color: transparent; }
.badge.cleaning { background: var(--info-bg); color: var(--info-fg); border-color: transparent; }

.job-status { font-size: 0.9rem; color: var(--muted); }
.job-failed { color: var(--error-fg); }
.job-finished { color: var(--ok-fg); }

/* ---- Spinner --------------------------------------------------------- */

.spinner {
  display: inline-block;
  width: 28px;
  height: 28px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: ch-spin 0.7s linear infinite;
}
.spinner-sm { width: 12px; height: 12px; border-width: 2px; }
@keyframes ch-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.5s; } }

/* ============================================================================
   DOCUMENT VIEWER — the hero. Image fills the main column; tools dock beside it.
   ============================================================================ */

.document-viewer-page { max-width: none; }

.doc-header {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin-bottom: 0.75rem;
}
.doc-header h1 { margin: 0; font-size: 1.35rem; }
.doc-series { margin: 0; }
.doc-series .label { color: var(--muted); font-weight: 600; font-size: 0.85rem; }
.doc-county { color: var(--muted); font-size: 0.9rem; }

/* Map measure tool. */
#measure-control { bottom: 1.5rem; right: 0.5rem; top: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 0.3rem; }
#measure-toggle.active { outline: 2px solid #ef4444; }
#measure-box { display: flex; align-items: center; gap: 0.5rem; background: var(--panel, #1e1e2e); color: var(--text, #e5e7eb); padding: 0.3rem 0.5rem; border-radius: 4px; font-size: 0.8rem; }

/* Map parcel search (sidebar). */
.map-search-results { display: flex; flex-direction: column; margin-top: 0.4rem; max-height: 18rem; overflow-y: auto; }
.map-search-result { display: flex; flex-direction: column; align-items: flex-start; gap: 0.05rem;
  text-align: left; padding: 0.35rem 0.4rem; border: none; border-bottom: 1px solid var(--border, #2a2a3a);
  background: transparent; color: inherit; cursor: pointer; font: inherit; }
.map-search-result:hover { background: rgba(127,127,127,0.12); }
.map-search-no { font-weight: 600; font-size: 0.85rem; }
.map-search-owner { font-size: 0.8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.map-search-meta, .map-search-empty { font-size: 0.72rem; color: var(--muted, #9ca3af); }
.map-search-empty { padding: 0.4rem; }
#parcel-search-input { width: 100%; box-sizing: border-box; }

/* Deed-plot launcher (doc-header "Plot this deed"). */
.deed-plot-launch { display: inline-flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.deed-plot-launch .link-btn svg, .deed-plot-badge svg { vertical-align: -0.12em; }
.deed-plot-badge {
  display: inline-flex; align-items: center; gap: 0.3rem;
  color: var(--ok, #1a7f37); font-size: 0.85rem; font-weight: 600; text-decoration: none;
}
/* Deed-plot sketcher panel (the map sidebar). */
.dp-mode-toggle { display: flex; gap: 0.4rem; margin-bottom: 0.5rem; }
.dp-mode-toggle .farmline-btn.active { outline: 2px solid var(--accent, #2563eb); }
.dp-actions { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.5rem; }
#deed-plot-panel-body textarea { width: 100%; box-sizing: border-box; font-family: monospace; }
#dp-metrics { font-weight: 600; }
/* Deed-plot link picker (appears on a saved plot). */
.dp-divider { border: 0; border-top: 1px solid var(--border, #ccc); margin: 0.6rem 0; }
.dp-links-title { font-weight: 600; font-size: 0.85rem; margin-bottom: 0.3rem; }
.dp-links-list { list-style: none; margin: 0 0 0.4rem; padding: 0; }
.dp-links-list li { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; padding: 0.1rem 0; }
.dp-links-list .dp-link-remove { margin-left: auto; padding: 0; line-height: 1; }
.dp-links-list .dp-link-remove svg { vertical-align: -0.12em; }
.dp-links-add summary { cursor: pointer; font-size: 0.8rem; color: var(--accent, #2563eb); }
.dp-link-options { display: flex; flex-direction: column; gap: 0.15rem; margin: 0.3rem 0; }
.dp-link-options label { display: flex; gap: 0.4rem; align-items: baseline; font-size: 0.8rem; }

/* Courthouse document request (doc-header launcher + form). */
.courthouse-panel { margin-left: auto; width: 100%; max-width: 100%; }
.doc-header > .courthouse-panel { width: auto; }
.courthouse-launch { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.courthouse-launch .link-btn svg,
.courthouse-success svg,
.courthouse-badge svg { vertical-align: -0.12em; }
.courthouse-badge {
  display: inline-flex; align-items: center; gap: 0.3rem;
  color: var(--ok, #1a7f37); font-size: 0.85rem; font-weight: 600;
}
.courthouse-success {
  display: flex; align-items: center; gap: 0.4rem;
  color: var(--ok, #1a7f37); margin: 0; font-size: 0.95rem;
}
.courthouse-form { margin-top: 0.75rem; width: 100%; }
.courthouse-form-head {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
}
.courthouse-form-head h3 { margin: 0; }
.courthouse-field { display: block; margin: 0.5rem 0; }
.courthouse-field > span { display: block; font-size: 0.85rem; font-weight: 600; color: var(--muted); margin-bottom: 0.15rem; }
.courthouse-field input,
.courthouse-field select,
.courthouse-field textarea { width: 100%; box-sizing: border-box; }
.courthouse-field .req { color: var(--danger, #b42318); }
.courthouse-field small { display: block; margin-top: 0.1rem; }
.courthouse-actions { margin-top: 0.75rem; }
.courthouse-msg { font-size: 0.9rem; }
.courthouse-msg.error { color: var(--danger, #b42318); }
.courthouse-errors { color: var(--danger, #b42318); margin: 0.25rem 0; padding-left: 1.1rem; font-size: 0.9rem; }

.doc-viewer { width: 100%; }
.doc-viewer-main { width: 100%; }

/* Toolbar above the image: page label + nav + quick-tools. On mobile the nav
   becomes a fixed thumb-reachable bar at the bottom (see media query). */
.viewer-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.6rem 0.75rem;
  margin-bottom: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.viewer-toolbar .page-label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  font-size: 0.95rem;
}
.doc-series-chip {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-strong);
}
.viewer-toolbar .viewer-nav { display: inline-flex; gap: 0.4rem; }
.viewer-toolbar .viewer-tools { display: inline-flex; flex-wrap: wrap; gap: 0.4rem; margin-left: auto; }
.viewer-toolbar .button { padding: 0.45rem 0.75rem; min-height: 38px; }

/* Minimize/restore toggle — hidden by default; the desktop toolbar stays visible,
   so it only appears on mobile (see the max-width query). */
.viewer-min-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  min-height: 34px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--muted);
  cursor: pointer;
}
.viewer-min-toggle svg { transition: transform 0.15s ease; }

/* Desktop + tablet: the viewer toolbar sticks just below the (already-sticky) top
   menu bar, so Next page / Next doc / zoom stay reachable while the document
   scrolls beneath it — no scrolling back up from the bottom of a long document. */
@media (min-width: 768px) {
  .viewer-toolbar {
    position: sticky;
    top: var(--nav-h);
    z-index: 500;
  }
}
/* Thin divider between the page pager and the Prev/Next-document pair. */
.viewer-nav .viewer-nav-sep {
  width: 1px;
  align-self: stretch;
  background: var(--border);
}

/* Jump-to-page picker on the viewer toolbar. */
.page-jump {
  margin: 0 0.25rem;
  padding: 0.15rem 0.35rem;
  max-width: 9rem;
  font-size: 0.9rem;
}
.page-jump[type="number"] { width: 4.5rem; max-width: 6rem; }

/* Stage: the scanned image, centered and large. */
.doc-page-host { width: 100%; }

/* Vault index overlay — sits absolutely on top of the page image so the
   user can drag a rectangle to record a name visible there. The popover
   is anchored under the freshly-drawn box. */
.doc-page-stack { position: relative; display: inline-block; }
/* z-index must beat .doc-page-img (z-index:1) or the image paints on top and
   eats the drag events — you'd only be able to draw past the image's edge. */
.vault-overlay { position: absolute; inset: 0; cursor: crosshair; z-index: 2; }
/* OCR parcel-detection rectangles: read-only highlights over auto-detected
   parcel numbers (fraction-positioned, same convention as the vault overlay).
   amber = autolinked (needs review), green = confirmed. */
.parcel-overlay { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.parcel-box {
  position: absolute;
  box-sizing: border-box;
  border: 2px solid rgba(217, 154, 30, 0.95);
  background: rgba(217, 154, 30, 0.16);
  border-radius: 2px;
}
.parcel-box-confirmed {
  border-color: rgba(34, 153, 84, 0.95);
  background: rgba(34, 153, 84, 0.16);
}
/* User-drawn parcel box (manual) — blue, distinct from the amber OCR autolinks. */
.parcel-box-manual,
.parcel-box-drawing {
  border-color: rgba(44, 123, 229, 0.95);
  background: rgba(44, 123, 229, 0.16);
}
/* Parcel index numbers: the notes' .note-num badge idiom in the parcels' blue —
   a small round numbered chip tying a page rectangle to its Parcels-panel row.
   Used as a clickable corner tab on a rectangle AND as the panel row's
   navigation button. */
.parcel-num {
  flex: 0 0 auto; align-self: center;
  min-width: 1.3rem; height: 1.3rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(44, 123, 229, 0.95); color: #fff;
  border-radius: 999px; font-size: 0.72rem; font-weight: 700; line-height: 1;
}
/* The badge as a clickable corner tab on a page rectangle (chParcelReveal opens
   the panel + flashes the row). Only the badge takes clicks — the box and the
   rest of .parcel-overlay stay click-through (pointer-events:none). */
.parcel-box-num {
  position: absolute; top: -0.6rem; left: -0.6rem;
  margin: 0; padding: 0 0.2rem; border: 0;
  font-family: inherit; white-space: nowrap;
  cursor: pointer; pointer-events: auto;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.parcel-box-num:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
/* The badge as the panel row's click-to-center link (chParcelJump). */
.parcel-item-num {
  margin: 0; padding: 0 0.2rem; border: 0;
  font-family: inherit; white-space: nowrap; cursor: pointer;
}
.parcel-item-num:hover,
.parcel-item-num:focus-visible { box-shadow: 0 0 0 2px rgba(44, 123, 229, 0.4); }
/* Flash a parcel's page rectangles when its panel badge is clicked
   (chParcelJump). Ring-only — no background frame — so the pulse sits cleanly
   on any status color (amber/green/blue). */
.parcel-box-flash { animation: parcelBoxFlash 2s ease-out; z-index: 5; }
@keyframes parcelBoxFlash {
  0%, 100% { box-shadow: 0 0 0 0 rgba(44, 123, 229, 0); }
  20% { box-shadow: 0 0 0 5px rgba(44, 123, 229, 0.55); }
}
/* Flash a parcel's panel row when its numbered box tab is clicked
   (chParcelReveal) — the reverse of .parcel-box-flash (page -> panel). */
.parcel-item-flash { animation: parcelItemFlash 2s ease-out; border-radius: 4px; }
@keyframes parcelItemFlash {
  0%, 100% { background: transparent; }
  20% { background: rgba(44, 123, 229, 0.18); }
}
/* Draw layers: inert until a parcel/note "+ box" arms them (adds .drawing). */
.parcel-draw-overlay,
.note-draw-overlay { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.parcel-draw-overlay.drawing,
.note-draw-overlay.drawing {
  pointer-events: auto;
  cursor: crosshair;
  touch-action: pinch-zoom;
}
/* Note rectangles (user-pinned) — purple, distinct from parcels (amber/green/blue). */
.note-overlay { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.note-box,
.note-box-saved,
.note-box-drawing {
  position: absolute;
  box-sizing: border-box;
  border: 2px solid rgba(124, 58, 173, 0.95);
  background: rgba(124, 58, 173, 0.16);
  border-radius: 2px;
}
.note-title { font-weight: 600; margin-top: 0.1rem; }
.note-box-btn { margin-left: auto; }
/* Flash a note's page rectangle when its panel entry is clicked (chNoteJump). */
.note-box-flash { animation: noteBoxFlash 2s ease-out; z-index: 5; }
@keyframes noteBoxFlash {
  0%, 100% { box-shadow: 0 0 0 0 rgba(124, 58, 173, 0); background: rgba(124, 58, 173, 0.16); }
  20% { box-shadow: 0 0 0 5px rgba(124, 58, 173, 0.5); background: rgba(124, 58, 173, 0.42); }
}
/* Note index numbers: a small round numbered chip tying a page box to its
   Notes-panel entry — mirrors the vault-index .vix-num badge, in the notes'
   purple (matching the .note-box rectangles). Used both in the sidebar (a
   <span>) and as a clickable corner tab on a page rectangle (a <button>). */
.note-num {
  flex: 0 0 auto; align-self: center;
  min-width: 1.3rem; height: 1.3rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(124, 58, 173, 0.95); color: #fff;
  border-radius: 999px; font-size: 0.72rem; font-weight: 700; line-height: 1;
}
/* The badge as a clickable corner tab on a page rectangle (chNoteReveal opens
   the panel + flashes the entry). Only the badge takes clicks — the box and the
   rest of .note-overlay stay click-through (pointer-events:none). */
.note-box-num {
  position: absolute; top: -0.6rem; left: -0.6rem;
  margin: 0; padding: 0 0.2rem; border: 0;
  font-family: inherit; white-space: nowrap;
  cursor: pointer; pointer-events: auto;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.note-box-num:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
/* Reading the scan UNDER a badge: hovering the corner chip fades it — and its
   box's tint — to near-invisible so the text beneath is legible (the badge was
   covering the very parcel number it marks). Still clickable while faded;
   snaps back on mouse-out. Box fade needs :has() (badges are the only
   hoverable part — boxes stay pointer-events:none); on a non-:has browser the
   chip alone fading still solves the read-under case. */
.parcel-box-num:hover,
.note-box-num:hover {
  opacity: 0.12;
  box-shadow: none;
  transition: opacity 120ms ease-in;
}
.parcel-box:has(> .parcel-box-num:hover),
.note-box:has(> .note-box-num:hover) {
  background: transparent;
  transition: background 120ms ease-in;
}
.parcel-box:has(> .parcel-box-num:hover) { border-color: rgba(217, 154, 30, 0.35); }
.parcel-box-confirmed:has(> .parcel-box-num:hover) { border-color: rgba(34, 153, 84, 0.35); }
.parcel-box-manual:has(> .parcel-box-num:hover) { border-color: rgba(44, 123, 229, 0.35); }
.note-box:has(> .note-box-num:hover) { border-color: rgba(124, 58, 173, 0.35); }
/* Flash a note's panel entry when its numbered box is clicked (chNoteReveal) —
   the reverse of .note-box-flash (panel -> box). */
.note-item-flash { animation: noteItemFlash 2s ease-out; border-radius: 4px; }
@keyframes noteItemFlash {
  0%, 100% { background: transparent; }
  20% { background: rgba(124, 58, 173, 0.18); }
}
.badge.autolinked {
  background: rgba(217, 154, 30, 0.18);
  color: #8a5a00;
  border: 1px solid rgba(217, 154, 30, 0.5);
}
.parcel-autolinked { background: rgba(217, 154, 30, 0.06); }
.parcel-actions { display: inline-flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; }
/* One suggested taxcard transfer-link candidate (badge + target + confirm/dismiss). */
.taxcard-link-suggest {
  display: inline-flex; gap: 0.35rem; align-items: center; flex-wrap: wrap;
  margin-left: 0.4rem; white-space: nowrap;
}
.parcel-change { display: inline-block; }
.parcel-change > summary { cursor: pointer; }
.parcel-change-form { display: inline-flex; gap: 0.3rem; margin-top: 0.3rem; }
.doc-page-ocr { margin-top: 0.4rem; font-size: 0.82rem; }
.doc-page-ocr > summary { cursor: pointer; color: var(--muted, #666); }
.doc-page-ocr-text {
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 16rem;
  overflow: auto;
  background: var(--bg-subtle, #f6f6f6);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.5rem;
  margin-top: 0.3rem;
  font-size: 0.8rem;
}
.vault-popover {
  position: absolute;
  z-index: 5;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
  padding: 0.5rem 0.6rem;
  min-width: 14rem;
  max-width: 22rem;
}
.vault-popover label { display: block; font-size: 0.78rem; margin: 0.25rem 0; }
.vault-popover input[type="text"] {
  width: 100%; box-sizing: border-box; padding: 0.3rem;
  font-size: 0.9rem;
}
.vault-popover-actions { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
.vault-popover-actions button { padding: 0.25rem 0.6rem; font-size: 0.85rem; }
/* "Open recorded document" link under the popover actions — a link, not a
   button; hidden unless the entry being edited has a complete recording ref. */
.vault-popover-open-rec {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-top: 0.4rem;
  font-size: 0.85rem;
}
.vault-popover-open-rec[hidden] { display: none; }

/* Sidebar list */
/* Explicit number badge (matches the orange number on the box) — the list is
   display:flex so the native decimal marker wouldn't render anyway. */
.vault-index-list { list-style: none; padding: 0; margin: 0.5rem 0; }
.vault-index-entry {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.4rem;
  border-bottom: 1px solid var(--border);
}
.vault-index-entry:last-child { border-bottom: 0; }
.vix-num {
  flex: 0 0 auto;
  min-width: 1.3rem; height: 1.3rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(217, 119, 6, 0.97); color: #fff;
  border-radius: 999px; font-size: 0.72rem; font-weight: 700;
}
.vault-index-entry-text { flex: 1; word-break: break-word; }
.vault-index-entry-actions { display: flex; align-items: center; gap: 0.25rem; flex: 0 0 auto; }
.vault-index-entry-delete { margin: 0; }

/* Inline sidebar edit of an entry's optional fields (the box popover still works). */
.vix-edit { flex-basis: 100%; margin-top: 0.25rem; }
.vix-edit > summary { cursor: pointer; color: var(--accent); font-size: 0.78rem; }
.vix-edit-form { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.4rem; }
.vix-edit-form label { display: flex; flex-direction: column; gap: 0.15rem; font-size: 0.72rem; color: var(--muted); }
.vix-edit-form input, .vix-edit-form textarea { width: 100%; box-sizing: border-box; padding: 0.3rem; font-size: 0.85rem; }
.vix-edit-rec, .vault-popover-recording {
  display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center;
  border: 1px solid var(--border); border-radius: 6px; padding: 0.35rem; margin: 0.25rem 0;
}
.vix-edit-rec legend, .vault-popover-recording legend { font-size: 0.7rem; color: var(--muted); padding: 0 0.3rem; }
.vix-edit-rec input, .vault-popover-recording input { flex: 1 1 4rem; min-width: 0; }
/* "More details" disclosures (popover + sidebar) read as a quiet accent link. */
.vault-popover-more > summary { cursor: pointer; color: var(--accent); font-size: 0.78rem; margin: 0.25rem 0; }

.doc-page-area {
  min-height: 420px;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
}
.doc-page-figure {
  position: relative;
  margin: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}
.doc-page-backdrop {
  position: absolute;
  top: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 0;
}
/* Image base styling. Size is driven by the viewer-mode classes (fit-width
   default / fit-screen) plus the --zoom CSS var written by viewerZoom JS. */
.doc-page-img {
  position: relative;
  z-index: 1;
  height: auto;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: #fff;
  box-shadow: var(--shadow-md);
}

/* Fit-width (default): image fills container width × zoom factor; height by
   aspect ratio. Vertical scroll if needed. */
.doc-viewer-mode-fit-width .doc-page-img {
  width: calc(100% * var(--zoom, 1));
  max-width: none;
  max-height: none;
}

/* Fit-screen: whole page visible, both width AND height capped by viewport
   (true "fit page"). Zoom scales the cap so >100% lets the page exceed the
   viewport. */
.doc-viewer-mode-fit-screen .doc-page-img {
  width: auto;
  max-width: calc(100% * var(--zoom, 1));
  max-height: calc((100vh - 260px) * var(--zoom, 1));
}

/* Rotation wrapper. viewerZoom JS swaps the rot-N class (0/90/180/270).
   Layout-flow simple version: rotate the wrapper as inline-block — for
   landscape (90°/270°) the parent gets overflow:auto so the user can pan if
   the rotated image overflows. */
.doc-page-rot {
  display: inline-block;
  transform-origin: center center;
  transition: transform 0.15s ease-out;
}
.doc-page-rot.rot-90  { transform: rotate(90deg); }
.doc-page-rot.rot-180 { transform: rotate(180deg); }
.doc-page-rot.rot-270 { transform: rotate(270deg); }

/* Let the page area scroll when zoom > 100% or after a 90°/270° rotation. */
.doc-page-area { overflow: auto; }

/* Zoom toolbar (sits in .viewer-toolbar between viewer-nav and viewer-tools). */
.viewer-toolbar .viewer-zoom {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  padding-left: 0.5rem;
  margin-left: 0.25rem;
  border-left: 1px solid var(--border);
}
.viewer-toolbar .viewer-zoom .button {
  padding: 0.25rem 0.55rem;
  min-width: 2.2rem;
  font-size: 1rem;
  line-height: 1;
}
.viewer-toolbar .viewer-zoom .zoom-display {
  display: inline-block;
  min-width: 3.6rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;
  color: var(--muted);
  padding: 0 0.3rem;
}
.doc-page-figure.img-error .doc-page-img,
.doc-page-figure.img-error .doc-page-backdrop { display: none; }
.doc-page-figure.img-error::after {
  content: "Image unavailable — retrying…";
  color: var(--muted);
  font-size: 0.9rem;
  padding: 2rem 1rem;
}
.doc-page-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  text-align: center;
  padding: 3rem 1rem;
}
.doc-page-status { margin-top: 0; }

.doc-escalate-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.6rem 0.8rem;
  margin-bottom: 0.6rem;
  background: var(--info-bg);
  color: var(--info-fg);
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
}
.doc-escalate-banner .link-btn { color: var(--info-fg); font-weight: 600; }
.doc-escalate-dismiss {
  margin-left: auto;            /* push to the right edge of the flex banner */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.2rem;
  background: none;
  border: none;
  color: var(--info-fg);
  cursor: pointer;
  opacity: 0.65;
  border-radius: var(--radius-sm);
}
.doc-escalate-dismiss:hover { opacity: 1; background: rgba(0, 0, 0, 0.07); }
.doc-find-results:not(:empty) { margin-top: 1rem; }

/* Admin page-editor panel (relabel / delete / reorder a document's pages). */
.doc-pages-editor-host:not(:empty) { margin-top: 1rem; }
.doc-pages-editor {
  border: 1px solid var(--border, #d5d9e0);
  border-radius: var(--radius-sm, 6px);
  padding: 0.75rem;
  background: rgba(0, 0, 0, 0.015);
}
.doc-pages-editor-head { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 0.5rem; }
.doc-pages-flash { margin: 0 0 0.5rem; }
.doc-pages-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.doc-pages-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem;
  padding: 0.4rem 0.3rem; border-top: 1px solid var(--border, #e3e6ec);
}
.doc-pages-row:first-child { border-top: 0; }
.doc-pages-no { font-variant-numeric: tabular-nums; color: var(--muted, #6b7280); min-width: 2.2rem; }
.doc-pages-thumb {
  width: 44px; height: 56px; object-fit: cover; border: 1px solid var(--border, #d5d9e0);
  border-radius: 3px; background: #fff;
}
.doc-pages-relabel { display: flex; align-items: flex-end; gap: 0.4rem; flex-wrap: wrap; }
.doc-pages-field { display: flex; flex-direction: column; font-size: 0.72rem; color: var(--muted, #6b7280); gap: 0.1rem; }
.doc-pages-field input { font-size: 0.85rem; padding: 0.2rem 0.35rem; }
.doc-pages-actions { display: inline-flex; gap: 0.3rem; margin-left: auto; }
.doc-pages-actions .button, .doc-pages-save { padding: 0.3rem 0.5rem; font-size: 0.8rem; }
.doc-pages-delete { color: var(--danger, #b42318); }

/* "Recently viewed by" — compact, collapsed visual weight. */
.doc-viewers-panel { margin-top: 1rem; }
.doc-viewers-panel h3 { color: var(--muted); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.03em; }
.doc-viewers { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 1.5rem; font-size: 0.85rem; }
.doc-viewers li { padding: 0.15rem 0; break-inside: avoid; }

/* ============================================================================
   SLIDE-OVER / DOCKED WORKSPACE
   Mobile: right-side drawer overlay (default below).
   Desktop: the workspace docks as a persistent right sidebar (media query).
   ============================================================================ */

.slideover { position: fixed; inset: 0; z-index: 1000; display: none; }
.slideover.open { display: block; }
.slideover-backdrop { position: absolute; inset: 0; background: rgba(16, 24, 40, 0.45); }
.slideover-panel {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 440px;
  max-width: 92vw;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
.slideover-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.9rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.slideover-body { padding: 0.9rem 1rem; }
.slideover-close {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0.2rem 0.5rem;
  min-height: 0;
}
.slideover-close:hover { background: var(--surface-2); color: var(--fg); }

/* Head action cluster (widen + close) and the widen toggle itself. Never
   shrinks — on narrow screens the TAB ROW scrolls instead (see .ws-tabs), so
   the last tabs can't slide under these buttons. */
.slideover-actions { display: flex; align-items: center; gap: 0.15rem; flex-shrink: 0; }
.slideover-widen {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 0.2rem 0.5rem;
  min-height: 0;
}
.slideover-widen:hover { background: var(--surface-2); color: var(--fg); }
#workspace-overlay.ws-wide .slideover-widen { color: var(--accent); }
/* Expandable workspace panel: the widen toggle grows it enough to show the wide
   results table when a search is run inside the panel. */
#workspace-overlay.ws-wide .slideover-panel { width: min(1080px, 92vw); }

/* ---- Tax-card image + full-screen zoom/pan lightbox ------------------- */
/* In-page thumbnail: readable size + zoom-in affordance (click → lightbox). */
.taxcard-img {
  display: block;
  max-width: 100%;
  max-height: 70vh;
  cursor: zoom-in;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.taxcard-open-full { display: inline-flex; align-items: center; gap: 0.3rem; }
.taxcard-open-full svg { vertical-align: -0.12em; }

/* Full-screen overlay — above the slideovers (z-index:1000). */
#ch-lightbox { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.93); display: none; z-index: 2000; overflow: hidden; touch-action: none; }
#ch-lightbox.show { display: block; }
#ch-lb-stage { position: absolute; inset: 0; cursor: grab; }
#ch-lb-stage.drag { cursor: grabbing; }
#ch-lb-img {
  position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform;
  user-select: none; -webkit-user-drag: none; box-shadow: 0 0 40px rgba(0, 0, 0, 0.6);
}
#ch-lb-bar {
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%); z-index: 2001;
  display: flex; gap: 4px; align-items: center; max-width: 94vw; flex-wrap: nowrap;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius); padding: 5px 7px; box-shadow: var(--shadow-md, 0 6px 22px rgba(0, 0, 0, 0.35));
}
.ch-lb-btn {
  display: inline-flex; align-items: center; gap: 0.3rem;
  background: none; border: none; color: var(--fg); cursor: pointer;
  padding: 5px 8px; border-radius: var(--radius-sm); font: inherit; line-height: 1;
  text-decoration: none;
}
.ch-lb-btn:hover { background: var(--accent-soft); color: var(--accent-strong); }
.ch-lb-btn svg { vertical-align: -0.12em; }
a.ch-lb-btn { color: var(--accent); }
.ch-lb-z { color: var(--fg); font-size: 0.8rem; min-width: 46px; text-align: center; }
.ch-lb-cap {
  color: var(--muted); font-size: 0.8rem; padding: 0 6px; max-width: 28vw;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ch-lb-sep { width: 1px; align-self: stretch; background: var(--border); margin: 2px 3px; }

.recent-section { padding: 0.6rem 1rem; }
.recent-section h3 { margin: 0 0 0.5rem; font-size: 0.9rem; }
.recent-list { list-style: none; margin: 0; padding: 0; }
.recent-list li { padding: 0.4rem 0; border-bottom: 1px solid var(--border); font-size: 0.9rem; }
.recent-list li:last-child { border-bottom: none; }
.recent-footer { padding: 0.6rem 1rem; }

/* Workspace tabs — one row; on narrow screens it scrolls horizontally (the
   viewer-tools pattern) instead of overflowing under the widen/close buttons. */
.ws-tabs {
  display: flex;
  gap: 0.1rem;
  flex-wrap: nowrap;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;            /* the active-tab underline is the cue */
}
.ws-tabs::-webkit-scrollbar { display: none; }
.ws-tab { flex-shrink: 0; }
.ws-tab {
  background: none;
  border: none;
  color: var(--muted);
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  padding: 0.4rem 0.5rem;
  min-height: 0;
  white-space: nowrap;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  border-bottom: 2px solid transparent;
}
.ws-tab:hover:not(:disabled) { background: var(--surface-2); color: var(--fg); }
.ws-tab.active { border-bottom-color: var(--accent); color: var(--accent); font-weight: 600; }
.ws-tab:disabled { opacity: 0.4; cursor: default; }

.ws-subtabs {
  display: inline-flex;
  gap: 0;
  margin-bottom: 0.85rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.2rem;
}
.ws-subtab {
  background: none;
  border: none;
  color: var(--muted);
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  padding: 0.35rem 0.95rem;
  min-height: 0;
  border-radius: 999px;
}
.ws-subtab.active { background: var(--surface); color: var(--accent); font-weight: 600; text-decoration: none; box-shadow: var(--shadow-sm); }

/* Workspace content blocks */
.doc-notes .doc-note-form { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; }
.note-list { list-style: none; margin: 0; padding: 0; }
.note-item { padding: 0.6rem 0; border-bottom: 1px solid var(--border); }
.note-item:last-child { border-bottom: none; }
.note-meta { display: flex; gap: 0.5rem; align-items: baseline; flex-wrap: wrap; }
.note-author { font-weight: 600; font-size: 0.9rem; }
.note-time { font-size: 0.8rem; }
.note-body { margin-top: 0.25rem; white-space: pre-wrap; }
/* Muted group headings — only shown when both groups exist. Shared by the notes
   panel (General / On the pages) and the parcels panel (Linked / On the pages) so
   the two read as one design system. */
.note-group-label,
.parcel-group-label {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em;
  margin: 0.8rem 0 0.1rem;
}
.note-list + .note-group-label,
.parcel-list + .parcel-group-label { margin-top: 1rem; }
/* Boxed-note text is a click target that jumps the viewer to the box + flashes it. */
.note-nav {
  display: block; width: 100%; text-align: left;
  background: none; border: none; padding: 0; margin: 0.25rem 0 0;
  font: inherit; color: inherit; cursor: pointer;
}
.note-nav:hover .note-title,
.note-nav:hover .note-body { color: var(--accent); }
.note-nav .note-body { margin-top: 0; }
.note-nav:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.note-del-btn:hover { color: var(--error-fg); }
.note-item-editing .note-actions { display: flex; gap: 0.5rem; margin-top: 0.25rem; }

.parcel-list { list-style: none; margin: 0 0 1rem; padding: 0; }
.parcel-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border);
}
.parcel-item:last-child { border-bottom: none; }
/* The pin/draw affordance right-aligns the trailing action cluster (+box · edit
   box, then unlink / OCR-review) — the notes panel's .note-box-btn idiom. It's the
   single auto-margin per row now, so unlink/actions ride along at the right edge. */
.parcel-box-btn { margin-left: auto; }
.parcel-find { display: flex; gap: 0.5rem; align-items: flex-end; }
.parcel-find input { flex: 1; }
.parcel-matches { margin-top: 0.85rem; }

.index-fields-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.index-fields label { margin-bottom: 0.6rem; }
.index-fields label > .muted { font-weight: 400; }

/* Party rows: Last/Business (grows) + First (narrower) + remove, per party. */
.party-group {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 0.5rem 0.6rem; margin: 0 0 0.6rem;
}
.party-group legend { font-size: 0.85rem; padding: 0 0.3rem; }
.party-rows { display: flex; flex-direction: column; gap: 0.35rem; }
.party-row { display: flex; gap: 0.4rem; align-items: center; }
.party-row input { flex: 1 1 auto; min-width: 0; margin: 0; }
.party-row input[name$="_first"] { flex: 0 1 9rem; }
.party-row .idx-remove-party { flex: 0 0 auto; line-height: 1; }
.idx-add-party { margin-top: 0.4rem; }

/* Bulk parcel upload: result readout + form. */
.bulk-result {
  border-left: 3px solid #2a8a5f; background: rgba(42, 138, 95, 0.08);
  padding: 0.5rem 0.75rem; border-radius: var(--radius-sm); margin-bottom: 0.75rem;
}
.bulk-result.bulk-error { border-left-color: #c0392b; background: rgba(192, 57, 43, 0.08); }
.bulk-form label { display: block; margin-bottom: 0.6rem; }
.bulk-help { margin-top: 0.6rem; }
.bulk-help code { font-size: 0.85em; }

.document-list { list-style: none; margin: 0.5rem 0 0; padding: 0; }
.document-item {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--border);
}
.document-item:last-child { border-bottom: none; }
.doc-actions { display: inline-flex; gap: 0.85rem; }

.doc-export-panel form { margin-bottom: 0.75rem; }

/* Admin */
.admin-tabs { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 1rem; border-bottom: 1px solid var(--border); }
.admin-tabs a {
  padding: 0.5rem 0.85rem;
  text-decoration: none;
  color: var(--muted);
  border-bottom: 2px solid transparent;
}
.admin-tabs a.active { color: var(--accent); font-weight: 600; border-bottom-color: var(--accent); }

/* Users page header row: title + the relocated "Invite a teammate" action. */
.admin-users-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.history-toggle { display: flex; gap: 0.5rem; margin-bottom: 1rem; }

.search-pending,
.job-status-inline { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.75rem 0; }
.pending-text { color: var(--muted); }

.empty { color: var(--muted); }

/* ============================================================================
   BREAKPOINTS
   ============================================================================ */

/* Tablet+ : show nav inline, side-by-side form rows, wider tables. */
@media (min-width: 768px) {
  .field-row { grid-template-columns: repeat(2, 1fr); }
  .content { padding: 0 1.5rem; margin-top: 1.5rem; }
}

/* Horizontal nav only at >=1024px. Below that (tablets + phones) the nav stays
   collapsed behind the hamburger, so the ~11 staff links + account never cram
   into one row (that cram is what stacked the username vertically on tablets). */
@media (min-width: 1024px) {
  .topnav { padding: 0 1.5rem; gap: 1rem; }
  .nav-toggle { display: none; }

  .navlinks {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;          /* wrap to a second row instead of cramming/overflowing */
    align-items: center;
    gap: 0.35rem;
    max-height: none;
    overflow: visible;
    opacity: 1;
    pointer-events: auto;
    padding: 0;
    box-shadow: none;
    border-bottom: none;
    background: transparent;
  }
  .navlinks a,
  .navlinks .navlink-btn {
    width: auto;
    padding: 0.4rem 0.6rem;
    font-size: 0.95rem;
  }

  /* Landman ▾ / Account ▾ on desktop: floating menus anchored under the toggle,
     right-edge aligned so they never spill off-screen (both sit at the row end). */
  .nav-dropdown {
    position: relative;
    width: auto;
  }
  .nav-dropdown-toggle { padding: 0.4rem 0.6rem; font-size: 0.95rem; }
  .nav-dropdown-menu {
    position: absolute;
    top: calc(100% + 0.35rem);
    right: 0;
    left: auto;
    min-width: 11rem;
    padding: 0.3rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    z-index: 950;
  }
  .nav-dropdown-menu a { padding: 0.45rem 0.6rem; font-size: 0.92rem; white-space: nowrap; }
}

@media (min-width: 980px) {
  .field-row { grid-template-columns: repeat(3, 1fr); }
  .tile-grid { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }

  /* Center single-column pages back into a comfortable reading width. The search
     page is intentionally NOT capped here — its results table is wide, so it uses
     the full content width; only its form is constrained (see .search-form). */
  .parcels, .exports, .history-page, .admin,
  .parcel-detail, .instrument-detail, .dashboard {
    max-width: 920px;
    margin-left: auto;
    margin-right: auto;
  }
  /* Keep the search form compact even though the results span the full width. */
  .search-form { max-width: 760px; }
}

/* On a narrow deed-view flow chart, People is not a second panel: restyle the
   existing workspace DOM in-flow immediately after <main> (and therefore after
   the chart). Every other workspace tab remains the ordinary fixed drawer. */
@media (max-width: 1099px) {
  body:has(.flow-page) #workspace-overlay.open.ws-flow-people {
    position: static;
    inset: auto;
    z-index: auto;
    width: calc(100% - 2rem);
    max-width: calc(var(--maxw) - 2rem);
    margin: 0 auto 1.5rem;
  }
  body:has(.flow-page) #workspace-overlay.open.ws-flow-people .slideover-backdrop {
    display: none;
  }
  body:has(.flow-page) #workspace-overlay.open.ws-flow-people .slideover-panel {
    position: static;
    width: 100%;
    max-width: none;
    height: auto;
    max-height: none;
    overflow: visible;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
  }
}
@media (min-width: 768px) and (max-width: 1099px) {
  body:has(.flow-page) #workspace-overlay.open.ws-flow-people {
    width: calc(100% - 3rem);
    max-width: calc(var(--maxw) - 3rem);
  }
}

/* ----------------------------------------------------------------------
   DESKTOP DOCKED WORKSPACE
   On wide screens the workspace stops being a fullscreen overlay and docks
   as a persistent right-hand sidebar next to the (hero) image. Same markup &
   JS: when .open, the panel sits in-flow on the right; the document column
   shrinks to make room. The Recent overlay stays a drawer (it's transient).
   ---------------------------------------------------------------------- */
@media (min-width: 1100px) {
  /* When the workspace drawer is open, dock it as a fixed right-hand sidebar
     and reserve room for it on the main content so nothing is occluded. The
     panel keeps the same markup/JS; only its presentation changes. */
  body:has(#workspace-overlay.open) .content,
  body:has(#workspace-overlay.open) .flash {
    margin-right: calc(420px + 1.5rem);
    max-width: none;
    transition: margin-right 0.18s ease;
  }
  /* Re-center the narrower single-column pages within the remaining space. */
  body:has(#workspace-overlay.open) .parcels,
  body:has(#workspace-overlay.open) .exports,
  body:has(#workspace-overlay.open) .history-page,
  body:has(#workspace-overlay.open) .admin,
  body:has(#workspace-overlay.open) .parcel-detail,
  body:has(#workspace-overlay.open) .instrument-detail,
  body:has(#workspace-overlay.open) .dashboard { margin-left: auto; margin-right: auto; }

  /* Let clicks pass through the (now backdrop-less) overlay to the page; only
     the docked panel itself remains interactive. */
  #workspace-overlay.open { pointer-events: none; }
  #workspace-overlay.open .slideover-panel { pointer-events: auto; }
  #workspace-overlay.open .slideover-backdrop { display: none; }
  #workspace-overlay.open .slideover-panel {
    top: var(--nav-h);
    height: calc(100vh - var(--nav-h));
    width: 420px;
    max-width: 420px;
    border-left: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
  }
  /* Widened: grow the docked panel and reserve matching room on the main column
     (more specific than the rules above — extra .ws-wide class — so it wins). */
  #workspace-overlay.open.ws-wide .slideover-panel {
    width: min(1080px, 92vw);
    max-width: min(1080px, 92vw);
  }
  body:has(#workspace-overlay.open.ws-wide) .content,
  body:has(#workspace-overlay.open.ws-wide) .flash {
    margin-right: calc(min(1080px, 92vw) + 1.5rem);
  }

  /* When the workspace overlay is docked alongside, fit-screen mode gets a
     slightly tighter cap so the rotated/scaled image still fits the reduced
     viewport. Fit-width mode is unaffected (its width is the contract). */
  .doc-viewer-mode-fit-screen .doc-page-img {
    max-height: calc((100vh - 200px) * var(--zoom, 1));
  }
}

/* ----------------------------------------------------------------------
   MOBILE VIEWER NAV — fixed, thumb-reachable Prev/Next/Refresh bar.
   ---------------------------------------------------------------------- */
@media (max-width: 767px) {
  .viewer-toolbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 800;
    margin: 0;
    padding: 0.4rem 0.6rem calc(0.4rem + env(safe-area-inset-bottom));
    border-radius: 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    box-shadow: 0 -2px 12px rgba(16, 24, 40, 0.12);
    flex-direction: column;
    align-items: stretch;
    gap: 0.4rem;
  }
  /* Thin centered page label across the top of the bar. */
  .viewer-toolbar .page-label {
    order: -2;
    width: 100%;
    justify-content: center;
    font-size: 0.82rem;
  }
  /* Primary nav: full-width Prev / Next with a fixed Refresh. */
  .viewer-toolbar .viewer-nav { order: -1; display: flex; gap: 0.4rem; }
  .viewer-toolbar .viewer-nav .button { flex: 1; min-height: 44px; }
  .viewer-toolbar .viewer-nav .doc-refresh { flex: 0 0 48px; }
  /* Tools: one horizontally scrollable row of equal pills (no vertical stack). */
  .viewer-toolbar .viewer-tools {
    margin-left: 0;
    display: flex;
    flex-wrap: nowrap;
    gap: 0.4rem;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .viewer-toolbar .viewer-tools .button { flex: 1 0 auto; padding: 0.45rem 0.7rem; font-size: 0.85rem; }
  /* Slightly smaller button text on the small screen. */
  .viewer-toolbar .button { font-size: 0.8rem; }
  /* Minimize/restore handle — a small chevron at the top-right of the bottom bar. */
  .viewer-min-toggle { display: inline-flex; order: -3; align-self: flex-end; width: 40px; }
  /* Collapsed = reading mode: hide every control but the handle, shrink to a thin
     bar, and reclaim the reserved space so the scan fills the screen. */
  .viewer-toolbar.collapsed {
    padding: 0.2rem 0.6rem calc(0.2rem + env(safe-area-inset-bottom));
    gap: 0;
  }
  .viewer-toolbar.collapsed > :not(.viewer-min-toggle) { display: none; }
  .viewer-toolbar.collapsed .viewer-min-toggle { order: 0; align-self: center; }
  .viewer-toolbar.collapsed .viewer-min-toggle svg { transform: rotate(180deg); }
  body:has(.viewer-toolbar.collapsed) .document-viewer-page { padding-bottom: 3.5rem; }
  /* Reserve space so the fixed bar never covers the bottom of the image. */
  .document-viewer-page { padding-bottom: 11rem; }
  /* On mobile the screen IS the viewport — no extra max-height cap needed. */
  .doc-viewer-mode-fit-screen .doc-page-img { max-height: none; }
  .doc-page-area { padding: 0.6rem; }

  .doc-viewers { columns: 1; }
}

/* --- Parcel-number autocomplete + cheat sheet (plan-parcel-number-guide) --- */
/* The autocomplete wrapper anchors the absolutely-positioned dropdown — both on
   the /parcels find-form and the doc-sidebar / adverse-sheet .parcel-find boxes. */
.find-form .autocomplete,
.parcel-find .autocomplete { position: relative; flex: 1 1 auto; }
.parcel-find .autocomplete input { width: 100%; }
.autocomplete-suggest { position: absolute; left: 0; right: 0; top: 100%; z-index: 30; }
.autocomplete-list {
  list-style: none; margin: 2px 0 0; padding: 0; background: var(--surface, #fff);
  border: 1px solid var(--border, #d0d0d0); border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .12); max-height: 16rem; overflow-y: auto;
}
.autocomplete-list li { border-bottom: 1px solid var(--border, #eee); }
.autocomplete-list li:last-child { border-bottom: 0; }
.autocomplete-list a,
.autocomplete-list .autocomplete-fill {
  display: flex; gap: .5rem; align-items: baseline; padding: .4rem .6rem; text-decoration: none;
}
/* The fill-mode suggestion is a <button> (no navigation) — strip the chrome so it
   reads identically to the link suggestions. */
.autocomplete-list .autocomplete-fill {
  width: 100%; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}
.autocomplete-list a:hover,
.autocomplete-list .autocomplete-fill:hover { background: var(--hover, #f2f6ff); }
.autocomplete-empty {
  padding: .4rem .6rem; margin: 2px 0 0; background: var(--surface, #fff);
  border: 1px solid var(--border, #d0d0d0); border-radius: 6px;
}
.cheat-dialog {
  max-width: 640px; width: 92%; border: 1px solid var(--border, #ccc);
  border-radius: 10px; padding: 1.25rem;
}
.cheat-dialog::backdrop { background: rgba(0, 0, 0, .4); }
.cheat-sheet h4 { margin: 1rem 0 .35rem; }
.cheat-county-codes td, .cheat-districts td, .cheat-active-codes td { padding: .18rem .5rem; }
.cheat-close { margin-top: 1rem; text-align: right; }
.link-btn.ghost { background: none; border: 0; color: var(--accent, #2563eb); cursor: pointer; }

/* cheat-sheet trigger: keypad icon + "Codes" label, aligned */
.cheat-btn { display: inline-flex; align-items: center; gap: .35em; }
.cheat-btn .cheat-icon { flex: none; }
/* parcels page: "Find a parcel" heading with the Codes link pushed to its right */
.find-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-bottom: .6rem; }
.find-head h2 { margin: 0; }

/* cheat-sheet view switcher (parcel-ID / WVDEP API) + clickable counties */
.cheat-link { color: var(--accent, #2563eb); cursor: pointer; }
.cheat-link:hover { text-decoration: underline; }
.cheat-tabs, .cheat-nav { display: flex; gap: 1rem; align-items: center; margin: .5rem 0; font-size: .92rem; }
.cheat-tab-active { font-weight: 700; }
.cheat-county-link { font-weight: 500; }

/* district view: county name + both county codes as a header card */
.cheat-district-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem;
  margin: .35rem 0 .85rem; padding: .6rem .8rem;
  background: var(--surface-2, #f6f8fa); border: 1px solid var(--border, #e3e3e3);
  border-radius: 8px;
}
.cheat-county-name { font-size: 1.05rem; font-weight: 700; margin-right: auto; }
.cheat-codes { display: flex; gap: .5rem; flex-wrap: wrap; }
.cheat-code {
  display: inline-flex; align-items: baseline; gap: .4rem;
  padding: .2rem .6rem; border-radius: 999px;
  background: var(--surface, #fff); border: 1px solid var(--border, #d8d8d8);
}
.cheat-code-label {
  font-size: .68rem; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--muted, #667);
}
.cheat-code code { font-weight: 700; font-size: .92rem; }
/* Era sub-heading above each district list when a county has a retired scheme
   (e.g. Marion "Current" vs "Prior to 2010"). */
.cheat-era {
  font-size: .72rem; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--muted, #667);
  margin: .9rem 0 .3rem;
}
.cheat-era:first-of-type { margin-top: .2rem; }

/* ---- Cache-coverage audit (/admin/coverage) -------------------------- */

.coverage-caveat {
  background: var(--info-bg); color: var(--info-fg);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: .6rem .8rem; font-size: .88rem; line-height: 1.45;
}
.coverage-toolbar { margin: .6rem 0 1rem; }

/* The lazy drill-down tree: nested <details> in <ul>s, indented per level. */
.coverage-tree { list-style: none; margin: 0; padding: 0; }
.coverage-children { padding-left: 1.1rem; margin: .25rem 0 .35rem; }
.coverage-node > details > summary {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .7rem;
  padding: .35rem .5rem; border-radius: var(--radius-sm); cursor: pointer;
  list-style-position: inside;
}
.coverage-node > details > summary:hover { background: var(--surface-2); }
.coverage-node > details[open] > summary { background: var(--surface-2); }
.coverage-label { font-weight: 600; }
.coverage-county .coverage-label code { font-weight: 700; }

/* The county rollup line: three side-by-side mode fractions (never blended). */
.coverage-county-summary {
  display: flex; flex-wrap: wrap; gap: .4rem .9rem;
  margin: .2rem 0 .6rem; font-size: .86rem;
}
.coverage-mode-chip {
  padding: .2rem .6rem; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
}
.coverage-mode-name { color: var(--muted); font-weight: 600; margin-right: .35rem; }
.coverage-star { color: var(--accent); font-weight: 700; }

/* The per-node count summary (fraction + bar + badge), rendered by the macro. */
.coverage-counts {
  display: inline-flex; flex-wrap: wrap; align-items: center;
  gap: .35rem .5rem; margin-left: auto; font-size: .85rem;
}
.coverage-bar { width: 90px; height: .55rem; vertical-align: middle; }
.coverage-frac { font-variant-numeric: tabular-nums; }
.coverage-pct { font-weight: 700; color: var(--accent); }

.badge-catalog { background: var(--ok-bg); color: var(--ok-fg); border-color: transparent; }
.badge-discovered { background: var(--surface-2); color: var(--muted); }
.badge-notcached { background: var(--surface-2); color: var(--muted); }
/* Offline (scan-at-courthouse) books — the team's gaps to scan, not the crawler's. */
.badge-offline { background: var(--accent-bg, var(--surface-2)); color: var(--accent); border-color: transparent; }
.badge-warn { background: var(--warn-bg, var(--surface-2)); color: var(--warn-fg, inherit); }

/* Offline-books facet + per-book upload page. */
.offline-panel .offline-county { margin: .5rem 0; }
.offline-books-table { margin: .5rem 0; border-collapse: collapse; }
.offline-books-table th, .offline-books-table td { padding: .25rem .6rem; text-align: left; }
.offline-register { margin: .4rem 0 .8rem; }
.offline-register form label { display: block; margin: .35rem 0; }
.offline-register form input[type="text"], .offline-register form input[type="date"] { max-width: 18rem; }
.offline-review-table { margin: .5rem 0; border-collapse: collapse; }
.offline-review-table th, .offline-review-table td { padding: .2rem .6rem; text-align: left; vertical-align: top; }
.offline-review-table td.offline-thumb-cell { padding: .3rem .4rem; }
/* Staged-page preview thumbnail (lazy-loaded; click opens the shared
   zoom/pan lightbox — the tax-card idiom). */
.offline-thumb {
  display: block; width: 120px; height: auto; max-height: 170px;
  object-fit: contain; border: 1px solid var(--border); border-radius: 3px;
  background: var(--surface-2);
  cursor: zoom-in;
}
.offline-missing-list { max-height: 8rem; overflow-y: auto; }
.offline-batches { list-style: none; padding-left: 0; }
.offline-batches li { margin: .3rem 0; }
.offline-batch-status { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }

/* The leaf: one line per document. */
.coverage-leaf { list-style: none; margin: 0; padding-left: .3rem; }
.coverage-instrument {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .7rem;
  padding: .25rem .4rem; border-bottom: 1px solid var(--border);
  font-size: .87rem;
}
.coverage-instrument:last-child { border-bottom: 0; }
.coverage-leaf-label { font-weight: 600; }
.coverage-leaf-counts { color: var(--muted); font-variant-numeric: tabular-nums; }
.coverage-instrument .badge { margin-left: auto; }
.coverage-state-not_cached .coverage-leaf-label { color: var(--muted); }

/* ---------------------------------------------------------------------------
   Library "Book coverage" facet — segmented per-book cache strips.
   The strip is a flex row of runs; each run's flex-grow is its page count, so
   widths are proportional and every run keeps its own hover tooltip. Segments
   are plain <span>s (not a CSS gradient) precisely so gaps are individually
   hoverable, and non-cached runs carry a min-width so a one-page hole in a big
   book still shows instead of vanishing to a sub-pixel sliver.
   --------------------------------------------------------------------------- */
.cov-legend { display: flex; flex-wrap: wrap; gap: .4rem 1rem; align-items: center; font-size: .85rem; }
.cov-legend-item { display: inline-flex; align-items: center; gap: .35rem; color: var(--muted); }
.cov-legend-swatch {
  display: inline-block; width: 1.1rem; height: .6rem; border-radius: 2px;
  vertical-align: middle;
}

.cov-county-summary,
.cov-rollup { display: inline-flex; align-items: center; gap: .5rem; margin-left: auto; flex-wrap: wrap; }
.cov-county-summary { font-size: .85rem; }

/* The segmented strip + the aggregate rollup bar share the segment colors. */
.cov-strip,
.cov-rollup-bar {
  display: flex; align-items: stretch; overflow: hidden;
  border-radius: 3px; background: var(--cov-strip-rail);
  box-shadow: inset 0 0 0 1px var(--border);
}
.cov-strip { width: min(420px, 46vw); height: .68rem; }
.cov-rollup-bar { width: 160px; height: .55rem; flex: none; }
.cov-rollup-bar-sm { width: 110px; height: .5rem; }

.cov-seg { display: block; min-width: 0; }
/* Give gaps + dead runs a floor width so a single missing page is still visible
   in a long book (cached runs can shrink freely). */
.cov-strip .cov-seg-gap,
.cov-strip .cov-seg-dead { min-width: 3px; }

.cov-seg-cached { background: var(--cov-cached); }
.cov-seg-gap { background: var(--cov-gap); }
/* Dead = muted grey with a subtle diagonal hatch: reads "not expected", clearly
   distinct from an actionable amber gap, and never alarm-red. */
.cov-seg-dead {
  background-color: var(--cov-dead);
  background-image: repeating-linear-gradient(
    45deg, transparent, transparent 2px,
    rgba(255, 255, 255, .5) 2px, rgba(255, 255, 255, .5) 4px);
}
.cov-strip-empty { box-shadow: inset 0 0 0 1px var(--border); }

.cov-book-tree .coverage-county > details > summary { align-items: center; }

/* Series + book rows. */
.cov-series-list, .cov-book-list { list-style: none; margin: .2rem 0; padding: 0; }
.cov-book-row {
  display: flex; align-items: center; gap: .5rem .8rem; flex-wrap: wrap;
  padding: .3rem .45rem; border-bottom: 1px solid var(--border); font-size: .87rem;
}
.cov-book-row:last-child { border-bottom: 0; }
.cov-book-row.is-complete .cov-book-label { color: var(--cov-cached); }
.cov-book-label { font-weight: 600; min-width: 6rem; }
.cov-book-meta { display: inline-flex; align-items: center; gap: .4rem .6rem; margin-left: auto; flex-wrap: wrap; }

.cov-frac { font-variant-numeric: tabular-nums; color: var(--muted); }
.cov-pct { font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.cov-rollup-text { display: inline-flex; align-items: center; gap: .35rem .55rem; flex-wrap: wrap; font-size: .85rem; }
.cov-gap-note { color: #9a6b12; font-weight: 600; }
.cov-dead-note { color: var(--muted); font-weight: 600; }

.cov-mode-badge { text-transform: none; }
.cov-mode-vault { background: rgba(133, 77, 28, 0.15); color: #8a5a1a; border-color: transparent; }
.cov-mode-opendoc { background: rgba(38, 122, 71, 0.15); color: #1f7a47; border-color: transparent; }
.cov-mode-offline { background: var(--accent-soft); color: var(--accent); border-color: transparent; }

/* ---------------------------------------------------------------------------
   Parcel chain-of-title editor (full-page canvas + summary card)
   --------------------------------------------------------------------------- */
.chain-page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
/* Chart-page head actions: the Workspace sidebar opener + the back link
   sit together (both are .chain-btn). */
.chain-page-actions { display: flex; align-items: center; gap: 0.5rem; flex: none; }
/* Anchors dressed as chain buttons (back link, the popovers' Open document). */
a.chain-btn { text-decoration: none; }
/* The node/tract popover's "Edit index" / "Open document" shortcuts
   (instrument-backed only) — compact, inside the muted instrument note. */
.chain-popover-editindex {
  font-size: 0.85rem; padding: 0.2rem 0.5rem; margin-left: 0.25rem;
  vertical-align: baseline;
}
/* Open-a-deed-in-its-own-window links on the chart side panels (conveyance
   rows, unfollowed branches, resolve candidates). */
.chain-open-doc {
  display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap;
}
.chain-help { max-width: 70ch; }
.chain-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin: 0.5rem 0 0.75rem; }
.chain-count { color: var(--muted); margin-left: auto; font-variant-numeric: tabular-nums; }
.chain-inline-form { display: inline; }
.chain-btn {
  display: inline-flex; align-items: center; gap: 0.35rem; cursor: pointer;
  font: inherit; padding: 0.35rem 0.7rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--fg);
}
.chain-btn:hover { background: var(--surface-2); }
.chain-btn-accept { border-color: var(--ok-fg); color: var(--ok-fg); }
.chain-btn-danger { border-color: var(--error-fg); color: var(--error-fg); }
.chain-badge {
  display: inline-block; padding: 0.3rem 0.6rem; border-radius: 999px;
  font-size: 0.85rem; font-weight: 600;
}
.chain-badge-green { background: var(--ok-bg); color: var(--ok-fg); }
.chain-badge-amber { background: #fdf3e3; color: #8a5a12; }
.chain-badge-muted { background: var(--surface-2); color: var(--muted); }
.chain-warnings { margin: 0 0 0.75rem; padding-left: 1.2rem; color: #8a5a12; }
.chain-warnings li { font-size: 0.88rem; }
.chain-suggestions ul, .chain-edge-list { list-style: none; padding: 0; margin: 0.5rem 0 0; }
.chain-suggestions li, .chain-edge-list li {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.3rem 0;
  border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
/* A RESERVING deed (the node contains the reservation language) reads
   distinct: a lavender marker pill with the reservation icon + kind. The full
   kind + note ride the badge's title tooltip. Node-level since 0079 — nodes
   are the transactions, so the deed that reserves owns the flag. */
.chain-reservation-badge {
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0.15rem 0.5rem; border-radius: 999px;
  background: #ede0f5; color: #5a3a86; font-size: 0.82rem; font-weight: 600;
}
.chain-reservation-badge svg { flex: none; }

.chain-canvas-wrap { position: relative; margin: 0.5rem 0 1rem; }
.chain-canvas {
  /* --ch-canvas-h is the height-factor stepper (chCanvasSize, base.html):
     node positions are fractions of the box, so a taller box spreads the
     layout proportionally. The painted row pitch shrinks by the same factor
     so it keeps matching the snap grid (GRID_ROWS × factor). */
  position: relative; width: 100%;
  height: calc(760px * var(--ch-canvas-h, 1));
  background:
    linear-gradient(var(--border) 1px, transparent 1px)
      0 0 / 100% calc(10% / var(--ch-canvas-h, 1)),
    linear-gradient(90deg, var(--border) 1px, transparent 1px) 0 0 / 8.333% 100%,
    var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  overflow: hidden; user-select: none;
}
.chain-empty { position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; text-align: center; padding: 2rem; pointer-events: none; }
/* Edges are cubic-bezier <path>s drawn by chChainEditor with an arrowhead
   <marker> at the newer end. Color flows through currentColor: set `color`
   on the edge group (relationship class / hover) and the line AND arrowhead
   (fill: context-stroke) follow together. */
svg.chain-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.chain-edge { color: var(--accent); }
/* Relationship accents mirror the node-kind rails. */
.chain-edge-merges_into { color: var(--accent-strong); }
.chain-edge-splits_from { color: #8a5a12; }
.chain-edge-out { color: var(--error-fg); }
.chain-edge-derives_from { color: var(--muted); }
.chain-edge-line { fill: none; stroke: currentColor; stroke-width: 2; }
.chain-edge-derives_from .chain-edge-line { stroke-dasharray: 5 4; }
/* Wide invisible twin of each edge so a 2px curve is hoverable. */
/* The fat invisible hit path makes the whole edge CLICKABLE (pointer-events
   re-enabled per-path under the pointer-events:none svg — the .chain-node-stub
   idiom): click opens the edge popover (endpoints / retype / delete). */
.chain-edge-hit { fill: none; stroke: transparent; stroke-width: 14; pointer-events: stroke; cursor: pointer; }
.chain-edge:hover { color: var(--accent-strong); }
.chain-edge:hover .chain-edge-line { stroke-width: 3.5; }
.chain-edge-rubber { stroke: var(--accent-strong); stroke-width: 2; stroke-dasharray: 4 3; }
/* Reserved-interest STUB: a short dashed offshoot out of a RESERVING deed's
   node ending in a small hollow circle — the visual seam where the reserved
   estate will sever onto its own chain (not a full node/edge). Lavender to
   match the reservation badge. */
.chain-node-stub { color: #7d5ba6; pointer-events: auto; cursor: crosshair; }
.chain-node-stub-line {
  fill: none; stroke: currentColor; stroke-width: 2; stroke-dasharray: 4 3;
}
.chain-node-stub-tip { fill: var(--surface); stroke: currentColor; stroke-width: 1.5; }

.chain-node {
  position: absolute; width: 170px; box-sizing: border-box; cursor: grab;
  padding: 0.4rem 0.5rem; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--border-strong);
  border-left: 4px solid var(--border-strong);
  box-shadow: var(--shadow-sm); font-size: 0.78rem; z-index: 2;
  transition: box-shadow 0.12s ease;
}
.chain-node:hover { box-shadow: var(--shadow-md); }
.chain-node:active { cursor: grabbing; }
.chain-node-dragging {
  cursor: grabbing; z-index: 5; box-shadow: var(--shadow-md); opacity: 0.92;
  transition: none;
}
/* Marquee multi-select (chCanvasSelect, base.html): selected cards carry an
   accent outline (dashed while the group is dragged); the marquee rubber
   band never eats pointer events. Flow-chart cards also carry .chain-node,
   so this one place covers both canvases. */
.chain-node-selected { outline: 2px solid var(--accent-strong); outline-offset: 1px; }
.chain-node-selected.chain-node-dragging { outline-style: dashed; }
.chain-marquee {
  position: absolute; z-index: 6; pointer-events: none;
  border: 1px dashed var(--accent-strong);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
/* Canvas height stepper (toolbar) — see chCanvasSize in base.html. */
.chain-canvas-size { display: inline-flex; align-items: center; gap: 0.35rem; }
.chain-canvas-size .chain-btn { display: inline-flex; align-items: center; gap: 0.3rem; }
.chain-canvas-size .chain-btn svg { flex: none; }
.chain-canvas-size .chain-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.chain-canvas-size-factor {
  color: var(--muted); font-variant-numeric: tabular-nums;
  min-width: 2.2em; text-align: center; font-size: 0.85rem;
}
.chain-node-handle {
  position: absolute; top: -7px; right: -7px; width: 14px; height: 14px;
  border-radius: 999px; background: var(--accent); border: 2px solid var(--surface);
  cursor: crosshair; z-index: 3;
}
.chain-node-kind { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
.chain-node-bp { font-weight: 700; }
/* Grantors and grantees each get their OWN truncating line (one shared nowrap
   line always ellipsized the grantee away); full text in the title attr. */
.chain-node-parties { color: var(--fg); }
.chain-node-party { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Dates (inst/rec, labeled) + acreage: one muted line that wraps when needed. */
.chain-node-meta { color: var(--muted); font-variant-numeric: tabular-nums;
  display: flex; flex-wrap: wrap; column-gap: 0.45rem; font-size: 0.72rem; }
.chain-node-tract_root { border-left: 4px solid var(--ok-fg); }
.chain-node-merge { border-left: 4px solid var(--accent-strong); }
.chain-node-split { border-left: 4px solid #8a5a12; }
.chain-node-outsale { border-left: 4px solid var(--error-fg); }
.chain-node-provisional { border-style: dashed; background: var(--surface-2); }
/* The reservation badge sized down to the node card's scale. */
.chain-node .chain-node-resv { margin-top: 0.2rem; }
.chain-node .chain-reservation-badge {
  font-size: 0.68rem; padding: 0.05rem 0.4rem; gap: 0.25rem;
}

/* ---------------------------------------------------------------------------
   The DEED projection of the flow chart (?view=deeds — the ratified model:
   every card is a CONVEYANCE, the tracts it conveys are sub-rows inside it,
   arrows are per-tract guidance tagged with the tract that flows).
   docs/plan-deed-node-reprojection.md §3. The cards reuse .chain-node, so
   marquee multi-select, group move, snap and the height stepper are inherited
   untouched — only the extra sub-layer is styled here.
   --------------------------------------------------------------------------- */
.chain-node.flow-deed { width: 216px; }
.flow-deed .flow-subrows {
  list-style: none; margin: 0.3rem 0 0; padding: 0;
  border-top: 1px solid var(--border);
}
.flow-deed .flow-subrow {
  position: relative;
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.25rem;
  padding: 0.15rem 0.9rem 0.15rem 0.25rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.72rem; line-height: 1.25;
}
.flow-deed .flow-subrow:last-child { border-bottom: none; }
.flow-deed .flow-subrow-label { font-weight: 600; }
.flow-deed .flow-subrow-ac {
  color: var(--muted); font-variant-numeric: tabular-nums;
}
.flow-deed .flow-subrow-more {
  color: var(--muted); font-style: italic; justify-content: center;
}
/* Hovering an arrow lights its tract rows; hovering a row lights its arrows. */
.flow-subrow-hl { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.chain-edge-hl { color: var(--accent-strong); }
.chain-edge-hl .chain-edge-line { stroke-width: 3.5; }
/* Per-tract connect handle: drag a tract row onto the conveyance it flows
   into (a 3-tract deed can feed three different follow-up conveyances). */
.flow-subrow-handle {
  position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
  width: 9px; height: 9px; border-radius: 999px;
  background: var(--accent); border: 2px solid var(--surface);
  cursor: crosshair; opacity: 0; transition: opacity 0.1s ease;
}
.flow-deed:hover .flow-subrow-handle,
.flow-subrow:hover .flow-subrow-handle { opacity: 1; }
/* The accumulated undivided-interest chip (OQ-10) on a tract row. */
.flow-interest-chip {
  display: inline-flex; align-items: center; gap: 0.2rem;
  padding: 0.02rem 0.32rem; border-radius: 999px;
  background: #e6f2e6; color: #2c6e2c;
  font-size: 0.68rem; font-weight: 600; white-space: nowrap;
}
.flow-interest-warn { color: var(--error-fg); font-weight: 700; cursor: help; }
/* The tract tag(s) riding the from end of an arrow (OQ-12: one arrow, stacked
   tags) — the visible answer to "which tract goes with which chain". */
.flow-arrow-tag {
  font-size: 10px; font-weight: 600; fill: currentColor;
  paint-order: stroke; stroke: var(--surface); stroke-width: 3px;
  stroke-linejoin: round; pointer-events: none;
}
/* Deed popover: the identity block + the per-tract editors. */
.flow-deed-popover { width: 420px; }
.flow-deed-popover h4 { margin: 0; }
.flow-popover-subhead { margin: 0.6rem 0 0.3rem; font-size: 0.82rem; }
.flow-popover-subrow {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 0.35rem 0.45rem; margin-bottom: 0.4rem; background: var(--surface-2);
}
.flow-popover-subrow .flow-subrow-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.3rem;
  margin-bottom: 0.25rem;
}
.flow-popover-flow {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.3rem;
  margin-top: 0.25rem; padding-top: 0.25rem; border-top: 1px dashed var(--border);
  font-size: 0.76rem;
}
.flow-popover-subrow .chain-inline-form { display: inline-flex; gap: 0.3rem;
  align-items: center; flex-wrap: wrap; }
.flow-popover-subrow input[type="text"] { max-width: 160px; }
/* The drop pick: which tract of a multi-tract deed does this flow land on? */
.flow-subrow-pick {
  position: fixed; left: 50%; top: 30%; transform: translateX(-50%); z-index: 60;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius); box-shadow: var(--shadow-md); padding: 0.8rem;
  min-width: 240px;
}
.flow-subrow-pick ul { list-style: none; margin: 0.4rem 0; padding: 0; }
.flow-subrow-pick li { padding: 0.15rem 0; }
/* The server-rendered mirror of the canvas (one block per conveyance). */
.flow-deed-block {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 0.5rem 0.6rem; margin-bottom: 0.6rem;
}
.flow-deed-block-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem; margin: 0;
}
.flow-deed-block-parties { margin: 0.15rem 0 0.4rem; font-size: 0.82rem; }
.flow-deed-subrows { list-style: none; margin: 0; padding: 0; }
.flow-deed-subrows > li {
  padding: 0.35rem 0; border-top: 1px dashed var(--border);
}
.flow-deed-subrows .flow-subrow-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem;
}
.flow-subrow-form, .flow-add-subrow {
  display: inline-flex; align-items: center; gap: 0.35rem; flex-wrap: wrap;
}
.flow-subrow-flow {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem;
  margin-top: 0.25rem; font-size: 0.82rem;
}
.flow-unattributed-warning { color: var(--error-fg); }
.flow-view-toggle { font-weight: 600; }

.chain-popover, .chain-edge-popover {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 50; width: 340px;
  max-height: calc(100vh - 2rem); overflow: auto;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius); box-shadow: var(--shadow-md); padding: 0.9rem;
}
.chain-popover h4, .chain-edge-popover h4 { margin: 0 0 0.5rem; }
.chain-popover label, .chain-edge-popover label { display: block; margin-bottom: 0.4rem; }
/* Edge popover endpoints: "older deed → newer deed" by book/page label. */
.chain-edge-endpoints { display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.35rem; font-weight: 600; margin: 0 0 0.25rem; }
.chain-edge-endpoints-arrow { color: var(--muted); display: inline-flex; }
.chain-edge-popover-note { font-size: 0.78rem; margin: 0 0 0.5rem; }
.chain-popover input:disabled { opacity: 0.55; cursor: not-allowed; }
.chain-popover-instnote { font-size: 0.78rem; margin: 0.2rem 0 0.4rem; }
.chain-popover-actions { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
.chain-edge-rel { margin: 0 0.4rem; }
.chain-field-row { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.chain-field-row label { flex: 1 1 120px; }
.chain-candidates { max-height: 240px; overflow: auto; }
.chain-summary-line { font-variant-numeric: tabular-nums; }

/* ============================================================================
   Vault OCR-assisted indexing — suggested entries + the layout-profile editor.
   ========================================================================== */

/* A suggested (OCR) entry in the sidebar list — amber, set apart from the
   confirmed/manual rows (mirrors the amber autolinked-parcel treatment). */
.vault-index-suggested {
  background: rgba(217, 154, 30, 0.08);
  border-left: 3px solid rgba(180, 83, 9, 0.85);
}
.vault-index-suggested .vix-num { background: rgba(180, 83, 9, 0.97); }
.badge.vix-suggested-badge {
  background: rgba(217, 154, 30, 0.18);
  color: #8a5a00;
  border: 1px solid rgba(217, 154, 30, 0.5);
  margin-left: 0.3rem;
}
/* Confirm / Dismiss live in the shared .vault-index-entry-actions row; keep
   their little forms inline + margin-free like the delete form. */
.vix-suggested-confirm, .vix-suggested-dismiss { margin: 0; }

/* On-image: a suggested box's amber color is set inline by chVaultIndexer; this
   only adds a subtle pulse so an unreviewed band catches the eye. */
.vault-box-suggested { animation: vaultSuggestPulse 2.4s ease-in-out infinite; }
@keyframes vaultSuggestPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.72; }
}

/* --- Layout-profile editor (admin) --------------------------------------- */
.vault-profile-editor { margin: 0.75rem 0; }
.vpe-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
  margin-bottom: 0.5rem;
}
.vpe-toolbar label { display: inline-flex; flex-direction: column; gap: 0.15rem; font-size: 0.78rem; color: var(--muted); }
.vpe-stage { position: relative; display: inline-block; max-width: 100%; }
.vpe-stage-empty {
  min-height: 8rem; width: 100%;
  border: 1px dashed var(--border-strong); border-radius: 6px;
  background: var(--surface-2);
}
.vpe-img { display: block; max-width: 100%; height: auto; }
.vpe-overlay { position: absolute; inset: 0; cursor: crosshair; touch-action: pinch-zoom; z-index: 2; }
/* A committed column band (drawn over the page); spans the full height. */
.vpe-col {
  background: rgba(37, 99, 168, 0.14);
  border-left: 2px solid rgba(28, 77, 133, 0.9);
  border-right: 2px solid rgba(28, 77, 133, 0.9);
  box-sizing: border-box;
}
.vpe-col-rubber { background: rgba(37, 99, 168, 0.22); border-style: dashed; }
.vpe-col-label {
  position: absolute; top: 0.2rem; left: 0.2rem;
  font-size: 0.66rem; font-weight: 700; color: #fff;
  background: rgba(28, 77, 133, 0.92);
  padding: 0 0.25rem; border-radius: 3px; white-space: nowrap;
}
.vpe-columns { list-style: none; padding: 0; margin: 0.5rem 0; }
.vpe-columns li {
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0.2rem 0.3rem; border-bottom: 1px solid var(--border);
}
.vpe-columns li:last-child { border-bottom: 0; }
.vpe-col-num {
  flex: 0 0 auto; min-width: 1.2rem; height: 1.2rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(28, 77, 133, 0.92); color: #fff;
  border-radius: 999px; font-size: 0.68rem; font-weight: 700;
}
.vpe-columns li .link-btn-danger { margin-left: auto; }
.vpe-yband, .vpe-range { margin: 0.5rem 0; }
.vpe-yband label, .vpe-range label { display: inline-flex; flex-direction: column; gap: 0.15rem; font-size: 0.78rem; color: var(--muted); margin-right: 0.6rem; }
.vpe-range input[type="number"] { width: 6.5rem; }
.vpe-range > .muted { display: block; font-size: 0.78rem; margin-top: 0.25rem; }
.vault-layout-save-form, .vault-layout-open, .vault-layout-propose-form { margin: 0.5rem 0; }
.vault-layout-open { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: flex-end; }
.vault-layout-open label { display: flex; flex-direction: column; gap: 0.15rem; font-size: 0.8rem; }

/* Webmap affordance — small map-pin link next to a parcel number (see
   partials/_webmap.html). Muted until hovered so it doesn't compete with the
   number itself; sits on the text baseline at 1em. */
.webmap-link {
  display: inline-flex; align-items: center; justify-content: center;
  margin-left: 0.35rem; color: var(--muted); vertical-align: -0.05em;
  text-decoration: none; line-height: 1;
}
.webmap-link:hover { color: var(--accent); }

/* /admin/tasks — per-county job blocks (visibility + Run next / Cancel). Each
   county is a card with a header line then its described queued/running jobs. */
.county-tasks {
  border: 1px solid var(--border); border-radius: 6px;
  padding: 0.5rem 0.7rem; margin: 0.5rem 0; background: var(--surface);
}
.county-tasks.task-stalled { border-color: var(--error-fg); }
.county-tasks-head {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
}
.county-tasks-head .muted.small { margin-left: auto; }
.county-jobs-table { margin: 0.5rem 0 0; }
.county-jobs-table td { padding: 0.25rem 0.4rem; vertical-align: middle; }
.county-job-actions { display: flex; gap: 0.5rem; white-space: nowrap; }
.county-job-actions .link-btn {
  display: inline-flex; align-items: center; gap: 0.25rem;
}
/* Job-kind chips — mirror the eventual search/opendoc/vault lanes. */
.badge.job-kind-search   { background: rgba(28, 77, 133, 0.15);  color: var(--accent); }
.badge.job-kind-opendoc  { background: rgba(38, 122, 71, 0.15);  color: #1f7a47; }
.badge.job-kind-vault    { background: rgba(133, 77, 28, 0.15);  color: #8a5a1a; }
.badge.job-kind-document { background: rgba(90, 90, 120, 0.15);  color: var(--muted); }
.badge.job-kind-other    { background: var(--surface-2); color: var(--muted); }

/* /admin/tasks — the three per-county lanes (search / opendoc / vault). */
.county-lanes { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.4rem 0 0; }
.county-lane {
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0.15rem 0.4rem; border: 1px solid var(--border); border-radius: 999px;
}
.county-lane.lane-starved { border-color: var(--error-fg); }

/* Workspace "Workers" tab — compact worker status in the sidebar. */
.ws-section-title { margin: 0.6rem 0 0.3rem; font-size: 0.85rem; color: var(--muted-fg, #777); text-transform: uppercase; letter-spacing: 0.04em; }
.workers-tasks, .workers-jobs { list-style: none; margin: 0 0 0.6rem; padding: 0; font-size: 0.85rem; }
.workers-tasks li, .workers-jobs li { display: flex; align-items: center; gap: 0.4rem; padding: 0.15rem 0; flex-wrap: wrap; }
.workers-tasks progress { flex: 1 1 4rem; min-width: 3rem; height: 0.6rem; }
.workers-county { border-top: 1px solid var(--border, #ddd3); padding: 0.45rem 0; }
.workers-county.workers-current { background: var(--accent-bg, #8881); border-radius: 4px; padding: 0.45rem 0.4rem; }
/* Machine-labeled client-agent leases under a county (host + agents view). */
.county-agents { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0.35rem 0 0; }
.county-agent { font-size: 0.8rem; }

/* --- Contribution progress tab + scoreboard (recognition-only) --- */
.progress-me-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.progress-streak { display: inline-flex; align-items: center; gap: 0.2rem; color: var(--accent-fg, #d97706); font-size: 0.9rem; }
.progress-counters { width: 100%; border-collapse: collapse; font-size: 0.9rem; margin: 0.3rem 0 0.5rem; }
.progress-counters th, .progress-counters td { padding: 0.25rem 0.4rem; text-align: right; }
.progress-counters thead th { font-size: 0.72rem; color: var(--muted-fg, #777); text-transform: uppercase; letter-spacing: 0.03em; }
.progress-counters th[scope="row"] { text-align: left; font-weight: 600; }
.progress-counters tbody tr:nth-child(odd) { background: var(--accent-bg, #8881); }
.progress-me-link { margin-top: 0.5rem; font-size: 0.9rem; }

.scoreboard { max-width: 60rem; }
.scoreboard-windows { display: flex; gap: 0.4rem; margin: 0.5rem 0 1rem; }
.btn-window { padding: 0.25rem 0.7rem; border: 1px solid var(--border, #ccc); border-radius: 999px; font-size: 0.85rem; text-decoration: none; color: inherit; }
.btn-window.active { background: var(--accent-bg, #2563eb22); border-color: var(--accent-fg, #2563eb); font-weight: 600; }
.scoreboard-table { width: 100%; border-collapse: collapse; margin-bottom: 1.5rem; }
.scoreboard-table th, .scoreboard-table td { padding: 0.4rem 0.6rem; text-align: right; border-bottom: 1px solid var(--border, #eee2); }
.scoreboard-table th:nth-child(2), .scoreboard-table td:nth-child(2) { text-align: left; }
.scoreboard-table thead th { font-size: 0.75rem; color: var(--muted-fg, #777); text-transform: uppercase; letter-spacing: 0.03em; }
.scoreboard-table tr.me { background: var(--accent-bg, #2563eb1a); font-weight: 600; }
.scoreboard-table td.rank { color: var(--muted-fg, #999); }
.scoreboard-coverage-title { margin-top: 1rem; font-size: 1.05rem; }
.scoreboard-coverage-controls { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin: 0.5rem 0; }
.coverage-list { list-style: none; padding: 0; margin: 0.4rem 0 1rem; }
.coverage-list li { display: flex; align-items: center; gap: 0.6rem; padding: 0.3rem 0; border-bottom: 1px solid var(--border, #eee1); flex-wrap: wrap; }
.coverage-list .book-label { min-width: 6rem; font-weight: 600; }

/* --- Ownership panel (person layer phase 2 / redeye-absorption Phase A) --- */
.ownership-inline-form { display: inline; }
.ownership-toolbar { display: flex; gap: 0.6rem; align-items: center; margin-bottom: 0.4rem; }
.ownership-kind { margin: 0.8rem 0 0.3rem; }
.ownership-table td { vertical-align: top; }
.ownership-actions { white-space: nowrap; }
.ownership-actions form { display: inline; }
.ownership-warning { display: block; margin: 0.2rem 0; }
.ownership-pending { background: var(--accent-bg, #8881); }
.ownership-note-row td { font-size: 0.85rem; padding-top: 0; }
.ownership-field-row { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.4rem; }
.ownership-field-row label { flex: 1 1 140px; }
.ownership-person-candidates { list-style: none; margin: 0.4rem 0; padding: 0; }
.ownership-person-candidates li { display: flex; align-items: center; gap: 0.5rem; padding: 0.15rem 0; flex-wrap: wrap; }
.ownership-person-search { width: 100%; max-width: 28rem; }
.ownership-dismissed-note { font-size: 0.85rem; }
.chain-people-list { list-style: none; margin: 0.3rem 0 0; padding: 0; }
.chain-people-list li { display: flex; align-items: center; gap: 0.5rem; padding: 0.15rem 0; flex-wrap: wrap; }
.flow-people-panel h2 { margin-top: 0; }
.flow-people-panel .chain-person-row {
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--border);
}
.flow-people-panel .chain-person-row.is-selected-deed {
  border-left: 3px solid var(--accent);
  padding-left: 0.55rem;
}
.flow-people-appearances {
  flex: 1 0 100%;
  list-style: none;
  margin: 0.2rem 0 0;
  padding: 0 0 0 1rem;
}
.chain-people-list .flow-people-appearances li {
  display: block;
  padding: 0.15rem 0;
  color: var(--muted);
}
.chain-people-list .flow-people-appearances li.is-selected-deed {
  color: var(--fg);
}
.flow-provisional-people { margin-bottom: 0; }
.flow-person-create,
.flow-succession-create,
.flow-person-attach {
  margin: 0.8rem 0;
  padding: 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.flow-person-create summary,
.flow-succession-create summary { cursor: pointer; font-weight: 600; }
.flow-person-action-form {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 0.6rem;
  margin-top: 0.6rem;
}
.flow-person-action-form label { flex: 1 1 12rem; }
.flow-person-action-form input,
.flow-person-action-form select { width: 100%; }
.flow-person-attach h3 { margin-top: 0; }
.flow-succession-form { display: grid; gap: 0.6rem; margin-top: 0.6rem; }
.flow-succession-fields,
.flow-succession-heir-row,
.flow-succession-evidence {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 0.6rem;
}
.flow-succession-fields label,
.flow-succession-heir-row label,
.flow-succession-evidence label { flex: 1 1 9rem; }
.flow-succession-form input,
.flow-succession-form select { width: 100%; }
.flow-person-choice { margin-bottom: 0.4rem; }
.flow-person-candidates { margin-bottom: 0.5rem; }
.flow-succession-link-card + .flow-succession-link-card {
  border-top: 1px solid var(--border); margin-top: 0.75rem; padding-top: 0.75rem;
}
.flow-succession-link-card form { display: grid; gap: 0.45rem; }
.person-contact-fields { display: flex; flex-wrap: wrap; gap: 0.6rem; border: 1px solid var(--border, #ddd3); border-radius: 6px; padding: 0.5rem; margin: 0.4rem 0; }
.person-contact-fields legend { font-size: 0.85rem; color: var(--muted, inherit); }
.person-contact-fields label { flex: 1 1 140px; }
.person-batch-bar {
  margin: 0.75rem 0;
  padding: 0.75rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
}
.person-batch-bar[hidden] { display: none; }
.person-batch-head,
.person-batch-fields,
.person-batch-list li {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.person-batch-head { justify-content: space-between; }
.person-batch-list { margin: 0.45rem 0; padding-left: 1.5rem; }
.person-batch-list li { justify-content: space-between; padding: 0.15rem 0; }
.person-batch-fields { align-items: flex-end; }
.person-batch-fields label { flex: 1 1 12rem; }
.person-batch-fields input,
.person-batch-fields select { width: 100%; }
.person-batch-status { margin: 0.6rem 0; padding: 0.6rem; border-radius: var(--radius-sm); }
.person-batch-success { color: var(--ok-fg); background: var(--ok-bg); }
.person-batch-error { color: var(--error-fg); background: var(--error-bg); }
.person-batch-checkbox { width: 1.1rem; height: 1.1rem; }
.person-relationship-table td:last-child { min-width: 15rem; }
.person-relationship-link-form {
  display: grid;
  gap: 0.35rem;
  margin-top: 0.45rem !important;
}
.person-relationship-link-form label,
.person-relationship-paste > form > label {
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 600;
}
.person-relationship-link-form input,
.person-relationship-paste textarea,
.person-relationship-paste input[type="text"] { width: 100%; }
.person-relationship-paste { margin-top: 0.9rem; }
.person-relationship-paste > summary { cursor: pointer; font-weight: 600; }
.person-relationship-paste > form {
  display: grid;
  gap: 0.55rem;
  margin-top: 0.65rem;
}
.person-relationship-paste textarea {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.person-relationship-issues {
  color: var(--error-fg);
  background: var(--error-bg);
  border-radius: var(--radius-sm);
  margin-top: 0.7rem;
  padding: 0.65rem;
}
.person-relationship-issues ul { margin-bottom: 0; }
.person-relationship-other { background: var(--warn-bg, var(--surface-2)); }
.person-relationship-other-confirm {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
}
.person-relationship-other-confirm input { width: auto; }

/* --- Lease workflow (redeye-absorption Phase B) --------------------------- */
.lease-inline-form { display: inline; }
.lease-table td { vertical-align: top; }
.lease-fields { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: flex-end; }
.lease-fields label { flex: 1 1 150px; display: block; }
.lease-fields textarea { width: 100%; }
.lease-hbp-choice, .lease-expiring-choice { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 0.35rem; }
.lease-filters { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: flex-end; margin: 0.6rem 0; }
.lease-pipeline-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.lease-pipeline-chips .lease-chip-active { outline: 2px solid currentColor; }
.lease-status { text-transform: none; }
.lease-status-draft { opacity: 0.75; }
.lease-status-requested { background: #f5d76e33; }
.lease-status-approved { background: #7fc97f33; }
.lease-status-out_for_signature { background: #74a9cf33; }
.lease-status-signed, .lease-status-recorded { background: #31a35433; }
.lease-status-rejected, .lease-status-dead { background: #d6604d33; }
.lease-chip-leased_ours { background: #31a35433; }
.lease-chip-pending_ours { background: #f5d76e33; }
.lease-chip-leased_other { background: #d6604d33; }
.lease-expiry-expired { background: #d6604d33; }
.lease-expiry-expiring { background: #f5d76e33; }
.lease-hbp { background: #74a9cf33; }
.lease-terms-grid { display: grid; grid-template-columns: max-content 1fr; gap: 0.25rem 0.8rem; }
.lease-terms-grid dt { color: var(--muted-fg, #777); }
.lease-terms-grid dd { margin: 0; }
.lease-move-form { display: inline-flex; gap: 0.4rem; align-items: center; margin: 0.2rem 0.6rem 0.2rem 0; }
.lease-move-locked { display: flex; align-items: center; gap: 0.35rem; }
.lease-doc-list { list-style: none; margin: 0.3rem 0; padding: 0; }
.lease-doc-list li { display: flex; gap: 0.5rem; align-items: center; padding: 0.15rem 0; flex-wrap: wrap; }
.lease-interest-list { list-style: none; margin: 0.3rem 0; padding: 0; }
.lease-interest-list li { padding: 0.15rem 0; }
.lease-external-add { margin-top: 0.5rem; }
.buyer-company-list { margin: 0.3rem 0; padding-left: 1.2rem; }
.user-capabilities-cell code { font-size: 0.8rem; }

/* Vault layout preview: before/after (old whole-band vs bucketed coalesce). */
.vpe-preview-scroll { overflow-x: auto; max-height: 22rem; overflow-y: auto; }
.vpe-preview-low td { color: #b45309; }
.vpe-preview-ba { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-items: start; }
@media (max-width: 800px) { .vpe-preview-ba { grid-template-columns: 1fr; } }

/* --- Discover parcels by owner (live WV assessor-roll search) ---------- */
/* A sibling of the "Find a parcel" box: the form is a responsive row (county
   selector + owner-name input, which grows, + submit). Results htmx-swap into
   #owner-results as a standard .data-table with a per-row Import action.
   The .find-form base caps width at 640px; override so the row can use the card
   width and its results table (6 cols) stays readable — the parcels .card already
   scrolls overflow-x. */
.owner-search-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.6rem;
  max-width: none;
}
/* Field label above its control (matches the muted .field label look). */
.owner-search-form label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
}
.owner-search-form select { min-width: 12rem; }
.owner-search-form input[name="owner_q"] { flex: 1 1 16rem; min-width: 12rem; }
.owner-search-form button { flex: 0 0 auto; }

#owner-results { margin-top: 0.85rem; }
/* Keep the six columns legible; the enclosing card handles horizontal scroll. */
.owner-search-table { min-width: 680px; }
.owner-search-table .legal-hint {
  color: var(--muted);
  font-size: 0.85rem;
  max-width: 24rem;
}
.owner-search-table .import-cell { white-space: nowrap; }

/* Truncation / error notices — subtle, consistent with other .muted notes. */
.owner-search-truncated,
.owner-search-error { margin: 0 0 0.6rem; }

/* Per-row Import affordance: an icon+label secondary button (mirrors .cheat-btn's
   inline-flex icon layout). The inline SVG sizes to 1em / currentColor. */
.owner-import-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  white-space: nowrap;
}
.owner-import-btn .import-icon { flex: none; }

/* Post-import / already-present states: a plain link in place of the button.
   ".muted" (already-in-system) inherits the muted color; ".ok" reads as success. */
.owner-import-done {
  display: inline-block;
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
.owner-import-done:hover { text-decoration: underline; }
.owner-import-done.ok { color: var(--ok-fg); }

/* Admin dedup queue: side-by-side context columns + gate-conflict reasons. */
.dedup-context { white-space: nowrap; font-variant-numeric: tabular-nums; }
.dedup-reasons { margin: 0.25rem 0 0; padding-left: 1.1rem; max-width: 28rem; }
.dedup-reasons li { margin: 0; }

/* Refs panel: "Open…" affordance for citations with no cached match. */
.ref-open-link { display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap; }

/* Courthouse document requests (the in-app examiner workflow, /requests). */
.request-form {
  margin: 0.6rem 0;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2, var(--surface));
  max-width: 34rem;
  text-align: left;
  font-size: 0.95rem;
}
.request-form-title { margin: 0 0 0.25rem; }
.request-form-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin: 0.4rem 0;
}
.request-form-grid label { display: flex; flex-direction: column; gap: 0.15rem; font-size: 0.85rem; }
/* Party names + the county's own fields: the examiner must be able to READ the
   whole value that will be submitted, so these inputs FILL their column instead
   of clipping a long name at the default input width. */
.request-form-parties {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin: 0.4rem 0;
}
.request-form-parties label {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  font-size: 0.85rem;
  flex: 1 1 14rem;
  min-width: 0;
}
.request-form-parties input { width: 100%; box-sizing: border-box; }
.request-form textarea { width: 100%; }
.request-form-actions { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
.request-optin { display: flex; gap: 0.4rem; align-items: baseline; font-size: 0.9rem; }
.request-evidence-warning { max-width: 34rem; }
.request-pending { display: inline-flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; }
.request-slot { text-align: left; }
.requests-table .requests-actions { white-space: nowrap; }
.requests-actions .inline-form { display: inline; }
/* Recently fulfilled: the returned deeds are grouped under the PARCEL they were
   requested for (a parcel's deeds are one chain of title — they only read
   together), so each group gets a heading and its own table. */
.fulfilled-group + .fulfilled-group { margin-top: 1.25rem; }
.fulfilled-parcel {
  display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap;
  margin: 0 0 0.35rem; font-size: 1rem;
}
.requests-walkup-embed { margin-top: 0.5rem; }
/* Header-nav ambient count on the Requests link: quiet at zero (empty mount),
   a compact count pill when > 0 (self-polled /requests/status). */
.nav-count-mount { display: inline-flex; align-items: center; }
.nav-count-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 0.35rem;
  padding: 0 0.45rem;
  min-width: 1.2em;
  border-radius: 999px;
  background: var(--accent-soft);
  font-size: 0.75rem;
  line-height: 1.4;
  white-space: nowrap;
}

/* ============================================================================
   Admin → Users (compact roster + facet bar + expandable per-user detail).
   Goal: the primary table fits a laptop viewport with zero horizontal scroll;
   every per-user action moved into the .user-detail-panel (hx-get .../detail).
   ============================================================================ */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.admin-users-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 0.9rem;
  margin: 0.6rem 0 0.9rem;
}
.admin-users-search {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1 1 16rem;
  max-width: 24rem;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--muted);
}
.admin-users-search input[type="search"] {
  flex: 1 1 auto;
  border: 0;
  padding: 0.15rem 0;
  background: transparent;
  color: var(--fg);
  font: inherit;
}
.admin-users-search input[type="search"]:focus { outline: none; }
.admin-users-chips { display: inline-flex; flex-wrap: wrap; gap: 0.3rem; }
.admin-users-chips .chip {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.85rem;
  color: var(--muted);
  cursor: pointer;
  user-select: none;
}
.admin-users-chips .chip:hover { border-color: var(--accent); }
.admin-users-chips .chip input { position: absolute; opacity: 0; pointer-events: none; }
.admin-users-chips .chip.chip-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-strong);
  font-weight: 600;
}
.admin-users-status { font-size: 0.9rem; color: var(--muted); }
.admin-users-count { margin: 0.2rem 0 0.6rem; }

/* Compact primary table: name+email stacked, no wide action columns. */
.admin-users-table { table-layout: auto; }
.admin-users-table td { vertical-align: middle; }
.user-identity { display: flex; flex-direction: column; gap: 0.05rem; }
.user-identity .user-name { font-weight: 600; }
.user-identity .user-email { font-size: 0.82rem; }
.user-company { display: block; font-size: 0.8rem; }
.user-detail-row > td { padding: 0 !important; border-bottom: 0; }
.user-detail-row:empty { display: none; }

.badge.role-badge { text-transform: capitalize; }
.badge.role-admin { background: var(--accent-soft); color: var(--accent-strong); border-color: transparent; }
.badge.role-member { background: var(--surface-2); color: var(--muted); }
.badge.role-lease_buyer { background: #f3ecfa; color: #6f4fb0; border-color: transparent; }
.badge.status-active { background: var(--ok-bg); color: var(--ok-fg); border-color: transparent; }
.badge.status-disabled { background: var(--surface-2); color: var(--muted); }
tr.user-disabled { opacity: 0.72; }

.user-flags-cell { white-space: nowrap; }
.user-flag {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  margin-right: 0.5rem;
  color: var(--muted);
}
.user-flag svg { vertical-align: -0.12em; }
.user-flag-count { font-size: 0.78rem; }

/* Expandable detail/action panel (loaded into the detail row). */
.user-detail-panel {
  background: var(--surface-2);
  border-top: 2px solid var(--accent);
  padding: 0.85rem 1rem 1rem;
}
.user-detail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.75rem;
}
.user-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.9rem 1.4rem;
}
.user-detail-field h4 {
  margin: 0 0 0.35rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
}
.user-detail-field .inline-form { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.user-detail-summary { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin: 0; }
.user-detail-field .user-counties-editor-slot:not(:empty),
.user-detail-field .user-capabilities-editor-slot:not(:empty) { margin-top: 0.5rem; }

/* Heir-row attach state (death → heirs builder): a typed-but-unpicked name is
   flagged, never dropped silently. */
.heir-attach-state {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.85rem;
}
.heir-attach-state.is-attached { color: var(--ok-fg); }
.heir-attach-state.is-unattached { color: var(--error-fg); }
.heir-attach-state .heir-create-inline { color: var(--accent); }
.heir-row--incomplete {
  border-left: 3px solid var(--error-fg);
  padding-left: 0.5rem;
}
.heir-row--attached {
  border-left: 3px solid var(--ok-fg);
  padding-left: 0.5rem;
}
