:root{
  --paper:#f5f2ec;
  --ink:#161512;
  --ink-soft:#4a4640;
  --asphalt:#22303a;
  --line-yellow:#e8b23a;
  --signal:#2e6f5e;
  --rule:#d8d2c6;
  --card:#fffdf9;
  --shadow:0 1px 0 rgba(22,21,18,.05),0 12px 32px -18px rgba(22,21,18,.22);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:"Public Sans",system-ui,sans-serif;
  font-size:17px;line-height:1.6;-webkit-font-smoothing:antialiased;
}
.wrap{max-width:1120px;margin:0 auto;padding:0 24px}
a{color:inherit}
.skip{position:absolute;left:-999px;top:0;background:var(--ink);color:var(--paper);padding:10px 16px;z-index:1000}
.skip:focus{left:8px;top:8px}

/* Masthead */
.masthead{position:sticky;top:0;z-index:500;background:rgba(245,242,236,.9);backdrop-filter:blur(8px);border-bottom:1px solid var(--rule)}
.masthead-inner{display:flex;align-items:center;justify-content:space-between;height:64px}
.brand{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--asphalt)}
.brand-mark{display:inline-flex;color:var(--asphalt)}
.brand-text{font-family:"Fraunces",serif;font-weight:900;font-size:24px;letter-spacing:-.01em;color:var(--ink)}
.brand-text.small{font-size:20px}
.brand-dot{color:var(--line-yellow)}
.nav{display:flex;gap:26px}
.nav a{font-weight:600;font-size:15px;text-decoration:none;color:var(--ink-soft);padding:4px 0;border-bottom:2px solid transparent;white-space:nowrap}
.nav a:hover{color:var(--ink);border-color:var(--line-yellow)}

/* The masthead used to overflow on every common phone width: the wordmark and
   four nav links needed ~385px of a 327px content box, so `Agencies` was cut
   to `Ag` and the wordmark sat flush against `Map`. The old rule here only
   tightened the nav's gap and font size, which was never going to close a
   58px gap.
   The brand is what gives way, in two stages — the wordmark is redundant
   next to the mark, which stays. Nav labels never shrink below 13px and never
   wrap: they are the only way to reach the sections. */
@media(max-width:760px){
  .masthead-inner{gap:16px}
  .brand-text{font-size:20px}
  .nav{gap:18px}
  .nav a{font-size:14px}
}
@media(max-width:600px){
  .brand-mark svg{width:28px;height:28px}
  .brand-text{font-size:18px}
  .nav{gap:14px}
  .nav a{font-size:13px}
}
/* Neither side may shrink. Letting the brand absorb the shortfall is what
   produced the original bug — flex quietly squeezed the nav until `Agencies`
   became `Ag`, and nothing about that reads as broken layout until you look
   at it on a phone. With both fixed, a masthead that no longer fits overflows
   visibly instead, which is a thing testing catches. */
.brand,.nav{flex:0 0 auto}
.brand-text{white-space:nowrap}

/* Measured, not guessed: the wordmark at 18px plus the four labels at 13px
   plus the gaps and the wrap's 48px of padding need a 412px viewport. Below
   that they genuinely cannot coexist at legible sizes, so the wordmark goes
   and the mark — still a link to `/` — carries the brand. 430px leaves a
   little margin over the measured 412px minimum. */
@media(max-width:430px){
  .brand-text{display:none}
  .brand-mark svg{width:30px;height:30px}
}

/* Hero */
.hero{position:relative;padding:72px 0 0}
.eyebrow{font-family:"IBM Plex Mono",monospace;text-transform:uppercase;letter-spacing:.18em;font-size:12px;color:var(--signal);margin:0 0 20px}
.hero-title{font-family:"Fraunces",serif;font-weight:900;font-size:clamp(42px,8vw,88px);line-height:.98;letter-spacing:-.02em;margin:0 0 24px}
.hero-title .ink{color:var(--asphalt)}
.hero-lede{max-width:640px;font-size:clamp(17px,2.2vw,21px);color:var(--ink-soft);margin:0 0 40px}

