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

/* ---- Institutional slate/navy + emerald palette. Header is always dark
   slate-900 (like a bank/title-company portal), independent of the light/
   dark body theme toggle below - --header-* variables don't change between
   themes on purpose. ---- */
:root {
  --font-sans:'IBM Plex Sans',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --font-mono:'IBM Plex Mono',ui-monospace,Consolas,monospace;
  --ink:#0F172A; --ink-soft:#64748B; --paper:#F8FAFC; --paper-line:#E2E8F0;
  --card:#FFFFFF; --card-line:#E2E8F0; --accent:var(--led-accent); --accent-soft:var(--led-soft);
  --brass:#D97706; --ok:#059669; --ok-bg:#ECFDF5; --bad:#DC2626; --bad-bg:#FEF2F2;
  --warn:#D97706; --warn-bg:#FFFBEB;
  --shadow:0 1px 2px rgba(15,23,42,.05),0 1px 6px rgba(15,23,42,.06);
}
:root[data-theme="dark"]{
  --ink:#F1F5F9; --ink-soft:#94A3B8; --paper:#0A0D13; --paper-line:#1B2333;
  --card:#0F1620; --card-line:#212C40; --accent:var(--led-accent-d); --accent-soft:var(--led-soft-d);
  --brass:#FBBF24; --ok:#34D399; --ok-bg:#062A20; --bad:#F87171; --bad-bg:#3A1414;
  --warn:#FBBF24; --warn-bg:#332405;
  --shadow:0 1px 2px rgba(0,0,0,.3),0 1px 8px rgba(0,0,0,.3);
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --ink:#F1F5F9; --ink-soft:#94A3B8; --paper:#0A0D13; --paper-line:#1B2333;
    --card:#0F1620; --card-line:#212C40; --accent:var(--led-accent-d); --accent-soft:var(--led-soft-d);
    --brass:#FBBF24; --ok:#34D399; --ok-bg:#062A20; --bad:#F87171; --bad-bg:#3A1414;
    --warn:#FBBF24; --warn-bg:#332405;
    --shadow:0 1px 2px rgba(0,0,0,.3),0 1px 8px rgba(0,0,0,.3);
  }
}
/* Header stays dark navy no matter the theme - the one deliberately
   theme-independent surface, like a title company / bank portal chrome. */
:root{ --header-bg:#0F172A; --header-line:#1E293B; --header-ink:#F1F5F9; --header-ink-soft:#94A3B8; }

/* ---- Per-ledger accent -------------------------------------------------
   Each ledger is its own page, and the cheapest honest way to make that
   land is to recolour the app rather than decorate a header: --accent is
   already threaded through buttons, links, focus rings, map pins, chips,
   the filters toggle and the strip cards, so setting it per ledger changes
   the whole surface at once.

   The four --led-* values below are the ONLY thing data-ledger sets. The
   theme blocks above still own --accent itself, each picking the light or
   dark variant, so theme and ledger compose without either one having to
   out-specify the other, and a new ledger needs four values here and
   nothing else.

   Auctions keep the original blue - it is what the app has always looked
   like and it is still the busiest ledger. Lands Available is emerald: no
   auction, fixed price, buy it now. Certificates are violet, and
   deliberately not the amber already spoken for by --warn/--brass, since a
   whole ledger tinted warning-yellow reads as "something is wrong here".

   :root carries the auction values too, so anything rendering before the
   first setLedger() (the auth gate, the skeleton) is never left with an
   unresolved var(). */
:root,
:root[data-ledger="auction"]{ --led-accent:#2563EB; --led-soft:#DBEAFE; --led-accent-d:#60A5FA; --led-soft-d:#16294A;
  --led-tint:37,99,235; --led-tint-d:96,165,250; }
:root[data-ledger="laft"]{ --led-accent:#047857; --led-soft:#D1FAE5; --led-accent-d:#34D399; --led-soft-d:#062A20;
  --led-tint:4,120,87; --led-tint-d:52,211,153; }
:root[data-ledger="certificate"]{ --led-accent:#6D28D9; --led-soft:#EDE9FE; --led-accent-d:#A78BFA; --led-soft-d:#241A45;
  --led-tint:109,40,217; --led-tint-d:167,139,250; }
/* One RGB triple resolved per theme, so rgba() tints below don't each need
   their own light/dark pair. */
:root{ --led-rgb:var(--led-tint) }
:root[data-theme="dark"]{ --led-rgb:var(--led-tint-d) }
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]){ --led-rgb:var(--led-tint-d) } }

*{box-sizing:border-box}
html,body{margin:0;padding:0}
/* Nearly every size in this file is set in rem against the 16px UA default,
   which is fine on a laptop but reads as too small/dense on a phone held at
   arm's length - reported as "the app looks zoomed out, I can't read it".
   Bumping the root size under this one query scales every rem-based font,
   padding and gap in the file proportionally (icons/borders set in raw px
   are untouched, which is fine - it's the text that was unreadable), without
   having to touch each component's rule individually. 112.5% = 18px root. */
@media (max-width:640px){
  html{font-size:112.5%}
}
body{
  background:var(--paper); color:var(--ink);
  font-family:var(--font-sans);
  -webkit-font-smoothing:antialiased; max-width:680px; margin:0 auto;
  padding-bottom:3rem; overflow-x:hidden;
}
a{color:var(--accent)} button{font-family:inherit}
.mono{font-family:var(--font-mono)}

/* ---- auth gate: dedicated sign-in screen - centered card over a subtle
   navy-to-emerald gradient wash, brand mark + tagline up top, instead of
   bare centered text on the plain page background. ---- */
#authGate, #pendingGate, #planGate{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:1.2rem;
  background:
    radial-gradient(ellipse 90% 60% at 15% -10%, color-mix(in srgb, var(--ok) 16%, transparent), transparent),
    radial-gradient(ellipse 90% 60% at 100% 110%, color-mix(in srgb, var(--header-bg) 30%, transparent), transparent),
    var(--paper)}
/* The ID selector above beats the UA [hidden]{display:none} rule on
   specificity, so #authGate/#pendingGate would stay visible (as
   display:flex) even while hidden without this override - same class of
   bug as an earlier .pagination-bar[hidden] miss in this app. */
#authGate[hidden], #pendingGate[hidden], #planGate[hidden]{display:none}
.auth-card{width:100%;max-width:360px;background:var(--card);border:1px solid var(--card-line);
  border-radius:4px;box-shadow:0 1px 2px rgba(15,23,42,.06),0 16px 40px rgba(15,23,42,.14);
  padding:2rem 1.6rem 1.7rem;text-align:center}
.auth-brand{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-bottom:1rem}
#authGate h1, #pendingGate h1, #planGate h1{font-family:var(--font-sans);font-weight:800;font-size:1.35rem;margin:0;
  letter-spacing:-.01em;color:var(--ink)}
.auth-tagline{font-size:.78rem;color:var(--ink-soft);line-height:1.4;margin:0 0 1.5rem}
.auth-tagline:has(+ .auth-subtagline){margin-bottom:.2rem;font-weight:600}
.auth-subtagline{font-size:.74rem;color:var(--ink-soft);line-height:1.4;margin:0 0 1.5rem}
#authGate p.auth-lead, #pendingGate p.auth-lead, #planGate p.auth-lead{font-size:.85rem;color:var(--ink-soft);margin:0 0 1.2rem}
/* Phase 63: real labels for #authForm's fields (see index.html's comment
   on the form for why) - .auth-field wraps each <input>, same idiom as
   #profileForm's .pf-field. The label itself carries no hidden state of its
   own: app.js's setAuthMode() still toggles the hidden attribute on the
   <input> directly (unchanged), and :has() below hides the whole label
   (including its text) whenever its input is hidden, so a field's name
   never floats visible above a field that isn't. */
.auth-field{display:block;text-align:left;margin-bottom:.6rem}
.auth-field:has(input[hidden]){display:none}
.auth-field > span{display:block;margin-bottom:.2rem;font-size:.68rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.05em;color:var(--ink-soft)}
#authGate input{
  width:100%;padding:.65rem .75rem;font-size:.95rem;
  border:1px solid var(--card-line);border-radius:3px;background:var(--paper);color:var(--ink);
}
#authGate input:focus{outline:2px solid var(--accent);outline-offset:1px}
/* --header-bg (not --ink) on purpose: --ink flips to a light color in dark
   theme (it's the body text color), which would leave white button text
   unreadable on a now-light background. --header-bg is the one color this
   app deliberately keeps dark navy in both themes. */
#authGate button, #pendingGate button, #planGate button{
  width:100%;padding:.7rem;font-size:.92rem;font-weight:700;border:none;border-radius:3px;
  background:var(--header-bg);color:#fff;cursor:pointer;margin-top:.2rem;letter-spacing:.01em;
}
#authGate button:hover, #pendingGate button:hover, #planGate button:hover{background:var(--ok)}
#authGate button:disabled, #pendingGate button:disabled, #planGate button:disabled{opacity:.5;cursor:default;background:var(--header-bg)}
#authGate button.auth-mode-toggle, #pendingGate button.auth-mode-toggle, #planGate button.auth-mode-toggle{width:100%;background:none;border:none;padding:.55rem 0 0;margin:0;
  font-size:.78rem;color:var(--accent);cursor:pointer;text-decoration:underline;font-weight:400}
#authGate button.auth-mode-toggle:hover, #pendingGate button.auth-mode-toggle:hover, #planGate button.auth-mode-toggle:hover{background:none;text-decoration:none}
.auth-msg{margin-top:.9rem;font-size:.82rem;min-height:1.2em}
.auth-msg.err{color:var(--bad)}

/* ---- masthead: always dark slate-900, regardless of light/dark theme ---- */
/* Deliberately NOT sticky itself. With the filters panel open this block is
   tall enough to cover most of the screen, so pinning it hid the property
   list - the .quick-controls bar below handles "reachable while scrolling"
   instead (sticky on mobile only). */
.masthead{background:var(--header-bg); color:var(--header-ink);
  border-bottom:2px solid var(--header-line);padding:.85rem 1.1rem .9rem}
/* The account badge sits in the sticky .topbar with the brand now, pushed
   to the right end of it - that bar is the entire header. */
.topbar .header-btns{margin-left:auto}
.header-btns{display:flex;align-items:center;gap:.4rem;flex-shrink:0}
h1{font-family:var(--font-sans);font-weight:800;font-size:1.45rem;line-height:1.15;
  margin:0;letter-spacing:-.01em;color:var(--header-ink)}
