/* App shell — the County hub, from the TractCue Screens canvas.
   Tokens match the TractCue Identity system the canvas installs. Fonts are the
   self-hosted ones: the canvas artboards link Google Fonts, which this site
   deliberately does not. */
/* Tokens live in tokens.css (linked before this file). */
*{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--text);
  font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased}
a{color:var(--signal);text-decoration:none}
a:hover{color:var(--signal-d);text-decoration:underline}
:focus-visible{outline:2px solid var(--rule-strong);outline-offset:2px}

.app{display:flex;min-height:100vh;align-items:stretch}

/* ---------------------------------------------------------------- sidebar */
.side{width:236px;flex:none;border-right:1px solid var(--rule);
  background:var(--surface);display:flex;flex-direction:column}
.side .brand{display:flex;align-items:center;gap:10px;padding:20px;
  border-bottom:1px solid var(--rule);color:var(--ink);text-decoration:none}
.side .brand span{font-family:var(--display);font-size:20px;font-weight:600;
  letter-spacing:-.01em}
.side nav{display:flex;flex-direction:column;gap:1px;padding:14px 12px}
.side nav a,.side nav .soon{display:flex;align-items:center;gap:8px;
  padding:9px 10px;border-radius:3px;font-size:14px;color:var(--ink);
  text-decoration:none}
.side nav a:hover{background:var(--tint);color:var(--signal);text-decoration:none}
/* an unbuilt screen is named and marked, never a dead link */
.side nav .soon{color:var(--muted);cursor:default}
.side nav .soon i{margin-left:auto;font-style:normal;font-size:10px;
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted);
  border:1px solid var(--rule);border-radius:999px;padding:1px 6px}
.sect{padding:10px 20px 6px;font-size:11px;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted)}
.mine{display:flex;flex-direction:column;padding:0 12px}
.mine a{display:flex;justify-content:space-between;align-items:baseline;gap:8px;
  padding:7px 10px;border-radius:3px;font-size:13px;color:var(--ink);
  text-decoration:none}
.mine a:hover{background:var(--tint);color:var(--signal)}
.mine a.on{background:var(--tint);color:var(--signal);font-weight:600}
.mine b{font-family:var(--record);font-size:12px;font-weight:400;color:var(--muted)}
.mine a.on b{color:var(--signal)}
.side .foot{margin-top:auto;border-top:1px solid var(--rule);padding-bottom:16px}
.side .foot p{margin:0;padding:0 20px;font-size:13px;color:var(--muted)}

/* ------------------------------------------------------------------- main */
main{flex:1;min-width:0;display:flex;flex-direction:column}
.crumb{padding:12px 32px;border-bottom:1px solid var(--rule);
  background:var(--surface);font-size:13px;color:var(--muted)}
.crumb span{margin:0 8px}
.crumb b{color:var(--ink)}

.hdr{display:flex;gap:32px;align-items:flex-start;padding:22px 32px 18px;
  border-bottom:1px solid var(--rule);flex-wrap:wrap}
.hdr>div:first-child{flex:1;min-width:0}
.ttl{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.hdr h1{margin:0;font-family:var(--display);font-size:38px;font-weight:600;
  line-height:1.1;letter-spacing:-.015em}
.hdr .sub{margin-top:8px;font-size:13px;color:var(--muted)}
.acts{display:flex;gap:8px;flex:none;flex-wrap:wrap}
.btn{display:inline-block;padding:9px 14px;border-radius:3px;font-size:13px;
  font-weight:600;background:var(--signal);color:var(--paper);
  border:1px solid var(--signal);text-decoration:none}
.btn:hover{background:var(--signal-d);border-color:var(--signal-d);
  color:var(--paper);text-decoration:none}
.btn.ghost{background:transparent;color:var(--ink);border-color:var(--rule-strong)}
.btn.ghost:hover{background:var(--surface);color:var(--ink)}
.chip{display:inline-block;padding:4px 10px;border-radius:3px;color:var(--paper);
  font-size:11px;font-weight:600;letter-spacing:.06em;white-space:nowrap}

/* issuer strip: coverage honesty sits above the numbers it qualifies */
.issuers{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:20px;padding:14px 32px;border-bottom:1px solid var(--rule);
  background:var(--surface)}
.iss .ln{display:flex;align-items:center;gap:7px}
.iss .dot{width:8px;height:8px;border-radius:999px;flex:none;display:inline-block}
.iss .nm{font-size:13px;font-weight:600}
.iss .dt{font-size:12px;color:var(--muted);margin-top:3px}
.iss .mo{font-family:var(--record);font-size:11px;color:var(--muted);margin-top:2px}

.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:24px;padding:20px 32px;border-bottom:1px solid var(--rule)}
.stats .lb{font-size:11px;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted)}
.stats .vl{font-family:var(--display);font-size:31px;font-weight:600;
  line-height:1.15;margin-top:2px}