/* Hero lookup */
.hero-find{max-width:640px;margin:0 0 44px}
.hero-find-label{display:block;font-family:"IBM Plex Mono",monospace;text-transform:uppercase;letter-spacing:.1em;font-size:12px;color:var(--ink-soft);margin-bottom:10px}
.hero-find-row{display:flex;gap:10px}
.hero-find input{
  flex:1;min-width:0;font:inherit;font-size:17px;padding:14px 18px;
  border:1px solid var(--rule);border-radius:6px;background:var(--card);color:var(--ink);
}
.hero-find input::placeholder{color:var(--ink-soft);opacity:.75}
.hero-find input:focus{outline:2px solid var(--signal);outline-offset:1px}
.hero-find button{
  flex:0 0 auto;font:inherit;font-weight:700;font-size:16px;padding:14px 26px;
  border:1px solid var(--asphalt);border-radius:6px;background:var(--asphalt);color:var(--paper);
  cursor:pointer;transition:background .15s ease,border-color .15s ease;
}
.hero-find button:hover{background:var(--signal);border-color:var(--signal)}
.hero-find button:focus-visible{outline:2px solid var(--signal);outline-offset:2px}
.hero-find-hint{font-size:14px;color:var(--ink-soft);margin:10px 0 0}
@media(max-width:520px){
  .hero-find-row{flex-wrap:wrap}
  .hero-find input{flex:1 1 100%}
  .hero-find button{flex:1 1 100%}
}

.hero-stats{display:flex;flex-wrap:wrap;gap:40px;padding:0 0 60px}
.stat{display:flex;flex-direction:column}
.stat-num{font-family:"Fraunces",serif;font-weight:900;font-size:44px;line-height:1;color:var(--ink)}
.stat-label{font-family:"IBM Plex Mono",monospace;font-size:12px;text-transform:uppercase;letter-spacing:.1em;color:var(--ink-soft);margin-top:8px}
.hero-rule{height:8px;background:repeating-linear-gradient(90deg,var(--line-yellow) 0 48px,transparent 48px 88px)}

/* Blocks */
.block{padding:80px 0}
.block-alt{background:var(--card);border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.block-head{display:flex;gap:24px;align-items:baseline;margin-bottom:40px}
.section-num{font-family:"IBM Plex Mono",monospace;font-size:14px;color:var(--line-yellow);font-weight:500;margin:0;padding-top:6px}
.block-head h2{font-family:"Fraunces",serif;font-weight:900;font-size:clamp(30px,4.5vw,44px);line-height:1.02;letter-spacing:-.01em;margin:0 0 10px}
.section-sub{color:var(--ink-soft);max-width:640px;margin:0}

/* Map */
#tollmap{height:520px;border-radius:6px;border:1px solid var(--rule);box-shadow:var(--shadow);z-index:1}
@media(max-width:620px){#tollmap{height:400px}}
.map-foot{font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--ink-soft);margin-top:14px}
.maplibregl-popup-content{border-radius:6px}
.pop h4{font-family:"Fraunces",serif;font-weight:600;font-size:17px;margin:0 0 4px}
.pop .meta{font-size:12px;color:var(--ink-soft);margin:0 0 6px;font-family:"IBM Plex Mono",monospace}
.pop p{margin:6px 0 0;font-size:13px}
.pop a{color:var(--signal);font-weight:600;font-size:13px}
.pop-party{margin:6px 0 0;font-size:13px}
.pop-role{font-family:"IBM Plex Mono",monospace;font-size:10px;text-transform:uppercase;
  letter-spacing:.08em;color:var(--ink-soft)}
/* The role note is what makes two links useful instead of confusing — it says
   which one answers the reader's question — so it sits directly under its own
   link, not in a shared block. */
.pop-role-note{margin:2px 0 0!important;font-size:12px!important;color:var(--ink-soft);line-height:1.4}
.pop-label{font-family:"IBM Plex Mono",monospace;font-size:10px;text-transform:uppercase;
  letter-spacing:.08em;color:var(--ink-soft);margin-right:6px}
.pop-accepts{margin-top:8px!important}
.pop-verified{margin:4px 0 0!important;font-family:"IBM Plex Mono",monospace;
  font-size:10px!important;color:var(--ink-soft)}
/* Scope nuance is a footnote to the badges above it, never a replacement for
   them: the binary answer is the headline. */
.pop-scope{margin:6px 0 0!important;font-size:12px!important;color:var(--ink-soft);line-height:1.4}
.pop-more{margin:10px 0 0!important;padding-top:8px;border-top:1px solid var(--rule)}
.pop-notconfirmed{margin:6px 0 0!important;font-size:12px!important;line-height:1.4;
  padding-left:8px;border-left:2px solid var(--rule)}

/* Controls */
.controls{display:flex;gap:14px;margin-bottom:32px;flex-wrap:wrap}
.controls input,.controls select{
  font:inherit;padding:12px 16px;border:1px solid var(--rule);border-radius:6px;background:var(--paper);color:var(--ink)
}
.controls input{flex:1;min-width:220px}
.controls input:focus,.controls select:focus{outline:2px solid var(--signal);outline-offset:1px}
.road-count{font-family:"IBM Plex Mono",monospace;font-size:13px;color:var(--ink-soft);align-self:center;white-space:nowrap}

/* Map legend */
.map-legend{display:flex;gap:20px;margin-top:14px;flex-wrap:wrap}
.map-legend span{display:flex;align-items:center;gap:7px;font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--ink-soft)}
.map-legend i{width:12px;height:12px;border-radius:50%;border:2px solid var(--asphalt);display:inline-block}