h1 .brand-accent{color:#60A5FA}
.tagline{font-size:.875rem;line-height:1.5;color:var(--header-ink-soft);margin:0 0 .75rem;max-width:52ch;font-weight:400}
/* Lives in the Terms modal now, not the masthead - so it takes the modal's
   body colours rather than the dark header's. */
.generated{font-size:.78rem;color:var(--ink-soft);margin:.3rem 0 .6rem;font-weight:600}
/* Sync pipeline runs on a PC, not a server - nothing guarantees it ran
   today. This makes a dead sync visually loud instead of reading the same
   as "quiet week, nothing new". --warn is already used for county-format
   notes, reusing it here keeps the palette to one "pay attention" color. */
.generated.stale{color:var(--warn);font-weight:700}

/* ---- slim brand strip: pinned above the (deliberately non-sticky, see
   below) masthead so the brand mark stays visible while scrolling a long
   card list, without the taller filters-bearing masthead needing to pin
   itself (that hid the property list - see the note on .masthead). ---- */
.topbar{position:sticky;top:0;z-index:35;display:flex;align-items:center;gap:.5rem;
  background:var(--header-bg);border-bottom:1px solid var(--header-line);
  padding:.5rem 1.1rem}
.brand-mark{flex-shrink:0;display:block}
.brand-name{font-family:var(--font-sans);font-weight:800;font-size:.85rem;
  color:var(--header-ink);letter-spacing:-.01em}
.brand-name .brand-accent{color:var(--ok)}
@media (min-width:1024px){.topbar{padding:.5rem 1.6rem}}

/* ---- admin: pending sign-up approvals banner ---- */
.admin-approvals{background:var(--warn-bg);border-bottom:1px solid var(--warn);
  padding:.6rem 1.1rem}
.admin-approvals-head{font-size:.72rem;font-weight:700;color:var(--warn);margin-bottom:.4rem;
  text-transform:uppercase;letter-spacing:.02em}
.admin-approvals-list{display:flex;flex-direction:column;gap:.4rem}
.admin-approval-row{display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;
  font-size:.78rem;background:var(--card);border:1px solid var(--card-line);
  border-radius:3px;padding:.4rem .6rem}
.admin-approval-info{display:flex;flex-direction:column;gap:.1rem;flex:1}
.admin-approval-name{font-weight:600;color:var(--ink)}
.admin-approval-email{font-size:.72rem;color:var(--ink-soft)}
.admin-approval-when{color:var(--ink-soft);font-size:.7rem}
.admin-approve-btn{background:var(--ok-bg);color:var(--ok);border-color:var(--ok)}
@media (min-width:1024px){.admin-approvals{padding:.6rem 1.6rem}}

.ledger-tab-icon svg,.ledger-head-icon svg,.vt-icon svg,.link-icon svg,.mini-btn svg{width:1em;height:1em;vertical-align:-.125em}
.icon{width:1em;height:1em;vertical-align:-.125em;display:inline-block}

/* A small classification-code line on the card (dor_use_code for FL,
   tx_category/SPTB for TX) - reuses .type-badge's look (see below) rather
   than inventing a new chip style, since it's the same "state's own raw
   category" idea the detail modal already shows via .type-badge. */
.prop-classification-line{margin:.15rem 0}

/* ---- ledger tabs: the top-level Auctions / Lands Available / Certificates
   switcher. First thing under the masthead so both ledgers are visible right
   after sign-in, instead of Lands Available being buried under 300+ auction
   cards on one long scrolling page. ---- */
.ledger-tabs{display:flex;gap:.5rem;overflow-x:auto;scrollbar-width:none;margin:1rem 0 .85rem;padding-bottom:.1rem}
.ledger-tabs::-webkit-scrollbar{display:none}
.ledger-tab{flex:1 1 auto;display:flex;align-items:center;justify-content:center;gap:.35rem;
  white-space:nowrap;background:rgba(255,255,255,.06);border:1.5px solid var(--header-line);border-radius:3px;
  padding:.6rem .7rem;font-size:.8rem;font-weight:600;color:var(--header-ink-soft);
  font-family:inherit;cursor:pointer;transition:all 0.2s ease}
.ledger-tab:hover{background:rgba(255,255,255,.12);border-color:var(--led-accent-d)}
.ledger-tab:active{opacity:.8}
/* The masthead is dark navy in BOTH themes (see the --header-* note at the
   top), so every accent used inside it takes --led-accent-d directly rather
   than --accent, which flips to the light-mode variant and disappears
   against navy. */
/* The active tab is FILLED, not tinted. A 20% tint plus a border reads as
   "this one is highlighted"; a solid block of the ledger's own colour reads
   as "you are on this page", which is the point. Deliberately not a little
   pointer/arrow under the tab: .ledger-tabs sets overflow-x:auto, which
   makes overflow-y clip as well, so anything drawn below a tab is cut off. */
.ledger-tab.on{border-color:var(--led-accent-d);border-width:2px;padding:.55rem .65rem;
  background:var(--led-accent-d);color:#0B1220;font-weight:700}
.ledger-tab.on:hover{background:var(--led-accent-d);opacity:.92}
.ledger-tab b{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-size:.85rem}
.ledger-tab.on b{background:rgba(11,18,32,.16);border-radius:999px;padding:.02rem .4rem}
.ledger-tab-icon{display:inline-flex;width:14px;height:14px}
/* An accent rule under the whole strip ties the filled tab to the page it
   opened without needing anything to escape the scroll container. */
.ledger-tabs{border-bottom:2px solid rgba(var(--led-tint-d),.35);padding-bottom:.55rem}
@media (prefers-reduced-motion:reduce){.ledger-tab{transition:none}}

/* ---- quick controls: search + county + per-page + CSV export. Sticky on
   mobile only (top:0) so they stay reachable while scrolling a long card
   list, without stickying the whole (much taller) masthead. ---- */
.quick-controls{background:var(--card);border:1px solid var(--card-line);border-radius:3px;
  padding:.65rem .7rem;margin:.8rem 0 .6rem;display:flex;flex-wrap:wrap;gap:.5rem;box-shadow:var(--shadow)}
.qc-field{position:relative;flex:1 1 160px}
.qc-field input,.qc-field select{width:100%;font-family:inherit;font-size:.82rem;
  padding:.5rem .6rem .5rem 2rem;border-radius:3px;border:1px solid var(--card-line);
  background:var(--paper);color:var(--ink);appearance:none}
.qc-field select{padding-left:2rem;padding-right:1.8rem;cursor:pointer}
.qc-icon{position:absolute;left:.6rem;top:50%;transform:translateY(-50%);width:14px;height:14px;
  color:var(--ink-soft);pointer-events:none}
.qc-chevron{position:absolute;right:.6rem;top:50%;transform:translateY(-50%);width:9px;height:9px;
  border-right:2px solid var(--ink-soft);border-bottom:2px solid var(--ink-soft);
  transform:translateY(-70%) rotate(45deg);pointer-events:none}
/* --header-bg, not --ink - see the note on #authGate button above; same
   dark-in-both-themes button chrome, same reason. */
.export-btn{flex:0 0 auto;display:inline-flex;align-items:center;gap:.35rem;font-size:.78rem;
  font-weight:700;color:#fff;background:var(--header-bg);border:none;border-radius:3px;
  padding:.5rem .8rem;cursor:pointer;white-space:nowrap}
.export-btn:hover{background:var(--accent)}
.expand-all-btn{flex:0 0 auto;font-size:.78rem;font-weight:700;color:var(--ink);
  background:var(--paper);border:1px solid var(--card-line);border-radius:3px;
  padding:.5rem .8rem;cursor:pointer;white-space:nowrap;font-family:inherit}
.expand-all-btn:hover{border-color:var(--accent);color:var(--accent)}
@media (max-width:640px){
  .quick-controls{position:sticky;top:0;z-index:30;margin-top:0;border-radius:0;
    border-left:none;border-right:none}
}

.summary-strip{display:flex;gap:.6rem;overflow-x:auto;padding-bottom:.15rem;
  scrollbar-width:none;margin-bottom:.9rem;flex-wrap:wrap}
.summary-strip::-webkit-scrollbar{display:none}
.chip{flex:0 0 auto;display:flex;align-items:baseline;gap:.35rem;background:rgba(255,255,255,.06);
  border:1.5px solid var(--header-line);border-radius:3px;padding:.35rem .8rem;
  font-size:.8rem;white-space:nowrap;color:var(--header-ink);font-family:inherit;cursor:pointer;transition:all 0.2s ease}
.chip:hover{background:rgba(255,255,255,.12);border-color:var(--header-ink)}
.chip:active{opacity:.8}
.chip.on{border-width:2px;padding:.3rem .75rem}
.chip.total.on{border-color:var(--led-accent-d);background:rgba(var(--led-tint-d),.15)}
.chip.ok.on{border-color:var(--ok);background:rgba(5,150,105,.18)}
.chip.bad.on{border-color:var(--bad);background:rgba(220,38,38,.18)}
.chip b{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:.85rem}
/* .chip.archive is gone - Archive moved into Filters & Sort. */
.chip.total b{color:var(--led-accent-d)} .chip.ok b{color:#6EE7B7} .chip.bad b{color:#FCA5A5}
/* Watchlist chip always reads as "on" (border+bg), not just when active like
   the status-view chips above - it's a button that opens a modal, not a
   toggle in that filter group, so it should look permanently inviting. */
.chip.bidlist{border-width:2px;padding:.28rem .71rem;border-color:var(--led-accent-d);background:rgba(var(--led-tint-d),.15)}
.chip.bidlist b{color:var(--led-accent-d)}

/* ---- filters ---- */
.filters-toggle{width:100%;display:flex;align-items:center;justify-content:space-between;
  background:rgba(255,255,255,.05);border:1px solid var(--header-line);border-radius:3px;
  padding:.6rem .85rem;font-size:.85rem;font-weight:600;color:var(--header-ink);cursor:pointer}
.filters-badge{background:var(--accent);color:#fff;font-size:.68rem;font-weight:700;
  padding:.08rem .44rem;border-radius:3px;font-family:var(--font-mono)}
.chevron{width:9px;height:9px;border-right:2px solid var(--header-ink-soft);
  border-bottom:2px solid var(--header-ink-soft);transform:rotate(-45deg);transition:transform .18s}
.filters-toggle.open .chevron{transform:rotate(45deg)}
/* Capped height with its own scroll: 14 county chips plus type and title rows
   overflow a phone screen, and the bottom rows were unreachable. */
.filters-panel{display:none;background:var(--card);border:1px solid var(--card-line);
  border-radius:3px;padding:.7rem .8rem;margin-top:.5rem;
  max-height:60vh;overflow-y:auto;-webkit-overflow-scrolling:touch}
.filters-panel.open{display:block}
/* ---- filters panel: organized into clearly separated sections instead of
   one long run-on list of rows, so it reads as "clean" rather than
   convoluted even with a dozen+ controls in play. ---- */
.filters-section{padding-bottom:.7rem;margin-bottom:.7rem;border-bottom:1px solid var(--card-line)}
.filters-section:last-child{border-bottom:none;margin-bottom:0;padding-bottom:0}
.filters-section-head{display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.5rem}
.filters-section-title{font-size:.7rem;font-weight:800;text-transform:uppercase;
  letter-spacing:.06em;color:var(--ink-soft)}
.filters-row{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;margin-bottom:.55rem}
.filters-row:last-child{margin-bottom:0}
/* Same bug class as #authGate[hidden]/#installBtn[hidden] elsewhere in this
   file: .filters-row's own display:flex is an author rule, so it beats the
   UA stylesheet's `[hidden]{display:none}` on a specificity tie - without
   this, toggling the junk-land row's `hidden` property (see applyLedgerChrome
   in app.js) sets the DOM property correctly but leaves it visually on
   screen on every ledger. */
.filters-row[hidden]{display:none}
.filters-group{flex-direction:column;align-items:stretch;gap:.25rem}
.group-head{display:flex;align-items:center;justify-content:space-between;gap:.5rem}
.group-actions{display:flex;gap:.3rem;flex-shrink:0;margin-bottom:.4rem}

/* Property Type / Title Status / County collapse behind a click-to-expand
   "dropdown" summary instead of always showing their full chip list. */
.filter-dropdown{border:1px solid var(--card-line);border-radius:3px;margin-bottom:.5rem;
  background:var(--paper);overflow:hidden}
.filter-dropdown:last-child{margin-bottom:0}
.filter-dropdown summary{list-style:none;cursor:pointer;padding:.55rem .7rem;
  font-size:.78rem;font-weight:700;color:var(--ink);display:flex;align-items:center;
  justify-content:space-between;gap:.5rem}
.filter-dropdown summary::-webkit-details-marker{display:none}
.filter-dropdown summary::after{content:"";width:8px;height:8px;flex-shrink:0;
  border-right:2px solid var(--ink-soft);border-bottom:2px solid var(--ink-soft);
  transform:rotate(45deg);transition:transform .15s;margin-left:auto}
.filter-dropdown[open] summary::after{transform:rotate(225deg)}
.filter-dropdown-count{font-family:var(--font-mono);font-size:.68rem;
  font-weight:600;color:var(--accent);background:var(--accent-soft);border-radius:3px;
  padding:.05rem .45rem;margin-right:auto;margin-left:.5rem}
.filter-dropdown-body{padding:0 .7rem .65rem}
.mini-btn{font-size:.62rem;text-transform:uppercase;letter-spacing:.05em;font-weight:700;
  color:var(--accent);background:none;border:1px solid var(--card-line);border-radius:5px;
  padding:.1rem .35rem;cursor:pointer}
.field-label{font-size:.66rem;text-transform:uppercase;letter-spacing:.05em;
  color:var(--ink-soft);margin-bottom:.2rem;display:block}
.field{flex:1 1 auto;min-width:80px}
.field input,.field select{width:100%;font-family:var(--font-mono);font-size:.82rem;
  padding:.35rem .5rem;border-radius:3px;border:1px solid var(--card-line);
  background:var(--paper);color:var(--ink)}
.field select{font-family:inherit}
.to-sep{color:var(--ink-soft);font-size:.78rem;padding-top:1.1rem}
.chips{display:flex;flex-wrap:wrap;gap:.35rem}

/* Phase 53: the legacy #pageMap picker/zoom-banner/seat-label CSS that used
to live here (.map-wrap, #mapHost, .map-legend/.lg-*, .map-zoom-banner,
.zoom-seat-label, .seat-dot/.seat-label-text) is removed along with the
#pageMap markup it styled (see index.html/tx.html) - the JS that built it
(ensureMapLoaded, zoomToCounty, renderZoomSeatLabel, etc. in app.js) is left
in place as documented dead code, but nothing in the DOM can match these
selectors any more, so the CSS itself is deleted rather than kept as an
orphan. explore.css's .explore-map-* rules are the one map's styling now. */
.chipx{font-size:.72rem;padding:.28rem .6rem;border-radius:3px;border:1px solid var(--card-line);
  background:var(--paper);color:var(--ink-soft);cursor:pointer;user-select:none}
.chipx.on{background:var(--accent-soft);color:var(--accent);border-color:var(--accent);font-weight:600}
.chipx.lien-clean.on{background:var(--ok-bg);color:var(--ok);border-color:var(--ok)}
.chipx.lien-flag.on{background:var(--warn-bg);color:var(--warn);border-color:var(--warn)}
.chipx.lien-serious.on{background:var(--bad-bg);color:var(--bad);border-color:var(--bad)}
/* Counties with 0 live properties still get a chip (so all 67 always show),
   just dimmer/dashed so it visually reads as "no data yet" rather than
   looking identical to a county that's just unselected. */
.chipx.chip-empty{opacity:.55;border-style:dashed}
.chipx.chip-empty.on{opacity:.85}

/* ---- county reference links: Appraiser / Auction / Tax Collector links
   for counties with 0 scraped properties, so they can still be manually
   verified against the county's own official sites. ---- */
.county-ref-links{margin-top:.7rem;padding-top:.65rem;border-top:1px dashed var(--card-line)}
.county-ref-links-head{font-size:.68rem;color:var(--ink-soft);margin-bottom:.5rem;line-height:1.35}
.county-ref-list{display:flex;flex-direction:column;gap:.35rem;max-height:220px;overflow-y:auto}
.county-ref-row{display:flex;align-items:center;justify-content:space-between;gap:.6rem;
  flex-wrap:wrap;font-size:.72rem;padding:.3rem .1rem;border-bottom:1px solid var(--card-line)}
.county-ref-row:last-child{border-bottom:none}
.county-ref-name{font-weight:600;color:var(--ink);min-width:6.5rem}
.county-ref-links-row{display:flex;gap:.7rem;flex-wrap:wrap}
.county-ref-links-row a{color:var(--accent);text-decoration:none;font-size:.72rem;
  display:inline-flex;align-items:center;gap:.15rem}
.county-ref-links-row a:hover{text-decoration:underline}
.county-ref-none{color:var(--ink-soft);font-style:italic;font-size:.7rem}
.reset-btn{font-size:.72rem;color:var(--accent);background:none;border:none;cursor:pointer;
  padding:.3rem 0;text-decoration:underline}
/* ---- county tax-roll facts on a card -----------------------------------
   The card is deliberately lean - headline numbers, one glance, everything
   else on the full page - so these earn their place by being a single
   compact line each rather than a second stat grid.

   Coverage is partial by design (vacant land has a lot size and no building,
   so year_built is blank on much of this inventory), which is why each line
   renders only when it has something to say. A card with none of them has to
   look like the old lean card, not like a card with holes in it. */
.prop-spec{display:flex;flex-wrap:wrap;gap:.2rem .5rem;margin:.45rem 0 0;
  font-size:.72rem;color:var(--ink-soft);font-weight:600}
.prop-spec span{display:inline-flex;align-items:center}
.prop-spec span+span::before{content:"·";margin-right:.5rem;opacity:.6}
.prop-lastsale{margin:.3rem 0 0;font-size:.72rem;color:var(--ink-soft)}
.prop-lastsale b{color:var(--ink);font-family:var(--font-mono);
  font-variant-numeric:tabular-nums;font-weight:700}
/* One line, clamped. A legal description is a paragraph of surveyor's
   shorthand ("BEG 418 FT S AND 110 FT W OF INTER OF E AND W HALF SEC LI...")
   and pasting it whole into a card would bury everything under it. Enough to
   recognise the parcel here; the whole thing on the full page, and in the
   title attribute for a hover. */
.prop-legal{margin:.25rem 0 0;font-size:.68rem;line-height:1.35;color:var(--ink-soft);
  font-family:var(--font-mono);opacity:.85;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* The full page has the room the card does not. */
.detail-legal{margin:.7rem 0 .2rem;padding:.55rem .7rem;background:var(--paper);
  border:1px solid var(--card-line);border-radius:3px;}
.detail-legal-label{display:block;font-size:.64rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-soft);margin-bottom:.25rem}
.detail-legal p{margin:0;font-size:.72rem;line-height:1.5;color:var(--ink);
  font-family:var(--font-mono);word-break:break-word}

/* Phase 35: where this row's data came from and when it last synced - the
   printed counterpart to the card's amber-edge color signal (cardStatus()/
   isRowStale() in app.js), finally somewhere a viewer can read the actual
   date instead of just a border color. Same muted/warn palette as
   .generated/.generated.stale (the aggregate line in the Terms modal) so
   the "this is a freshness signal" visual language stays consistent
   app-wide rather than inventing a second one. */
.detail-provenance{margin:.5rem 0 .2rem;font-size:.72rem;color:var(--ink-soft);
  display:flex;flex-direction:column;gap:.2rem}
.detail-provenance .stale{color:var(--warn);font-weight:700}

.tog{display:flex;align-items:center;gap:.35rem;font-size:.78rem;color:var(--ink);cursor:pointer}
/* Same bug class as #authGate[hidden]/#installBtn[hidden]/.filters-row[hidden]
   elsewhere in this file: .tog's own display:flex is an author rule, so it
   beats the UA stylesheet's `[hidden]{display:none}` on a specificity tie.
   Confirmed live (not just reasoned about) on #archiveToggleRow: setting its
   `hidden` property to true (applyLedgerChrome in app.js, non-auction
   ledgers) left it fully visible on screen with real dimensions - the DOM
   property was correct the whole time, only the paint was wrong. Filed as
   a backlog item after the .filters-row fix and confirmed/fixed here. */
.tog[hidden]{display:none}
/* The archive toggle carries its own count (it replaced a count chip), so it
   needs the same tabular figures the chips use or the number jitters as it
   changes. Scoped to b inside a toggle so no other toggle picks it up. */
.tog b{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-size:.72rem;font-weight:700;color:var(--ink-soft);background:var(--paper);
  border:1px solid var(--card-line);border-radius:999px;padding:.02rem .38rem}
.tog input:checked+span b{color:var(--accent);border-color:var(--accent)}

main{padding:.9rem 1.1rem 0}
.mega-section{margin-bottom:1.2rem}
.mega-head{margin-bottom:.55rem}
.mega-head h2{font-family:var(--font-sans);font-weight:800;font-size:1.2rem;margin:0 0 .15rem}
.mega-sub{font-size:.76rem;color:var(--ink-soft);margin:0}

/* ---- the ledger page header ----------------------------------------------
   A masthead for the page you are on, not a heading above a list. It carries
   the ledger's icon and colour, what the ledger IS, what you actually do on
   it, and one live fact computed from the rows in view (ledgerFacts() in
   app.js). The left accent bar is the same --accent the rest of the page is
   using, so the header, the buttons and the map all agree on which ledger
   this is. */
.ledger-head{background:var(--card);border:1px solid var(--card-line);
  border-left:4px solid var(--accent);border-radius:3px;
  padding:.85rem 1rem .9rem;margin-bottom:.8rem;box-shadow:var(--shadow)}
.ledger-head-top{display:flex;align-items:center;gap:.55rem}
.ledger-head-icon{display:inline-flex;width:1.2rem;height:1.2rem}
.ledger-head h2{margin:0}
.ledger-head .mega-sub{margin-top:.3rem;line-height:1.45}
.ledger-how{font-size:.74rem;line-height:1.5;color:var(--ink);margin:.5rem 0 0;
  background:var(--accent-soft);border-radius:3px;padding:.45rem .6rem}
.ledger-facts{font-size:.72rem;font-weight:600;color:var(--accent);margin:.5rem 0 0;
  font-variant-numeric:tabular-nums}
/* Archive hides every current listing, so saying so - and offering the way
   back - matters more now that the toggle lives in a collapsed panel and the
   old always-visible Archive chip is gone. */
.ledger-mode-note{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;
  font-size:.73rem;font-weight:600;color:var(--warn);margin:.55rem 0 0;
  background:var(--warn-bg);border-radius:3px;padding:.4rem .55rem}
.ledger-mode-exit{font-family:inherit;font-size:.71rem;font-weight:700;cursor:pointer;
  color:var(--warn);background:none;border:1px solid var(--warn);border-radius:3px;
  padding:.15rem .45rem}
.ledger-mode-exit:hover{background:var(--warn);color:var(--card)}

/* Auctions are grouped by county+date (app.js groupKeyOf) - this divider
   sits above each new date cluster so a run of same-day counties reads as
   one visual group instead of every county card repeating its own small
   date line with nothing higher-level separating one sale date from the
   next. Suppressed right after the section title (.mega-head) so the very
   first cluster doesn't get a redundant rule line under the h2. */
.date-divider{font-family:var(--font-sans);font-weight:800;font-size:.95rem;color:var(--ink);
  margin:1.1rem 0 .55rem;padding-top:.7rem;border-top:1px solid var(--card-line)}
.mega-head+.date-divider{margin-top:0;padding-top:0;border-top:none}

/* ---- county grouping: each ledger is organized into one collapsible
   <details> per county (name, an auction date/format line, and an "N/M
   active" count) instead of one long flat card list - the structure a
   county with 300+ properties needs to stay scannable. ---- */
.county-group{background:var(--card);border:1px solid var(--card-line);border-radius:4px;
  margin-bottom:.7rem;box-shadow:var(--shadow);overflow:hidden;transition:border-color .12s}
.county-group:hover{border-color:color-mix(in srgb,var(--accent) 35%,var(--card-line) 65%)}
.county-group[open]{padding-bottom:.3rem}
summary.county-head{list-style:none;cursor:pointer;padding:.85rem 1rem;display:flex;
  align-items:center;justify-content:space-between;gap:.75rem}
summary.county-head::-webkit-details-marker{display:none}
.county-name{font-family:var(--font-sans);font-weight:700;font-size:1.05rem;color:var(--ink)}
.county-meta{font-size:.74rem;color:var(--ink-soft);margin-top:.1rem}
.county-right{display:flex;align-items:center;gap:.6rem;flex-shrink:0}
.county-count{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-size:.78rem;font-weight:600;color:var(--ink-soft);white-space:nowrap}
/* Chevron is scoped to the county summary (not the shared .chevron class,
   which is tuned for the dark masthead's --header-ink-soft) so it stays
   visible against the light card background in both themes. */
.county-chevron{width:8px;height:8px;flex-shrink:0;border-right:2px solid var(--ink-soft);
  border-bottom:2px solid var(--ink-soft);transform:rotate(45deg);transition:transform .15s}
.county-group[open] .county-chevron{transform:rotate(225deg)}
/* .freshness-badge is gone - staleness is the card's amber left edge now. */
.county-info{display:flex;align-items:flex-start;gap:.5rem;margin:0 .6rem .6rem;padding:.5rem .65rem;
  background:var(--accent-soft);border-radius:8px;font-size:.74rem;line-height:1.4;color:var(--ink)}
.fmt-pill{flex-shrink:0;font-weight:700;font-size:.6rem;text-transform:uppercase;letter-spacing:.03em;
  color:var(--accent);background:var(--card);border-radius:4px;padding:.15rem .4rem;margin-top:.05rem}
.fmt-pill.inperson{color:var(--brass)}

.prop-list{padding:0 .6rem;display:flex;flex-direction:column;gap:.5rem}
.prop-list.flat{padding:0}
/* flex-col at every breakpoint (not just desktop) so footer/link rows stay
   pinned to the bottom and every card in a row reads the same height. */
.prop-card{border:1px solid var(--card-line);border-left:3px solid var(--card-line);
  border-radius:4px;padding:.7rem .8rem;background:var(--card);box-shadow:var(--shadow);
  display:flex;flex-direction:column}
/* Property photo strip (Phase 51 visual rebuild) - bleeds to the card's own
   edges via negative margins matching .prop-card's padding above, so it
   reads as a photo banner rather than an inset thumbnail. Real photo when
   photo_url is a real cached Street View image (see hasPhoto() in app.js);
   otherwise a plain muted icon placeholder - never a fake/stock image, and
   never different-looking for "not checked yet" vs. "checked, no coverage"
   (see the NULL/''/real-value contract note on photoOrPlaceholder()). */
.prop-card-photo{margin:-.7rem -.8rem .6rem;border-radius:3px 3px 0 0;overflow:hidden;
  background:var(--paper)}
/* Phase 66: a real photo is a banner, not the whole card - a wide 21:9 crop
   capped in height so the address and the two headline figures stay on
   the first screen on a phone. The caption names what it is (a Street View
   still), so it is never read as a listing or current-condition photo. */
.prop-card-photo.has-photo{aspect-ratio:21/9;max-height:170px;position:relative}
.prop-card-photo.has-photo img{width:100%;height:100%;object-fit:cover;display:block}
.photo-caption{position:absolute;left:.5rem;bottom:.45rem;font-size:.6rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;color:#fff;background:rgba(15,23,42,.62);
  border-radius:3px;padding:.15rem .4rem;pointer-events:none;z-index:1}
/* Phase 67: visual hierarchy rungs 2-4 (see propertyVisual() in app.js).
   Rung 2 (static satellite) reuses .has-photo sizing above. Rung 3 is the
   county context: the app's own county outline, framed 2:1, neighbours in
   the land tone, the county tinted, one dot at the real coordinate. Rung 4
   names both absences on the same slim bar as before. */
.prop-card-photo.minimap,.detail-hero-photo.minimap{position:relative;aspect-ratio:21/9;max-height:170px;
  background:var(--map-sea,#D6E6F2);overflow:hidden}
.detail-hero-photo.minimap{aspect-ratio:16/7;max-height:220px}
.minimap svg{position:absolute;inset:0;width:100%;height:100%;display:block}
.minimap .mm-neighbor{fill:var(--map-neighbor,#E7E4DC);stroke:var(--map-land-line,#DAD4C6);stroke-width:1.2;vector-effect:non-scaling-stroke}
.minimap .mm-county{fill:color-mix(in srgb,var(--accent) 22%,var(--map-land,#F4F1EA));stroke:var(--accent);stroke-width:1.4;vector-effect:non-scaling-stroke}
.minimap .mm-halo{fill:color-mix(in srgb,var(--bad) 25%,transparent);stroke:var(--bad);stroke-width:1;vector-effect:non-scaling-stroke}
.minimap .mm-dot{fill:var(--bad);stroke:#fff;stroke-width:1.2;vector-effect:non-scaling-stroke}
.minimap.minimap-unavailable{aspect-ratio:auto;height:2.2rem}
/* County-only (no coordinates): the county drawn in context behind rung 4's
   two lines - never a dot. Overrides the slim .no-photo bar. */
.prop-card-photo.minimap-county.no-photo,.detail-hero-photo.minimap-county.no-photo{display:block;height:auto}
.minimap.minimap-county > svg.mm-map{position:absolute;inset:0;width:100%;height:100%;opacity:1}
.minimap-county .mm-county-caption{display:flex;flex-wrap:wrap;gap:.1rem .4rem;max-width:calc(100% - 1rem)}
.minimap.minimap-county .mm-county-caption .vis-sub{color:#fff;opacity:.85}
.minimap.minimap-county .mm-county-caption .vis-sub::before{content:none}
.prop-card-photo.no-photo .vis-sub,.detail-hero-photo.no-photo .vis-sub{color:var(--ink-soft);font-weight:500;opacity:.85}
.prop-card-photo.no-photo .vis-sub::before,.detail-hero-photo.no-photo .vis-sub::before{content:"·";margin-right:.4rem;opacity:.6}
.static-sat img{background:var(--paper)}
/* Deliberately a slim bar, not a blank photo-sized box - see the comment on
   photoOrPlaceholder() in app.js. Most rows have no cached photo yet, and a
   tall empty rectangle repeated down the whole list would read as broken,
   not "coming soon". */
.prop-card-photo.no-photo{display:flex;align-items:center;justify-content:center;gap:.4rem;
  height:2.2rem;color:var(--ink-soft);font-size:.68rem;font-weight:600}
.prop-card-photo.no-photo svg{width:16px;height:16px;opacity:.6;flex-shrink:0}
/* ---- the card's left edge reports STATUS, and only status ---------------
   It used to mean three different things at once - accent for a
   certificate, brass for a favourite, green for a top pick - which is why
   it could not be read as meaning anything. Both of those still announce
   themselves perfectly well on their own: a favourite has a filled ♥ in the
   card, a top pick has a "★ Top pick" banner across the top of it. So the
   edge is free to carry the one thing that was previously only available as
   a per-county "✓ Fresh (3h ago)" badge nobody acted on.

   Green active, amber not-synced-recently, red closed. Precedence is set in
   cardStatus() in app.js - closed beats stale beats active, because once the
   outcome is known it does not matter how fresh the row is. The colours are
   the theme's existing --ok/--warn/--bad, so they already carry the right
   meaning everywhere else in the app and follow the light/dark palette. */
.prop-card.status-active{border-left-color:var(--ok)}
.prop-card.status-stale{border-left-color:var(--warn)}
.prop-card.status-closed{border-left-color:var(--bad)}
/* Top pick keeps its tint - that is a different axis (worth a look) from
   status (still open), and the banner names it in words either way. */
.prop-card.toppick{background:color-mix(in srgb,var(--ok-bg) 35%,var(--card) 65%)}

/* A key for the three colours, in the ledger header where the list starts.
   Quiet by design - the cards also carry a status pill and a closed banner,
   so this confirms rather than being the only signal. */
.ledger-legend{display:flex;flex-wrap:wrap;gap:.4rem .85rem;margin:.55rem 0 0;
  font-size:.68rem;font-weight:600;color:var(--ink-soft)}
.lgd{display:inline-flex;align-items:center;gap:.3rem}
.lgd::before{content:"";width:3px;height:11px;border-radius:2px;background:currentColor}
.lgd-active{color:var(--ok)} .lgd-stale{color:var(--warn)} .lgd-closed{color:var(--bad)}
/* Top Pick: soft green fill + a bold (2px) outline, called out in the spec
   as its own badge treatment distinct from the plain status pill. */
.toppick-banner{display:inline-flex;align-items:center;gap:.35rem;font-size:.68rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.05em;color:var(--ok);margin-bottom:.4rem;
  background:var(--ok-bg);border:2px solid var(--ok);border-radius:3px;padding:.22rem .6rem .22rem .5rem}
.closed-banner{display:inline-flex;align-items:center;gap:.3rem;font-size:.7rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.04em;color:#fff;margin-bottom:.4rem;
  background:var(--bad);border:2px solid var(--bad);border-radius:3px;padding:.25rem .55rem;width:100%}
.ratio-pill{font-family:var(--font-mono);font-weight:700;text-transform:none;
  background:var(--card);border-radius:4px;padding:.05rem .3rem}

/* Compact title-status pill, shown alongside the availability status pill so
   the title screen result is scannable without reading the banner below -
   emerald/clear, amber/flag, red/serious, gray/unscreened. */
.lien-pill{flex-shrink:0;font-size:.66rem;font-weight:700;text-transform:uppercase;
  padding:.22rem .5rem;border-radius:3px;white-space:nowrap;border:1px solid transparent}
.lien-pill.clean{color:var(--ok);background:var(--ok-bg);border-color:color-mix(in srgb,var(--ok) 40%,transparent)}
.lien-pill.flag{color:var(--warn);background:var(--warn-bg);border-color:color-mix(in srgb,var(--warn) 40%,transparent)}
.lien-pill.serious{color:var(--bad);background:var(--bad-bg);border-color:color-mix(in srgb,var(--bad) 40%,transparent)}
.lien-pill.unscreened{color:var(--ink-soft);background:var(--paper-line)}
.lien-pill.homestead{color:var(--warn);background:var(--warn-bg);
  border-color:color-mix(in srgb,var(--warn) 40%,transparent);cursor:help}
/* flex-wrap - the actions row (heart/bid/hide icons + countdown + 2 pills)
   can legitimately need 200px+ on its own once every icon/pill is present.
   Without wrap, that row was claiming its full width first (it's
   flex-shrink:0) and squeezing the address/title down to a couple of
   characters on phone-width screens - reported as "card shows almost
   nothing, not the address." Letting the row wrap means the actions drop to
   their own line under the title once both can't fit side by side, instead
   of both being force-fit onto one line. */
.prop-top{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:flex-start;gap:.3rem .6rem}
/* min-width:160px (as a flex-basis, via the flex shorthand) keeps the title
   from shrinking past a legible width before flex-wrap kicks in and moves
   the actions row below it. */
.prop-address{flex:1 1 160px;min-width:160px;font-size:.92rem;font-weight:700;line-height:1.3;
  overflow:hidden;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical}
.prop-county-tag{font-size:.66rem;font-weight:700;text-transform:uppercase;color:var(--accent);margin-bottom:.15rem}
/* Phase 65: the deed/LAFT card's first line - ledger word + phase word (see
   cardKickerHtml() in app.js). The ledger word takes the ledger's own accent
   token; the phase word takes the status palette, so "past due" and "closed"
   read as warnings and a fixed-price LAFT row reads as open, in text, not
   just by badge colour. Certificate cards keep .prop-county-tag above. */
.prop-kicker{display:flex;flex-wrap:wrap;align-items:baseline;gap:.1rem .4rem;
  font-size:.66rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;margin-bottom:.2rem}
.kicker-county{color:var(--ink)}
.kicker-type{color:var(--accent)}
.kicker-sep{color:var(--ink-soft);opacity:.55}
.kicker-phase{color:var(--ink-soft);font-weight:600}
.kicker-phase.phase-fixed{color:var(--ok)}
.kicker-phase.phase-soon{color:var(--warn)}
.kicker-phase.phase-today,.kicker-phase.phase-past,.kicker-phase.phase-closed{color:var(--bad)}
/* Desktop split view: the card whose full page is open in the side panel is
   outlined in the accent, same as the table row (.data-table tr.selected). */
@media (min-width:1024px){
  .prop-card.selected{box-shadow:0 0 0 2px var(--accent),var(--shadow)}
}
.prop-top-actions{flex-shrink:0;display:flex;align-items:center;gap:.3rem}
/* Phase 66: 32px minimum hit area (the glyph itself stays the same size) so
   heart / watchlist / hide are tappable on a phone without a precise thumb. */
.icon-btn{border:none;background:transparent;font-size:1.05rem;line-height:1;cursor:pointer;
  padding:.1rem .25rem;color:var(--ink-soft);min-width:32px;min-height:32px;
  display:inline-flex;align-items:center;justify-content:center}
.heart-btn.on{color:var(--brass)}
.bid-btn.on{color:var(--accent)}
.remove-btn:hover{color:var(--bad)}
.pill{flex-shrink:0;font-size:.66rem;font-weight:700;text-transform:uppercase;
  padding:.22rem .5rem;border-radius:3px;white-space:nowrap}
.pill.active,.pill.available{color:var(--ok);background:var(--ok-bg)}
.pill.dropped,.pill.sold,.pill.closed{color:var(--bad);background:var(--bad-bg)}
.pill.notfound{color:var(--warn);background:var(--warn-bg)}
.countdown{font-size:.66rem;font-weight:700;padding:.22rem .5rem;border-radius:3px;
  white-space:nowrap;background:var(--paper-line);color:var(--ink-soft)}
.countdown.soon{background:var(--warn-bg);color:var(--warn)}
.countdown.urgent{background:var(--bad-bg);color:var(--bad)}
/* Archive view only - muted on purpose, this is a record not an alert. */
.countdown.past{background:var(--card-line);color:var(--ink-soft)}

.prop-meta{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-size:.74rem;color:var(--ink-soft);margin-top:.3rem;display:flex;flex-wrap:wrap;gap:.15rem .6rem}
.meta-bid{color:var(--bad);font-weight:700}
.meta-assessed{color:var(--ok);font-weight:700}
.meta-market{color:var(--accent);font-weight:700}

/* ---- parcel # reference line: a quiet single line right under the address
   on deed/LAFT cards (the headline numbers below are Opening Bid + Est.
   Value now, so parcel # steps back to a plain reference, not a stat box). */
.prop-parcel-line{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-size:.72rem;color:var(--ink-soft);margin-top:.2rem}
/* Phase 65: parcel # and case # side by side on one quiet identifier row.
   A missing parcel says so ("Parcel # not published") in the same slot
   instead of the row silently shrinking - the absence is information. */
.prop-ids{display:flex;flex-wrap:wrap;gap:.1rem .75rem;margin-top:.2rem}
.prop-ids:empty{display:none}
.prop-ids .prop-parcel-line{margin-top:0}
.prop-ids .muted{font-style:italic;opacity:.8}
.prop-case-line{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-size:.72rem;color:var(--ink-soft)}
/* Phase 65: facts row (cardFactsHtml in app.js) - label in small caps, value
   in mono. "muted" is the honest-absence state (not yet geocoded, flood not
   checked); "warn" is a real FEMA Special Flood Hazard Area finding. */
.prop-facts{display:flex;flex-wrap:wrap;gap:.15rem .9rem;margin-top:.45rem;
  font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:.7rem;color:var(--ink)}
.prop-facts>span{display:inline-flex;align-items:baseline;gap:.3rem;white-space:nowrap}
.prop-facts b{font-family:var(--font-sans);font-weight:600;font-size:.6rem;text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink-soft)}
.prop-facts .muted{color:var(--ink-soft)}
.prop-facts .warn{color:var(--warn);font-weight:700}
/* Phase 66: progressive disclosure on the card. Last sale and the legal
   description are reference material, not first-glance facts - folded
   behind one line so the card stays short on a phone. Both stay in the DOM
   (the legal text is still in the title attribute, the full page shows
   both in full). */
.card-more{margin-top:.4rem;font-size:.72rem}
.card-more summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:.3rem;
  min-height:28px;color:var(--ink-soft);font-weight:600;font-size:.68rem;text-transform:uppercase;
  letter-spacing:.04em}
.card-more summary::-webkit-details-marker{display:none}
.card-more summary::before{content:"";width:6px;height:6px;border-right:1.5px solid currentColor;
  border-bottom:1.5px solid currentColor;transform:rotate(-45deg);transition:transform .12s;margin-right:.1rem}
.card-more[open] summary::before{transform:rotate(45deg)}
.card-more summary:hover{color:var(--accent)}
.card-more .prop-lastsale,.card-more .prop-legal{margin-top:.3rem}

/* ---- card stat grid: the headline numbers the card keeps as labeled boxes
   instead of a run-on inline meta line. Everything else that used to live
   on the card - assessed value, potential equity, fees, the full
   title-status banner, owner/parcel copy buttons, notes - moved to the full
   property page so the card itself stays scannable at a glance. min-width:0
   lets a box shrink instead of overflowing the grid when a value runs long.
   Certificate cards (amount / account # / expiration) keep the plain
   3-column .card-stat-grid; deed & LAFT cards add .card-stat-grid-2 to drop
   to 2 columns for just Opening Bid + Est. Value/Assessed - per the user,
   these two are "the selling point of the card" (cost vs. worth at a
   glance), so .card-stat-headline gives them extra size/weight instead of
   splitting attention across three same-sized boxes. ---- */
.card-stat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:.4rem;margin-top:.45rem}
.card-stat-grid.card-stat-grid-2{grid-template-columns:repeat(2,1fr);gap:.5rem}
/* Phase (mobile UX pass): dropped the 1px outline that used to box every
   one of these in - three+ bordered rectangles per card, on a page full of
   bordered cards, read as an itemized receipt rather than a property
   listing. A subtle background tint against the card's own surface is
   enough separation; the numbers themselves (mono, tabular, color-coded
   above) still carry the visual weight. */
.card-stat{background:var(--paper);border-radius:4px;
  padding:.4rem .5rem;min-width:0}
.card-stat-headline{padding:.55rem .65rem .55rem .55rem;border-left:3px solid var(--accent);
  background:var(--paper-raised,var(--paper))}
.card-stat-label{display:flex;align-items:center;gap:.25rem;font-size:.62rem;text-transform:uppercase;
  letter-spacing:.04em;color:var(--ink-soft);margin-bottom:.1rem}
.card-stat-val{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-size:.8rem;font-weight:700;color:var(--ink);overflow-wrap:anywhere}
/* explore.css (loaded after this file) raises this to 1.18rem and adds the
   phone-width clamp - see its ".card-stat-headline .card-stat-val" rule. */
.card-stat-headline .card-stat-val{font-size:1.05rem}
.card-stat-val.bid{color:var(--bad)}
.card-stat-val.assessed{color:var(--ok)}
.card-stat-val.market{color:var(--accent)}
.card-stat-val.over{color:var(--bad)}
.card-stat-val.under{color:var(--ok)}

/* ---- info tooltip: small "ⓘ" affordance for the Fees calculation
   breakdown (doc stamps, recording, homestead adjustment) - keyboard
   focusable so it isn't hover-only on touch devices. ---- */
.info-tip{position:relative;display:inline-flex;align-items:center;justify-content:center;
  width:13px;height:13px;border-radius:50%;background:var(--card-line);color:var(--ink-soft);
  font-size:.6rem;font-style:normal;line-height:1;cursor:help;flex-shrink:0}
/* Anchored to the icon's right edge (opens leftward) rather than centered -
   these icons tend to sit in a card's right-hand column, and a centered
   popover would run off the edge of a narrow phone screen. */
.info-tip::after{content:attr(data-tip);position:absolute;right:-8px;left:auto;bottom:calc(100% + 6px);
  transform:translateY(4px);width:190px;max-width:68vw;background:var(--header-bg);
  color:#fff;font-size:.68rem;font-weight:400;line-height:1.4;text-transform:none;
  letter-spacing:normal;border-radius:3px;padding:.5rem .6rem;box-shadow:var(--shadow);
  opacity:0;visibility:hidden;transition:opacity .12s,transform .12s;pointer-events:none;z-index:20}
.info-tip::before{content:"";position:absolute;right:2px;left:auto;bottom:100%;
  border:5px solid transparent;border-top-color:var(--header-bg);margin-bottom:-2px;
  opacity:0;visibility:hidden;transition:opacity .12s;z-index:20}
.info-tip:hover::after,.info-tip:focus::after{opacity:1;visibility:visible;transform:translateY(0)}
.info-tip:hover::before,.info-tip:focus::before{opacity:1;visibility:visible}

/* ---- potential equity / spread badge: market value minus opening bid,
   shown wherever there's a bid and a market figure to compare it to. ---- */
.spread-badge{display:inline-flex;align-items:baseline;gap:.3rem;font-family:var(--font-sans);
  font-size:.72rem;font-weight:700;color:var(--ok);background:var(--ok-bg);
  border:1px solid color-mix(in srgb,var(--ok) 35%,transparent);border-radius:3px;
  padding:.2rem .55rem;margin-top:.35rem}
.spread-badge .spread-mult{font-family:var(--font-mono);font-weight:600;opacity:.85}

.cost-row{display:flex;flex-wrap:wrap;gap:.2rem .8rem;margin-top:.4rem;font-size:.72rem;
  font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.cost-tag{text-transform:uppercase;font-size:.6rem;color:var(--ink-soft)}
.cost-item.over b{color:var(--bad)} .cost-item.under b{color:var(--ok)}
.hs-flag{color:var(--warn);font-size:.62rem}

.lien-banner{margin-top:.5rem;padding:.5rem .65rem;border-radius:3px;border-left:4px solid;
  display:flex;flex-direction:column;gap:.18rem}
.lien-toprow{display:flex;align-items:center;justify-content:space-between;gap:.5rem;flex-wrap:wrap}
.lien-label{font-size:.78rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em}
.lien-text{font-size:.78rem;color:var(--ink);line-height:1.4;font-weight:500}
.muni-lien-note{font-size:.68rem;color:var(--ink-soft);line-height:1.35;display:flex;
  align-items:flex-start;gap:.3rem;margin-top:.1rem}
.type-badge{font-size:.74rem;font-weight:800;color:var(--ink);background:var(--card);
  padding:.1rem .5rem;border-radius:5px;border:1px solid var(--card-line);white-space:nowrap}
.lien-banner.clean{background:var(--ok-bg);border-color:var(--ok)}
.lien-banner.clean .lien-label{color:var(--ok)}
.lien-banner.flag{background:var(--warn-bg);border-color:var(--warn)}
.lien-banner.flag .lien-label{color:var(--warn)}
.lien-banner.serious{background:var(--bad-bg);border-color:var(--bad)}
.lien-banner.serious .lien-label{color:var(--bad)}
.lien-banner.unscreened{background:var(--paper-line);border-color:var(--ink-soft)}
.lien-banner.unscreened .lien-label{color:var(--ink-soft)}

.copy-row{display:flex;flex-wrap:wrap;gap:.3rem;margin-top:.4rem}
.copy-btn{display:inline-flex;align-items:center;gap:.28rem;max-width:100%;font-size:.68rem;
  font-family:var(--font-mono);color:var(--ink-soft);background:var(--paper);
  border:1px dashed var(--card-line);border-radius:3px;padding:.22rem .45rem;cursor:pointer}
.copy-btn.copied{border-style:solid;border-color:var(--ok);color:var(--ok)}
.copy-btn.unknown{color:var(--ink-soft);cursor:default;opacity:.65}
.copy-btn.owner-tag{font-family:inherit}
.copy-val{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.copy-tag{flex-shrink:0;text-transform:uppercase;font-size:.6rem;opacity:.75}

.prop-links{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.55rem}
.prop-links a{flex:1 1 calc(33.333% - .24rem);display:flex;align-items:center;justify-content:center;
  gap:.28rem;text-align:center;font-size:.68rem;font-weight:600;min-height:36px;
  text-decoration:none;padding:.38rem .25rem;border-radius:3px;background:var(--accent-soft);
  color:var(--accent);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.prop-links a:hover{background:var(--accent);color:#fff}
.prop-links a .link-icon{flex-shrink:0;font-size:.8em}

.cta-btn{display:block;text-align:center;margin-top:.55rem;padding:.6rem .5rem;border-radius:3px;
  background:var(--ok);color:#fff;font-weight:700;font-size:.82rem;text-decoration:none;
  letter-spacing:.01em}
.cta-btn:hover{filter:brightness(1.08)}
/* Phase 72: the auction-link slot when there is no link to show - the
   source published none, or a sale-event page's date has passed. Plain
   muted text in the button's place, never a disabled-looking button and
   never an anchor. */
.auction-link-none{display:block;text-align:center;margin-top:.55rem;padding:.45rem .5rem;
  font-size:.74rem;font-weight:600;color:var(--ink-soft);font-style:italic}
.detail-cta-none{margin:.6rem 0;padding:.6rem 1rem;font-size:.8rem;border:1px dashed var(--card-line);
  border-radius:3px}

/* Deliberately a small text link, not a filled button - the card already
   has one strong call to action (the CTA button above, when there's an
   auction/LAFT listing to go to); "view everything else about this
   property" is a lighter-weight, secondary action. */
.detail-btn{display:inline-flex;align-items:center;min-height:36px;margin-top:.3rem;padding:0;
  background:none;border:none;color:var(--accent);font-weight:600;font-size:.74rem;
  text-decoration:none;cursor:pointer;font-family:inherit}
.detail-btn:hover{text-decoration:underline}

.notes-block{margin-top:.5rem;border-top:1px solid var(--card-line);padding-top:.45rem}
.notes-head{display:flex;align-items:center;justify-content:space-between;gap:.5rem;
  font-size:.66rem;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-soft);margin-bottom:.3rem}
.notes-visibility{text-transform:none;letter-spacing:0;font-style:italic}
.note-item{font-size:.74rem;line-height:1.4;margin-bottom:.3rem;padding:.3rem .45rem;
  background:var(--paper);border-radius:3px;}
.note-author{font-weight:700;color:var(--brass);font-size:.66rem}
.note-stage-tag{font-size:.6rem;text-transform:uppercase;font-weight:700;color:var(--accent);
  background:var(--accent-soft);border-radius:4px;padding:.05rem .3rem;margin-left:.3rem}
.note-editor{display:flex;flex-direction:column;gap:.3rem;margin-top:.3rem}
.note-editor select,.note-editor textarea{width:100%;font-family:inherit;font-size:.75rem;
  padding:.3rem .4rem;border-radius:3px;border:1px solid var(--card-line);
  background:var(--paper);color:var(--ink);resize:vertical}
.note-save{align-self:flex-start;font-size:.68rem;font-weight:600;padding:.25rem .7rem;
  border-radius:3px;border:none;background:var(--accent);color:#fff;cursor:pointer}
.note-save.saved{background:var(--ok)}

/* ---- property detail modal: the "full property page" - same data as the
   card, laid out roomier, with big tappable link buttons instead of the
   compact 3-across grid. ---- */
.detail-modal{position:fixed;inset:0;z-index:100;background:rgba(15,23,42,.6);
  display:flex;align-items:flex-end;justify-content:center;padding:0}
.detail-modal[hidden]{display:none}
.detail-modal-inner{background:var(--paper);width:100%;max-width:600px;max-height:92vh;
  overflow-y:auto;border-radius:4px 4px 0 0;padding:1rem 1.1rem 1.6rem;position:relative;
  -webkit-overflow-scrolling:touch}
@media (min-width:640px){
  .detail-modal{align-items:center;padding:1.5rem}
  .detail-modal-inner{border-radius:16px;max-height:88vh}
}
/* My Bid List modal reuses the detail-modal shell (same overlay, close
   button, scroll behavior) but holds up to BID_LIST_MAX full property cards
   rather than one roomy detail page - wider than the single-property detail
   modal so its .prop-list.flat can fall into the same auto-fill grid
   (min 330px/column, see the 1024px breakpoint below) instead of forcing
   ten cards into one long single-file scroll on a big screen. */
.bidlist-modal-inner{max-width:600px}
@media (min-width:1024px){.bidlist-modal-inner{max-width:1000px}}
/* Queued-while-full properties, shown below the main bid-list card grid -
   a plain stacked list (not cards) since these aren't on the list yet, just
   waiting their turn. */
.bidlist-pending{margin-top:1rem;padding-top:.8rem;border-top:1px dashed var(--card-line)}
.bidlist-pending-head{font-size:.72rem;font-weight:700;color:var(--ink-soft);margin-bottom:.5rem}
.bidlist-pending-row{display:flex;justify-content:space-between;align-items:center;gap:.6rem;
  font-size:.82rem;padding:.4rem 0;border-bottom:1px solid var(--card-line)}
.bidlist-pending-row:last-child{border-bottom:none}
.bid-btn.pending{color:var(--warn)}

/* Hidden Properties modal rows - same plain-stacked-list treatment as
   .bidlist-pending-row above (not full cards; a hidden property just needs
   enough context to recognize it and a Restore button, not the whole card
   UI). .inactive rows (sale date passed, or the county's own listing
   dropped it past goneExpired()'s grace period) are dimmed and get a
   disabled-reading label instead of a working Restore button - restoring
   one would just have it filtered right back out. */
.hidden-list{display:flex;flex-direction:column}
.hidden-row{display:flex;justify-content:space-between;align-items:center;gap:.8rem;
  font-size:.82rem;padding:.55rem 0;border-bottom:1px solid var(--card-line)}
.hidden-row:last-child{border-bottom:none}
.hidden-row.inactive{opacity:.55}
.hidden-row-info{display:flex;flex-direction:column;gap:.1rem;min-width:0}
.hidden-row-label{color:var(--ink);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hidden-row-meta{font-size:.72rem;color:var(--ink-soft)}
.hidden-row-inactive-tag{font-size:.68rem;color:var(--warn)}
.hidden-row-unavailable{font-size:.72rem;color:var(--ink-soft);white-space:nowrap;flex-shrink:0}
.hidden-row .reset-btn{flex-shrink:0}

/* Shared error toast - see showErrorToast() in app.js. Every write action
   (favorite/hide/restore/bid-list/note) used to fail completely silently on
   error - the button just re-enabled with no explanation. Fixed to the
   bottom so it never shifts layout or covers the header/filters; tap to
   dismiss early, otherwise auto-hides on its own. */
.err-toast{position:fixed;left:50%;bottom:1.2rem;transform:translateX(-50%) translateY(1rem);
  max-width:min(92vw,420px);background:var(--bad);color:#fff;font-size:.82rem;font-weight:600;
  padding:.7rem 1rem;border-radius:3px;box-shadow:var(--shadow);z-index:9999;cursor:pointer;
  opacity:0;pointer-events:none;transition:opacity .18s ease,transform .18s ease}
.err-toast.show{opacity:1;pointer-events:auto;transform:translateX(-50%) translateY(0)}
.detail-close{position:sticky;top:0;z-index:4;float:right;border:none;background:var(--card);
  color:var(--ink-soft);width:2rem;height:2rem;border-radius:999px;font-size:1.1rem;
  cursor:pointer;box-shadow:var(--shadow);margin-bottom:.3rem}
.detail-address{font-family:var(--font-sans);font-weight:800;font-size:1.25rem;
  line-height:1.25;margin:.3rem 0 .2rem;clear:both}
.detail-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:.6rem;
  margin:.8rem 0}
/* Phase (mobile UX pass): border -> soft shadow, same reasoning as
   .card-stat above - a grid of outlined boxes was the "purchase receipt"
   look. box-shadow lifts each tile off the page instead of outlining it. */
.detail-stat{background:var(--card);border-radius:6px;
  padding:.55rem .65rem;box-shadow:var(--shadow)}
.detail-stat-label{font-size:.62rem;text-transform:uppercase;letter-spacing:.04em;
  color:var(--ink-soft);display:block;margin-bottom:.15rem}
.detail-stat-val{font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-size:1rem;font-weight:700}

/* ==================== detail sections (Phase 51 visual rebuild) ====================
   Financial / Property Details / History / Risk & Legal / GIS & Location /
   Research & Sources / Data Quality & Provenance - each a labeled card in
   the deed/LAFT full property page. See detailSectionHtml()/statGroupHtml()
   in app.js. The detail modal is a fairly narrow column even on desktop
   (see .detail-panel/[data-ledger="auction"] .detail-modal-inner below), so
   these stack full-width by design rather than trying to force a
   multi-column layout into ~420-480px. */
.detail-hero-photo{margin:.5rem 0 .8rem;border-radius:8px;overflow:hidden;
  background:var(--paper);color:var(--ink-soft)}
.detail-hero-photo.has-photo{aspect-ratio:16/9;max-height:260px;position:relative;flex-shrink:0}
.detail-hero-photo.has-photo img{width:100%;height:100%;object-fit:cover;display:block}
/* Same "slim bar, not a blank box" reasoning as .prop-card-photo.no-photo -
   one per detail page instead of dozens down a list, but still not worth a
   tall empty rectangle before the photo pipeline is populated. */
.detail-hero-photo.no-photo{display:flex;align-items:center;justify-content:center;gap:.5rem;
  height:2.6rem;font-size:.78rem;font-weight:600}
.detail-hero-photo.no-photo svg{width:18px;height:18px;opacity:.55;flex-shrink:0}
.detail-section{margin:.8rem 0;padding:.75rem .8rem;background:var(--card);
  border:1px solid var(--card-line);border-radius:8px}
.detail-section-head{font-family:var(--font-sans);font-weight:800;font-size:.78rem;
  letter-spacing:.02em;color:var(--ink);margin-bottom:.5rem}
.detail-section .detail-grid,.detail-section .detail-links{margin:0}
.detail-section-note{margin:0 0 .55rem;font-size:.72rem;line-height:1.45;color:var(--ink-soft)}
.kv-list{display:flex;flex-direction:column}
.kv-row{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;
  padding:.35rem 0;border-bottom:1px dashed var(--card-line);font-size:.78rem}
.kv-row:last-child{border-bottom:none}
.kv-label{color:var(--ink-soft)}
.kv-val{font-weight:700;color:var(--ink);text-align:right}
.kv-val.muted{font-weight:600;color:var(--ink-soft);font-style:italic}
.kv-val.mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.kv-val.stale{color:var(--warn)}
.kv-val.ok{color:var(--ok)}
/* Inventory & Purchase card: three labelled groups (Inventory / Property /
   Purchase path). The property-level purchase link is the one prominent
   action; instructions pages render as an ordinary link with a caption. */
.kv-group-head{margin:.55rem 0 .15rem;font-size:.72rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft)}
.kv-list[data-group]+.kv-list[data-group]{margin-top:.4rem;border-top:1px solid var(--card-line)}
.kv-val .kv-wrap{display:inline-block;max-width:100%;white-space:normal;word-break:break-word;font-weight:600;text-align:right}
.purchase-action{display:inline-flex;align-items:center;min-height:36px;padding:0 .8rem;border-radius:8px;background:var(--accent);color:#fff;font-weight:800;text-decoration:none}
.purchase-action:hover{filter:brightness(1.08);text-decoration:none}
.risk-legal-card .detail-section-head{color:var(--warn)}
.detail-map-embed{margin-top:.6rem;border-radius:6px;overflow:hidden;border:1px solid var(--card-line)}
.detail-map-embed iframe{display:block;width:100%;height:180px;border:none}
.show-on-map-btn{display:inline-flex;align-items:center;gap:.4rem;margin-top:.6rem;min-height:36px;
  padding:.45rem .8rem;border-radius:3px;border:1px solid var(--accent);background:var(--accent-soft);
  color:var(--accent);font-size:.78rem;font-weight:700;cursor:pointer}
.show-on-map-btn svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2}
.show-on-map-btn:hover{background:var(--accent);color:#fff}

/* ==================== Phase 66: section nav + opportunity summary ====================
   The full property page is a long single column. The nav is a sticky row of
   jump pills (one per section that rendered - see detailNavHtml() in app.js)
   so summary -> financial -> property -> risk -> map -> sources is one tap
   each instead of a scroll hunt. Sticky inside the modal/panel's own scroll
   box, under the close button. */
.detail-nav{position:sticky;top:-1rem;z-index:3;display:flex;gap:.3rem;overflow-x:auto;
  scrollbar-width:none;padding:1.35rem 0 .45rem;margin:0 0 .3rem;
  background:var(--paper);border-bottom:1px solid var(--card-line);
  /* flex-shrink:0 - the modal body is a flex column with a max-height, and a
     child with overflow:auto gets min-height:0 there, so without this the
     nav was squeezed to a few pixels while the page was taller than the
     modal. top:-1rem + the extra padding-top: the scroll box has 1rem of
     padding above the first child, and a sticky nav at top:0 would let the
     scrolled content show through that strip. */
  flex-shrink:0}
.detail-nav::-webkit-scrollbar{display:none}
.detail-nav button{flex:0 0 auto;min-height:32px;padding:.3rem .65rem;border-radius:999px;
  border:1px solid var(--card-line);background:var(--card);color:var(--ink-soft);
  font-size:.7rem;font-weight:700;letter-spacing:.02em;cursor:pointer;white-space:nowrap}
.detail-nav button:hover{border-color:var(--accent);color:var(--accent)}
.detail-nav button.on{background:var(--accent);border-color:var(--accent);color:#fff}
/* scroll-margin keeps a jumped-to section from tucking under the sticky nav */
.detail-section[data-section]{scroll-margin-top:3.2rem}

/* "At a glance": six labelled answers (opportunitySummaryHtml in app.js) -
   what / where / when / minimum bid / value on file / missing. Two columns
   where there is room, one on a phone. The accent edge marks it as the
   page's headline block; the Missing cell is the honest one, listing every
   tracked field this row does NOT have yet. */
.opp-summary{border-left:3px solid var(--accent)}
.opp-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.55rem .9rem}
@media (max-width:480px){ .opp-grid{grid-template-columns:1fr} }
.opp-cell{display:flex;flex-direction:column;gap:.15rem;min-width:0}
.opp-cell:last-child{grid-column:1 / -1}
.opp-label{font-size:.6rem;text-transform:uppercase;letter-spacing:.06em;font-weight:700;color:var(--ink-soft)}
.opp-val{font-size:.85rem;font-weight:700;color:var(--ink);line-height:1.35;overflow-wrap:anywhere}
.opp-val.bid{font-family:var(--font-mono);font-variant-numeric:tabular-nums;color:var(--bad);font-size:1rem}
.opp-val.muted,.opp-val .muted{color:var(--ink-soft);font-style:italic;font-weight:600}
.opp-val.ok{color:var(--ok)} .opp-val.warn{color:var(--warn)} .opp-val.bad{color:var(--bad)}
.opp-sub{display:block;font-family:var(--font-sans);font-size:.7rem;font-weight:500;color:var(--ink-soft);
  font-style:normal;margin-top:.1rem}
.opp-gaps{margin:0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:.3rem}
.opp-gaps li{font-size:.68rem;font-weight:600;color:var(--ink-soft);background:var(--paper);
  border:1px dashed var(--card-line);border-radius:3px;padding:.15rem .45rem}
.detail-links{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:.5rem;
  margin:.9rem 0}
.detail-links a{display:flex;align-items:center;justify-content:center;gap:.35rem;text-align:center;
  font-size:.8rem;font-weight:700;text-decoration:none;padding:.65rem .5rem;border-radius:3px;
  background:var(--accent-soft);color:var(--accent)}
.detail-links a:hover{filter:brightness(1.05)}
.detail-links a .link-icon{flex-shrink:0}

/* Bid & profit calculator - same collapsed-by-default disclosure pattern as
   .filter-dropdown (chevron rotates open), so it reads as consistent with
   the rest of the app rather than a bolted-on widget. */
/* #detailModalInner is also .prop-card (display:flex;flex-direction:column),
   so this is laid out as a flex item, not a plain block child. overflow:hidden
   sets its flexbox automatic minimum size to 0 (spec: min-size:auto computes
   to 0 for a non-visible-overflow item) - without flex-shrink:0, the column
   layout would rather crush THIS item to nothing than let the fixed-height
   modal (max-height:92vh) scroll, since every sibling div's own content sets
   an effective floor that resists shrinking and this was the one item happy
   to go to zero. Confirmed live: without this line the drawer rendered at a
   real 2px (exactly its two 1px borders, content clipped to nothing) despite
   its own children measuring their normal height. */
.calc-drawer{border:1px solid var(--card-line);border-radius:3px;margin:.8rem 0;
  background:var(--paper);overflow:hidden;flex-shrink:0}
.calc-drawer summary{list-style:none;cursor:pointer;padding:.6rem .75rem;
  font-size:.82rem;font-weight:700;color:var(--ink);display:flex;align-items:center;
  justify-content:space-between;gap:.5rem}
.calc-drawer summary::-webkit-details-marker{display:none}
.calc-drawer summary::after{content:"";width:8px;height:8px;flex-shrink:0;
  border-right:2px solid var(--ink-soft);border-bottom:2px solid var(--ink-soft);
  transform:rotate(45deg);transition:transform .15s}
.calc-drawer[open] summary::after{transform:rotate(225deg)}
.calc-body{padding:0 .75rem .75rem;display:flex;flex-direction:column;gap:.5rem}
.calc-row{display:flex;align-items:center;justify-content:space-between;gap:.5rem;
  font-size:.82rem}
.calc-row b{font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.calc-row.calc-minus b{color:var(--ink-soft)}
.calc-row.calc-total{padding-top:.35rem;border-top:1px dashed var(--card-line);
  font-weight:800}
.calc-row.calc-total b{font-size:1rem}
.calc-row.calc-total b.neg{color:var(--bad)}
.calc-input-row{display:flex;align-items:center;justify-content:space-between;gap:.5rem;
  font-size:.78rem;color:var(--ink-soft)}
.calc-input{width:6.5rem;text-align:right;font-family:var(--font-mono);
  font-variant-numeric:tabular-nums;background:var(--card);color:var(--ink);
  border:1px solid var(--card-line);border-radius:3px;padding:.3rem .4rem;font-size:.82rem}
.calc-input:focus{outline:2px solid var(--accent);outline-offset:1px}
.calc-divider{border-top:1px solid var(--card-line);margin:.1rem 0}

/* ---- skeleton loaders: card-shaped shimmer placeholders shown while the
   first Supabase fetch is in flight, instead of a bare "Loading" line. ---- */
.skeleton-group{background:var(--card);border:1px solid var(--card-line);border-radius:4px;
  margin-bottom:.7rem;box-shadow:var(--shadow);padding:.85rem 1rem}
.skel{position:relative;overflow:hidden;background:var(--card-line);border-radius:3px;}
.skel::after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--card) 60%,transparent),transparent);
  animation:skel-shimmer 1.4s ease-in-out infinite}
@keyframes skel-shimmer{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
.skel-title{height:16px;width:55%;margin-bottom:.6rem}
.skel-line{height:11px;margin-bottom:.5rem}
.skel-line.w60{width:60%} .skel-line.w80{width:80%} .skel-line.w40{width:40%}
.skel-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.5rem;margin-top:.6rem}
.skel-box{height:38px;border-radius:3px;}
@media (prefers-reduced-motion:reduce){.skel::after{animation:none}}

.empty-state{text-align:center;padding:2rem 1rem;color:var(--ink-soft);font-size:.85rem}
/* Phase 36: a failed properties fetch previously rendered the same neutral
   .empty-state as a genuinely-empty ledger, with no visual distinction -
   this variant borrows the same --bad tokens already used for closed/
   dropped-listing pills elsewhere, so an actual data-load error reads as
   clearly different from "nothing here yet". */
.empty-state.error-state{color:var(--bad);font-weight:600}
.empty-state.error-state .empty-hint{font-weight:400}
.error-state .reload-btn{display:inline-block;margin-top:.6rem;padding:.5rem 1rem;
  border-radius:3px;border:1px solid var(--bad);background:var(--bad-bg);color:var(--bad);
  font-weight:700;font-size:.8rem;font-family:inherit;cursor:pointer}
.error-state .reload-btn:hover{background:var(--bad);color:#fff}
footer{padding:1.2rem 1.1rem 0;font-size:.72rem;color:var(--ink-soft);text-align:center}

/* ---- wide / desktop: automatic, no toggle ---- */
@media (min-width:1024px){
  body{max-width:1500px}
  .masthead{padding:1.1rem 1.6rem .8rem}
  h1{font-size:1.9rem}
  main{padding:1.1rem 1.6rem 0}
  /* Room for the filters, so no collapse button is needed */
  .filters-panel{display:block;max-height:none;overflow-y:visible}
  .filters-toggle{display:none}
  .field{flex:0 1 190px}
  .prop-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));
    gap:.75rem;padding:0 .9rem;align-items:start}
  .prop-list.flat{padding:0}
  .prop-card{height:100%}
  .notes-block{margin-top:auto}
  .quick-controls{position:static}
}
@media (prefers-reduced-motion:reduce){.chevron{transition:none}}

#changePasswordModal input{
  width:100%;padding:.65rem .75rem;margin-bottom:.6rem;font-size:.95rem;
  border:1px solid var(--card-line);border-radius:3px;background:var(--paper);color:var(--ink);
}
#changePasswordModal input:focus{outline:2px solid var(--accent);outline-offset:1px}
#changePasswordModal button[type="submit"]{
  width:100%;padding:.7rem;font-size:.92rem;font-weight:700;border:none;border-radius:3px;
  background:var(--header-bg);color:#fff;cursor:pointer;margin-top:.2rem;letter-spacing:.01em;
}
#changePasswordModal button[type="submit"]:hover{background:var(--ok)}
#changePasswordModal button[type="submit"]:disabled{opacity:.5;cursor:default;background:var(--header-bg)}

/* ---- Price range sliders ---- */
.price-range-section{flex:1 1 100%;display:flex;flex-direction:column;gap:.5rem}
.price-range-controls{display:flex;flex-direction:column;gap:.6rem}
.price-range-sliders{position:relative;height:24px;display:flex;align-items:center}
.slider{position:absolute;width:100%;height:5px;top:50%;transform:translateY(-50%);background:transparent;
  border:none;border-radius:5px;pointer-events:none;appearance:none;outline:none;
  -webkit-appearance:none;z-index:5}
.slider::-webkit-slider-thumb{appearance:none;-webkit-appearance:none;width:18px;height:18px;
  border-radius:50%;background:var(--accent);border:2px solid #fff;cursor:pointer;
  box-shadow:0 2px 4px rgba(0,0,0,.2);pointer-events:auto;z-index:7}
.slider::-moz-range-thumb{width:18px;height:18px;border-radius:50%;background:var(--accent);
  border:2px solid #fff;cursor:pointer;box-shadow:0 2px 4px rgba(0,0,0,.2);pointer-events:auto;z-index:7}
.slider-right{z-index:6}
.slider::-webkit-slider-runnable-track{background:linear-gradient(to right,
  var(--card-line) 0%,var(--card-line) 0%,
  var(--accent) 0%,var(--accent) 100%,
  var(--card-line) 100%,var(--card-line) 100%);
  height:5px;border-radius:5px;border:none}
.slider::-moz-range-track{background:var(--card-line);height:5px;border-radius:5px;border:none}
.slider:focus{outline:none}
.price-range-display{display:flex;align-items:center;gap:.4rem;justify-content:center}
/* Phase 65: .price-input is a label wrapping a real number field now, not a
read-only span - the wrapper carries the box chrome so the "$" prefix and
the field read as one control. */
.price-input{display:inline-flex;align-items:center;gap:.1rem;padding:0 0 0 .5rem;
  background:var(--paper);border:1px solid var(--card-line);border-radius:3px;
  font-family:var(--font-mono);font-size:.8rem;flex:1 1 0;min-width:0;max-width:150px;
  color:var(--accent);font-weight:600;cursor:text}
.price-input:focus-within{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}
.price-prefix{color:var(--ink-soft);font-weight:600}
.price-input input{flex:1 1 0;min-width:0;width:100%;border:0;background:transparent;
  font:inherit;color:inherit;padding:.32rem .4rem .32rem .1rem;outline:none;
  -moz-appearance:textfield;appearance:textfield}
.price-input input::-webkit-outer-spin-button,.price-input input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.price-input input::placeholder{color:var(--ink-soft);font-weight:500;opacity:1}
.price-range-display .to-sep{padding-top:0}

/* ---- Map city labels ---- */
.city-labels{pointer-events:none}
.city-label{font-family:var(--font-sans);font-weight:700;fill:var(--ink-soft);
  text-shadow:1px 1px 3px rgba(255,255,255,.8),1px 1px 6px rgba(0,0,0,.15);
  pointer-events:none;opacity:.7;transition:opacity 0.2s ease}
.city-label.city-large{font-size:14px}
.city-label.city-medium{font-size:11px}
.city-label.city-small{font-size:9px}
@media (prefers-color-scheme:dark){
  .city-label{fill:var(--header-ink-soft);text-shadow:1px 1px 2px rgba(0,0,0,.6),1px 1px 4px rgba(0,0,0,.3)}
}

/* ==================== Three distinct ledger layouts ====================
   Auctions, Lands Available and Certificates already had their own colour,
   header and filters (see the "three ledgers, three pages" work) - this
   layer gives each a genuinely different SHAPE at desktop widths too, on
   top of the same shared card/detail-modal markup and click/back-button
   logic (deliberately untouched - see the project handoff for why a true
   multi-pane rewrite was judged too risky to do blind). Below the 1024px
   breakpoint all three fall back to the same single-column list - none of
   this is worth fighting for on a phone screen. ---- */

/* Opening-Bid-vs-Just-Value bar on auction cards - the same two numbers
   already on the card, just a visual read of the spread instead of two
   separate figures someone has to do the division on themselves. */
.spread-bar{margin-top:.4rem}
.spread-bar-track{height:6px;border-radius:999px;background:var(--card-line);overflow:hidden}
.spread-bar-fill{height:100%;background:var(--accent);border-radius:999px}
.spread-bar-labels{display:flex;justify-content:space-between;font-size:.62rem;
  color:var(--ink-soft);margin-top:.25rem;font-family:var(--font-mono)}

/* Certificates: dense financial grid. The stat grid grows from 3 to 6
   columns (Amount / Account# / Expires / Interest Rate / Est. Accrued
   Interest / TDA Eligibility) and, on wide screens, sits beside the header
   instead of below it - a spreadsheet row, not a stacked card. */
.cert-stat-grid{grid-template-columns:repeat(3,1fr)}
/* AVAILABLE commercialization (2026-09-30): withheld-inventory note, provenance legend. */
.ledger-withheld{margin:.4rem 0 0;font-size:.76rem;color:var(--ink-soft);border-left:3px solid var(--card-line);padding-left:.55rem}
/* Collection vs customer publication (2026-10-02): a source's review status
   is its own fact, labelled apart from the property's availability. */
/* Scale (2026-10-02): "Show next" inside a county group / the data table. */
.group-more{display:block;width:100%;margin:.5rem 0 .2rem;padding:.55rem .8rem;font-size:.82rem;font-weight:600;color:var(--accent);background:transparent;border:1px dashed var(--accent);border-radius:8px;cursor:pointer}
.group-more:hover{background:var(--card)}
.ledger-review-pending{margin:.4rem 0 0;font-size:.76rem;color:var(--ink);border-left:3px solid var(--warn);padding-left:.55rem}
.prop-source-line{display:flex;flex-wrap:wrap;gap:.3rem;margin:.15rem 0 .1rem}
.source-program{font-size:.72rem;font-weight:600;color:var(--ink);background:var(--card-line);border-radius:999px;padding:.05rem .5rem}
.source-review-chip{font-size:.72rem;font-weight:600;color:var(--warn);background:var(--warn-bg);border:1px solid var(--warn);border-radius:999px;padding:.05rem .5rem}
/* Detroit customer subset (2026-10-03): an admin label, never an availability fact. */
.source-subset-chip{font-size:.72rem;font-weight:600;color:var(--ink-soft);background:transparent;border:1px dashed var(--card-line);border-radius:999px;padding:.05rem .5rem}
.ledger-detroit-subset{margin:.4rem 0 0;font-size:.76rem;color:var(--ink-soft);border-left:3px solid var(--card-line);padding-left:.55rem}
.source-review-banner{margin:0 0 .7rem;padding:.55rem .7rem;font-size:.82rem;line-height:1.4;color:var(--ink);background:var(--warn-bg);border:1px solid var(--warn);border-radius:8px}
.source-review-row{display:flex;flex-wrap:wrap;gap:.25rem 1rem;margin:.45rem 0;font-size:.8rem;color:var(--ink-soft)}
.source-review-row.pending b{color:var(--warn)}
.dash-source-review-mode{margin:.1rem 0 .5rem;font-size:.78rem;color:var(--ink-soft)}
.prov-legend{margin:.5rem 0 0;font-size:.72rem;color:var(--ink-soft);line-height:1.45}
.prov-available .prov-v .muted{color:var(--ink-soft)}
#availableFilters select{font:inherit;font-size:.8rem;padding:.35rem .4rem;border:1px solid var(--card-line);border-radius:3px;background:var(--card);color:var(--ink);min-height:32px}
/* Three ledgers: the per-ledger emphasis line under the headline figures. */
.prop-ledger-line{display:flex;flex-wrap:wrap;gap:.25rem .9rem;margin:.3rem 0 .05rem;font-size:.76rem;color:var(--ink)}
.prop-ledger-line>span{display:inline-flex;align-items:baseline;gap:.35rem}
.prop-ledger-line b{font-size:.64rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-soft)}
.prop-ledger-line .muted{color:var(--ink-soft)}
/* Liens & Certificates: the instrument's own status lines (2026-09-30). */
.cert-status-lines{display:flex;flex-wrap:wrap;gap:.25rem .9rem;margin:.35rem 0 .1rem;font-size:.76rem;color:var(--ink)}
.cert-status-line{display:inline-flex;align-items:baseline;gap:.35rem}
.cert-status-tag{font-size:.64rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-soft)}
/* Same parcel in other ledgers (shared property layer). */
.related-record{display:grid;grid-template-columns:auto 1fr auto auto;gap:.5rem;align-items:center;padding:.4rem 0;border-top:1px solid var(--card-line);font-size:.8rem}
.related-record:first-child{border-top:none}
.related-ledger{font-size:.66rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase}
.related-ident{font-family:var(--font-mono);font-size:.78rem}
.related-phase{color:var(--ink-soft);font-size:.74rem}
.related-open{border:1px solid var(--card-line);background:var(--card);color:var(--ink);border-radius:3px;padding:.2rem .55rem;font-size:.72rem;font-weight:700;cursor:pointer;min-height:32px}
.related-empty{margin:0;font-size:.78rem;color:var(--ink-soft)}
.dash-row-fresh{font-size:.7rem;color:var(--ink-soft);margin-left:.5rem}
.unit-empty{margin:.2rem 0 .5rem}
@media (min-width:1024px){
  [data-ledger="certificate"] .prop-list{grid-template-columns:1fr}
  /* .prop-card's own base rule sets flex-direction:column - without
     overriding it back to row here, the flex-basis values below (480px
     etc.) resolve against the CROSS axis instead of the main axis and the
     stat grid renders ~480px TALL instead of wide. Caught by inspecting
     actual computed height, not by trusting the rule fired - same category
     of miss as the .calc-drawer min-size-0 bug from the prior phase. */
  [data-ledger="certificate"] .cert-card{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap;gap:.7rem 1rem;padding:.6rem .85rem}
  [data-ledger="certificate"] .cert-card .prop-top{flex:0 0 auto;min-width:200px}
  [data-ledger="certificate"] .cert-card .cert-stat-grid{flex:1 1 480px;margin-top:0;
    grid-template-columns:repeat(6,minmax(90px,1fr))}
  [data-ledger="certificate"] .cert-card .cta-btn,
  [data-ledger="certificate"] .cert-card .detail-btn{flex:0 0 auto;width:auto;margin-top:0}
}

/* Lands Available: the visual catalog. Wider minimum card width than the
   other two ledgers so the (currently text-only - see the project handoff
   on satellite imagery) card reads as a browsable listing tile rather than
   a dense row. */
@media (min-width:1024px){
  [data-ledger="laft"] .prop-list{grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:1rem}
}

/* Auctions: the event terminal. A narrower single-file list (instead of the
   auto-fill catalog grid) reads as a worklist you scan top to bottom, and
   the detail modal docks to the right edge as a due-diligence pane rather
   than centering over the list - CSS-only, so the modal's open/close/
   back-button behaviour (see the ledger-pages writeup on why that stays
   fragile) is completely untouched. */
@media (min-width:1024px){
  [data-ledger="auction"] .prop-list{grid-template-columns:1fr;max-width:680px}
  [data-ledger="auction"] .detail-modal{justify-content:flex-end;padding:0;background:rgba(15,23,42,.32)}
  [data-ledger="auction"] .detail-modal-inner{max-width:480px;width:100%;height:100vh;max-height:100vh;
    border-radius:0;box-shadow:-12px 0 32px rgba(0,0,0,.28)}
}

/* ====================================================================
   APP SHELL — sidebar nav (desktop) / bottom tab bar (mobile), a real
   Dashboard page, a dense data-table list view, and a persistent
   master-detail panel at wide desktop widths. Added on top of the
   existing single-column app: every original id/class above still
   renders and behaves exactly as before — this section only adds a
   navigation layer and desktop-width enhancements around it. ==================================================================== */

.app-shell{display:block}
/* Bug fix (mobile UX pass): #app carries both id="app" and class="app-shell",
   and is given the `hidden` attribute pre-login (index.html). The `hidden`
   attribute's UA-stylesheet rule (`[hidden]{display:none}`) has the exact
   same specificity as this plain class selector, and this rule is the one
   that appears later in the cascade - so on a specificity tie, THIS rule
   silently wins and #app stays visible and in normal flow the whole time
   the sign-in screen is showing. #authGate/#pendingGate aren't position:
   fixed, they're inline flow (min-height:100vh) - so #app sitting visible
   right after them in the DOM was reachable by scrolling straight past the
   login card ("scroll up and see the ledger" on the sign-in screen). Same
   bug class as #authGate[hidden]/#installBtn[hidden]/.filters-row[hidden]
   elsewhere in this file - this one instance was missed. */
.app-shell[hidden]{display:none}
.nav-rail{display:none}
.nav-bottom{display:none}

/* ---- sidebar nav (>=1024px) ---- */
@media (min-width:1024px){
  body{max-width:none;margin:0;padding-bottom:0}
  .app-shell{display:grid;grid-template-columns:224px minmax(0,1fr);align-items:start;min-height:100vh}
  .nav-rail{
    display:flex;flex-direction:column;position:sticky;top:0;align-self:start;height:100vh;
    background:var(--header-bg);border-right:1px solid var(--header-line);
    padding:.9rem .8rem;color:var(--header-ink);overflow-y:auto
  }
  .nav-rail-brand{display:flex;align-items:center;gap:.5rem;padding:.35rem .3rem .9rem;margin-bottom:.5rem;border-bottom:1px solid var(--header-line)}
  .nav-rail-brand img{width:44px;height:44px;flex-shrink:0}
  .nav-rail-brand span{font-family:var(--font-sans);font-weight:800;font-size:.92rem;color:var(--header-ink);white-space:nowrap}
  .nav-rail-brand .brand-accent{color:var(--led-accent-d)}
  .nav-list{display:flex;flex-direction:column;gap:.15rem;margin-bottom:.7rem}
  .nav-item{display:flex;align-items:center;gap:.65rem;padding:.55rem .6rem;border-radius:3px;
    border:none;background:none;color:var(--header-ink-soft);font-family:var(--font-sans);
    font-size:.82rem;font-weight:600;cursor:pointer;text-align:left;width:100%}
  .nav-item svg{width:16px;height:16px;flex-shrink:0}
  .nav-item:hover{background:rgba(255,255,255,.07);color:var(--header-ink)}
  .nav-item.on{background:var(--led-accent-d);color:#0B1220;font-weight:700}
  /* The List entry carries the sum of the ledger counts, the Watchlist
     entry its n/10 - same mono treatment as the ledger tabs. */
  .nav-item .nav-count{margin-left:auto;font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:.78rem;font-weight:600;opacity:.85}
  .nav-item.on .nav-count{background:rgba(11,18,32,.16);border-radius:999px;padding:.02rem .4rem;opacity:1}
  /* Settings sits in its own small footer block, not the primary nav-list -
     it's an entry point to the account menu, not a page like the four
     above it (see the HTML comment on #navSettingsBtn). margin-top:auto
     pushes it (and the portfolio block after it) to the bottom of the
     rail even when the primary nav-list is short. */
  .nav-rail-foot{margin-top:auto;padding-top:.5rem;border-top:1px solid var(--header-line)}
  .nav-rail-portfolio{padding:.8rem .65rem;border-top:1px solid var(--header-line);color:var(--header-ink)}
  .nav-rail-portfolio h3{margin:0 0 .55rem;font-size:.66rem;font-weight:700;letter-spacing:.06em;
    text-transform:uppercase;color:var(--header-ink-soft)}
  .nav-rail-stat{display:flex;align-items:baseline;justify-content:space-between;padding:.22rem 0;font-size:.76rem}
  .nav-rail-stat span:first-child{color:var(--header-ink-soft)}
  .nav-rail-stat b{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:.86rem;color:var(--header-ink)}
  .shell-main{min-width:0}
  .topbar .brand-mark,.topbar .brand-name{display:none}
  .topbar{justify-content:flex-end}
}

/* ---- bottom tab bar (<1024px) ---- */
@media (max-width:1023.98px){
  .nav-bottom{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:40;
    background:var(--header-bg);border-top:1px solid var(--header-line);
    padding:.35rem .2rem calc(.35rem + env(safe-area-inset-bottom));
  }
  body{padding-bottom:4.2rem}
  .nav-bottom-item{flex:1 1 0;display:flex;flex-direction:column;align-items:center;gap:.2rem;
    border:none;background:none;color:var(--header-ink-soft);font-family:var(--font-sans);
    font-size:.62rem;font-weight:600;padding:.3rem .1rem;cursor:pointer}
  .nav-bottom-item svg{width:18px;height:18px}
  .nav-bottom-item.on{color:var(--led-accent-d)}
}

/* ---- page router: one .page visible at a time, driven by [hidden] ---- */
.page{max-width:680px;margin:0 auto}
@media (min-width:1024px){.page{max-width:none;padding:0 1.4rem 1.4rem}}

/* ---- Dashboard page ---- */
.dash-head{padding:1.1rem .6rem .3rem}
@media (min-width:1024px){.dash-head{padding:1.3rem 0 .4rem}}
.dash-head h1{margin:0 0 .2rem;font-family:var(--font-sans);font-weight:800;font-size:1.25rem;color:var(--ink)}
.dash-head p{margin:0;font-size:.82rem;color:var(--ink-soft)}
/* Settings button sits beside the title/subtitle rather than under them -
   .dash-head-row only changes layout, .dash-head's own padding is untouched
   so the plain (no-button) .dash-head elsewhere still looks the same. */
.dash-head-row{display:flex;align-items:flex-start;justify-content:space-between;gap:.6rem}
.dash-settings-btn{flex:0 0 auto;display:inline-flex;align-items:center;gap:.35rem;
  margin-top:.1rem;font-size:.78rem;font-weight:700;font-family:inherit;color:var(--ink);
  background:var(--card);border:1px solid var(--card-line);border-radius:8px;
  padding:.45rem .7rem;cursor:pointer;white-space:nowrap}
.dash-settings-btn:hover{border-color:var(--accent);color:var(--accent)}
.dash-settings-btn svg{width:15px;height:15px}
@media (max-width:400px){.dash-settings-btn span{display:none}}
.dash-stats{display:grid;grid-template-columns:repeat(2,1fr);gap:.6rem;padding:.8rem .6rem}
@media (min-width:640px){.dash-stats{grid-template-columns:repeat(4,1fr)}}
@media (min-width:1024px){.dash-stats{padding:0 0 1rem}}
/* Phase (mobile UX pass): border -> soft shadow, same reasoning as
   .card-stat/.detail-stat above. */
/* Icon chip + figure (Phase 51 visual rebuild) - .stat-tile is now a flex
   row: a colored rounded-square icon on the left, label/value/sub stacked
   on the right, matching the reference design's Dashboard tiles instead of
   a bare number in a box. Markup: <span class="stat-tile-icon">+ <div>
   wrapping the existing label/val/sub - see renderDashboard(). */
.stat-tile{display:flex;align-items:flex-start;gap:.7rem;background:var(--card);border-radius:8px;
  padding:.85rem .9rem;box-shadow:var(--shadow)}
.stat-tile-icon{flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  width:2.15rem;height:2.15rem;border-radius:8px;background:var(--accent-soft);color:var(--accent)}
.stat-tile-icon svg{width:18px;height:18px}
.stat-tile-icon.accent{background:var(--accent);color:#fff}
.stat-tile-label{font-size:.68rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-soft)}
.stat-tile-val{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-weight:700;
  font-size:1.5rem;color:var(--ink);margin-top:.2rem}
.stat-tile-val.accent{color:var(--accent)}
.stat-tile-sub{font-size:.72rem;color:var(--ink-soft);margin-top:.15rem}
.dash-grid{display:grid;grid-template-columns:1fr;gap:.9rem;padding:.2rem .6rem 1.4rem}
@media (min-width:1024px){.dash-grid{grid-template-columns:repeat(auto-fit,minmax(280px,1fr));padding:0 0 1.4rem}}
.dash-panel{background:var(--card);border:1px solid var(--card-line);border-radius:4px;overflow:hidden}
.dash-panel-head{padding:.7rem .9rem;border-bottom:1px solid var(--card-line);font-family:var(--font-sans);
  font-weight:700;font-size:.85rem;color:var(--ink)}
.dash-row{display:flex;align-items:center;justify-content:space-between;gap:.6rem;
  padding:.55rem .9rem;border-bottom:1px solid var(--card-line);font-size:.8rem}
.dash-row:last-child{border-bottom:none}
.dash-row-name{color:var(--ink);font-weight:600;display:flex;align-items:center;gap:.5rem}
.dash-row-name svg{width:15px;height:15px;color:var(--ink-soft)}
.dash-row-vals{display:flex;gap:1rem;font-family:var(--font-mono);font-variant-numeric:tabular-nums;color:var(--ink-soft)}
.dash-row-vals b{color:var(--ink);font-weight:700}
.dash-empty{padding:1.4rem .9rem;color:var(--ink-soft);font-size:.8rem;text-align:center}
.dash-cta{display:inline-flex;align-items:center;gap:.4rem;margin:.7rem .9rem 0;padding:.5rem .8rem;
  border-radius:3px;background:var(--accent);color:#fff;font-weight:700;font-size:.78rem;
  text-decoration:none;border:none;cursor:pointer}

/* ---- Auctions page: desktop table view + persistent detail panel ---- */
/* .auctions-body has THREE children - .data-table-wrap, #main (the card
   list - Phase 54 removed the .explore-shell wrapper that used to carry an
   embedded map beside it; see the Phase 54 comment above the auctions-body
   markup in index.html/tx.html), and .detail-panel - but only two of them
   are ever visible at once (table vs. list mode toggles which of the first
   two shows). A plain 2-column grid put the third child on its own implicit
   row instead of beside the list, pushing the detail panel full-width below
   everything - caught in the fixture screenshot before ship. Pinning both
   list-area children to column 1 and the panel to column 2/row 1 keeps the
   layout correct regardless of which list view is active. */
.auctions-body{display:block}
@media (min-width:1024px){
  .auctions-body{display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:1.1rem;align-items:start}
  .auctions-body>.data-table-wrap,.auctions-body>#main{grid-column:1;grid-row:1}
  .auctions-body>.detail-panel{grid-column:2;grid-row:1}
}
@media (min-width:1280px){
  .auctions-body{grid-template-columns:minmax(0,1fr) 420px}
}
.detail-panel{display:none}
@media (min-width:1024px){
  .detail-panel{display:block;position:sticky;top:.9rem;max-height:calc(100vh - 1.8rem);overflow-y:auto;
    background:var(--card);border:1px solid var(--card-line);border-radius:4px;padding:1rem}
  .detail-panel-empty{padding:2.2rem 1rem;text-align:center;color:var(--ink-soft);font-size:.82rem}
  .detail-panel .detail-close{display:none}
}

.data-table-wrap{display:none}
.table-toggle-btn{display:none}
@media (min-width:1024px){
  .table-toggle-btn{display:inline-flex;align-items:center;gap:.35rem;padding:.45rem .7rem;
    border-radius:3px;border:1px solid var(--card-line);background:var(--card);color:var(--ink-soft);
    font-size:.78rem;font-weight:600;cursor:pointer}
  .table-toggle-btn svg{width:14px;height:14px}
  .table-toggle-btn.on{color:var(--accent);border-color:var(--accent)}
}
[data-listmode="table"] #main{display:none}
[data-listmode="table"] .data-table-wrap{display:block}
.data-table{width:100%;border-collapse:collapse;background:var(--card);border:1px solid var(--card-line);
  border-radius:4px;overflow:hidden;font-size:.8rem}
.data-table thead th{text-align:left;font-size:.66rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--ink-soft);padding:.55rem .7rem;border-bottom:1px solid var(--card-line);background:var(--paper)}
.data-table tbody td{padding:.55rem .7rem;border-bottom:1px solid var(--card-line);vertical-align:middle;color:var(--ink)}
.data-table tbody tr:last-child td{border-bottom:none}
.data-table tbody tr{cursor:pointer}
.data-table tbody tr:hover{background:var(--paper)}
.data-table tbody tr.selected{background:var(--accent-soft)}
.dt-address{font-weight:700;color:var(--ink)}
.dt-parcel{font-family:var(--font-mono);font-size:.72rem;color:var(--ink-soft);margin-top:.1rem}
.dt-num{font-family:var(--font-mono);font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.dt-actions{display:flex;gap:.35rem;justify-content:flex-end}
.dt-actions button{border:1px solid var(--card-line);background:var(--card);border-radius:3px;
  width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;
  color:var(--ink-soft);cursor:pointer}
.dt-actions button:hover{color:var(--accent);border-color:var(--accent)}
.dt-actions button svg{width:14px;height:14px}
.dt-actions button.on{color:var(--accent);border-color:var(--accent)}

/* ---- quick-action tiles (detail links), upgraded from plain link row to
   bordered icon-over-label tiles — applies everywhere the detail is shown
   (mobile full page, desktop modal, desktop persistent panel), matching
   the terminal-reference "Street View / Appraiser / Zillow" tile row. ---- */
.detail-links{display:grid;grid-template-columns:repeat(2,1fr);gap:.5rem;margin:.7rem 0}
@media (min-width:420px){.detail-links{grid-template-columns:repeat(4,1fr)}}
.detail-links a{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.3rem;
  padding:.65rem .3rem;border:1px solid var(--card-line);border-radius:3px;background:var(--paper);
  color:var(--ink);text-decoration:none;font-size:.68rem;font-weight:600;text-align:center}
.detail-links a:hover{border-color:var(--accent);color:var(--accent)}
.detail-links a .link-icon{margin:0}
.detail-links a .link-icon svg{width:18px;height:18px}
.detail-cta{display:flex;align-items:center;justify-content:center;gap:.5rem;width:100%;margin:.6rem 0;
  padding:.8rem 1rem;border-radius:3px;border:none;background:var(--ok);color:#fff;font-weight:700;
  font-size:.85rem;text-decoration:none;cursor:pointer}
.detail-cta:hover{filter:brightness(1.06)}
.detail-cta svg{width:17px;height:17px}

/* Phase 53: the standalone Map page's own card chrome/FL-TX switcher/legend
overrides (.map-page-wrap, .map-region-tabs, .map-legend i) that used to
live here are removed with the #pageMap section itself - see the note by
.chipx above. */


/* Phase 58: the flood row in Risk & Legal. `kv-sub` is the provenance line
   under a value (which source, checked when) - the card's other rows read
   "Not tracked" with nothing under them, so this is the first place a value
   needs to carry its own attribution. `kv-flag-warn` is deliberately the
   only attention colour in this card: being inside a Special Flood Hazard
   Area is the one fact here that changes what a bidder has to budget for.
   Phase 63: two real bugs fixed here.
   1. `--muted`/`--line` were never defined anywhere (:root or either theme
      block) - this app's real tokens are `--ink-soft`/`--card-line`, used
      everywhere else in this file. With no fallback given, these two
      properties were invalid at computed-value time and fell back to the
      inherited/initial color, which could render invisible or wrong in
      both themes.
   2. `--watch`/`--watch-soft` ARE defined (explore.css - the Watchlist
      map-pill's pink accent), so var()'s fallback never applied and this
      flood-hazard warning rendered in that unrelated pink instead of a
      real danger color - reading as decorative rather than a risk flag,
      and confusable with the Watchlist feature. `--bad`/`--bad-bg` are
      this app's actual danger tokens (used for the hide/remove chip and
      auth error text above), same red family the old rgba()/hex fallback
      values here were already aiming for. */
.kv-sub { display: block; margin-top: 2px; font-size: 12px; color: var(--ink-soft); line-height: 1.35; }
.kv-flag { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  font-size: 11px; font-weight: 600; border: 1px solid var(--card-line); color: var(--ink-soft); white-space: nowrap; }
.kv-flag-warn { border-color: transparent; background: var(--bad-bg); color: var(--bad); }
/* Launch-readiness 2026-09-26: visible caveats beside the fields they qualify */
.lien-caveat{display:block;font-size:.72rem;color:var(--ink-soft);font-style:italic;margin-top:.2rem}
.calc-disclaimer{font-size:.72rem;color:var(--ink-soft);font-style:italic;margin:0 0 .45rem}


/* ==================== SaaS hardening (2026-09-29) ==================== */
/* Dataset health rows (Dashboard "Data sources", Terms) */
.health-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:.35rem .6rem;padding:.45rem 0;border-bottom:1px solid var(--card-line);font-size:.8rem}
.health-row:last-child{border-bottom:none}
.health-row .health-label{flex:1 1 12rem;font-weight:600}
.health-row .health-sub{flex:1 1 100%;color:var(--ink-soft);font-size:.74rem}
.health-badge{display:inline-block;font-size:.64rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:.12rem .45rem;border-radius:999px;border:1px solid transparent}
.health-badge.healthy{color:var(--ok);background:var(--ok-bg)}
.health-badge.incomplete,.health-badge.stale{color:var(--warn);background:var(--warn-bg)}
.health-badge.failed{color:var(--bad);background:var(--bad-bg)}
.health-badge.not_run{color:var(--ink-soft);background:var(--paper-line)}
.source-health-terms{margin:.4rem 0 .8rem}
.source-health-terms .health-row{font-size:.76rem}
/* Watchlist change signals */
.watch-changes{display:flex;flex-direction:column;gap:.35rem}
.watch-change{font-size:.8rem;padding:.4rem 0;border-bottom:1px solid var(--card-line)}
.watch-change:last-child{border-bottom:none}
.watch-change .wc-title{font-weight:600}
.watch-change ul{margin:.15rem 0 0 1rem;padding:0;color:var(--ink-soft);font-size:.76rem}
.watch-changes-note{font-size:.72rem;color:var(--ink-soft);margin:.2rem 0 0}
/* Sale event history (Phase B) on the property page */
.event-list{display:flex;flex-direction:column;gap:.5rem}
.event-item{padding:.5rem .6rem;border:1px solid var(--card-line);border-radius:8px;font-size:.8rem}
.event-item .ev-head{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.3rem .6rem;font-weight:600}
.event-item .ev-life{font-weight:600;color:var(--ink-soft)}
.event-item .ev-life.completed{color:var(--warn)}
.event-item .ev-life.scheduled{color:var(--ok)}
.event-item .ev-meta{color:var(--ink-soft);font-size:.74rem;margin-top:.2rem}
.event-item .ev-outcome{margin-top:.25rem;font-size:.76rem}
.event-item .ev-prov{display:block;margin-top:.15rem;color:var(--ink-soft);font-size:.72rem;line-height:1.4}
.event-note{font-size:.72rem;color:var(--ink-soft);margin:.4rem 0 0}
/* Support modal */
.support-topics{display:flex;flex-direction:column;gap:.35rem;margin:.4rem 0 .8rem}
.support-topics a,.support-topics button{display:block;text-align:left;padding:.5rem .7rem;border:1px solid var(--card-line);border-radius:8px;background:none;color:inherit;font:inherit;font-size:.84rem;text-decoration:none;cursor:pointer}
.support-topics a:hover,.support-topics button:hover{border-color:var(--accent);color:var(--accent)}
.support-context{font-size:.74rem;color:var(--ink-soft);margin:.2rem 0 .6rem}
.support-unconfigured{border:1px dashed var(--warn);border-radius:8px;padding:.6rem .8rem;font-size:.8rem;background:var(--warn-bg)}
.danger-btn{background:var(--bad)!important;border-color:var(--bad)!important;color:#fff!important}
.detail-report-btn{margin-top:.5rem}

/* Production-readiness (2026-09-30): per-field provenance table on the full
   property page (app.js provenanceRowsHtml), the OTC row-level provenance
   lines, the inventory status value, and the Dashboard's per-county
   freshness rows. Plain, terminal-like: no badges, no meters. */
.prov-fresh{margin:.35rem 0 .2rem;font-size:.74rem;color:var(--ink-soft)}
.prov-table{display:flex;flex-direction:column;margin:.35rem 0;border-top:1px solid var(--card-line);font-size:.72rem}
.prov-row{display:grid;grid-template-columns:minmax(7rem,1.1fr) minmax(8rem,1.4fr) minmax(8rem,1.3fr) minmax(6rem,.9fr);gap:.4rem;padding:.3rem 0;border-bottom:1px solid var(--card-line);align-items:baseline}
.prov-row.prov-head{font-weight:800;letter-spacing:.04em;text-transform:uppercase;font-size:.66rem;color:var(--ink-soft)}
.prov-row .prov-field{font-weight:600}
.prov-row .prov-source .mono{color:var(--ink-soft);font-size:.66rem}
.prov-row .prov-when{color:var(--ink-soft)}
.prov-empty{margin:.35rem 0;font-size:.72rem;color:var(--ink-soft)}
.prov-lines{display:flex;flex-direction:column;gap:.15rem;margin:.4rem 0;font-size:.72rem}
.prov-line{display:flex;gap:.5rem;align-items:baseline}
.prov-line .prov-k{flex:0 0 7.5rem;font-weight:600;color:var(--ink-soft)}
.prov-line .prov-v{flex:1 1 auto;overflow-wrap:anywhere}
.inv-status{font-weight:700}
.inv-status[data-status="closed"],.inv-status[data-status="unknown"]{color:var(--ink-soft)}
.unit-head{margin:.6rem 0 .1rem;font-size:.7rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-soft)}
.unit-row .unit-source{font-size:.66rem;color:var(--ink-soft)}
.health-badge.stale{color:var(--warn)}
@media (max-width:640px){.prov-row{grid-template-columns:1fr 1fr}.prov-row.prov-head{display:none}}

/* ---- Available decision page (2026-09-30, migration 023) ---- */
.dec-list{display:flex;flex-direction:column;gap:.1rem}
.dec-row{display:grid;grid-template-columns:minmax(0,11rem) minmax(0,1fr);gap:.35rem .8rem;padding:.45rem 0;border-top:1px solid var(--card-line);font-size:.8rem;line-height:1.4}
.dec-row:first-child{border-top:none}
@media (max-width:560px){ .dec-row{grid-template-columns:1fr;gap:.15rem} }
.dec-q{font-family:var(--font-sans);font-weight:700;color:var(--ink-soft);font-size:.74rem;letter-spacing:.01em}
.dec-a{min-width:0;overflow-wrap:anywhere}
.dec-a.ok{color:var(--ok)} .dec-a.bad{color:var(--bad)} .dec-a.warn{color:var(--warn)} .dec-a.muted{color:var(--ink-soft)}
.dec-sub{display:block;font-size:.72rem;color:var(--ink-soft);margin-top:.15rem}
.dec-sub .ok{color:var(--ok)} .dec-sub .warn{color:var(--warn)}
.dec-gaps{margin:0;padding-left:1.1rem} .dec-gaps li{margin:.1rem 0}
.dec-history{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.25rem}
.dec-history li{display:grid;grid-template-columns:6.2rem minmax(0,1fr);gap:.5rem;align-items:baseline}
.dec-history .dec-when{font-family:var(--font-mono,monospace);font-size:.72rem;color:var(--ink-soft)}
.dec-history li[data-kind="removed"] .dec-what{color:var(--bad)}
.dec-history li[data-kind="reactivated"] .dec-what,.dec-history li[data-kind="result_published"] .dec-what{color:var(--ok)}
/* ---- Admin source publication panel ---- */
.admin-publication{border-top:1px solid var(--warn)}
.admin-pub-note{margin:0 0 .5rem;font-size:.72rem;line-height:1.45;color:var(--ink-soft)}
.admin-pub-list{display:flex;flex-direction:column;gap:.5rem}
.admin-pub-row{background:var(--card);border:1px solid var(--card-line);border-radius:.5rem;padding:.5rem .65rem;font-size:.76rem}
.admin-pub-head{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center;font-weight:700}
.admin-pub-counties{color:var(--ink-soft);font-weight:500}
.admin-pub-status{margin-left:auto;font-size:.68rem;font-weight:800;letter-spacing:.03em;padding:.1rem .45rem;border-radius:.4rem;border:1px solid var(--card-line)}
.admin-pub-status[data-status="APPROVED"],.admin-pub-status[data-status="APPROVED_GRANDFATHERED"]{color:var(--ok);border-color:var(--ok)}
.admin-pub-status[data-status="RESTRICTED"],.admin-pub-status[data-status="BLOCKED"]{color:var(--bad);border-color:var(--bad)}
.admin-pub-meta,.admin-pub-review{color:var(--ink-soft);margin-top:.2rem}
.admin-pub-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(11rem,1fr));gap:.4rem;margin-top:.45rem;align-items:end}
.admin-pub-form label{display:flex;flex-direction:column;gap:.15rem;font-size:.68rem;color:var(--ink-soft)}
.admin-pub-form input,.admin-pub-form select{font:inherit;font-size:.76rem;padding:.3rem .4rem;border:1px solid var(--card-line);border-radius:.35rem;background:var(--bg);color:var(--ink)}
.admin-pub-msg{font-size:.7rem;color:var(--ink-soft);grid-column:1 / -1}

/* ---- Customer-value sprint: cross-ledger timing, instructions, first-observed note ---- */
.related-when{display:block;font-size:.68rem;color:var(--ink-soft)}
.related-when.prev{color:var(--warn)} .related-when.now{color:var(--ok)}
.dec-instructions{white-space:pre-line}
/* Acquisition sprint (2026-09-30): the acquisition answer - mode, ordered
   steps, the published contact block. Terminal style, no card. */
.acq-mode{font-weight:700}
.auction-process-mode{font-weight:700}
/* A source whose reuse terms are under review: named, never styled as an error. */
.prov-review{display:inline-block;margin-left:.3rem;padding:0 .35rem;border-radius:.3rem;font-size:.68rem;font-weight:600;color:var(--warn);background:var(--warn-bg);white-space:nowrap}
.acq-first{display:block;margin-top:.2rem;font-size:.78rem}
.acq-verified .warn{color:var(--warn)}
.acq-steps{margin:.3rem 0 0;padding-left:1.25rem} .acq-steps li{margin:.12rem 0}
.acq-contact{display:grid;grid-template-columns:minmax(0,9rem) minmax(0,1fr);gap:.12rem .6rem;margin:0;font-size:.78rem}
.acq-contact dt{color:var(--ink-soft);font-weight:600} .acq-contact dd{margin:0;overflow-wrap:anywhere}
.acq-match{font-family:var(--font-mono);font-size:.7rem}
@media (max-width:480px){ .acq-contact{grid-template-columns:1fr} .acq-contact dd{margin-bottom:.2rem} }
/* HOW TO ACQUIRE (Acquisition-path sprint, 2026-10-01): why it is available,
   one primary action, then method / instructions / official source / last
   verified. No badge, no score. */
.acquire-card .acq-block{display:flex;flex-direction:column;gap:.3rem}
.acq-h{font-size:.68rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft);margin-top:.35rem}
/* "How to acquire" (2026-10-05): one block per investor question */
.acquire-card .acq-q{display:flex;flex-direction:column;gap:.25rem;padding:.45rem 0;border-top:1px solid var(--card-line)}
.acquire-card .acq-q:first-child{border-top:0;padding-top:0}
.acq-muted{margin:0;color:var(--ink-soft);font-size:.86rem}
/* Saved property: the way back to the official path, under its watchlist card */
.bidlist-acq{display:flex;flex-direction:column;gap:.35rem;margin:-.35rem 0 .8rem;padding:.55rem .75rem;border:1px solid var(--card-line);border-top:0;border-radius:0 0 10px 10px;font-size:.86rem}
.bidlist-acq-head{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center}
.bidlist-acq-amount{color:var(--ink-soft)}
.bidlist-acq-links{display:flex;flex-wrap:wrap;gap:.35rem}
.bidlist-acq .reset-btn{align-self:flex-start}
.acq-why-text{margin:0;font-size:.86rem;font-weight:600}
.acq-why-basis{margin:0;font-size:.74rem;color:var(--ink-soft)}
.acq-why-link{margin:.1rem 0 0;font-size:.78rem}
.acq-cta-row{margin:.15rem 0 .25rem;display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}
.acq-cta{display:inline-flex;align-items:center;min-height:40px;padding:.45rem .95rem;border-radius:8px;background:var(--accent);color:var(--card);font-weight:700;font-size:.85rem;text-decoration:none}
.acq-cta:hover,.acq-cta:focus-visible{filter:brightness(1.08);text-decoration:none}
.acq-cta-sub{font-family:var(--font-mono);font-size:.74rem;color:var(--ink-soft)}
.acq-dl{display:grid;grid-template-columns:minmax(0,8.5rem) minmax(0,1fr);gap:.25rem .7rem;margin:0;font-size:.8rem}
.acq-dl dt{color:var(--ink-soft);font-weight:600} .acq-dl dd{margin:0;overflow-wrap:anywhere}
.acq-dl .acq-steps{margin:0}
/* "Not yet verified" is an enrichment state, not an error: neutral ink, no warning colour. */
.acq-pending{color:var(--ink-soft);font-weight:600}
@media (max-width:480px){ .acq-dl{grid-template-columns:1fr} .acq-dl dd{margin-bottom:.3rem} }
.dec-first-note{display:block;margin-bottom:.35rem}

/* ---- Unified navigation (2026-09-30) ---- */
/* Ledger tiles on the Dashboard are buttons (they open the List page on
   that ledger) but keep the tile look. */
.stat-tile-btn{font:inherit;text-align:left;cursor:pointer;color:inherit;border:1px solid var(--card-line)}
.stat-tile-btn:hover{border-color:var(--accent)}
.stat-tile-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.stat-tile-btn .stat-tile-icon svg{width:18px;height:18px}
.dash-row-vals{flex-wrap:wrap;justify-content:flex-end;row-gap:.15rem}
.dash-row-sub{font-size:.7rem;color:var(--ink-soft)}
.dash-note{margin:0;padding:.55rem .9rem .7rem;font-size:.72rem;color:var(--ink-soft)}
/* Map page: title + context line ("Ledger: Available · County: All
   counties"). The state is the header's #stateSelect. */
.map-page-titlebox{display:flex;flex-direction:column;gap:.1rem;min-width:0}
.map-context b{color:var(--ink);font-weight:700}
/* Watchlist layer: the same parcel's other ledger rows, folded under one card. */
/* Watchlist: items saved under another state (or no longer listed) are
   counted here, never removed - the state is a viewing context. */
.bidlist-elsewhere{margin:0 0 .7rem;font-size:.76rem;color:var(--ink-soft)}
/* Saved-property status (2026-10-05): one line above each saved card. */
.saved-status{margin:.6rem 0 -.2rem;padding:.4rem .6rem;border-radius:8px 8px 0 0;font-size:.78rem;line-height:1.35;border:1px solid var(--card-line);border-bottom:0}
.saved-status.saved-active{color:var(--ink-soft);background:var(--ok-bg, transparent)}
.saved-status.saved-changed{color:var(--ink);background:var(--warn-bg, transparent)}
.saved-status.saved-gone{color:var(--bad);background:var(--bad-bg, transparent)}
.saved-missing{margin:.8rem 0;padding:.6rem .7rem;border:1px dashed var(--card-line);border-radius:8px;font-size:.8rem}
.saved-missing ul{margin:0;padding-left:1rem}
.saved-missing-row{margin:.25rem 0}
.saved-missing-row .reset-btn{min-height:36px}
.ss-rename{display:flex;flex-wrap:wrap;gap:.4rem;align-items:flex-end;margin:.4rem 0}
.ss-rename[hidden]{display:none}
.bidlist-related{margin:-.35rem 0 .7rem;padding:.45rem .7rem;border:1px dashed var(--card-line);border-radius:4px;background:var(--card);font-size:.76rem}
.bidlist-related-head{font-weight:700;color:var(--ink-soft);font-size:.68rem;letter-spacing:.04em;text-transform:uppercase;margin-bottom:.2rem}
.bidlist-related ul{margin:0;padding-left:1.1rem}

/* ---- Admin area (/admin, 2026-09-30) - admin.html / admin.js ---- */
body[data-page="admin"]{background:var(--paper);color:var(--ink);min-height:100vh}
.admin-shell{max-width:720px;margin:0 auto;padding:2rem 1rem 3rem}
.admin-shell[hidden]{display:none}
.admin-head{display:flex;align-items:center;gap:.8rem;margin-bottom:1.25rem}
.admin-eyebrow{margin:0;font-size:.75rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft)}
.admin-title{margin:0;font-size:1.4rem}
.admin-card{background:var(--card);border:1px solid var(--card-line);border-radius:12px;padding:1rem 1.1rem;margin-bottom:1rem;box-shadow:var(--shadow)}
.admin-label{margin:0 0 .25rem;font-size:.78rem;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-soft)}
.admin-identity{margin:0 0 .4rem;font-size:1.35rem;font-weight:700}
.admin-note{margin:.2rem 0;color:var(--ink-soft);font-size:.92rem}
.admin-actions{display:flex;flex-wrap:wrap;gap:.6rem;margin:.8rem 0 0}
.admin-btn{display:inline-flex;align-items:center;min-height:40px;padding:.45rem .95rem;border-radius:10px;border:1px solid var(--accent);background:var(--accent);color:#fff;font:inherit;text-decoration:none;cursor:pointer}
.admin-btn-quiet{background:transparent;color:var(--ink);border-color:var(--card-line)}

/* Source Publication Governance as its own admin-only view (account menu /
   #/governance). The panel inside is the existing .admin-publication UI;
   inside the view it drops the workspace banner chrome (warning strip,
   duplicate heading) since the view's own title says what it is. */
.governance-modal-inner{max-width:52rem}
.governance-modal-inner .admin-publication{background:none;border:0;padding:0;margin:0}
.governance-modal-inner .admin-approvals-head{display:none}

/* ===== Customer monitoring (2026-10-01): saved searches, alerts, change history ===== */
.ss-badge{display:inline-block;margin-left:.3rem;padding:0 .4rem;border-radius:999px;background:var(--accent);color:#fff;font-size:.68rem;font-weight:700;line-height:1.4}
.ss-badge[hidden]{display:none}
.link-btn{background:none;border:0;padding:0;color:var(--accent);font:inherit;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.ss-form{display:flex;flex-direction:column;gap:.4rem;margin:0 0 .6rem}
.ss-form-label{display:flex;flex-direction:column;gap:.25rem;font-size:.78rem;font-weight:600}
.ss-form input{padding:.45rem .55rem;border:1px solid var(--card-line);border-radius:6px;background:var(--card);color:var(--ink);font:inherit}
.ss-form .detail-btn{align-self:flex-start}
.saved-search-list{display:flex;flex-direction:column;gap:.6rem}
.saved-search{border:1px solid var(--card-line);border-radius:8px;padding:.6rem .7rem;background:var(--card)}
.ss-head{display:flex;flex-wrap:wrap;gap:.3rem;align-items:baseline}
.ss-criteria{font-size:.74rem}
.ss-counts{font-size:.78rem;margin:.3rem 0;color:var(--ink-soft)}
.ss-counts .ss-new{color:var(--ok);font-weight:600}
.ss-counts .ss-changed{color:var(--warn);font-weight:600}
.ss-detail summary{cursor:pointer;font-size:.76rem;color:var(--accent)}
.ss-group{margin:.35rem 0}
.ss-label{font-size:.7rem;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-soft)}
.ss-group ul{margin:.15rem 0 0 1rem;padding:0;font-size:.78rem}
.ss-actions{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center;margin-top:.4rem}
.detail-btn.danger{color:var(--bad);border-color:var(--bad)}
.alert-prefs{display:flex;flex-direction:column;gap:.3rem;margin:0 0 .6rem}
.alert-actions{display:flex;gap:.5rem;align-items:center;font-size:.78rem;margin:.2rem 0 .4rem}
.alert-item.unread .dec-what b::before{content:"";display:inline-block;width:.45rem;height:.45rem;border-radius:50%;background:var(--accent);margin-right:.35rem;vertical-align:middle}
.monitor-block p{margin:.2rem 0}
.monitor-status{font-size:.85rem}
.watch-server-changes{margin-top:.5rem}
.watch-server-changes ul{margin:.15rem 0 0 1rem;padding:0;color:var(--ink-soft);font-size:.76rem}
#monitorFilters{border-top:1px dashed var(--card-line);padding-top:.5rem;margin-top:.4rem}
.admin-usage-table{width:100%;border-collapse:collapse;font-size:.8rem}
.admin-usage-table th,.admin-usage-table td{text-align:left;padding:.25rem .4rem;border-bottom:1px solid var(--card-line)}
.admin-usage-table td:nth-child(n+2),.admin-usage-table th:nth-child(n+2){text-align:right}
/* Admin source panel (all-sources enrichment engine, 2026-10-01) */
.admin-filters{display:flex;flex-wrap:wrap;gap:.6rem;font-size:.8rem;margin:.3rem 0}
.admin-sources{overflow-x:auto;max-height:70vh}
.admin-sources-table td,.admin-sources-table th{text-align:left!important;vertical-align:top}
.admin-sources-table td{max-width:22rem;overflow-wrap:anywhere}
.gov-approved{color:var(--ok);font-weight:600}
.gov-review_required{color:var(--warn);font-weight:600}
.gov-hard_blocked{color:var(--bad);font-weight:600}

/* Load resilience (2026-10-04): a page of results that could not be loaded.
   The rows that did load stay on screen; this says so and offers a retry. */
.load-issue{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap;margin:0 0 .75rem;padding:.6rem .8rem;
  border:1px solid var(--warn,#b7791f);border-left-width:4px;border-radius:8px;background:var(--warn-bg,rgba(183,121,31,.1));
  color:var(--ink,inherit);font-size:.9rem}
.load-issue-text{flex:1 1 16rem}
.load-issue-retry{padding:.4rem .9rem;min-height:36px;border-radius:6px;border:1px solid currentColor;background:transparent;
  color:inherit;font:inherit;font-weight:600;cursor:pointer}
.load-issue.retrying .load-issue-retry{opacity:.6;pointer-events:none}

/* =====================================================================
   SHELL REDESIGN (2026-10-04)
   Dark navy shell, light panels, one accent per ledger (green Available,
   blue Auctions, purple Liens & Certificates), amber for warnings, red for
   errors. Modest radii, thin borders, no gradients. Everything above still
   applies; this block only re-skins and lays out the new shell pieces.
   ===================================================================== */
:root{
  --shell-bg:#0B1324; --shell-line:#1C2740; --shell-ink:#E6ECF5; --shell-ink-soft:#8C9AB3;
  --c-laft:#047857; --c-laft-soft:#D1FAE5; --c-laft-d:#34D399;
  --c-auction:#2563EB; --c-auction-soft:#DBEAFE; --c-auction-d:#60A5FA;
  --c-certificate:#6D28D9; --c-certificate-soft:#EDE9FE; --c-certificate-d:#A78BFA;
  --radius:8px; --radius-sm:6px;
}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
[data-ledger="laft"]{--lc:var(--c-laft);--lc-soft:var(--c-laft-soft);--lc-d:var(--c-laft-d)}
[data-ledger="auction"]{--lc:var(--c-auction);--lc-soft:var(--c-auction-soft);--lc-d:var(--c-auction-d)}
[data-ledger="certificate"]{--lc:var(--c-certificate);--lc-soft:var(--c-certificate-soft);--lc-d:var(--c-certificate-d)}
:root[data-theme="dark"] [data-ledger]{--lc-soft:color-mix(in srgb, var(--lc) 22%, transparent)}
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]) [data-ledger]{--lc-soft:color-mix(in srgb, var(--lc) 22%, transparent)} }