.stats .sb{font-size:12px;color:var(--muted)}

.cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(440px,1fr));
  gap:40px;padding:24px 32px 8px}
.h2{display:flex;align-items:baseline;gap:12px;padding-bottom:8px;
  border-bottom:2px solid var(--ink)}
.h2 h2{margin:0;font-family:var(--display);font-size:23px;font-weight:600}
.h2 .note{font-size:12px;color:var(--muted)}
.h2 .more{margin-left:auto;font-size:13px;font-weight:600}

table{width:100%;border-collapse:collapse;font-size:13px;margin-top:4px}
th{text-align:left;padding:8px;font-size:11px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--rule)}
td{padding:9px 8px;border-bottom:1px solid var(--rule);vertical-align:top}
th:first-child,td:first-child{padding-left:0}
th:last-child,td:last-child{padding-right:0}
.n{text-align:right}
.mono{font-family:var(--record);font-size:12px;white-space:nowrap}
.m2{color:var(--muted)}
td.w{word-break:break-word}

.tag{display:inline-block;padding:2px 7px;border-radius:3px;font-size:11px;
  font-weight:600;white-space:nowrap}
.tag.fill{background:var(--ink);color:var(--paper)}
.tag.open{background:var(--tint);color:var(--signal);border:1px solid var(--signal)}
.tag.quiet{background:var(--surface);color:var(--muted);border:1px solid var(--rule)}
.tag.v-lic{background:var(--green);color:var(--paper)}
.tag.v-rec{background:transparent;color:var(--green);border:1px solid var(--green)}

/* the honest-gap block: an empty table would read as "nothing happens here" */
.gap{margin-top:14px;background:var(--surface);border:1px solid var(--rule);
  border-left:3px solid var(--amber);border-radius:3px;padding:14px 16px}
.gap b{display:block;font-size:13px}
.gap p{margin:6px 0 0;font-size:13px;color:var(--muted)}

.fine{font-size:12px;color:var(--muted);margin:10px 0 0}
.fine.pad{padding:8px 32px 28px}

@media (max-width:900px){
  .app{flex-direction:column}
  .side{width:auto;border-right:0;border-bottom:1px solid var(--rule)}
  .side .foot{margin-top:0}
  .crumb,.hdr,.issuers,.stats,.cols,.fine.pad{padding-left:16px;padding-right:16px}
  .cols{grid-template-columns:minmax(0,1fr);gap:28px}
  .hdr h1{font-size:30px}
}

/* ------------------------------------------------------------- feed screen */
.side nav a.on{background:var(--tint);color:var(--signal);font-weight:600}
.lensbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:12px 32px;border-bottom:1px solid var(--rule);background:var(--surface)}
.lensbar .lb{font-size:11px;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);margin-right:4px}
.lens{padding:5px 11px;border-radius:999px;border:1px solid var(--rule-strong);
  background:transparent;color:var(--ink);font-family:var(--text);font-size:12px;
  cursor:pointer;line-height:1.4}
.lens b{font-weight:400;color:var(--muted);font-family:var(--record);font-size:11px}
.lens:hover{border-color:var(--signal);color:var(--signal)}
.lens.on{background:var(--signal);border-color:var(--signal);color:var(--paper);
  font-weight:600}
.lens.on b{color:var(--paper);opacity:.8}