/* System flags & interop on cards */
.road-system{font-size:13px;color:var(--ink);margin:0 0 8px;display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.flag{font-family:"IBM Plex Mono",monospace;font-size:10px;letter-spacing:.04em;background:var(--paper);border:1px solid var(--rule);color:var(--ink-soft);padding:2px 6px;border-radius:3px}
.road-interop{font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--signal);margin:0 0 10px}
.agency-count{font-family:"IBM Plex Mono",monospace;font-size:13px;color:var(--ink-soft);text-align:right}

/* Road grid */
/* minmax(min(300px,100%),...) rather than minmax(300px,...): a 300px floor plus
   the wrap's 24px side padding is 324px, so on a 320px viewport the grid was
   4px wider than the page and it scrolled sideways — small enough to look
   like nothing and still a horizontal scroll on a phone. min() lets the floor
   give way only below that point; every wider viewport is unchanged. */
.road-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr));gap:18px}
.road{background:var(--card);border:1px solid var(--rule);border-radius:6px;padding:22px;box-shadow:var(--shadow);transition:transform .15s ease}
@media (prefers-reduced-motion:reduce){.road{transition:none}}
.road:hover{transform:translateY(-2px)}
.road-top{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:10px}
.road h3{font-family:"Fraunces",serif;font-size:20px;font-weight:600;margin:0;line-height:1.15}
.road .state{font-family:"IBM Plex Mono",monospace;font-size:12px;font-weight:500;background:var(--asphalt);color:var(--paper);padding:3px 8px;border-radius:4px;white-space:nowrap}
.road .agency{font-size:13px;color:var(--signal);font-weight:600;margin:0 0 12px}
.road-facts{display:flex;flex-wrap:wrap;gap:6px 14px;font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--ink-soft);margin:0 0 10px}
.road-notes{font-size:14px;color:var(--ink-soft);margin:0}
/* The facility name is a link to that facility's own page, on the homepage's
   cards and the generated state pages alike — so it lives here, in the sheet
   both load, rather than in styles-pages.css. Underlined on hover only: 359
   cards with permanently underlined headings reads as a link farm, and the
   card is already obviously interactive. */
.road-top h3 a{color:inherit;text-decoration:none}
.road-top h3 a:hover{color:var(--signal);text-decoration:underline;
  text-decoration-thickness:1px;text-underline-offset:2px}
.road-top h3 a:focus-visible{outline:2px solid var(--signal);outline-offset:2px}
.empty{grid-column:1/-1;text-align:center;color:var(--ink-soft);padding:40px;font-family:"IBM Plex Mono",monospace;font-size:14px}
.road-grid-toggle{display:block;margin:28px auto 0;padding:12px 28px;font:inherit;font-weight:600;font-size:14px;background:var(--card);color:var(--ink);border:1px solid var(--rule);border-radius:6px;cursor:pointer;transition:border-color .15s ease,color .15s ease}
.road-grid-toggle:hover{border-color:var(--signal);color:var(--signal)}
.road-grid-toggle:focus{outline:2px solid var(--signal);outline-offset:1px}
.road-grid-toggle[hidden]{display:none}

/* Basics */
.basics-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);border-radius:6px;overflow:hidden}
.basic{background:var(--paper);padding:28px}
.basic h3{font-family:"Fraunces",serif;font-size:19px;font-weight:600;margin:0 0 10px}
.basic p{margin:0;font-size:15px;color:var(--ink-soft)}

/* Agencies */
.agency-controls{display:flex;gap:14px;margin-bottom:20px;flex-wrap:wrap;align-items:center}
.agency-controls input,.agency-controls select{
  font:inherit;font-size:14px;padding:9px 12px;border:1px solid var(--rule);
  border-radius:4px;background:var(--card);color:var(--ink)}
.agency-controls input{flex:1;min-width:200px}
.agency-controls input:focus,.agency-controls select:focus{outline:2px solid var(--signal);outline-offset:1px}
.agency-count-label{font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--ink-soft)}
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.agency-table{border:1px solid var(--rule);border-radius:6px;overflow:hidden;background:var(--card)}
.agency-row{display:grid;grid-template-columns:2.4fr 72px 1fr 1fr 70px;gap:16px;align-items:center;padding:14px 22px;border-bottom:1px solid var(--rule);font-size:14px}
.agency-row:last-child{border-bottom:0}
.agency-row.head{background:var(--asphalt);color:var(--paper);font-family:"IBM Plex Mono",monospace;font-size:11px;text-transform:uppercase;letter-spacing:.1em}
.agency-name{font-weight:600}
.agency-tags{color:var(--ink-soft);font-family:"IBM Plex Mono",monospace;font-size:12px}
.agency-row a{color:var(--signal);font-weight:600;text-decoration:none;font-size:13px;white-space:nowrap}
.agency-row a:hover{text-decoration:underline}