/* ---- ledger badge (cards, search results, state picker) ---- */
.ledger-badge{display:inline-flex;align-items:center;gap:.3rem;padding:.12rem .5rem;border-radius:999px;
  font-size:.66rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;white-space:nowrap;
  background:var(--lc-soft,var(--paper));color:var(--lc,var(--ink));border:1px solid color-mix(in srgb, var(--lc,var(--ink-soft)) 35%, transparent);text-decoration:none}
:root[data-theme="dark"] .ledger-badge{color:var(--lc-d,var(--ink))}
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]) .ledger-badge{color:var(--lc-d,var(--ink))} }
.ledger-badge b{font-family:var(--font-mono);font-weight:700}
a.ledger-badge:hover{text-decoration:underline}
.ledger-badge.pending,.ledger-badge.unknown{background:var(--paper);color:var(--ink-soft);border-color:var(--card-line)}

/* ---- sidebar ---- */
@media (min-width:1024px){
  .app-shell{grid-template-columns:248px minmax(0,1fr)}
  .nav-rail{background:var(--shell-bg);border-right-color:var(--shell-line);padding:1rem .75rem}
  .nav-rail-brand{gap:.6rem;border-bottom-color:var(--shell-line);padding:.2rem .3rem 1rem}
  .nav-rail-brand img{width:36px;height:36px}
  .nav-rail-brand .brand-lockup{display:flex;flex-direction:column;line-height:1.15;min-width:0}
  .nav-rail-brand .brand-title{font-weight:800;font-size:.95rem;color:#fff;letter-spacing:-.01em}
  .nav-rail-brand .brand-sub{font-weight:500;font-size:.68rem;color:var(--shell-ink-soft);white-space:nowrap}
  .nav-group-label{display:block;margin:.85rem .6rem .3rem;font-size:.62rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--shell-ink-soft)}
  .nav-item{color:var(--shell-ink-soft);border-radius:var(--radius-sm);padding:.5rem .6rem;text-decoration:none;position:relative}
  .nav-item:hover{background:rgba(255,255,255,.06);color:var(--shell-ink)}
  .nav-item.on{background:rgba(255,255,255,.09);color:#fff;font-weight:700;box-shadow:inset 3px 0 0 var(--nav-accent,#60A5FA)}
  .nav-item.on .nav-count{background:rgba(255,255,255,.12)}
  .nav-item:focus-visible{outline:2px solid #93C5FD;outline-offset:1px}
  .nav-item[data-nav-ledger]{--nav-accent:var(--lc-d)}
  .nav-dot{width:9px;height:9px;border-radius:50%;background:var(--lc-d);flex-shrink:0;margin:0 3.5px}
  .nav-rail-foot{border-top-color:var(--shell-line);display:flex;flex-direction:column;gap:.15rem}
  .nav-rail-foot .nav-item[hidden]{display:none}
}
.nav-item[data-nav-ledger="laft"],.nav-item[data-nav-ledger="laft"] *{--lc:var(--c-laft);--lc-d:var(--c-laft-d)}
.nav-item[data-nav-ledger="auction"],.nav-item[data-nav-ledger="auction"] *{--lc:var(--c-auction);--lc-d:var(--c-auction-d)}
.nav-item[data-nav-ledger="certificate"],.nav-item[data-nav-ledger="certificate"] *{--lc:var(--c-certificate);--lc-d:var(--c-certificate-d)}

/* ---- top bar: global search + state ---- */
.topbar{background:var(--shell-bg);border-bottom-color:var(--shell-line);gap:.6rem;flex-wrap:wrap}
@media (min-width:1024px){ .topbar{justify-content:flex-start;padding:.6rem 1.4rem;flex-wrap:nowrap} }
.global-search{position:relative;flex:1 1 360px;max-width:680px;min-width:0;display:flex;align-items:center}
.global-search-icon{position:absolute;left:.7rem;top:50%;transform:translateY(-50%);color:#64748B;display:flex;pointer-events:none}
.global-search-icon svg{width:16px;height:16px}
.global-search input{width:100%;height:40px;border-radius:var(--radius);border:1px solid #CBD5E1;background:#fff;color:#0F172A;
  font:500 .86rem var(--font-sans);padding:0 2.2rem 0 2.2rem;-webkit-appearance:none;appearance:none}
.global-search input::-webkit-search-cancel-button{display:none}
.global-search input::placeholder{color:#64748B}
.global-search input:focus{outline:2px solid #60A5FA;outline-offset:1px;border-color:#60A5FA}
.global-search-clear{position:absolute;right:.35rem;top:50%;transform:translateY(-50%);border:0;background:none;color:#64748B;
  font-size:1.2rem;line-height:1;width:30px;height:30px;border-radius:50%;cursor:pointer}
.global-search-clear:hover{background:#F1F5F9;color:#0F172A}
.global-search-results{position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:60;background:var(--card);color:var(--ink);
  border:1px solid var(--card-line);border-radius:var(--radius);box-shadow:0 12px 32px rgba(15,23,42,.18);max-height:min(70vh,520px);overflow-y:auto;padding:.3rem}
.gs-row{display:flex;align-items:flex-start;gap:.6rem;width:100%;text-align:left;border:0;background:none;color:inherit;cursor:pointer;
  padding:.55rem .6rem;border-radius:var(--radius-sm);font:inherit}
.gs-row:hover,.gs-row[aria-selected="true"]{background:var(--paper)}
.gs-row .ledger-badge{margin-top:.1rem;flex-shrink:0}
.gs-main{display:flex;flex-direction:column;min-width:0}
.gs-title{font-weight:700;font-size:.84rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gs-sub{font-size:.72rem;color:var(--ink-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gs-all{display:block;width:100%;text-align:left;border:0;border-top:1px solid var(--card-line);background:none;color:var(--accent);
  font:700 .78rem var(--font-sans);padding:.6rem .6rem .45rem;cursor:pointer;margin-top:.2rem}
.gs-status{padding:.8rem .7rem;font-size:.8rem;color:var(--ink-soft);display:flex;align-items:center;gap:.5rem}
.gs-spinner{width:14px;height:14px;border-radius:50%;border:2px solid var(--card-line);border-top-color:var(--accent);animation:gsSpin .8s linear infinite;flex-shrink:0}
@keyframes gsSpin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.gs-spinner{animation:none}}
.state-switch select{height:36px;border-radius:var(--radius-sm);border:1px solid var(--shell-line);background:#16203A;color:var(--shell-ink);
  font:600 .8rem var(--font-sans);padding:0 .5rem;max-width:150px}
.state-picker-btn{height:36px;border-radius:var(--radius-sm);border:1px solid var(--shell-line);background:transparent;color:var(--shell-ink);
  font:600 .78rem var(--font-sans);padding:0 .7rem;cursor:pointer}
.state-picker-btn:hover{background:rgba(255,255,255,.07)}
@media (max-width:640px){
  .topbar{padding:.5rem .6rem}
  .topbar .brand-name{display:none}
  .global-search{order:10;flex:1 1 100%;max-width:none}
  .state-picker-btn{display:none}
  .state-switch select{max-width:120px}
}

/* ---- Home ---- */
.home-hero{background:var(--card);border:1px solid var(--card-line);border-radius:var(--radius);padding:1.6rem 1.2rem 1.2rem;margin:1rem .6rem .8rem}
@media (min-width:1024px){ .home-hero{margin:1.2rem 0 1rem;padding:2.2rem 2rem 1.6rem} }
.home-title{color:var(--ink);font-size:1.6rem;font-weight:800;letter-spacing:-.02em;margin:0 0 .35rem}
@media (min-width:1024px){ .home-title{font-size:2.1rem} }
.home-sub{margin:0 0 1.1rem;color:var(--ink-soft);font-size:.95rem}
.home-search{display:flex;align-items:center;gap:.5rem;position:relative;max-width:820px}
.home-search-icon{position:absolute;left:.85rem;color:var(--ink-soft);display:flex;pointer-events:none}
.home-search-icon svg{width:18px;height:18px}
.home-search input{flex:1;min-width:0;height:50px;border-radius:var(--radius);border:1px solid var(--card-line);background:var(--paper);color:var(--ink);
  font:500 .95rem var(--font-sans);padding:0 1rem 0 2.6rem}
.home-search input:focus{outline:2px solid var(--c-auction);outline-offset:1px}
.home-search-btn{height:50px;border-radius:var(--radius);border:0;background:#0F172A;color:#fff;font:700 .9rem var(--font-sans);padding:0 1.3rem;cursor:pointer}
:root[data-theme="dark"] .home-search-btn{background:#E2E8F0;color:#0F172A}
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]) .home-search-btn{background:#E2E8F0;color:#0F172A} }
.home-scope{margin:.7rem 0 0;font-size:.78rem;color:var(--ink-soft)}
.home-ledgers{display:grid;gap:.75rem;margin:0 .6rem 1rem;grid-template-columns:1fr}
@media (min-width:640px){ .home-ledgers{grid-template-columns:1fr 1fr} }
@media (min-width:1280px){ .home-ledgers{grid-template-columns:1.25fr 1fr 1fr 1fr;margin:0 0 1.2rem} }
.home-ledger-card{display:flex;flex-direction:column;align-items:flex-start;gap:.2rem;text-align:left;cursor:pointer;
  background:var(--card);border:1px solid var(--card-line);border-top:3px solid var(--lc,#475569);border-radius:var(--radius);
  padding:1rem 1.1rem;color:var(--ink);font:inherit;min-height:168px}
.home-ledger-card:hover{border-color:color-mix(in srgb, var(--lc,#475569) 55%, var(--card-line));box-shadow:var(--shadow)}
.home-ledger-card:focus-visible{outline:2px solid var(--lc,#2563EB);outline-offset:2px}
.home-ledger-card.primary{background:color-mix(in srgb, var(--lc-soft) 45%, var(--card))}
.home-ledger-kicker{font-size:.68rem;font-weight:800;letter-spacing:.08em;color:var(--lc,var(--ink-soft))}
:root[data-theme="dark"] .home-ledger-kicker{color:var(--lc-d,var(--ink-soft))}
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]) .home-ledger-kicker{color:var(--lc-d,var(--ink-soft))} }
.home-ledger-count{font-family:var(--font-mono);font-weight:700;font-size:2rem;line-height:1.1;font-variant-numeric:tabular-nums}
.home-ledger-unit{font-size:.78rem;color:var(--ink-soft);font-weight:600}
.home-ledger-blurb{font-size:.76rem;color:var(--ink-soft);margin-top:.25rem;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.home-ledger-go{margin-top:auto;padding-top:.5rem;font-size:.8rem;font-weight:700;color:var(--lc,var(--accent))}
.home-states-card{--lc:#475569;--lc-d:#94A3B8}
.home-section{margin:0 .6rem 1.4rem}
@media (min-width:1024px){ .home-section{margin:0 0 1.6rem} }
.home-section-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:.55rem}
.home-section-head h2{margin:0;font-size:1rem;font-weight:800;color:var(--ink)}
.home-recent{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(230px,1fr);gap:.7rem;overflow-x:auto;padding-bottom:.3rem;scroll-snap-type:x proximity}
@media (min-width:1280px){ .home-recent{grid-auto-flow:row;grid-template-columns:repeat(3,1fr);overflow:visible} }
.home-recent-card{display:flex;flex-direction:column;text-align:left;background:var(--card);border:1px solid var(--card-line);border-radius:var(--radius);
  padding:0;overflow:hidden;cursor:pointer;color:var(--ink);font:inherit;scroll-snap-align:start}
.home-recent-card:hover{box-shadow:var(--shadow)}
.home-recent-card .prop-card-photo{margin:0;border-radius:0;max-height:120px}
.home-recent-body{display:flex;flex-direction:column;gap:.2rem;padding:.7rem .8rem .8rem}
.home-recent-title{font-weight:700;font-size:.86rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-recent-sub,.home-recent-when{font-size:.72rem;color:var(--ink-soft)}
.home-recent-amount{display:flex;justify-content:space-between;align-items:baseline;font-size:.72rem;color:var(--ink-soft);margin-top:.2rem}
.home-recent-amount b{font-family:var(--font-mono);font-size:.9rem;color:var(--ink)}
.home-recent-amount b.unpublished{font-family:var(--font-sans);font-size:.78rem;color:var(--ink-soft);font-weight:600}
.skel-card{padding:.7rem;gap:.5rem;cursor:default}
.skel-photo{height:96px}
.skel-line.short{width:55%}
.dash-title{margin:0 0 .2rem;font-family:var(--font-sans);font-weight:800;font-size:1.05rem;color:var(--ink)}

/* ---- List page head + filter chips (inside the dark masthead) ---- */
.list-head{display:flex;align-items:flex-end;justify-content:space-between;gap:.8rem;margin:.85rem 0 .4rem}
.list-title{font-size:1.35rem;font-weight:800;color:var(--header-ink);margin:0}
.list-sub{margin:.15rem 0 0;font-size:.78rem;color:var(--header-ink-soft)}
.list-map-btn{display:inline-flex;align-items:center;gap:.4rem;height:34px;padding:0 .8rem;border-radius:var(--radius-sm);border:1px solid var(--header-line);
  background:transparent;color:var(--header-ink);font:600 .78rem var(--font-sans);cursor:pointer;white-space:nowrap}
.list-map-btn svg{width:15px;height:15px}
.list-map-btn:hover{background:rgba(255,255,255,.07)}
.filter-chips{display:flex;flex-wrap:wrap;gap:.35rem;margin:.1rem 0 .6rem;align-items:center}
.filter-chips[hidden]{display:none}
.filter-chip{display:inline-flex;align-items:center;gap:.15rem;padding:.12rem .2rem .12rem .6rem;border-radius:999px;font-size:.74rem;font-weight:600;
  background:rgba(255,255,255,.1);color:var(--header-ink);border:1px solid rgba(255,255,255,.16)}
.filter-chip-x{border:0;background:none;color:var(--header-ink-soft);width:24px;height:24px;border-radius:50%;cursor:pointer;font-size:1rem;line-height:1}
.filter-chip-x:hover{background:rgba(255,255,255,.14);color:#fff}
.filter-chip-x:focus-visible,.filter-chip-clear:focus-visible{outline:2px solid #93C5FD;outline-offset:1px}
.filter-chip-clear{border:0;background:none;color:#93C5FD;font:700 .74rem var(--font-sans);cursor:pointer;padding:.2rem .4rem;text-decoration:underline;text-underline-offset:2px}

/* ---- card acquisition badge ---- */
.card-acq{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem .6rem;margin:.45rem 0 .1rem}
.acq-badge{display:inline-flex;align-items:center;padding:.15rem .55rem;border-radius:var(--radius-sm);font-size:.72rem;font-weight:700;
  background:var(--c-laft-soft);color:var(--c-laft);border:1px solid color-mix(in srgb, var(--c-laft) 30%, transparent)}
.acq-badge[data-acq="unverified"]{background:var(--warn-bg);color:var(--warn);border-color:color-mix(in srgb, var(--warn) 35%, transparent)}
.acq-badge[data-acq="none"]{background:var(--paper);color:var(--ink-soft);border-color:var(--card-line)}
.acq-note{font-size:.7rem;color:var(--ink-soft)}
:root[data-theme="dark"] .acq-badge:not([data-acq="unverified"]):not([data-acq="none"]){background:color-mix(in srgb, var(--c-laft) 22%, transparent);color:var(--c-laft-d)}
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]) .acq-badge:not([data-acq="unverified"]):not([data-acq="none"]){background:color-mix(in srgb, var(--c-laft) 22%, transparent);color:var(--c-laft-d)} }
.prop-card{border-radius:var(--radius)}

/* ---- property page: breadcrumb, tabs, why-seeing ---- */
.detail-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:.3rem;font-size:.74rem;color:var(--ink-soft);margin:0 2.2rem .5rem 0}
.crumb{border:0;background:none;padding:.15rem .1rem;color:var(--accent);font:600 .74rem var(--font-sans);cursor:pointer}
.crumb:hover{text-decoration:underline}
.crumb-here{color:var(--ink);font-weight:600;max-width:28ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.detail-nav{border-bottom:1px solid var(--card-line)}
.detail-nav button{border-radius:0;border:0;border-bottom:2px solid transparent;background:none}
.detail-nav button.on,.detail-nav button:hover{border-bottom-color:var(--accent);color:var(--accent);background:none}
.why-seeing{margin:.6rem 0 .8rem;border:1px solid var(--card-line);border-radius:var(--radius-sm);background:var(--paper);padding:.45rem .7rem}
.why-seeing summary{cursor:pointer;font-size:.78rem;font-weight:700;color:var(--ink)}
.why-seeing ul{margin:.45rem 0 .2rem;padding-left:1.1rem;font-size:.78rem;color:var(--ink-soft);display:flex;flex-direction:column;gap:.25rem}
.why-seeing b{color:var(--ink)}

/* ---- List layout: filters left, list centre, map / property right ---- */
.filters-sheet-head{display:none}
@media (min-width:1024px){
  .auctions-body>.filters-panel{grid-column:1 / -1;grid-row:1;margin:0}
  .auctions-body>.data-table-wrap,.auctions-body>#main{grid-row:2}
  .auctions-body>.detail-panel{grid-row:2}
}
/* Three columns only where the centre list keeps a readable width (>=1440px);
   below that the filters stay behind their toggle and the list gets the room. */
@media (min-width:1440px){
  .auctions-body{grid-template-columns:236px minmax(0,1fr) 360px}
  .auctions-body>.filters-panel{display:block;grid-column:1;grid-row:1;position:sticky;top:4.2rem;max-height:calc(100vh - 5rem);
    overflow-y:auto;box-shadow:none;border-radius:var(--radius);margin-top:1rem}
  .auctions-body>.data-table-wrap,.auctions-body>#main{grid-column:2;grid-row:1}
  .auctions-body>.detail-panel{grid-column:3;grid-row:1;margin-top:1rem;border-radius:var(--radius)}
  .quick-controls .filters-toggle{display:none}
  .auctions-body>.filters-panel .filters-row{flex-direction:column;align-items:stretch}
  .auctions-body>.filters-panel .field{flex:none;width:100%}
  .auctions-body>.filters-panel .price-range-display{flex-wrap:wrap}
  .auctions-body>.filters-panel .filters-section-head{flex-wrap:wrap}
}
@media (min-width:1700px){ .auctions-body{grid-template-columns:256px minmax(0,1fr) 420px} }
/* Phone / tablet: the panel opens in place, between the controls and the
   list, with its own header and close button - a fixed sheet would cover
   the controls that are used with it open. */
@media (max-width:1023.98px){
  .auctions-body>.filters-panel{margin:.5rem .6rem}
  .auctions-body>.filters-panel.open .filters-sheet-head{display:flex;align-items:center;justify-content:space-between;
    padding:.1rem 0 .5rem;margin-bottom:.5rem;border-bottom:1px solid var(--card-line);font-weight:800;font-size:.95rem;color:var(--ink)}
}
.sheet-close{border:0;background:none;color:var(--ink-soft);font-size:1.4rem;line-height:1;width:36px;height:36px;border-radius:50%;cursor:pointer}
.sheet-close:hover{background:var(--paper);color:var(--ink)}

/* ---- List county panel (wide desktop, nothing selected) ---- */
.list-county-panel{display:flex;flex-direction:column;gap:.5rem}
.lcp-head{display:flex;flex-direction:column;gap:.1rem}
.lcp-head b{font-size:.9rem;color:var(--ink)}
.lcp-head span{font-size:.74rem;color:var(--ink-soft)}
.lcp-map svg{width:100%;height:auto;max-height:52vh;display:block}
.lcp-map path{fill:var(--paper);stroke:var(--card-line);stroke-width:.8;vector-effect:non-scaling-stroke}
.lcp-map path.has{fill:color-mix(in srgb, var(--accent) calc(var(--lcp-level) * 100%), var(--card));cursor:pointer}
.lcp-map path.has:hover,.lcp-map path.has:focus{stroke:var(--ink);stroke-width:1.6;outline:none}
.lcp-legend{display:flex;align-items:center;gap:.4rem;font-size:.68rem;color:var(--ink-soft)}
.lcp-ramp{flex:0 0 90px;height:8px;border-radius:4px;background:linear-gradient(to right, color-mix(in srgb, var(--accent) 25%, var(--card)), var(--accent))}
.list-county-panel + .detail-panel-empty{padding:1rem .5rem 0}

/* ---- sheets (state picker) ---- */
.sheet-backdrop{position:fixed;inset:0;background:rgba(2,6,23,.5);z-index:80}
.sheet-backdrop[hidden],.sheet[hidden]{display:none}
.sheet{position:fixed;z-index:81;background:var(--card);color:var(--ink);display:flex;flex-direction:column;
  left:0;right:0;bottom:0;max-height:86vh;border-radius:14px 14px 0 0;box-shadow:0 -12px 40px rgba(2,6,23,.4)}
@media (min-width:768px){ .sheet{left:50%;right:auto;top:8vh;bottom:auto;width:min(620px,92vw);transform:translateX(-50%);border-radius:var(--radius);max-height:84vh} }
.sheet-head{display:flex;align-items:center;justify-content:space-between;padding:.8rem 1rem .4rem}
.sheet-head h2{margin:0;font-size:1.05rem;font-weight:800;color:var(--ink)}
.sheet-search{padding:0 1rem .6rem}
.sheet-search input{width:100%;height:42px;border-radius:var(--radius-sm);border:1px solid var(--card-line);background:var(--paper);color:var(--ink);font:500 .88rem var(--font-sans);padding:0 .8rem}
.sheet-search input:focus{outline:2px solid var(--c-auction);outline-offset:1px}
.state-picker-body{overflow-y:auto;padding:0 1rem 1rem}
.state-group-head{font-size:.68rem;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-soft);margin:.8rem 0 .35rem}
.state-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.4rem .8rem;padding:.6rem .2rem;border-bottom:1px solid var(--card-line)}
.state-row.current{background:color-mix(in srgb, var(--c-auction) 6%, transparent)}
.state-row-name{display:inline-flex;align-items:center;gap:.45rem;font-weight:700;font-size:.9rem;color:var(--ink);text-decoration:none}
.state-row-name:hover{text-decoration:underline}
.state-row-code{font-family:var(--font-mono);font-size:.7rem;color:var(--ink-soft);font-weight:600}
.state-row-here{font-size:.64rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--c-auction)}
.state-row-ledgers{display:flex;flex-wrap:wrap;gap:.3rem;align-items:center}
.state-row-none{font-size:.72rem;color:var(--ink-soft)}
.state-picker-note{font-size:.72rem;color:var(--ink-soft);margin:.8rem 0 0}

/* ---- phone bottom bar: five entries ---- */
@media (max-width:1023.98px){
  .nav-bottom{background:var(--shell-bg);border-top-color:var(--shell-line)}
  .nav-bottom-item{color:var(--shell-ink-soft);font-size:.64rem;min-height:48px}
  .nav-bottom-item.on{color:#fff}
  .nav-bottom-item.on svg{color:#60A5FA}
  .nav-bottom-item:focus-visible{outline:2px solid #93C5FD;outline-offset:-2px}
}
#lcpOpenMap,#homeRecentAll,#homeChangeState{font-size:.8rem;font-weight:700}
/* Tablet (768-1023px): use the width - the phone column was 680px. */
@media (min-width:768px) and (max-width:1023.98px){
  body{max-width:none}
  .page{max-width:none}
  #main .prop-list:not(.flat){display:grid;grid-template-columns:1fr 1fr;gap:.7rem;align-items:start}
}

/* Inside the three-column List the centre column is narrower than the old
   full-width list: certificate cards stack instead of using their one-row
   desktop layout, and card pill rows wrap instead of clipping. */
@media (min-width:1440px){
  [data-ledger="certificate"] .auctions-body .cert-card{display:flex;flex-direction:column;align-items:stretch}
  [data-ledger="certificate"] .auctions-body .cert-card .cert-stat-grid{grid-template-columns:repeat(2,minmax(0,1fr));flex:none}
  [data-ledger="certificate"] .auctions-body .cert-card .cta-btn,[data-ledger="certificate"] .auctions-body .cert-card .detail-btn{width:100%}
}
.prop-top-actions{flex-wrap:wrap;flex-shrink:1;min-width:0;max-width:100%}
/* Card grids never ask for more than their column: the List column is
   narrower beside the filters / county panel than the old full-width list. */
@media (min-width:1024px){
  .prop-list{grid-template-columns:repeat(auto-fill,minmax(min(330px,100%),1fr))}
  [data-ledger="laft"] .prop-list{grid-template-columns:repeat(auto-fill,minmax(min(360px,100%),1fr))}
  [data-ledger="certificate"] .prop-list,[data-ledger="auction"] .prop-list{grid-template-columns:1fr}
}
/* Small laptops (1024-1279px): the side column gives the list the room. */
@media (min-width:1024px) and (max-width:1279.98px){
  .auctions-body{grid-template-columns:minmax(0,1fr) 300px}
  .app-shell{grid-template-columns:220px minmax(0,1fr)}
}

/* Available price honesty (2026-10-05): an opening bid is never shown as the
   price to buy now; the note under it says what the county's total adds, or
   how current the county's purchase statement is. */
.card-stat-val.partial{color:var(--ink-soft)}
.card-price-note{margin-top:.3rem;font-size:.72rem;line-height:1.35;color:var(--ink-soft)}
.card-price-note.expired{color:var(--warn)}
/* 2026-10-05 Available amount semantics: what a figure is, what the clerk adds,
   the official total (current / expired), the forms. */
.card-stat-val.expired{color:var(--warn)}
.acq-cost .acq-amt{font-weight:700;font-variant-numeric:tabular-nums}
.acq-cost .acq-amt.ok{color:var(--ok)}
.acq-sub{display:block;margin-top:.15rem;font-size:.74rem;line-height:1.35;color:var(--ink-soft)}
.acq-adds,.acq-history,.acq-forms{margin:0;padding-left:1.1rem}
.acq-adds li,.acq-history li{margin:.12rem 0}
.acq-adds li b{font-variant-numeric:tabular-nums}
.acq-adds li b.muted{color:var(--ink-soft);font-weight:600}
.acq-forms{list-style:none;padding-left:0;margin:.2rem 0 .5rem;font-size:.8rem}
.acq-form{padding:.35rem 0;border-bottom:1px solid var(--card-line)}
.acq-form:last-child{border-bottom:0}
.acq-form-req{display:inline-block;margin-left:.35rem;padding:.05rem .4rem;border-radius:999px;font-size:.7rem;background:var(--card-line);color:var(--ink-soft)}
.acq-form-req.req{background:var(--bad-bg);color:var(--bad);font-weight:700}
.dt-sub{display:block;font-size:.68rem;color:var(--ink-soft);font-weight:400}
.pv-amount-note{display:block;font-size:.68rem;line-height:1.3;color:var(--ink-soft);font-weight:400;margin-top:.15rem}
/* ==================== paid beta: plan screen, billing, legal links (2026-10-05) ==================== */
#planGate #planSubscribeBtn{width:100%;margin-top:.8rem}
.plan-state{font-size:.9rem;margin:0 0 .9rem}
.plan-card{border:1px solid var(--card-line);border-radius:10px;padding:.9rem 1rem;background:var(--card)}
.plan-name{font-weight:700;font-size:1.02rem}
.plan-price{font-size:1.3rem;font-weight:700;margin:.2rem 0 .4rem}
.plan-scope{font-size:.8rem;color:var(--ink-soft);margin:0}
.plan-unconfigured{border:1px dashed var(--card-line);border-radius:10px;padding:.8rem 1rem;font-size:.85rem;color:var(--ink-soft)}
.plan-tester-note{font-size:.78rem;color:var(--ink-soft);margin:.9rem 0 0}
.auth-legal-links,.terms-legal-links{font-size:.75rem;color:var(--ink-soft);margin:.9rem 0 0;text-align:center;line-height:1.6}
.auth-legal-links a,.terms-legal-links a{color:inherit}
.terms-legal-links{text-align:left}
.billing-list{margin:0 0 1rem;display:grid;gap:.45rem}
.billing-row{display:grid;grid-template-columns:minmax(7rem,30%) 1fr;gap:.75rem;font-size:.88rem}
.billing-row dt{color:var(--ink-soft);margin:0}
.billing-row dd{margin:0}
@media (max-width:480px){.billing-row{grid-template-columns:1fr;gap:.1rem}}
.admin-customers{overflow-x:auto}
.admin-customers-table td,.admin-customers-table th{text-align:left !important;vertical-align:top}
.admin-sub{color:var(--ink-soft);font-size:.74rem}

/* Home first-run guide (2026-10-05). */
.home-guide{margin:0 0 1rem;padding:.8rem 1rem;border:1px solid var(--card-line);border-radius:10px;background:var(--card)}
.home-guide.collapsed{padding:0;border:0;background:none}
.home-guide-head{display:flex;justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:.4rem}
.home-guide-steps{list-style:none;margin:0;padding:0;display:grid;gap:.5rem;grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.home-guide-step{display:flex;gap:.55rem;align-items:flex-start;font-size:.84rem;line-height:1.4;color:var(--ink-soft)}
.home-guide-step b{color:var(--ink)}
.home-guide-num{flex:0 0 1.5rem;height:1.5rem;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:700;font-size:.78rem;background:var(--ink);color:var(--card)}
.home-guide-collapsed{margin:0 0 .6rem}

/* ---- acquisition checklist, source truth, county intelligence (2026-10-05) ---- */
.acq-checklist-wrap{border:1px solid var(--card-line);border-radius:10px;padding:.55rem .7rem;margin:0 0 .8rem}
.acq-checklist-head{display:flex;justify-content:space-between;align-items:baseline;gap:.5rem;font-size:.82rem;margin-bottom:.35rem}
.acq-checklist-head span{color:var(--ink-soft);font-size:.74rem}
.acq-checklist{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.25rem .9rem;font-size:.78rem}
.acq-checklist li{display:grid;grid-template-columns:minmax(0,7.2rem) minmax(0,1fr);gap:.1rem .5rem;padding:.25rem 0;border-top:1px dashed var(--card-line);align-items:start}
.acq-checklist li[data-check="not_published"]{grid-column:1/-1}
.acq-checklist .ck-label{color:var(--ink-soft);font-weight:600}
.acq-checklist .ck-val{overflow-wrap:anywhere}
.acq-checklist .ck-sub{display:block;color:var(--ink-soft);font-size:.72rem}
.acq-checklist .ck-state{grid-column:2;justify-self:start;font-size:.68rem;padding:.05rem .4rem;border-radius:999px;background:var(--warn-bg,rgba(200,140,0,.12));color:var(--warn,#9a6700)}
.acq-checklist li[data-check-state="not_published"] .ck-val,.acq-checklist li[data-check-state="not_verified"] .ck-val{color:var(--ink-soft)}
.acq-checklist li[data-check-state="summary"] .ck-val{color:var(--ink)}
@media (max-width:640px){ .acq-checklist{grid-template-columns:1fr} }
.truth-dl{display:grid;grid-template-columns:minmax(0,9rem) minmax(0,1fr);gap:.3rem .7rem;margin:0;font-size:.8rem}
.truth-dl dt{color:var(--ink-soft);font-weight:600}
.truth-dl dd{margin:0;overflow-wrap:anywhere}
.truth-dl .kv-sub{display:block;color:var(--ink-soft);font-size:.74rem;margin-top:.15rem}
@media (max-width:480px){ .truth-dl{grid-template-columns:1fr} .truth-dl dd{margin-bottom:.35rem} }
.health-chip,.intel-chip{display:inline-block;font-size:.72rem;font-weight:600;padding:.08rem .5rem;border-radius:999px;border:1px solid var(--card-line);white-space:nowrap}
.health-chip.ok,.intel-chip.ok{background:var(--ok-bg,rgba(0,140,70,.12));color:var(--ok,#137a3f);border-color:transparent}
.health-chip.warn,.intel-chip.warn{background:var(--warn-bg,rgba(200,140,0,.12));color:var(--warn,#9a6700);border-color:transparent}
.health-chip.bad,.intel-chip.bad{background:var(--bad-bg,rgba(200,40,40,.12));color:var(--bad,#b42318);border-color:transparent}
.health-chip.muted,.intel-chip.muted{color:var(--ink-soft)}
.county-intel-row{padding:.15rem .9rem .35rem;font-size:.76rem}
.county-modal-inner{max-width:720px}
.dossier h3{font-size:.9rem;margin:1rem 0 .35rem}
.dossier-head{display:flex;flex-direction:column;gap:.35rem}
.dossier-head p{margin:0}
.dossier-ledger{border:1px solid var(--card-line);border-radius:10px;padding:.55rem .7rem;margin:.45rem 0}
.dl-head{display:flex;flex-wrap:wrap;gap:.35rem .7rem;align-items:baseline}
.dl-cov{font-size:.74rem;font-weight:600}
.dossier-ledger[data-coverage="COVERED"] .dl-cov{color:var(--ok,#137a3f)}
.dossier-ledger[data-coverage="SOURCE_UNAVAILABLE"] .dl-cov{color:var(--bad,#b42318)}
.dossier-ledger[data-coverage="PARTIALLY_COVERED"] .dl-cov,.dossier-ledger[data-coverage="RESEARCH_ONLY"] .dl-cov{color:var(--warn,#9a6700)}
.dossier-ledger[data-coverage="NO_SOURCE_BACKED_INVENTORY"] .dl-cov{color:var(--ink-soft)}
.dl-count{margin-left:auto;font-size:.74rem;color:var(--ink-soft)}
.dl-text{margin:.25rem 0;font-size:.78rem;color:var(--ink-soft)}
.dossier-srcs{list-style:none;margin:.3rem 0;padding:0;display:flex;flex-direction:column;gap:.45rem}
.dossier-src{font-size:.8rem}
.ds-meta,.ds-health-text{color:var(--ink-soft);font-size:.74rem}
.ds-health{display:flex;flex-wrap:wrap;gap:.3rem;align-items:baseline;margin-top:.15rem}
.dossier-note{font-size:.74rem;color:var(--ink-soft);margin-top:1rem}

/* ---- understood search, research queue, coverage explorer, why (2026-10-05) ---- */
.gs-nq{display:flex;flex-wrap:wrap;align-items:center;gap:.3rem .4rem;padding:.5rem .7rem;border-bottom:1px solid var(--card-line);font-size:.78rem}
.gs-nq-lead{color:var(--ink-soft);font-weight:600}
.gs-nq-chip{padding:.08rem .5rem;border-radius:999px;background:var(--accent-soft,rgba(37,99,235,.1));border:1px solid var(--card-line)}
.gs-nq-apply{margin-left:auto;font-size:.78rem;font-weight:600;background:none;border:0;color:var(--accent,#2563eb);cursor:pointer;min-height:32px}
.gs-nq-note{flex-basis:100%;color:var(--ink-soft);font-size:.72rem}
.research-queue{border:1px solid var(--card-line);border-radius:10px;padding:.5rem .7rem;margin:0 0 .8rem;font-size:.8rem}
.research-queue summary{cursor:pointer}
.research-queue > ul{list-style:none;margin:.4rem 0 0;padding:0;display:flex;flex-direction:column;gap:.45rem}
.rq-ledger{margin-left:.4rem;font-size:.72rem;color:var(--ink-soft)}
.rq-items{margin:.15rem 0 0 1rem;padding:0;color:var(--ink-soft);font-size:.76rem}
.rq-note{font-size:.72rem;margin:.4rem 0 0}
.coverage-explorer{margin-top:.8rem}
.cov-summary{display:flex;flex-wrap:wrap;gap:.35rem .7rem;margin:.3rem 0 .5rem;font-size:.78rem}
.cov-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(13rem,1fr));gap:.25rem .8rem;font-size:.8rem}
.cov-list li{display:flex;align-items:center;gap:.4rem;justify-content:space-between}
.cov-note{font-size:.74rem}
.why-list{margin:.3rem 0 .8rem 1.1rem;padding:0;display:flex;flex-direction:column;gap:.35rem}