.feedwrap{flex:1;display:flex;align-items:stretch;min-height:0}
.feed{flex:1;min-width:0;padding:0 32px 28px}
.grp{margin-top:22px}
.grp .h2 .note{margin-left:0}
.grp .h2 .chip{font-size:10px;padding:3px 8px}

.rail{width:320px;flex:none;border-left:1px solid var(--rule);
  background:var(--surface);padding:20px}
.rl{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted)}
.rs{font-size:12px;color:var(--muted);margin:4px 0 12px}
.rsep{height:1px;background:var(--rule);margin:22px 0}
.slots{display:flex;flex-direction:column}
.slot{display:flex;align-items:baseline;gap:10px;padding:8px 0;
  border-bottom:1px solid var(--rule)}
.slot .sl{flex:1;min-width:0}
.sb1{font-size:13px;word-break:break-word}
.sb2{font-size:12px;color:var(--muted)}
.sn{font-family:var(--record);font-size:13px;font-weight:500;color:var(--signal)}
.fresh{display:flex;flex-direction:column}
.fr{display:flex;justify-content:space-between;align-items:baseline;gap:8px;
  padding:6px 0;border-bottom:1px solid var(--rule);font-size:13px}
.fd{font-family:var(--record);font-size:12px;color:var(--muted)}

@media (max-width:1100px){
  .feedwrap{flex-direction:column}
  .rail{width:auto;border-left:0;border-top:1px solid var(--rule)}
  .feed{padding-left:16px;padding-right:16px}
  .lensbar{padding-left:16px;padding-right:16px}
}

/* --------------------------------------------------------------- sign-in */
.acct{font-size:12px;color:var(--muted);word-break:break-word}
.acct .who{display:block}
.acct .out{font-size:12px}
.login{max-width:30rem;margin:0 auto;padding:56px 20px 64px}
.login .brand{display:flex;align-items:center;gap:10px;color:var(--ink);
  text-decoration:none;margin-bottom:28px}
.login .brand span{font-family:var(--display);font-size:22px;font-weight:600}
.login h1{font-family:var(--display);font-size:34px;font-weight:600;margin:0 0 8px}
.login .lede{color:var(--muted);margin:0 0 18px}
.login .note{min-height:20px;font-size:13px;margin:0 0 12px}
.login label{display:block;font-size:13px;font-weight:500;color:var(--muted);
  margin:0 0 14px}
.login input{display:block;width:100%;margin-top:5px;padding:10px;
  font-family:var(--text);font-size:15px;color:var(--ink);background:var(--paper);
  border:1px solid var(--rule-strong);border-radius:3px}
.login button{border:0;cursor:pointer;font-family:var(--text)}
.login .fine{margin-top:14px}

/* call to action on the teaser screens */
.cta{display:flex;gap:24px;align-items:center;flex-wrap:wrap;margin:8px 32px 24px;
  padding:20px 24px;background:var(--tint);border:1px solid var(--rule);
  border-radius:3px}
.cta>div{flex:1;min-width:260px}
.cta h2{margin:0 0 6px;font-family:var(--display);font-size:22px;font-weight:600}
.cta p{margin:0;font-size:13px;color:var(--muted);max-width:60ch}
@media (max-width:900px){.cta{margin-left:16px;margin-right:16px}}

/* ---------------------------------------------------------------------------
   Rendering standard, 19 September 2026.

   The binding number is acceptance #2: at 1366x768 every app page must show at
   least 420px of table rows below the sticky chrome. Measured before this
   block existed, /app/feed gave 350px — 418px of chrome above the first row,
   54% of the screen spent before any data. That is precisely the failure mode
   the standard describes, and it was built the way the standard warns against:
   a 38px display headline and a 31px stat band, both sized for a marketing
   page, competing with the rows for vertical space and winning.

   The constraint is vertical. Everything below buys height back.
   --------------------------------------------------------------------------- */

/* Chrome height, in one place, so the sticky table header knows where to stop.
   Two values because the stat band collapses on short screens. */
.app{--chrome:74px}
@media (max-height:799px){ .app{--chrome:66px} }

/* The sidebar scrolls itself. Without this a long "counties held" list makes
   the page taller than the viewport and the sticky header has nothing to stick
   against. */