/* Sortable header */
.agency-row.head .sortable{cursor:pointer;user-select:none;display:flex;align-items:center;gap:4px}
.agency-row.head .sortable:hover{color:var(--paper);opacity:.8}
.agency-row.head .sort-arrow{font-size:9px}

/* Clickable operator row -> facility list */
.agency-row:not(.head) .agency-name{cursor:pointer;color:var(--signal)}
.agency-row:not(.head) .agency-name:hover{text-decoration:underline}
.agency-row.open{flex-wrap:wrap}
.agency-detail{grid-column:1/-1;margin-top:12px;padding-top:12px;border-top:1px dashed var(--rule)}
.agency-facility-list{list-style:none;margin:0;padding:0;display:grid;gap:6px}
.agency-facility-list li{display:flex;justify-content:space-between;gap:12px;font-size:13px}
.af-name{font-weight:500}
/* Same uppercase role marker as the map popup, for the same reason: on a
   multi-party facility, "owner" and "concessionaire" are different jobs. */
.af-role{font-family:"IBM Plex Mono",monospace;font-size:10px;text-transform:uppercase;
  letter-spacing:.08em;color:var(--ink-soft);margin-left:6px;font-weight:400}
.af-meta{font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--ink-soft);white-space:nowrap}
.agency-fullname{display:block;font-weight:400;font-size:12px;color:var(--ink-soft);margin-top:2px}
.agency-brand{font-family:"IBM Plex Mono",monospace;font-size:12px}
.agency-dash{color:var(--ink-soft);opacity:.5}
.agency-issuer{margin:0 0 10px;font-size:13px}
.agency-nets{margin:0 0 10px;font-size:13px}
.agency-note{margin:0 0 10px;font-size:13px;color:var(--ink-soft)}
.agency-backoffice{margin:0 0 10px;font-size:13px;color:var(--ink-soft)}
.agency-links{display:flex;flex-wrap:wrap;gap:14px;margin:0 0 12px}
.agency-link{font-size:13px}

/* Chips: one visual language for a transponder brand or a network, used by
   both the agency index and the map popups. */
.chip{display:inline-block;font-family:"IBM Plex Mono",monospace;font-size:11px;
  padding:2px 7px;border-radius:3px;background:var(--asphalt);color:var(--paper);
  margin:0 4px 4px 0;white-space:nowrap}
.chip-agreement{background:transparent;color:var(--ink);border:1px dashed var(--rule)}
.chip-network{background:transparent;color:var(--ink-soft);border:1px solid var(--rule)}
.chip-qual{opacity:.7}

/* A crossing that is still a toll facility but is not charging today. Amber
   rather than the muted .flag treatment: this changes what a driver should
   expect at the gantry, so it has to survive a glance rather than blend into
   the row of system flags beside it. */
.status-badge{display:inline-block;font-family:"IBM Plex Mono",monospace;font-size:10px;
  letter-spacing:.04em;text-transform:uppercase;background:var(--line-yellow);
  color:var(--ink);padding:2px 7px;border-radius:3px;white-space:nowrap}
.pop .status-badge{margin:0 0 8px}

@media(max-width:760px){
  .agency-row{grid-template-columns:1fr auto;gap:6px}
  .agency-row .agency-st,.agency-row .agency-tags,.agency-row .agency-brand{display:none}
}

/* Footer */
.foot{background:var(--asphalt);color:var(--paper);padding:48px 0}
.foot-inner{display:flex;justify-content:space-between;gap:24px;flex-wrap:wrap}
.foot .brand-text{color:var(--paper)}
.foot-note{max-width:460px;color:#c7cdd0;font-size:14px;margin:10px 0 0}
.foot-updated{font-family:"IBM Plex Mono",monospace;font-size:12px;color:#9aa4a8;margin:0}

/* A pointer out of a section to the pages that expand it. Lives here rather
   than in styles-pages.css because the homepage is what uses it — and it is
   the only crawlable path into /toll-roads/, since the state <select> beside
   it is invisible to anything that does not run the filter. */
.block-aside{margin:0 0 24px;font-size:15px;color:var(--ink-soft)}
.block-aside a{color:var(--signal);font-weight:600;text-decoration-thickness:1px;text-underline-offset:2px}
.block-aside a:hover{color:var(--ink)}