@media (min-width:901px){
  .side{position:sticky;top:0;height:100vh;overflow-y:auto}
}

/* Header inside the 56px budget at short viewports. The subtitle stays: on the
   foreclosure page it is the line that says no notices are loaded, and dropping
   honest framing to save 18px is the wrong trade. */
main>.hdr{position:sticky;top:0;z-index:12;background:var(--paper);
  padding:12px 32px;gap:20px;align-items:center;
  border-bottom:1px solid var(--rule)}
.hdr h1{font-size:23px;line-height:29px}
.hdr .sub{margin-top:3px;line-height:17px}
@media (max-height:799px){
  main>.hdr{padding:7px 32px}
  .hdr h1{font-size:20px;line-height:25px}
  .hdr .sub{margin-top:2px}
}

/* Stat band: 72px budget, collapsing to a single summary line below 800px of
   viewport height. Acceptance #3. The numbers stay readable; what goes is the
   vertical stacking and the sub-labels, which are the expensive part. */
.stats{padding-top:10px;padding-bottom:10px}
.stats .vl{font-size:26px;line-height:31px}
@media (max-height:799px){
  .stats{display:flex;flex-wrap:nowrap;overflow-x:auto;white-space:nowrap;
    gap:0 24px;padding:4px 32px;align-items:baseline;border-bottom:1px solid var(--rule)}
  .stats>div{display:flex;align-items:baseline;gap:6px;padding:0;border:0;
    flex:none}
  .stats .lb{font-size:11px;letter-spacing:.06em}
  .stats .vl{font-family:var(--text);font-size:15px;line-height:20px;font-weight:600}
  .stats .sb{display:none}
}

/* Sticky table head, 36px, parked under the header. */
thead th{position:sticky;top:var(--chrome);z-index:6;background:var(--paper);
  padding:7px 8px;box-shadow:inset 0 -1px 0 var(--rule)}
td{padding:7px 8px}

/* Column priority. Dropped in the order the standard sets as width shrinks;
   address, work type, date and permit number always survive. */
/* Column priority, per the rendering standard: district, lot, fees, square
   footage, subdivision, valuation — dropped in that order as width shrinks,
   with address, work type, date and permit number always kept.

   Only the last two of those six exist as columns in this product. There is no
   district, lot, fee or square-footage column anywhere, so drop-1 and drop-2
   are defined and bind to nothing today; they are here so the order is written
   down once rather than rediscovered when those fields land. A class goes on
   the th AND every matching td, or the column misaligns the moment it hides. */
@media (max-width:1500px){ .drop-1{display:none} }   /* district, lot */
@media (max-width:1320px){ .drop-2{display:none} }   /* fees, square footage */
@media (max-width:1180px){ .drop-3{display:none} }   /* subdivision */
@media (max-width:1060px){ .drop-4{display:none} }   /* valuation */

/* Right rail below the main column at lg rather than compressed into it.
   `.cols` is the two-column section grid the feed and county pages use. */
@media (max-width:1279px){
  /* minmax(0,1fr), not 1fr: a bare 1fr track has an implicit min-content floor,
     so a wide table inside a section held the column at 407px in a 360px
     viewport and scrolled the page sideways. */
  .cols{grid-template-columns:minmax(0,1fr)}
}

/* sm: the page body never scrolls sideways — the table does, inside its own
   box, with the first column pinned so a row stays identifiable. */
@media (max-width:900px){
  main>.hdr{position:static}
  .stats{padding-left:20px;padding-right:20px}
  /* `main table`, not `section>table`: the feed's tables are not direct
     children of a section, so the narrower selector missed them and a 496px
     table scrolled the whole page sideways at 360. */
  main table{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;
    max-width:100%}
  /* .h2 is a non-wrapping flex row; a long section title pushed the "see all"
     link past the viewport edge and scrolled the body by 13px. */
  .h2{flex-wrap:wrap;gap:6px 12px}
  main table thead th{position:static}
  main table td:first-child,main table th:first-child{
    position:sticky;left:0;background:var(--paper);z-index:2}
}

/* Stat band toggle. The band collapses below 800px of viewport height to
   protect the row budget; this is the "expandable on click" half of that rule.

   The button exists in the DOM at every size (the script adds it once) but is
   only shown where there is something to expand — at tall viewports the band is
   already full, so a control offering to expand it would be a lie. */
.statx{display:none}
@media (max-height:799px){
  /* PINNED, NOT MERELY PUSHED. `margin-left:auto` puts the toggle after the
     last stat — which in a 360px viewport is 741px along a band that scrolls
     sideways, so the control that expands the band could only be found by
     first discovering the band scrolls. Sticky holds it against the right edge
     of the scrollport at every width; the paper background and the soft edge
     keep the stats from sliding out from under it. */
  .statx{display:inline-flex;align-items:center;flex:none;
    margin-left:auto;align-self:center;
    position:sticky;right:0;background:var(--paper);
    box-shadow:-12px 0 10px -6px var(--paper);
    min-height:28px;padding:0 10px;border:1px solid var(--rule-strong);
    border-radius:999px;background:transparent;color:var(--muted);
    font-family:var(--text);font-size:11px;font-weight:600;letter-spacing:.06em;
    text-transform:uppercase;cursor:pointer;line-height:1}
  .statx:hover{color:var(--signal);border-color:var(--signal)}
  .statx:focus-visible{outline:2px solid var(--signal);outline-offset:2px}

  /* expanded: back to the full grid, exactly as it renders on a tall screen */
  main .stats.open{display:grid;
    grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
    white-space:normal;overflow:visible;padding:10px 32px;gap:0}
  main .stats.open>div{display:block;flex:initial}
  main .stats.open .vl{font-family:var(--display);font-size:26px;line-height:31px}
  main .stats.open .sb{display:block}
  main .stats.open .statx{position:absolute;right:32px;margin-top:-34px}
}

/* Nav icons. They sit alongside the label at full width and carry the item on
   their own at rail width. */
.side nav a,.side nav .soon{gap:10px}
.side .ni{flex:none;opacity:.75}
.side nav a.on .ni{opacity:1}
.side nav .nl{display:inline-flex;align-items:center;gap:8px;min-width:0}

/* ---- lg: 64px icon rail -------------------------------------------------
   Standard, breakpoints table: "lg (1024-1279): Sidebar collapses to 64px icon
   rail." Between 1024 and 1279 a 236px sidebar plus a two-column main is more
   chrome than content; the rail buys ~170px back for the data.

   The labels are hidden with a clip, not display:none. A screen reader still
   reads them and they remain each link's accessible name — a rail of seven
   unlabelled squares would be a different page for anyone not using their eyes.
   -------------------------------------------------------------------------- */
@media (min-width:901px) and (max-width:1279px){
  .side{width:64px}
  .side .brand{justify-content:center;padding:18px 0}
  .side .brand span{position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap}
  .side nav{padding:12px 8px;gap:2px}
  .side nav a,.side nav .soon{justify-content:center;padding:10px 0;
    border-radius:4px}
  .side nav .nl{position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap}
  /* the county list and the account line have no iconic form — they are data,
     not navigation, so they go rather than being abbreviated into nonsense */
  .side .sect,.side .mine{display:none}
  .side .foot{border-top:0;padding-bottom:10px}
  .side .foot .acct{display:none}
}

/* The feed's row filter. It sits at the right end of the lens bar, which is
   why it is pushed rather than placed: the chips wrap first and it stays
   attached to the end of them. */
.lensbar .find{margin-left:auto;display:flex;align-items:center}
.lensbar .find input{font:inherit;font-size:13px;width:13rem;padding:5px 10px;
  min-height:32px;background:var(--paper);color:var(--ink);
  border:1px solid var(--rule-strong);border-radius:999px}
.lensbar .find input:focus{outline:none;border-color:var(--signal)}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  white-space:nowrap}
@media (max-width:760px){
  /* Full width and a 44px target: this is a text field on a phone, and the
     pager next to it already holds itself to 44. */
  .lensbar .find{margin-left:0;width:100%}
  .lensbar .find input{width:100%;min-height:44px}
}
