/* The palette now lives in ui.css, which every page loads first — the map, the
   dashboard, the matching workspace and the reports builder all read the same
   tokens, and dark mode is a single block there rather than a rewrite here.
   This file keeps only the three names of its own that ui.css has no use for,
   each pointed at the shared token it corresponds to. */
:root{
  --panel:var(--surface);
  --shadow:var(--shadow-3);
  --radius:var(--r-lg);
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;font-family:var(--font);color:var(--ink)}

/* The map fills the viewport and nothing on it is meant to scroll the page.
   The closed inspector is parked off-canvas with translateX(100%) — 400px to
   the right of the viewport — which counts towards the scrollable area and
   put a stray horizontal scrollbar under the map.

   The class is on <html>, not <body>, and deliberately. `overflow` set on the
   body is propagated to the viewport only while the root's own overflow is
   `visible`, and the body then computes to visible itself — so the rule reads
   as applied in devtools while the page carries on scrolling. Setting it on
   the root is the version that actually holds.

   Map page only: the dashboard, the matching workspace and the reports
   builder are all documents that must scroll. */
html.mapview, html.mapview > body{overflow:hidden}

#map{position:absolute;inset:0}

/* ---------------- Panel ---------------- */
.panel{
  position:absolute;top:14px;left:14px;bottom:14px;width:340px;max-width:calc(100vw - 28px);
  background:var(--panel);border-radius:var(--radius);box-shadow:var(--shadow);
  display:flex;flex-direction:column;z-index:5;overflow:hidden;transition:transform .28s ease,opacity .28s;
}
.panel.hidden{transform:translateX(-380px);opacity:0;pointer-events:none}
.panel-head{display:flex;align-items:center;justify-content:space-between;padding:16px 16px 12px;border-bottom:1px solid var(--line)}
.brand{display:flex;align-items:center;gap:12px}
.brand-mark{width:42px;height:42px;border-radius:12px;background:linear-gradient(135deg,var(--brand),#1e40af);
  color:#fff;font-weight:700;font-size:20px;display:grid;place-items:center;box-shadow:0 6px 14px -4px rgba(37,99,235,.6)}
.brand-txt h1{margin:0;font-size:17px;font-weight:700;letter-spacing:-.01em}
.brand-txt span{font-size:12px;color:var(--muted)}
.icon-btn{border:0;background:var(--surface-3);color:var(--muted);width:30px;height:30px;border-radius:9px;cursor:pointer;font-size:13px}
.icon-btn:hover{background:var(--line)}

.panel-tools{padding:12px 14px;border-bottom:1px solid var(--line)}

/* One segmented strip instead of two rows of look-alike buttons. */
.tool-row{display:flex;gap:0;margin-top:9px;border:1px solid var(--line);border-radius:10px;overflow:hidden}
.tool{flex:1;display:flex;align-items:center;justify-content:center;gap:5px;border:0;
  border-right:1px solid var(--line);background:var(--surface);padding:7px 4px;font:inherit;font-size:12px;
  color:var(--muted);cursor:pointer;transition:.12s}
.tool:last-child{border-right:0}
.tool:hover{background:var(--surface-2);color:var(--ink)}
.tool.on{background:var(--brand-soft);color:var(--brand);font-weight:600}
.tool-ico{font-size:12px;line-height:1}

.mini{border:1px solid var(--line);background:var(--surface);border-radius:9px;padding:6px 10px;
  font:inherit;font-size:12px;color:var(--muted);cursor:pointer}
.mini:hover{background:var(--surface-2);color:var(--ink)}

/* Shown only while something is switched on, so the panel stays quiet at rest. */
.active-bar{display:flex;align-items:center;gap:10px;padding:8px 16px;font-size:12px;
  color:var(--brand);background:var(--brand-soft);border-bottom:1px solid #dbeafe;font-weight:600}
.active-bar[hidden]{display:none}
.active-bar .link-btn{margin-left:auto;font-weight:600}

.layers{flex:1;overflow-y:auto;padding:8px 10px}
.loading{padding:24px;text-align:center;color:var(--muted);font-size:13px}

.cat{margin:2px 2px 10px}
.cat-head{display:flex;align-items:center;gap:8px;padding:7px 8px;cursor:pointer;border-radius:9px;user-select:none}
.cat-head:hover{background:var(--surface-2)}
.cat-dot{width:8px;height:8px;border-radius:50%}
.cat-title{font-weight:600;font-size:12.5px;flex:1}
.cat-count{font-size:10.5px;color:var(--muted);font-variant-numeric:tabular-nums}
.cat-caret{color:#94a3b8;transition:transform .18s;font-size:10px;width:10px;text-align:center}
.cat.collapsed .cat-caret{transform:rotate(-90deg)}
.cat.collapsed .cat-body{display:none}
.cat-body{padding:1px 0 0 2px}

.lyr{display:flex;align-items:center;gap:9px;padding:6px 8px;border-radius:9px;
  border-left:2px solid transparent}
.lyr:hover{background:var(--surface-2)}
.lyr.on{background:var(--surface-2);border-left-color:var(--brand)}
.sw{width:12px;height:12px;border-radius:3px;flex:0 0 auto;border:1px solid rgba(0,0,0,.12)}
.sw.line{height:3px;border-radius:2px}
.sw.point{border-radius:50%}
.lyr-main{flex:1;min-width:0}
.lyr-name{font-size:12.5px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lyr-meta{font-size:10.5px;color:var(--muted);font-variant-numeric:tabular-nums}
.lyr-heavy{color:#b45309;background:#fef3c7;border-radius:20px;padding:0 5px;font-size:9px;font-weight:700}
.lyr-act{display:flex;align-items:center;gap:4px}

/* The download button is noise on 46 rows at once — it appears on approach. */
.dl{color:var(--muted);text-decoration:none;font-size:13px;opacity:0;transition:opacity .12s}
.lyr:hover .dl,.lyr.on .dl{opacity:.65}
.dl:hover{opacity:1;color:var(--brand)}
/* There is no hover on a touch screen, so the button simply stays visible. */
@media (hover:none){ .dl{opacity:.6} }

/* A layer is "busy" from the moment it is switched on until its worker has the
   features. The bar rides the row's own left edge, so a heavy layer reads as
   working without a spinner competing with the toggle. */
.lyr.busy{border-left-color:transparent;position:relative;overflow:hidden}
.lyr.busy:before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--brand);
  animation:lyrbusy 1.1s ease-in-out infinite}
@keyframes lyrbusy{0%{opacity:.25}50%{opacity:1}100%{opacity:.25}}
.spin{width:13px;height:13px;border:2px solid #cbd5e1;border-top-color:var(--brand);border-radius:50%;animation:sp .7s linear infinite}
@keyframes sp{to{transform:rotate(360deg)}}

/* toggle */
.tg{position:relative;width:34px;height:20px;flex:0 0 auto}
.tg input{opacity:0;width:0;height:0}
.tg .track{position:absolute;inset:0;background:#cbd5e1;border-radius:20px;transition:.2s;cursor:pointer}
.tg .track:before{content:"";position:absolute;width:14px;height:14px;left:3px;top:3px;background:#fff;border-radius:50%;transition:.2s}
.tg input:checked + .track{background:var(--brand)}
.tg input:checked + .track:before{transform:translateX(14px)}

.panel-foot{padding:12px 14px;border-top:1px solid var(--line);background:#fafbfc}
.foot-grid{display:flex;gap:8px}
.foot-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:7px;
  border:1px solid var(--line);background:var(--surface);border-radius:10px;padding:9px 8px;
  font:inherit;font-size:12.5px;font-weight:600;color:var(--ink);cursor:pointer;
  text-decoration:none;white-space:nowrap}
.foot-btn:hover{background:var(--brand-soft);border-color:#bfdbfe;color:var(--brand)}
.foot-btn span{font-size:14px;line-height:1}
.dl-gpkg{display:block;text-align:center;background:linear-gradient(135deg,var(--brand),#1e40af);color:#fff;
  padding:10px;border-radius:10px;text-decoration:none;font-size:13px;font-weight:600;box-shadow:0 6px 14px -6px rgba(37,99,235,.7)}
.dl-gpkg:hover{filter:brightness(1.06)}
.attrib{font-size:10.5px;color:var(--muted);text-align:center;margin:8px 0 0}

.panel-open{position:absolute;top:14px;left:14px;z-index:4;display:none;border:0;background:var(--surface);
  box-shadow:var(--shadow);border-radius:11px;padding:10px 14px;font-weight:600;font-size:13px;cursor:pointer}
.panel.hidden ~ .panel-open{display:block}

/* ---------------- Basemaps ---------------- */
.basemaps{position:absolute;top:14px;right:14px;z-index:4;background:var(--surface);border-radius:11px;box-shadow:var(--shadow);padding:4px;display:flex;gap:2px}
.basemaps button{border:0;background:transparent;padding:7px 12px;border-radius:8px;font-size:12px;font-weight:500;color:var(--muted);cursor:pointer}
.basemaps button.active{background:var(--brand);color:#fff}

/* ---------------- Legend ---------------- */
.legend{position:absolute;right:14px;bottom:14px;z-index:4;background:var(--surface);border-radius:11px;box-shadow:var(--shadow);
  padding:12px 14px;max-width:220px;font-size:12px;max-height:40vh;overflow:auto}
.legend-head{font-weight:600;margin-bottom:8px;font-size:12px}
.legend .li{display:flex;align-items:center;gap:8px;margin:5px 0}
.legend .li .sw{width:12px;height:12px}
.legend:empty,.legend.empty{display:none}

/* ---------------- Popup ---------------- */
.maplibregl-popup{max-width:320px !important}
.maplibregl-popup-content{border-radius:12px;padding:0;overflow:hidden;box-shadow:var(--shadow);font-family:inherit}
.pop-head{background:var(--brand);color:#fff;padding:10px 14px;font-weight:600;font-size:13px}
.pop-body{max-height:280px;overflow:auto;padding:6px 0}
.pop-row{display:flex;gap:10px;padding:5px 14px;font-size:12px;border-bottom:1px solid #f1f5f9}
.pop-row:last-child{border:0}
.pop-k{color:var(--muted);flex:0 0 42%;word-break:break-word}
.pop-v{flex:1;font-weight:500;word-break:break-word}

/* toast */
.toast{position:absolute;bottom:20px;left:50%;transform:translateX(-50%) translateY(20px);z-index:9;
  background:#0f172a;color:#fff;padding:9px 16px;border-radius:10px;font-size:12.5px;opacity:0;transition:.25s;pointer-events:none}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}

@media (max-width:640px){
  .panel{width:calc(100vw - 20px);top:10px;left:10px;bottom:10px}
  .legend{display:none}
  .basemaps{top:auto;bottom:14px;right:14px}
}

/* ============ Auth button ============ */
.authbtn{width:100%;border:1px solid var(--line);background:var(--surface);border-radius:10px;padding:8px;font-size:12.5px;
  font-weight:600;color:var(--ink);cursor:pointer;margin-top:8px}
.authbtn:hover{background:var(--surface-2)}
#selectBtn.on{background:var(--brand);color:#fff}

/* ============ Login modal ============ */
.modal{position:fixed;inset:0;background:rgba(15,23,42,.5);z-index:20;display:none;align-items:center;justify-content:center;backdrop-filter:blur(2px)}
.modal.show{display:flex}
.modal-card{background:var(--surface);border-radius:16px;padding:26px;width:340px;max-width:calc(100vw - 32px);box-shadow:var(--shadow)}
.modal-card h2{margin:0 0 6px;font-size:19px}
.modal-card p{margin:0 0 16px;font-size:13px;color:var(--muted)}
.modal-card input{width:100%;padding:11px 13px;border:1px solid var(--line);border-radius:10px;font-size:14px;outline:none}
.modal-card input:focus{border-color:var(--brand);box-shadow:0 0 0 3px rgba(37,99,235,.12)}
.modal-err{color:#dc2626;font-size:12.5px;min-height:16px;margin-top:6px}
.modal-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:14px}
.modal-actions button,.sel-bar button{border:0;border-radius:9px;padding:9px 16px;font-size:13px;font-weight:600;cursor:pointer;background:var(--brand);color:#fff}
.modal-actions .ghost,.sel-bar .ghost{background:var(--surface-3);color:var(--muted)}

/* ============ Summary tables ============ */
/* Both tables have to be readable at a glance without scrolling: 17 depots
   and 7 drains stacked in one 266px column ran past the bottom of the screen,
   and it was always the drain table — the shorter one, and the one the river
   programme is organised around — that fell off. Side by side, the panel is as
   tall as the depot table alone. `overflow:auto` stays only as a backstop for
   a very short window; at any normal height nothing scrolls. */
.summary{position:absolute;top:64px;right:14px;z-index:4;background:var(--surface);border-radius:12px;box-shadow:var(--shadow);
  padding:12px 14px;width:500px;max-height:calc(100vh - 84px);overflow:auto}
.sum-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 18px;align-items:start}
.sum-col{min-width:0}
.sum-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
.sum-head b{font-size:13px}
#sumReset{border:1px solid var(--line);background:var(--surface);border-radius:8px;font-size:11px;padding:4px 8px;cursor:pointer;color:var(--muted)}
#sumReset:hover{background:var(--surface-2);color:var(--ink)}
.sum-title{font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.03em;margin:2px 0 4px}
.sum-tbl{width:100%;border-collapse:collapse;font-size:12px}
.sum-tbl th{font-size:10.5px;color:var(--muted);font-weight:600;text-align:right;padding:3px 6px;border-bottom:1px solid var(--line)}
.sum-tbl th:first-child{text-align:left}
.sum-tbl th.dry{color:#16a34a}.sum-tbl th.wet{color:#dc2626}
.sum-tbl td{padding:2.5px 5px;border-bottom:1px solid #f1f5f9}
.sum-tbl .t-name{max-width:120px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink)}
.sum-tbl .t-num{text-align:right;cursor:pointer;font-variant-numeric:tabular-nums;border-radius:5px}
.sum-tbl .t-num:hover{background:var(--brand-soft)}
.sum-tbl .t-num.dry{color:#16a34a;font-weight:600}
.sum-tbl .t-num.wet{color:#dc2626;font-weight:600}
.sum-tbl .t-num.tot{font-weight:700}
.sum-tbl .t-num.sel{background:var(--brand);color:#fff!important}
.sum-tbl tfoot td{font-weight:700;border-top:2px solid var(--line);border-bottom:0}

/* ============ Select bar ============ */
.sel-bar{position:absolute;bottom:20px;left:50%;transform:translateX(-50%) translateY(20px);z-index:9;
  background:#0f172a;color:#fff;padding:9px 14px;border-radius:11px;font-size:13px;display:flex;gap:12px;align-items:center;
  opacity:0;transition:.25s;pointer-events:none}
.sel-bar.show{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
.sel-bar button{padding:6px 12px;font-size:12px}

/* Below this the two columns would crowd the map more than they help; the
   panel stacks and keeps every pixel of height it can. It is hidden outright
   under 640px, so this band is narrow. */
@media (max-width:780px){
  .summary{width:266px}
  .sum-grid{grid-template-columns:1fr;gap:0}
  .sum-col+.sum-col .sum-title{margin-top:10px}
}
@media (max-width:640px){ .summary{display:none} }

/* ============ Building register modal (item 9) ============ */
.modal-card.wide{width:560px;max-width:calc(100vw - 32px)}
.bx-head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}
.bx-head h2{margin:0;font-size:19px;letter-spacing:-.02em}
.bx-sub{margin:3px 0 0;font-size:12.5px;color:var(--muted)}
.bx-actions{margin:10px 0}
.bx-actions .dl-gpkg{display:inline-block;padding:8px 16px}
.bx-table-wrap{max-height:50vh;overflow:auto;border:1px solid var(--line);border-radius:10px}
.bx-table{width:100%;border-collapse:collapse;font-size:12.5px}
.bx-table th{position:sticky;top:0;background:var(--surface-2);text-align:right;padding:8px 10px;font-size:11px;color:var(--muted);border-bottom:1px solid var(--line)}
.bx-table th:first-child{text-align:left}
.bx-table td{padding:7px 10px;text-align:right;border-bottom:1px solid #f1f5f9;font-variant-numeric:tabular-nums}
.bx-table td:first-child{text-align:left;font-weight:600}
.bx-dl{color:var(--brand);text-decoration:none;font-weight:600;font-size:12px}
.bx-dl:hover{text-decoration:underline}

/* ============ Summary table alignment fix ============ */
.sum-tbl{table-layout:fixed}
.sum-tbl th:first-child,.sum-tbl td:first-child{width:52%;text-align:left}
.sum-tbl th:not(:first-child),.sum-tbl td:not(:first-child){width:16%;text-align:right;padding-right:6px}
.sum-tbl .t-name{max-width:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}


/* ==================================================================
   Feature inspector — docked right-hand drawer (items 1 & 4)
   ================================================================== */
:root{ --insp-w:400px; --ok:#16a34a; --bad:#dc2626; }

/* Fixed, not absolute, and for one reason beyond the pinning: the closed
   drawer is parked at translateX(100%), a full 400px to the right of the
   viewport. An absolutely positioned box there counts towards the document's
   scrollable width -- 1280px of map reported as 1680 -- and any browser that
   does not honour the root's overflow:hidden hands the operator a horizontal
   scrollbar under the map. A fixed box is excluded from that overflow
   altogether, so the page is exactly as wide as the window whatever the
   drawer is doing. */
.insp{
  position:fixed;top:0;right:0;bottom:0;width:var(--insp-w);max-width:100vw;z-index:8;
  background:var(--panel);display:flex;flex-direction:column;
  box-shadow:-14px 0 40px -18px rgba(2,6,23,.45);
  border-left:1px solid var(--line);
  transform:translateX(100%);transition:transform .3s cubic-bezier(.22,.7,.3,1);
}
.insp.show{transform:translateX(0)}

/* Everything pinned to the right edge steps aside for the drawer. The basemap
   switcher is narrow enough to always slide across; the wider summary and
   legend cards would land on top of the layer panel, so below ~1120px they
   simply stand down until the drawer closes. */
.basemaps,.summary,.legend{transition:transform .3s cubic-bezier(.22,.7,.3,1),opacity .22s}
body.insp-open .basemaps{transform:translateX(calc(-1 * var(--insp-w)))}

/* Click an outfall and the popup is the thing you want to read: the summary
   and the legend step aside at EVERY width, and come back when it closes.
   They used to stay put on a wide screen, which meant the table you clicked
   the outfall from was then sitting on top of it. */
body.insp-open .summary,
body.insp-open .legend{opacity:0;pointer-events:none;transform:translateX(-40px)}

}

.insp-grip{
  position:absolute;left:-26px;top:50%;transform:translateY(-50%);
  width:26px;height:58px;border:1px solid var(--line);border-right:0;background:var(--surface);
  border-radius:9px 0 0 9px;cursor:pointer;color:var(--muted);font-size:17px;line-height:1;
  box-shadow:-6px 0 16px -10px rgba(2,6,23,.4)
}
.insp-grip:hover{color:var(--ink);background:var(--surface-2)}

.insp-head{padding:18px 20px 14px;border-bottom:1px solid var(--line);background:linear-gradient(180deg,#f8fafc,#fff)}
.insp-head-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.insp-title{min-width:0}
.insp-title h2{margin:0;font-size:21px;font-weight:700;letter-spacing:-.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.insp-sub{font-size:12.5px;color:var(--muted);margin-top:3px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.insp-chips{display:flex;align-items:center;gap:10px;margin-top:11px;flex-wrap:wrap}

.chip{display:inline-flex;align-items:center;gap:6px;padding:3px 11px;border-radius:20px;
  font-size:11.5px;font-weight:700;letter-spacing:.02em}
.chip:before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.chip-dry{background:#dcfce7;color:#15803d}
.chip-wet{background:#fee2e2;color:#b91c1c}
.chip-na{background:var(--surface-3);color:#64748b}
.chip-layer:before{display:none}

.link-btn{border:0;background:none;padding:0;color:var(--brand);font:inherit;font-size:12px;
  font-weight:600;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.link-btn:hover{color:#1e40af}

.insp-pager{display:flex;align-items:center;gap:8px;margin-top:11px;padding:5px 8px;
  background:var(--surface-3);border-radius:8px;font-size:11.5px;color:var(--muted)}
.insp-pager button{border:1px solid var(--line);background:var(--surface);border-radius:6px;width:22px;height:22px;
  cursor:pointer;color:var(--ink);line-height:1;font-size:14px}
.insp-pager button:disabled{opacity:.35;cursor:default}

.insp-body{flex:1;overflow-y:auto;padding:4px 20px 18px;overscroll-behavior:contain}
.insp-sec{padding:16px 0;border-bottom:1px solid #f1f5f9}
.insp-sec:last-child{border-bottom:0}
.insp-sec h3{margin:0 0 10px;font-size:11px;font-weight:700;color:var(--muted);
  text-transform:uppercase;letter-spacing:.07em;display:flex;align-items:center;gap:8px}
.insp-count{background:var(--surface-3);color:var(--muted);border-radius:20px;padding:1px 8px;
  font-size:10.5px;font-weight:700;letter-spacing:0}
.insp-empty{font-size:12.5px;color:var(--muted);font-style:italic;padding:8px 0}

/* segmented wet / dry control */
.seg{display:flex;gap:6px;background:var(--surface-3);padding:4px;border-radius:11px}
.seg button{flex:1;border:0;background:transparent;border-radius:8px;padding:9px 6px;
  font:inherit;font-size:12.5px;font-weight:600;color:var(--muted);cursor:pointer;transition:.15s}
.seg button:hover{color:var(--ink)}
.seg button.on{background:var(--surface);color:var(--ink);box-shadow:0 1px 3px rgba(2,6,23,.16)}
.seg button[data-wd="dry"].on{color:var(--ok)}
.seg button[data-wd="wet"].on{color:var(--bad)}

/* key / value grid */
.kv{display:grid;grid-template-columns:minmax(96px,40%) 1fr;gap:1px 12px;font-size:12.5px}
.kv-k{color:var(--muted);padding:5px 0;border-bottom:1px solid #f8fafc}
.kv-v{font-weight:500;padding:5px 0;border-bottom:1px solid #f8fafc;word-break:break-word}

/* specification chips — size / depth / level at a glance (item 7) */
.specs{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.spec{background:var(--surface-2);border:1px solid var(--line);border-radius:10px;padding:9px 11px}
.spec span{display:block;font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em}
.spec b{font-size:14px;font-weight:700;letter-spacing:-.01em}

.insp-l{display:block;font-size:11px;font-weight:600;color:var(--muted);margin:10px 0 4px}
.insp-body textarea,.insp-filter{width:100%;border:1px solid var(--line);border-radius:9px;padding:9px 11px;
  font:inherit;font-size:12.5px;resize:vertical;background:var(--surface);color:var(--ink)}
.insp-body textarea:focus,.insp-filter:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(37,99,235,.12)}
.insp-filter{margin-bottom:10px;resize:none}
.insp-saved{font-size:11px;color:var(--muted);margin-top:6px;min-height:14px}

/* photo drop zone + gallery (items 2 & 3) */
.drop{border:1.5px dashed #cbd5e1;border-radius:12px;padding:16px;text-align:center;cursor:pointer;
  background:var(--surface-2);transition:.15s}
.drop:hover{border-color:var(--brand);background:var(--brand-soft)}
.drop.over{border-color:var(--brand);background:#dbeafe;border-style:solid}
.drop-in b{display:block;font-size:13px;margin-bottom:3px}
.drop-in span{font-size:11.5px;color:var(--muted)}

.gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:10px}
.ph{position:relative;margin:0;border-radius:10px;overflow:hidden;border:1px solid var(--line);background:var(--surface-3)}
.ph img{display:block;width:100%;aspect-ratio:1;object-fit:cover;cursor:zoom-in}
.ph figcaption{font-size:9.5px;color:var(--muted);padding:3px 5px;text-align:center;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ph-del{position:absolute;top:4px;right:4px;width:21px;height:21px;border:0;border-radius:6px;
  background:rgba(15,23,42,.62);color:#fff;font-size:10px;cursor:pointer;opacity:0;transition:.15s;line-height:1}
.ph:hover .ph-del{opacity:1}
.ph-del:hover{background:var(--bad)}

.prog{height:4px;background:var(--line);border-radius:4px;margin-top:10px;overflow:hidden;
  opacity:0;transition:opacity .2s}
.prog.show{opacity:1}
.prog-bar{height:100%;width:0;background:var(--brand);transition:width .25s}

.insp-foot{border-top:1px solid var(--line);padding:12px 20px 16px;background:var(--surface)}
.insp-foot-btns{display:flex;gap:8px;justify-content:flex-end}
.btn-primary,.btn-ghost{border:0;border-radius:10px;padding:10px 18px;font:inherit;font-size:13px;
  font-weight:600;cursor:pointer}
.btn-primary{background:var(--brand);color:#fff;box-shadow:0 6px 14px -8px rgba(37,99,235,.9)}
.btn-primary:hover{filter:brightness(1.07)}
.btn-ghost{background:var(--surface-3);color:var(--muted)}
.btn-ghost:hover{background:var(--line);color:var(--ink)}
.insp-msg{font-size:12px;color:var(--muted);min-height:17px;margin-bottom:8px;word-break:break-word}
.insp-msg.ok{color:var(--ok);font-weight:600}
.insp-msg.err{color:var(--bad);font-weight:600}
.insp-msg a{color:var(--brand)}


/* ===================== Depot filter =====================
   Sits directly under the tool strip, because "which depot am I looking at"
   frames everything below it — it is not one more layer option. */
.depot-row{margin-top:9px}
.depot-btn{
  display:flex;align-items:center;gap:8px;width:100%;
  border:1px solid var(--line);background:var(--surface);border-radius:10px;
  padding:8px 11px;font:inherit;font-size:12.5px;color:var(--ink-2);
  cursor:pointer;transition:.14s
}
.depot-btn:hover{background:var(--surface-2);border-color:var(--line-strong)}
.depot-ico{font-size:12px;line-height:1;color:var(--muted)}
#depotLabel{flex:1;text-align:left;font-weight:600}
.depot-caret{color:var(--muted);font-size:13px;line-height:1;transition:transform .2s}
.depot-btn.open .depot-caret{transform:rotate(180deg)}
/* Filtering is a state the whole map is in, so the control says so loudly —
   an operator must never mistake a depot view for the full zone. */
.depot-btn.filtered{
  border-color:var(--brand);background:var(--brand-soft);color:var(--brand)
}
.depot-btn.filtered .depot-ico{color:var(--brand)}

.depot-pop{margin-top:8px;border:1px solid var(--line);border-radius:11px;
  background:var(--surface-2);padding:9px}
.depot-pop[hidden]{display:none}
.depot-pop-head{display:flex;gap:6px;margin-bottom:8px}
.depot-all,.depot-multi{
  border:1px solid var(--line);background:var(--surface);border-radius:8px;
  padding:5px 10px;font:inherit;font-size:11.5px;font-weight:600;color:var(--muted);
  cursor:pointer;transition:.14s
}
.depot-all{flex:1}
.depot-all:hover,.depot-multi:hover{border-color:var(--brand);color:var(--brand)}
.depot-all.on,.depot-multi.on{background:var(--brand);border-color:var(--brand);color:#fff}

.depot-chips{display:grid;grid-template-columns:repeat(6,1fr);gap:5px}
.depot-chip{
  border:1px solid var(--line);background:var(--surface);border-radius:8px;
  padding:6px 0;font:inherit;font-size:11.5px;font-weight:600;color:var(--ink-2);
  cursor:pointer;font-variant-numeric:tabular-nums;transition:.12s
}
.depot-chip:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-soft)}
.depot-chip.on{background:var(--brand);border-color:var(--brand);color:#fff;
  box-shadow:0 2px 6px -2px rgba(37,99,235,.7)}
.depot-note{margin:8px 0 0;font-size:10.5px;line-height:1.5;color:var(--muted)}
.depot-note b{color:var(--ink-2)}

/* Said on the row itself, because a layer that cannot be narrowed by depot
   looks like a broken filter otherwise. */
.lyr-alldepots{color:#0e7490;background:#ecfeff;border:1px solid #a5f3fc;
  border-radius:20px;padding:0 5px;font-size:9px;font-weight:700}

/* ===================== Adjustable layer tint =====================
   Only appears while the layer is on: an intensity slider for something that
   is not drawn is a control with nothing on the other end of it. */
.lyr{flex-wrap:wrap}
.lyr-tint{display:none;flex-basis:100%;align-items:center;gap:10px;
  margin:6px 0 2px 21px;padding:7px 9px;border-radius:9px;
  background:var(--surface);border:1px solid var(--line)}
.lyr.on .lyr-tint{display:flex}
.tint-swatches{display:flex;gap:4px;flex:none}
.tint-sw{width:15px;height:15px;border-radius:5px;border:2px solid transparent;
  box-shadow:0 0 0 1px rgba(2,6,23,.15) inset;cursor:pointer;padding:0;transition:.12s}
.tint-sw:hover{transform:scale(1.15)}
.tint-sw.on{border-color:var(--ink);transform:scale(1.15)}
.tint-range{display:flex;align-items:center;gap:6px;flex:1;min-width:0;cursor:pointer}
.tint-range>span{font-size:10px;color:var(--muted);flex:none}
.tint-range input[type="range"]{flex:1;min-width:0;height:3px;accent-color:var(--brand);cursor:pointer}
.tint-val{font-size:10px;color:var(--muted);font-variant-numeric:tabular-nums;
  min-width:26px;text-align:right;flex:none}

@media (max-width:640px){
  .depot-chips{grid-template-columns:repeat(5,1fr)}
}


/* ===================== Print composer =====================
   The frame is a live preview, not an illustration of one: it is exactly the
   ground that ends up on the sheet, so it is dragged on the map itself rather
   than nudged with numbers in the dialog. */
.prt-sel{
  position:absolute;left:0;top:0;z-index:6;display:none;
  border:2px solid var(--brand);border-radius:2px;
  box-shadow:0 0 0 1px rgba(255,255,255,.9) inset
}
.prt-sel.show{display:block}
/* One element dims the entire rest of the map — cheaper and crisper than
   four positioned mask panels, and it can never leave a seam. */
.prt-dim{position:absolute;inset:0;pointer-events:none;
  box-shadow:0 0 0 12000px rgba(15,23,42,.42)}
.prt-grab{position:absolute;inset:0;cursor:move}
.prt-h{
  position:absolute;width:15px;height:15px;background:#fff;
  border:2px solid var(--brand);border-radius:3px;
  box-shadow:0 1px 4px rgba(2,6,23,.4)
}
.prt-nw{left:-8px;top:-8px;cursor:nwse-resize}
.prt-ne{right:-8px;top:-8px;cursor:nesw-resize}
.prt-se{right:-8px;bottom:-8px;cursor:nwse-resize}
.prt-sw{left:-8px;bottom:-8px;cursor:nesw-resize}
.prt-sel.dragging{border-color:var(--brand2, #0d9488)}
/* While the frame is up the map must not also pan under the drag. */
body.printing .maplibregl-canvas{cursor:default}

.prt-modal .modal-card{width:min(430px,calc(100vw - 24px));padding:0;overflow:hidden;
  display:flex;flex-direction:column;max-height:min(88vh,780px)}
/* The composer is a side panel wearing a modal's clothes, and the difference
   matters: the whole point of it is to drag a frame on the map WHILE it is
   open. Inheriting .modal gave it a full-screen scrim at z-index 20, which
   sat between the operator and the map and swallowed every pointer event
   aimed at the frame — the frame was visible and completely dead.

   So the backdrop keeps its layout job and gives up its two others: no scrim,
   no blur, and no pointer events. Hit testing falls straight through it to
   the frame underneath, while the card itself takes events back. The map also
   stays pannable and zoomable, which is what you want when the frame is a
   preview of the plot rather than a dialog control. */
.prt-modal{
  align-items:center;justify-content:flex-start;padding-left:24px;
  background:none;-webkit-backdrop-filter:none;backdrop-filter:none;
  pointer-events:none
}
.prt-modal .modal-card{pointer-events:auto}
.prt-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;
  padding:18px 20px 12px;border-bottom:1px solid var(--line)}
.prt-head h2{margin:0;font-size:17px}
.prt-sub{margin:3px 0 0;font-size:11.5px;color:var(--muted);line-height:1.45}
.prt-body{padding:14px 20px 4px;overflow-y:auto;flex:1}
.prt-l{display:block;font-size:10.5px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--muted);margin:12px 0 5px}
.prt-l:first-child{margin-top:0}
.prt-l b{float:right;font-weight:600;letter-spacing:0;text-transform:none;color:var(--ink-2)}
.prt-in{width:100%;border:1px solid var(--line);border-radius:9px;padding:8px 11px;
  font:inherit;font-size:12.5px;background:var(--surface-2);outline:none}
.prt-in:focus{border-color:var(--brand);background:var(--surface);
  box-shadow:0 0 0 3px rgba(37,99,235,.12)}

.prt-seg{display:flex;border:1px solid var(--line);border-radius:9px;overflow:hidden}
.prt-seg button{flex:1;border:0;border-right:1px solid var(--line);background:var(--surface);
  padding:7px 2px;font:inherit;font-size:11.5px;color:var(--muted);cursor:pointer;transition:.12s}
.prt-seg button:last-child{border-right:0}
.prt-seg button:hover{background:var(--surface-2);color:var(--ink)}
.prt-seg button.on{background:var(--brand);color:#fff;font-weight:600}

.prt-checks{display:flex;gap:14px;flex-wrap:wrap}
.prt-checks label{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--ink-2);cursor:pointer}
.prt-checks input{accent-color:var(--brand);cursor:pointer}
.prt-range{width:100%;accent-color:var(--brand);cursor:pointer}

/* ---- legend editor ---- */
.prt-leg-wrap[hidden]{display:none}
.prt-l .prt-mini{
  float:right;border:1px solid var(--line);background:var(--surface);border-radius:6px;
  padding:2px 7px;font:inherit;font-size:9.5px;font-weight:600;letter-spacing:0;
  text-transform:none;color:var(--muted);cursor:pointer;margin-top:-3px
}
.prt-l .prt-mini:hover{border-color:var(--brand);color:var(--brand)}
.prt-leg{display:flex;flex-direction:column;gap:5px;margin-top:7px}
.prt-leg-row{display:flex;align-items:center;gap:6px}
/* A native colour well, trimmed of the chrome browsers wrap it in. */
.prt-leg-c{
  flex:none;width:28px;height:28px;padding:0;border:1px solid var(--line);
  border-radius:7px;background:none;cursor:pointer
}
.prt-leg-c::-webkit-color-swatch-wrapper{padding:2px}
.prt-leg-c::-webkit-color-swatch{border:0;border-radius:5px}
.prt-leg-c::-moz-color-swatch{border:0;border-radius:5px}
.prt-leg-s{
  flex:none;width:66px;border:1px solid var(--line);border-radius:7px;
  padding:5px 4px;font:inherit;font-size:11px;background:var(--surface);
  color:var(--ink-2);cursor:pointer
}
.prt-leg-t{
  flex:1;min-width:0;border:1px solid var(--line);border-radius:7px;
  padding:5px 8px;font:inherit;font-size:11.5px;background:var(--surface-2);outline:none
}
.prt-leg-t:focus{border-color:var(--brand);background:var(--surface)}
.prt-leg-x{
  flex:none;width:24px;height:24px;border:0;border-radius:6px;background:none;
  color:var(--muted);font-size:11px;cursor:pointer
}
.prt-leg-x:hover{background:#fee2e2;color:var(--bad)}
.prt-leg-empty{font-size:11px;color:var(--muted);font-style:italic;padding:4px 0}
.prt-add{
  width:100%;margin-top:6px;border:1px dashed var(--line-strong);background:none;
  border-radius:8px;padding:6px;font:inherit;font-size:11.5px;font-weight:600;
  color:var(--muted);cursor:pointer;transition:.14s
}
.prt-add:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-soft)}
.prt-leg-note{margin:6px 0 0;font-size:10px;line-height:1.45;color:var(--muted)}
/* Saying which of the two modes the list is in is the whole trick: an
   operator who edits one label needs to know the map has stopped driving it. */
.prt-leg-note.held{color:var(--brand);font-weight:600}

.prt-readout{margin:14px 0 4px;padding:10px 12px;border-radius:10px;
  background:var(--surface-2);border:1px solid var(--line)}
.prt-ro{display:flex;justify-content:space-between;gap:12px;font-size:11.5px;
  color:var(--muted);padding:2px 0}
.prt-ro b{color:var(--ink);font-variant-numeric:tabular-nums;font-weight:600}
.prt-warn{margin-top:8px;padding-top:8px;border-top:1px solid var(--line);
  font-size:10.5px;line-height:1.5;color:#b45309}

.prt-foot{border-top:1px solid var(--line);padding:12px 20px 16px;background:var(--surface)}
.prt-msg{font-size:11.5px;color:var(--muted);min-height:16px;margin-bottom:8px;word-break:break-word}
.prt-msg.ok{color:var(--ok);font-weight:600}
.prt-msg.err{color:var(--bad);font-weight:600}
.prt-btns{display:flex;gap:8px;justify-content:flex-end}
.prt-btns button{border:0;border-radius:9px;padding:9px 14px;font:inherit;font-size:12.5px;
  font-weight:600;cursor:pointer;background:var(--brand);color:#fff}
.prt-btns .ghost{background:var(--surface-3);color:var(--muted)}
.prt-btns button:disabled{opacity:.55;cursor:progress}
/* A0 at 300 dpi is tens of seconds of work — the dialog says so by going
   quiet rather than looking hung. */
.prt-modal.working .prt-body{opacity:.45;pointer-events:none}

@media (max-width:640px){
  .prt-modal{padding-left:0;align-items:flex-end}
  /* On a phone the card is docked to the bottom, so its height is directly
     how much map is left to frame in. 82vh left a band too thin to drag a
     rectangle in at all. */
  .prt-modal .modal-card{width:100vw;max-height:58vh;border-radius:16px 16px 0 0}
  .prt-h{width:22px;height:22px}
  .prt-nw{left:-11px;top:-11px} .prt-ne{right:-11px;top:-11px}
  .prt-se{right:-11px;bottom:-11px} .prt-sw{left:-11px;bottom:-11px}
}

/* ============ Lightbox ============
   Hidden with visibility rather than display, so the fade has something to
   animate and — the part that matters — so the closed overlay never sits on
   top of the map eating clicks. Anything full-screen here follows the same
   three-property rule: opacity + visibility + pointer-events. */
.lightbox{position:fixed;inset:0;z-index:30;background:rgba(2,6,23,.92);display:flex;
  align-items:center;justify-content:center;cursor:zoom-out;touch-action:none;
  opacity:0;visibility:hidden;pointer-events:none;
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  transition:opacity .18s ease,visibility 0s .18s}
.lightbox.show{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .18s ease}
.lightbox img{max-width:92vw;max-height:86vh;border-radius:10px;box-shadow:0 24px 60px -20px #000;
  transform:scale(.96);opacity:0;
  transition:transform .22s cubic-bezier(.22,.7,.3,1),opacity .18s ease;
  touch-action:none;-webkit-user-select:none;user-select:none}
.lightbox.show img{transform:none;opacity:1}
/* While the next full-size file decodes, hold the frame instead of blanking
   it — a swap that flashes empty reads as a stall. */
.lightbox.is-busy img{opacity:.45}
.lightbox.is-busy:before{
  content:"";position:absolute;width:34px;height:34px;border-radius:50%;
  border:3px solid rgba(255,255,255,.22);border-top-color:#fff;
  animation:lbSpin .7s linear infinite;pointer-events:none;z-index:2
}
@keyframes lbSpin{to{transform:rotate(360deg)}}
.lb-nav{position:absolute;top:50%;transform:translateY(-50%);border:0;background:rgba(255,255,255,.14);
  color:#fff;width:46px;height:64px;border-radius:12px;font-size:28px;cursor:pointer;
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);transition:background .15s}
.lb-nav:hover{background:rgba(255,255,255,.28)}
.lb-nav[hidden]{display:none}
#lightboxPrev{left:20px} #lightboxNext{right:20px}
.lb-close{position:absolute;top:16px;right:18px;z-index:2;border:0;border-radius:10px;
  background:rgba(255,255,255,.14);color:#fff;width:40px;height:40px;font-size:18px;
  cursor:pointer;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);transition:background .15s}
.lb-close:hover{background:rgba(255,255,255,.3)}
.lb-cap{position:absolute;bottom:22px;left:0;right:0;text-align:center;color:#cbd5e1;font-size:12.5px;
  pointer-events:none}

/* Nothing behind a full-screen viewer needs to keep painting: the wet-outfall
   sheen and bob are infinite, and running them under an opaque overlay is
   compositing work that buys nothing and costs frames on a phone. */
body.lb-open,body.doc-open{overflow:hidden}
body.lb-open .ofx-hero.wd-wet:after,
body.doc-open .ofx-hero.wd-wet:after,
body.lb-open .ofx-hero.wd-wet .ofx-hero-ico,
body.doc-open .ofx-hero.wd-wet .ofx-hero-ico{animation:none}

/* ============ Layer download menu (item 8) ============ */
.dl{border:0;background:none;color:var(--muted);font-size:14px;cursor:pointer;padding:2px 4px;
  border-radius:6px;opacity:.75}
.dl:hover{opacity:1;color:var(--brand);background:var(--brand-soft)}
.dl-menu{position:fixed;z-index:25;background:var(--surface);border:1px solid var(--line);border-radius:11px;
  box-shadow:var(--shadow);padding:5px;min-width:216px}
.dl-menu-h{font-size:10.5px;color:var(--muted);padding:6px 10px 7px;border-bottom:1px solid var(--line);
  margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dl-menu button,.dl-menu a{display:block;width:100%;text-align:left;border:0;background:none;
  padding:8px 10px;border-radius:8px;font:inherit;font-size:12.5px;color:var(--ink);
  cursor:pointer;text-decoration:none}
.dl-menu button:hover,.dl-menu a:hover{background:var(--brand-soft);color:var(--brand)}

#labelsBtn.on{background:var(--brand-soft);border-color:#bfdbfe;color:var(--brand);font-weight:600}
.sum-btns{display:flex;gap:5px}
.sum-btns button{border:1px solid var(--line);background:var(--surface);border-radius:8px;font-size:11px;
  padding:4px 8px;cursor:pointer;color:var(--muted)}
.sum-btns button:hover{background:var(--surface-2);color:var(--ink)}
#sumXlsx{color:var(--brand);border-color:#bfdbfe}

/* ============ Small screens: drawer becomes a bottom sheet ============ */
@media (max-width:860px){
  .insp{top:auto;left:0;right:0;bottom:0;width:auto;height:76vh;border-left:0;
    border-top:1px solid var(--line);border-radius:18px 18px 0 0;
    transform:translateY(100%);box-shadow:0 -14px 40px -18px rgba(2,6,23,.45)}
  .insp.show{transform:translateY(0)}
  .insp-grip{left:50%;top:-24px;transform:translateX(-50%) rotate(-90deg)}
  body.insp-open .basemaps{transform:none}
  body.insp-open .summary,body.insp-open .legend{opacity:0;pointer-events:none;transform:none}
  .gallery{grid-template-columns:repeat(4,1fr)}
}
@media (max-width:640px){
  .lb-nav{width:38px;height:52px;font-size:22px}
  #lightboxPrev{left:8px} #lightboxNext{right:8px}
  .lb-close{top:10px;right:10px;width:36px;height:36px}
  .lightbox img{max-width:100vw;max-height:78vh;border-radius:0}
}

/* ============ Hover metric tooltip (sewer nodes, depot boundaries) ============ */
.hover-tip{
  position:absolute;top:0;left:0;z-index:6;pointer-events:none;
  background:rgba(15,23,42,.94);color:#f8fafc;border-radius:10px;padding:9px 11px;
  font-size:11.5px;line-height:1.35;max-width:280px;
  box-shadow:0 12px 30px -12px rgba(2,6,23,.8);
  opacity:0;transition:opacity .12s
}
.hover-tip.show{opacity:1}
.ht-title{font-weight:700;font-size:12.5px;margin-bottom:5px;color:#fff}
.ht-grid{display:grid;grid-template-columns:auto 1fr;gap:2px 10px}
.ht-k{color:#94a3b8;white-space:nowrap}
.ht-v{color:#f1f5f9;font-weight:500;word-break:break-word}

/* ============ Buildings workspace (register / reassign / search) ============ */
.modal-card.xwide{width:min(1180px,calc(100vw - 32px));max-width:none;
  max-height:calc(100vh - 32px);overflow:auto;overscroll-behavior:contain}
.bx-tabs{display:flex;gap:4px;margin:14px 0 12px;border-bottom:1px solid var(--line)}
.bx-tab{border:0;background:none;padding:9px 14px;font:inherit;font-size:13px;font-weight:600;
  color:var(--muted);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
.bx-tab:hover{color:var(--ink)}
.bx-tab.on{color:var(--brand);border-bottom-color:var(--brand)}

.bx-filters{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:12px}
.bx-filters input,.bx-filters select{border:1px solid var(--line);border-radius:9px;padding:8px 11px;
  font:inherit;font-size:12.5px;background:var(--surface);color:var(--ink);outline:none}
.bx-filters input:focus,.bx-filters select:focus{border-color:var(--brand);box-shadow:0 0 0 3px rgba(37,99,235,.12)}
.bx-filters input[type=search]{flex:1;min-width:190px}
.bx-spacer{flex:1}
.bx-stat{font-size:12px;color:var(--muted);white-space:nowrap}
.bx-stat b{color:var(--ink)}

/* ============ HSC building: CMCs in this building (portal's table) ============ */
.hsc-cmc-open{width:100%;margin-top:2px}
.cmc-card{display:flex;flex-direction:column;overflow:hidden}
.cmc-sub{margin:4px 0 0;font-size:12.5px;color:var(--muted)}
.cmc-filters{margin:14px 0 10px}
.cmc-filters label{display:flex;flex-direction:column;gap:3px;font-size:10.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
.cmc-filters .btn-ghost{align-self:flex-end;padding:8px 12px}
.cmc-wrap{flex:1;min-height:0;overflow:auto;border:1px solid var(--line);border-radius:10px}
.cmc-tbl{width:100%;border-collapse:collapse;font-size:12.5px}
.cmc-tbl th{position:sticky;top:0;z-index:1;background:var(--surface);text-align:left;padding:8px 9px;
  font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);
  border-bottom:1px solid var(--line);white-space:nowrap;cursor:pointer;user-select:none}
.cmc-tbl th:hover,.cmc-tbl th.on{color:var(--ink)}
.cmc-tbl td{padding:7px 9px;border-bottom:1px solid #f1f5f9;vertical-align:top}
.cmc-tbl tbody tr.r:nth-of-type(even) td{background:#f8fafc}
.cmc-tbl td.n{color:var(--muted);text-align:right;font-variant-numeric:tabular-nums}
.cmc-tbl td.addr{min-width:210px}
.cmc-tbl td.nw{white-space:nowrap}
.cmc-due{font-weight:650;font-variant-numeric:tabular-nums;white-space:nowrap}
.cmc-due.nz{color:#b91c1c}
.cmc-due.z{color:var(--muted);font-weight:400}
.cmc-meta{display:block;font-size:11px;color:var(--muted)}
.cmc-tog{border:0;background:none;padding:0;color:var(--brand);cursor:pointer;font:inherit;font-size:11.5px;white-space:nowrap}
.cmc-tog.hl{color:#b91c1c;font-weight:650}
.cmc-bd td{background:#f1f5f9 !important}
.cmc-bd-box{max-width:440px;margin:0 0 4px 30px;font-size:12px}
.cmc-bd-box div{display:flex;justify-content:space-between;gap:16px;padding:2px 0}
.cmc-bd-box .z{color:var(--muted)}
.cmc-bd-box .hl{color:#b91c1c;font-weight:650}
.cmc-bd-box .tot{border-top:1px solid var(--line);margin-top:3px;padding-top:4px;font-weight:700}
.cmc-foot{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;justify-content:space-between;
  margin-top:12px;font-size:12.5px;color:var(--muted)}

.bx-grid{max-height:56vh;overflow:auto;border:1px solid var(--line);border-radius:10px}
.bx-grid table{width:100%;border-collapse:collapse;font-size:12.5px}
.bx-grid th{position:sticky;top:0;z-index:1;background:var(--surface-2);text-align:right;padding:9px 10px;
  font-size:10.5px;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.03em;
  border-bottom:1px solid var(--line);white-space:nowrap;cursor:pointer;user-select:none}
.bx-grid th:first-child,.bx-grid th.txt{text-align:left}
.bx-grid th .sort{opacity:.35;margin-left:3px}
.bx-grid th.nosort{cursor:default;color:#94a3b8}
.bx-grid th.asc .sort,.bx-grid th.desc .sort{opacity:1;color:var(--brand)}
.bx-grid td{padding:7px 10px;text-align:right;border-bottom:1px solid #f1f5f9;
  font-variant-numeric:tabular-nums}
.bx-grid td:first-child,.bx-grid td.txt{text-align:left}
.bx-grid tbody tr:hover{background:var(--surface-2)}
.bx-grid tr.moved{background:#fff7ed}
.bx-grid tr.moved:hover{background:#ffedd5}

.depot-cell{display:flex;align-items:center;gap:6px;justify-content:flex-start}
.depot-pick{border:1px solid var(--line);border-radius:7px;padding:4px 7px;font:inherit;font-size:12px;
  background:var(--surface);color:var(--ink);cursor:pointer;max-width:140px}
.depot-pick:hover{border-color:var(--brand)}
.depot-pick.changed{border-color:#f97316;background:#fff7ed;color:#9a3412;font-weight:600}
.moved-tag{font-size:9.5px;font-weight:700;color:#9a3412;background:#ffedd5;border-radius:20px;
  padding:1px 7px;white-space:nowrap}
.revert{border:0;background:none;color:var(--muted);cursor:pointer;font-size:12px;padding:0 3px}
.revert:hover{color:var(--bad)}

.bx-foot{display:flex;align-items:center;gap:10px;margin-top:12px}
.bx-foot .bx-spacer{flex:1}
.bx-note{font-size:11.5px;color:var(--muted)}
.bx-note.err{color:var(--bad);font-weight:600}
.bx-note.ok{color:var(--ok);font-weight:600}

.auth-pill{display:inline-block;font-size:10px;font-weight:700;padding:1px 7px;border-radius:20px}
.auth-cmwss{background:#dbeafe;color:#1e40af}
.auth-gcc{background:#dcfce7;color:#15803d}
.auth-both{background:#f3e8ff;color:#7e22ce}

@media (max-width:760px){
  .bx-grid{max-height:48vh}
  .bx-filters input[type=search]{min-width:130px}
}

/* The outfall summary tables are meaningful only while that layer is on. */
.summary.hidden{opacity:0;pointer-events:none;visibility:hidden}

/* ============ Editable outfall record fields (update.html) ============ */
.of-row{display:grid;grid-template-columns:38% 1fr;align-items:center;gap:10px}
.of-row>span{font-size:11.5px;color:var(--muted)}
.of-field{width:100%;border:1px solid var(--line);border-radius:8px;padding:7px 9px;
  font:inherit;font-size:12.5px;background:var(--surface);color:var(--ink);outline:none}
.of-field:focus{border-color:var(--brand);box-shadow:0 0 0 3px rgba(37,99,235,.12)}
.of-field:placeholder-shown{color:var(--muted)}
.of-field[data-k="outfall_id"]{font-weight:700}

.btn-danger{border:1px solid #fecaca;background:var(--surface);color:var(--bad);border-radius:10px;
  padding:10px 16px;font:inherit;font-size:13px;font-weight:600;cursor:pointer}
.btn-danger:hover{background:var(--bad);border-color:var(--bad);color:#fff}

/* An <a> standing in for a button in the drawer footer. */
.btn-link{display:inline-flex;align-items:center;text-decoration:none}

/* ============ Presentation rows on the update page ============ */
.doc-row{display:flex;align-items:center;gap:10px;text-decoration:none;color:inherit;
  border:1px solid var(--line);border-radius:10px;padding:9px 11px;margin-bottom:8px;
  background:var(--surface);transition:border-color .15s,background .15s}
.doc-row:last-child{margin-bottom:0}
.doc-row:hover{border-color:var(--brand);background:var(--brand-soft)}
.doc-ico{flex:none;width:38px;height:38px;border-radius:8px;display:grid;place-items:center;
  font-size:10px;font-weight:800;letter-spacing:.04em;color:#fff;background:#c2410c}
.doc-ico.pdf{background:#b91c1c}
.doc-txt{min-width:0;flex:1;display:block}
.doc-txt b{display:block;font-size:12.5px;font-weight:600;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.doc-txt em{display:block;font-style:normal;font-size:11px;color:var(--muted);margin-top:2px}
.doc-dl{flex:none;font-size:15px;color:var(--muted)}
.doc-row:hover .doc-dl{color:var(--brand)}

/* ============ Outfall popup — the minimal, animated view ============
   The drawer opens on the answer (wet or dry), the two notes that only matter
   when it is wet, the photographs and the deck. The fourteen surveyed
   attributes live behind "More details", so the evidence is above the fold
   instead of below a wall of key/value rows.

   The entrance and the flourishes are transform/opacity only. The two
   expanders do animate height, deliberately — see the note above .ofx-drop.
   All of it is dropped under prefers-reduced-motion at the end of the block. */

/* -- the header takes the status colour ------------------------------- */
.insp-head.wd-wet{background:linear-gradient(180deg,#fff1f2,#fff)}
.insp-head.wd-dry{background:linear-gradient(180deg,#f0fdf4,#fff)}
.insp-head.wd-na {background:linear-gradient(180deg,var(--surface-2),#fff)}
.insp-head{transition:background .3s}

/* -- staggered entrance ------------------------------------------------ */
@keyframes ofxUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

.ofx{display:flex;flex-direction:column;gap:14px;padding:14px 0 4px}
.ofx>*{animation:ofxUp .34s cubic-bezier(.22,.7,.3,1) both}
.ofx>*:nth-child(1){animation-delay:.02s}
.ofx>*:nth-child(2){animation-delay:.07s}
.ofx>*:nth-child(3){animation-delay:.12s}
.ofx>*:nth-child(4){animation-delay:.17s}
.ofx>*:nth-child(5){animation-delay:.22s}
.ofx>*:nth-child(6){animation-delay:.27s}

/* -- the hero: is it flowing ------------------------------------------ */
.ofx-hero{
  position:relative;overflow:hidden;display:flex;align-items:center;gap:13px;
  padding:15px 16px;border-radius:14px;border:1px solid transparent;
  box-shadow:0 1px 2px rgba(2,6,23,.05)
}
.ofx-hero-ico{
  flex:none;width:44px;height:44px;border-radius:12px;display:grid;place-items:center;
  font-size:21px;background:rgba(255,255,255,.72);box-shadow:0 1px 3px rgba(2,6,23,.12)
}
.ofx-hero-txt{min-width:0;display:block}
.ofx-hero-txt b{display:block;font-size:19px;font-weight:700;letter-spacing:-.02em;line-height:1.15}
.ofx-hero-txt em{display:block;font-style:normal;font-size:11.5px;opacity:.78;margin-top:2px}

.ofx-hero.wd-wet{background:linear-gradient(120deg,#fee2e2,#fecdd3);border-color:#fecaca;color:#9f1239}
.ofx-hero.wd-dry{background:linear-gradient(120deg,#dcfce7,#d1fae5);border-color:#bbf7d0;color:#14532d}
.ofx-hero.wd-na {background:linear-gradient(120deg,var(--surface-3),var(--surface-2));
  border-color:var(--line);color:var(--muted)}

/* A slow sheen across the wet card — the one place a flourish earns its keep,
   because "wet" is the finding the whole survey exists to catch. */
@keyframes ofxSheen{0%{transform:translateX(-120%)}55%,100%{transform:translateX(220%)}}
.ofx-hero.wd-wet:after{
  content:"";position:absolute;top:0;bottom:0;width:38%;pointer-events:none;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.6),transparent);
  animation:ofxSheen 3.4s ease-in-out 1.1s infinite
}
.ofx-hero.wd-wet .ofx-hero-ico{animation:ofxBob 2.6s ease-in-out infinite}
@keyframes ofxBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}

/* -- note cards -------------------------------------------------------- */
.ofx-notes{display:flex;flex-direction:column;gap:10px}
.ofx-card{
  border:1px solid var(--line);border-left:3px solid var(--line-strong);
  border-radius:11px;padding:11px 13px;background:var(--surface);
  box-shadow:0 1px 2px rgba(2,6,23,.04)
}
.ofx-card.is-reason{border-left-color:var(--bad);background:linear-gradient(180deg,#fff7f7,var(--surface))}
.ofx-card.is-prop  {border-left-color:var(--brand2);background:linear-gradient(180deg,#f2fdfb,var(--surface))}
.ofx-card.is-empty{border-left-color:var(--line);background:var(--surface-2)}
.ofx-lab{display:block;font-size:10.5px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--muted);margin-bottom:5px}
.ofx-card p{font-size:13px;line-height:1.55;color:var(--ink-2);white-space:pre-wrap;margin:0}
.ofx-card.is-empty p{color:var(--muted);font-style:italic;font-size:12.5px}

/* -- section headings -------------------------------------------------- */
.ofx-block{display:block}
.ofx-h{margin:0 0 9px;font-size:10.5px;font-weight:700;color:var(--muted);
  text-transform:uppercase;letter-spacing:.07em;display:flex;align-items:center;gap:7px}
.ofx-n{background:var(--surface-3);color:var(--muted);border-radius:20px;
  padding:1px 8px;font-size:10px;letter-spacing:0}
.ofx-n:empty{display:none}
.ofx-h4{margin:16px 0 8px;font-size:10.5px;font-weight:700;color:var(--muted);
  text-transform:uppercase;letter-spacing:.07em}
.ofx-h4:first-child{margin-top:0}

/* -- photographs: a swipeable strip, not a cramped 3-up grid ---------- */
.ofx-shots{
  display:flex;gap:9px;overflow-x:auto;padding-bottom:5px;
  scroll-snap-type:x mandatory;scrollbar-width:thin
}
.ofx-shots.is-empty{display:block}
.ofx-shot{
  position:relative;margin:0;flex:none;width:132px;border-radius:12px;overflow:hidden;
  border:1px solid var(--line);background:var(--surface-3);cursor:zoom-in;
  scroll-snap-align:start;transition:transform .18s cubic-bezier(.22,.7,.3,1),box-shadow .18s
}
.ofx-shot:hover{transform:translateY(-3px) scale(1.015);box-shadow:0 10px 22px -12px rgba(2,6,23,.55)}
.ofx-shot img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover}
.ofx-shot figcaption{
  position:absolute;left:0;right:0;bottom:0;padding:12px 7px 4px;font-size:9.5px;color:#fff;
  background:linear-gradient(180deg,transparent,rgba(2,6,23,.72))
}

/* -- the deck ---------------------------------------------------------- */
.ofx-doc{border:1px solid var(--line);border-radius:12px;overflow:hidden;
  background:var(--surface);margin-bottom:9px}
.ofx-doc:last-child{margin-bottom:0}
.ofx-doc-row{
  display:flex;align-items:center;gap:11px;width:100%;text-align:left;cursor:pointer;
  border:0;background:transparent;padding:10px 12px;font:inherit;color:inherit;
  transition:background .15s
}
.ofx-doc-row:hover{background:var(--brand-soft)}
.ofx-doc-row.on{background:var(--brand-soft)}
.ofx-doc-ico{
  flex:none;width:40px;height:40px;border-radius:10px;display:grid;place-items:center;
  font-size:10px;font-weight:800;letter-spacing:.04em;color:#fff;background:#c2410c;
  box-shadow:0 2px 6px -2px rgba(194,65,12,.7)
}
.ofx-doc-ico.pdf{background:#b91c1c;box-shadow:0 2px 6px -2px rgba(185,28,28,.7)}
.ofx-doc-txt{min-width:0;flex:1;display:block}
.ofx-doc-txt b{display:block;font-size:12.5px;font-weight:650;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.ofx-doc-txt em{display:block;font-style:normal;font-size:10.5px;color:var(--muted);margin-top:2px}
.ofx-doc-caret{flex:none;color:var(--muted);font-size:15px;transition:transform .25s cubic-bezier(.22,.7,.3,1)}
.ofx-doc-row.on .ofx-doc-caret{transform:rotate(180deg)}

.ofx-frame{position:relative;background:#0f172a;aspect-ratio:16/10}
.ofx-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.ofx-noview{padding:13px;background:var(--warn-soft);border-top:1px solid var(--line)}
.ofx-noview b{display:block;font-size:12.5px;color:var(--warn);margin-bottom:5px}
.ofx-noview span{display:block;font-size:11.5px;line-height:1.55;color:var(--ink-2)}
.ofx-noview code{font-family:var(--mono);font-size:11px;background:var(--surface);
  border:1px solid var(--line);border-radius:5px;padding:0 4px}

.ofx-viewbar{display:flex;gap:7px;padding:9px 11px;border-top:1px solid var(--line);
  background:var(--surface-2);flex-wrap:wrap}
.ofx-vb{
  border:1px solid var(--line);background:var(--surface);border-radius:8px;
  padding:5px 10px;font:inherit;font-size:11.5px;font-weight:600;color:var(--ink-2);
  cursor:pointer;text-decoration:none;transition:.15s
}
.ofx-vb:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-soft)}

/* -- "More details" ---------------------------------------------------- */
.ofx-more{
  display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
  border:1px dashed var(--line-strong);background:var(--surface);border-radius:11px;
  padding:11px;font:inherit;font-size:12.5px;font-weight:650;color:var(--muted);
  cursor:pointer;transition:.18s
}
.ofx-more:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-soft)}
.ofx-more.on{border-style:solid;border-color:var(--brand-line);color:var(--brand);
  background:var(--brand-soft)}
.ofx-caret{font-style:normal;font-size:14px;line-height:1;
  transition:transform .28s cubic-bezier(.22,.7,.3,1)}
.ofx-more.on .ofx-caret{transform:rotate(180deg)}

/* Height is animated from a measured pixel value, then released to auto — see
   slide() in inspector.js. The tidier grid-template-rows 0fr-to-1fr trick was
   tried first and collapses here: .ofx-drop is a column-flex item, so the fr
   track has no indefinite height to resolve against and the row stayed at the
   padding. A measured height also never clips a long record, which a guessed
   max-height eventually would. */
.ofx-drop{height:0;overflow:hidden;transition:height .32s cubic-bezier(.22,.7,.3,1)}
.ofx-drop>.ofx-drop-in{opacity:0;transition:opacity .22s}
.ofx-drop.open>.ofx-drop-in{opacity:1}
#ofMoreBody>.ofx-drop-in{padding:4px 2px 2px}

/* -- skeletons, so the drawer never flashes empty --------------------- */
@keyframes ofxPulse{0%,100%{opacity:.55}50%{opacity:1}}
.skel{background:linear-gradient(90deg,var(--surface-3),var(--surface-2),var(--surface-3));
  border-color:transparent;animation:ofxPulse 1.3s ease-in-out infinite;pointer-events:none}
.ofx-card.skel{height:58px}
.ofx-card.skel.sm{height:44px}
.ofx-shot.skel{height:99px}
.skel>*{visibility:hidden}

/* -- the deck at reading size ----------------------------------------- */
/* The viewer overlay. It is created once and then reused, so the closed state
   MUST give up hit testing: with opacity alone it stayed stretched across the
   whole viewport at z-index 40 and swallowed every click on the map after the
   first PDF was closed — the page looked frozen. */
.docmodal{
  position:fixed;inset:0;z-index:40;background:rgba(2,6,23,.86);display:grid;place-items:center;
  padding:22px;opacity:0;visibility:hidden;pointer-events:none;
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  transition:opacity .2s,visibility 0s .2s
}
.docmodal.show{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .2s}
.docmodal-card{
  width:min(1180px,100%);height:min(88vh,100%);background:var(--surface);
  border-radius:14px;overflow:hidden;display:flex;flex-direction:column;
  box-shadow:0 30px 80px -30px #000;transform:scale(.97);transition:transform .22s cubic-bezier(.22,.7,.3,1)
}
.docmodal.show .docmodal-card{transform:none}
.docmodal-card header{
  display:flex;align-items:center;gap:10px;padding:10px 12px;border-bottom:1px solid var(--line);
  background:var(--surface-2)
}
.docmodal-card header b{flex:1;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.docmodal-card iframe{flex:1;width:100%;border:0;display:block;background:#0f172a}

@media (max-width:860px){
  .docmodal{padding:0}
  .docmodal-card{height:100%;border-radius:0}
  .ofx-shot{width:118px}
}

/* Motion is decoration here; the drawer is fully usable without any of it. */
@media (prefers-reduced-motion: reduce){
  .ofx>*,.ofx-hero.wd-wet:after,.ofx-hero.wd-wet .ofx-hero-ico,.skel{animation:none}
  .ofx-drop,.ofx-caret,.ofx-doc-caret,.ofx-shot,.docmodal,.docmodal-card,
  .lightbox,.lightbox img{transition:none}
  .lightbox img{transform:none}
  .lightbox.is-busy:before{animation:none}
  .ofx-hero.wd-wet:after{display:none}
}

/* ============ Street rename / locate in the register ============ */
.street-cell{display:flex;align-items:center;gap:6px;min-width:0}
.street-cell b{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.street-cell .unnamed{color:#9a3412;font-style:italic}
.street-act{border:0;background:none;color:var(--muted);cursor:pointer;font-size:12px;
  padding:1px 3px;border-radius:5px;opacity:0;transition:.12s}
tr:hover .street-act{opacity:.8}
.street-act:hover{opacity:1;color:var(--brand);background:var(--brand-soft)}
.renamed-tag{font-size:9.5px;font-weight:700;color:#1e40af;background:#dbeafe;
  border-radius:20px;padding:1px 7px;white-space:nowrap}

/* Assessment / consumer number lists on a multi-unit building */
.num-list{display:flex;flex-wrap:wrap;gap:4px;margin:2px 0}
.num-chip{font-size:10.5px;font-weight:600;background:#ecfeff;color:#0e7490;
  border:1px solid #a5f3fc;border-radius:6px;padding:1px 6px;
  font-variant-numeric:tabular-nums}

/* Register provenance badges */
.est-tag{font-size:9.5px;font-weight:700;color:#92400e;background:#fef3c7;
  border-radius:20px;padding:1px 7px;white-space:nowrap}
.merge-tag{font-size:9.5px;font-weight:700;color:#3730a3;background:#e0e7ff;
  border-radius:20px;padding:1px 7px;white-space:nowrap}

/* Direct-download link styled as a button */
.dl-link{display:inline-flex;align-items:center;text-decoration:none;
  line-height:1;padding:10px 16px}
.dl-link.disabled{opacity:.45;pointer-events:none}

/* Clickable legend entries */
.legend .li-click{cursor:pointer;border-radius:6px;padding:2px 5px;margin-left:-5px;
  transition:background .12s}
.legend .li-click:hover{background:var(--surface-3)}
.legend .li-click.on{background:#1e293b;color:#fff;font-weight:600}

/* ============ Correlating an unmatched CMC with a building ============ */
.corr-opt{display:block;width:100%;text-align:left;border:1px solid var(--line);
  background:var(--surface);border-radius:10px;padding:9px 11px;margin-bottom:6px;
  font:inherit;cursor:pointer;position:relative}
.corr-opt:hover{border-color:var(--brand);background:var(--brand-soft)}
.corr-opt:disabled{opacity:.5;cursor:wait}
.corr-opt b{display:block;font-size:12.5px}
.corr-opt span{display:block;font-size:11px;color:var(--muted);margin-top:2px}
.corr-opt em{position:absolute;top:9px;right:11px;font-size:10px;font-style:normal;
  color:#0e7490;background:#ecfeff;border:1px solid #a5f3fc;border-radius:6px;padding:1px 6px}
.corr-done{background:#dcfce7;border:1px solid #86efac;border-radius:10px;padding:10px 12px}
.corr-done b{display:block;font-size:12.5px;color:#15803d}
.corr-done span{display:block;font-size:11px;color:#166534;margin:2px 0 6px}

/* ============ CMC matching workspace ============ */

/* Headline strip: what is done, what is left, and on what evidence. */
.mw-stats{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:0 0 12px;
  padding:11px 13px;background:var(--surface-2);border:1px solid var(--line);border-radius:12px}
.mw-stats .stat{display:flex;flex-direction:column;gap:1px;padding:0 14px 0 0;
  border-right:1px solid var(--line);margin-right:6px}
.mw-stats .stat:last-of-type{border-right:0}
.mw-stats .stat b{font-size:16px;font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.mw-stats .stat span{font-size:10.5px;color:var(--muted)}
.mw-stats .stat.ok b{color:var(--ok)}
.mw-stats .stat.warn b{color:#b45309}
.mw-stats .stat.hand b{color:#7e22ce}
.mw-prog{flex:1;min-width:120px;height:7px;background:var(--line);border-radius:7px;overflow:hidden}
.mw-prog i{display:block;height:100%;background:linear-gradient(90deg,#16a34a,#22c55e);transition:width .3s}

/* Two panes: the queue on the left, the whole decision on the right. */
.mw{display:grid;grid-template-columns:280px 1fr;gap:12px;height:min(56vh,460px);min-height:300px}
.mw-list{overflow-y:auto;border:1px solid var(--line);border-radius:11px;background:var(--surface)}
.mw-detail{overflow-y:auto;border:1px solid var(--line);border-radius:11px;background:var(--surface);padding:14px 16px}

.mq-item{display:block;width:100%;text-align:left;border:0;border-bottom:1px solid #f1f5f9;
  background:none;padding:9px 12px;font:inherit;cursor:pointer;border-left:3px solid transparent}
.mq-item:hover{background:var(--surface-2)}
.mq-item.on{background:var(--brand-soft);border-left-color:var(--brand)}
.mq-item.done{background:var(--ok-soft);border-left-color:var(--ok)}
.mq-item.skipped{opacity:.45}
.mq-item b{display:block;font-size:12px;font-variant-numeric:tabular-nums}
.mq-item span{display:block;font-size:11px;color:var(--muted);margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mq-item em{display:block;font-style:normal;font-size:10px;color:#94a3b8;margin-top:2px}
.mq-item.done em{color:var(--ok);font-weight:700}

.mw-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;
  padding-bottom:12px;border-bottom:1px solid var(--line);margin-bottom:12px}
.mw-head h3{margin:0;font-size:18px;font-weight:700;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.mw-head p{margin:3px 0 0;font-size:12px;color:var(--muted)}

.mw-cols{display:grid;grid-template-columns:minmax(210px,1fr) minmax(320px,1.5fr);gap:18px}
.mw-cols h4{margin:0 0 9px;font-size:10.5px;font-weight:700;color:var(--muted);
  text-transform:uppercase;letter-spacing:.07em;display:flex;align-items:center;gap:8px}
.mw-rec .kv{grid-template-columns:minmax(90px,44%) 1fr}
.mw-keys{color:#94a3b8;font-size:11px}

/* One card per candidate building, carrying the facts that separate them. */
.cand{border:1px solid var(--line);border-radius:11px;padding:11px 12px;margin-bottom:9px;
  transition:.12s}
.cand:hover{border-color:#bfdbfe;background:var(--surface-2)}
.cand-h{display:flex;align-items:center;gap:8px}
.cand-h b{font-size:13px;font-variant-numeric:tabular-nums}
.cand-why{font-size:9.5px;font-weight:700;color:#15803d;background:#dcfce7;
  border-radius:20px;padding:1px 8px;white-space:nowrap}
.cand-key{margin-left:auto;width:19px;height:19px;border-radius:6px;background:var(--surface-3);
  color:var(--muted);font-size:10.5px;font-weight:700;display:grid;place-items:center}
.cand-door{font-size:12px;color:var(--ink);margin-top:4px}
.cand-facts{display:flex;flex-wrap:wrap;gap:4px;margin-top:7px}
.fact{font-size:10px;font-weight:600;color:var(--muted);background:var(--surface-3);
  border-radius:5px;padding:1px 6px;white-space:nowrap}
.fact.busy{background:#fef3c7;color:#92400e}
.fact.free{background:#dcfce7;color:#15803d}
.fact.idc{background:#fef3c7;color:#b45309}
.fact.gap{background:#fee2e2;color:#b91c1c}
.cand-acts{display:flex;gap:6px;margin-top:10px}
.cand-acts .btn-primary,.cand-acts .btn-ghost{padding:7px 13px;font-size:12px;border-radius:9px}
.fact.unknown{background:var(--surface);border:1px dashed var(--line);color:#94a3b8}

/* The leader is marked, never auto-selected — the operator still decides. */
.cand.best{border-color:#86efac;background:var(--ok-soft);box-shadow:0 0 0 3px rgba(22,163,74,.08)}
.cand.best:hover{background:var(--ok-soft)}
.cand-best{font-size:9.5px;font-weight:700;color:#15803d;background:#dcfce7;
  border:1px solid #86efac;border-radius:20px;padding:1px 8px;white-space:nowrap}
.cand-score{margin-left:auto;min-width:30px;height:22px;border-radius:7px;padding:0 7px;
  display:grid;place-items:center;font-size:12px;font-weight:700;font-variant-numeric:tabular-nums}
.cand-score.hi{background:#dcfce7;color:#15803d}
.cand-score.mid{background:#fef3c7;color:#92400e}
.cand-score.lo{background:var(--surface-3);color:#94a3b8}
.cand-h .cand-key{margin-left:0}

/* Why it scores what it scores — the figures, not just the verdict. */
.cand-why-box{margin-top:9px;border-top:1px solid #f1f5f9;padding-top:8px}
.cand-why-box summary{font-size:10.5px;font-weight:700;color:var(--muted);cursor:pointer;
  text-transform:uppercase;letter-spacing:.05em;list-style:none}
.cand-why-box summary::-webkit-details-marker{display:none}
.cand-why-box summary:before{content:"▸ ";color:#94a3b8}
.cand-why-box[open] summary:before{content:"▾ "}
.cand-why-box summary:hover{color:var(--ink)}
.sigs{margin-top:6px;display:flex;flex-direction:column;gap:2px}
.sig{display:grid;grid-template-columns:14px 62px 1fr auto;gap:7px;align-items:baseline;
  font-size:11px;padding:2px 0}
.sig-m{font-weight:700;text-align:center}
.sig-k{color:var(--muted);font-weight:600}
.sig-d{color:var(--ink)}
.sig-p{color:#94a3b8;font-variant-numeric:tabular-nums;font-size:10px}
.sig.good .sig-m{color:var(--ok)}
.sig.fair .sig-m{color:#b45309}
.sig.bad .sig-m{color:var(--bad)}
.sig.bad .sig-d{color:#b91c1c}
.sig.unknown .sig-m{color:#94a3b8}
.sig.unknown .sig-d{color:var(--muted);font-style:italic}

/* What is already on the candidate — the crux when it is not empty. */
.cand-has{margin-top:9px;background:var(--surface-2);border-radius:9px;padding:8px 10px}
.cand-has.empty{color:#15803d;background:var(--ok-soft);font-size:11.5px;font-weight:600}
.cand-has h5{margin:0 0 5px;font-size:10.5px;font-weight:700;color:var(--muted);
  text-transform:uppercase;letter-spacing:.04em}
.has-row{display:grid;grid-template-columns:auto auto auto auto 1fr;gap:8px;font-size:10.5px;
  padding:2px 0;border-top:1px solid #eef2f7;align-items:baseline}
.has-row:first-of-type{border-top:0}
.has-row b{font-variant-numeric:tabular-nums;font-weight:600}
.has-row span{color:var(--muted);white-space:nowrap}
.has-row em{font-style:normal;color:#94a3b8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.has-note{font-size:10px;color:#b45309;margin-top:5px;line-height:1.35}
.mw-hint{font-size:10px;font-weight:600;color:#94a3b8;text-transform:none;letter-spacing:0}

.bx-grid tr.pending{background:var(--warn-soft)}
.bx-grid tr.pending:hover{background:#fef3c7}

@media (max-width:1000px){
  .mw{grid-template-columns:1fr;height:auto}
  .mw-list{max-height:200px}
  .mw-cols{grid-template-columns:1fr}
}

/* ============================ workspace overview ============================
   The Buildings & CMC landing view. Deliberately plain: every figure is a
   published one, and the bars exist to make the shape of a distribution
   readable at a glance, not to decorate it. */
.ov-wrap{padding:14px 16px 18px;overflow:auto;max-height:calc(90vh - 132px)}
.ov-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:12px;margin:14px 0}
.ov-card{border:1px solid var(--line);border-radius:10px;padding:10px 12px 12px;
  background:var(--panel)}
.ov-card h4{margin:0 0 8px;font-size:12px;font-weight:700;letter-spacing:.01em;
  color:var(--ink)}
.ov-table{width:100%;border-collapse:collapse;font-size:12px}
.ov-table th{text-align:left;font-weight:500;color:var(--ink);padding:3px 8px 3px 0;
  white-space:nowrap}
.ov-table td{padding:3px 0}
.ov-n{text-align:right;padding-right:10px !important;font-variant-numeric:tabular-nums;
  color:var(--ink);white-space:nowrap}
.ov-pct{text-align:right;padding-left:8px !important;font-variant-numeric:tabular-nums;
  color:var(--muted);white-space:nowrap;width:44px}
.ov-bar{width:100%}
.ov-bar i{display:block;height:7px;border-radius:4px;background:var(--brand);
  min-width:2px;transition:width .2s}
.ov-bar i.ok{background:var(--ok)}
.ov-bar i.warn{background:#d97706}
.ov-depots th{font-variant-numeric:tabular-nums}
.ov-foot{margin:12px 0 0;font-size:11px;color:var(--muted)}
.ov-foot code{font-size:10.5px}
@media (max-width:900px){ .ov-grid{grid-template-columns:1fr} }
.ov-sub{font-weight:400;color:var(--muted);font-size:10.5px}
.ov-scroll{overflow-x:auto}
.ov-assets td,.ov-assets th{white-space:nowrap;padding-right:10px}
.ov-off{color:#b45309;font-weight:600}

/* ========================= Drawing Maker =========================
   A right-hand working panel rather than a modal: the whole point is to click
   on the map with it open, which a modal's backdrop makes impossible. It docks
   opposite the layer panel and shares the inspector's width so the two never
   both claim the same edge. */
.dw-panel{
  position:fixed;top:0;right:0;bottom:0;width:var(--insp-w);max-width:100vw;z-index:9;
  background:var(--panel);display:flex;flex-direction:column;
  box-shadow:-14px 0 40px -18px rgba(2,6,23,.45);
  border-left:1px solid var(--line);
  transform:translateX(100%);transition:transform .3s cubic-bezier(.22,.7,.3,1);
}
.dw-panel.show{transform:translateX(0)}
body.dw-open .basemaps{transform:translateX(calc(-1 * var(--insp-w)))}
body.dw-open .summary,
body.dw-open .legend{opacity:0;pointer-events:none;transform:translateX(-40px)}

.dw-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;
  padding:16px 18px 13px;border-bottom:1px solid var(--line);
  background:linear-gradient(180deg,var(--surface-2),var(--surface))}
.dw-head h2{margin:0;font-size:19px;font-weight:700;letter-spacing:-.02em;color:var(--ink)}
.dw-sub{margin:3px 0 0;font-size:12px;color:var(--muted)}

.dw-tools{display:grid;grid-template-columns:1fr 1fr;gap:6px;padding:12px 16px 8px}
.dw-tool{display:flex;align-items:center;gap:7px;border:1px solid var(--line);border-radius:9px;
  background:var(--surface);padding:8px 10px;font:inherit;font-size:12px;color:var(--ink-2);
  cursor:pointer;transition:.12s;text-align:left}
.dw-tool:hover{background:var(--surface-2);border-color:var(--line-strong)}
.dw-tool.on{border-color:var(--brand);background:var(--brand-soft);color:var(--brand);font-weight:600;
  box-shadow:0 0 0 3px rgba(37,99,235,.12)}
.dw-swatch{width:11px;height:11px;border-radius:3px;flex:none;
  box-shadow:0 0 0 1px rgba(15,23,42,.18)}

/* Only present while a tool is armed — a permanent instruction line becomes
   invisible after the second use. */
.dw-hint{margin:0;padding:0 16px;font-size:11.5px;color:var(--muted);
  max-height:0;overflow:hidden;transition:max-height .18s,padding .18s}
.dw-hint.on{max-height:44px;padding:2px 16px 8px;color:var(--brand)}

.dw-list{flex:1;overflow-y:auto;padding:6px 16px 10px}
.dw-blank{padding:22px 8px;text-align:center;font-size:12.5px;color:var(--muted);line-height:1.7}
.dw-blank span{font-size:11.5px;color:var(--faint)}

.dw-card{border:1px solid var(--line);border-radius:11px;padding:10px 11px;margin-bottom:9px;
  background:var(--surface)}
.dw-card-top{display:flex;align-items:center;gap:8px}
.dw-ref{flex:none;min-width:26px;height:22px;border-radius:6px;color:#fff;font-size:11.5px;
  font-weight:700;display:flex;align-items:center;justify-content:center;padding:0 6px}
.dw-card-t{flex:1;min-width:0;display:flex;flex-direction:column;line-height:1.35}
.dw-card-t b{font-size:12.5px;font-weight:600;color:var(--ink)}
.dw-card-t span{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.dw-x{border:0;background:none;color:var(--faint);cursor:pointer;font-size:13px;padding:3px 5px;
  border-radius:6px;line-height:1}
.dw-x:hover{background:var(--surface-3);color:var(--ink)}

.dw-run{margin-top:7px;font-size:11px;color:var(--muted)}
.dw-run b{color:var(--ink);font-variant-numeric:tabular-nums}
.dw-dims{display:grid;grid-template-columns:repeat(auto-fit,minmax(78px,1fr));gap:6px;margin-top:8px}
.dw-dim{display:flex;align-items:center;gap:4px;border:1px solid var(--line);border-radius:8px;
  padding:4px 6px;background:var(--surface-2)}
.dw-dim span{font-size:10px;color:var(--muted);flex:none}
.dw-dim i{font-size:10px;color:var(--faint);font-style:normal;flex:none}
.dw-dim input{width:100%;min-width:0;border:0;background:none;font:inherit;font-size:12px;
  color:var(--ink);outline:none;text-align:right;font-variant-numeric:tabular-nums}
.dw-vol{margin-top:7px;font-size:11px;color:var(--muted)}
.dw-vol b{color:var(--ink);font-variant-numeric:tabular-nums}
.dw-note{margin-top:8px}
.dw-geo{margin-top:7px;font-size:10.5px;color:var(--faint);font-variant-numeric:tabular-nums}

.dw-job{border-top:1px solid var(--line);padding:11px 16px 4px;background:var(--surface-2)}
.dw-2col{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.dw-l{display:block;font-size:10.5px;font-weight:600;color:var(--muted);
  text-transform:uppercase;letter-spacing:.04em;margin:7px 0 3px}
.dw-in{width:100%;border:1px solid var(--line);border-radius:8px;padding:7px 9px;
  font:inherit;font-size:12.5px;color:var(--ink);background:var(--surface);outline:none}
.dw-in:focus{border-color:var(--brand);box-shadow:0 0 0 3px rgba(37,99,235,.12)}

.dw-foot{border-top:1px solid var(--line);padding:10px 16px 13px;background:var(--surface)}
.dw-msg{min-height:16px;font-size:11.5px;color:var(--muted);margin-bottom:7px}
.dw-msg.ok{color:var(--ok)}
.dw-msg.bad{color:var(--bad,#dc2626)}
.dw-btns{display:flex;flex-wrap:wrap;gap:6px}
.dw-btns button{flex:1 1 auto;border:0;border-radius:9px;padding:9px 10px;font:inherit;font-size:12px;
  font-weight:600;cursor:pointer;background:var(--brand);color:#fff}
.dw-btns button.ghost{background:var(--surface-2);color:var(--ink-2);border:1px solid var(--line);
  font-weight:500}
.dw-btns button.ghost:hover{background:var(--surface-3)}
.dw-btns button.dw-danger:hover{color:#dc2626;border-color:#fecaca;background:#fef2f2}
.dw-btns button:disabled{opacity:.55;cursor:default}

@media (max-width:720px){
  .dw-panel{width:100vw}
  body.dw-open .basemaps{transform:none;opacity:0;pointer-events:none}
}
.dw-tip{margin:0 0 8px;font-size:10.5px;color:var(--faint);line-height:1.5}

/* ---- Drawing Maker: the selected mark ----
   A selected card and the handles on the map are the same state seen twice,
   so they share the accent the handles are drawn in. */
.dw-card.sel{border-color:var(--brand);box-shadow:0 0 0 3px rgba(37,99,235,.12)}
.dw-card{cursor:default}

/* The landmarks the map found in range, one tap each. Offering them as text to
   retype is what makes an operator skip the field altogether. */
.dw-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
.dw-chip{border:1px solid var(--line);background:var(--surface-2);border-radius:20px;
  padding:3px 9px;font:inherit;font-size:10.5px;color:var(--ink-2);cursor:pointer;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dw-chip:hover{border-color:var(--brand);background:var(--brand-soft);color:var(--brand)}

.dw-mini{float:right;border:0;background:none;font:inherit;font-size:10px;font-weight:600;
  color:var(--brand);cursor:pointer;padding:0;text-transform:none;letter-spacing:0}
.dw-mini:hover{text-decoration:underline}

/* Four size boxes across a 380 px panel clipped every value to one digit.
   Two-up wraps to two neat rows and leaves the number room to be read. */
.dw-dims{grid-template-columns:repeat(auto-fit,minmax(112px,1fr))}
.dw-dim{padding:5px 8px}
.dw-dim span{font-size:10.5px}
.dw-dim input{font-size:12.5px;min-width:34px}

/* Turning a pit to lie along the road is one tap, not a number to match by eye. */
.dw-align{margin-top:7px;width:100%;border:1px solid var(--brand-line);border-radius:8px;
  background:var(--brand-soft);color:var(--brand);font:inherit;font-size:11px;font-weight:600;
  padding:6px 8px;cursor:pointer}
.dw-align:hover{background:var(--brand);color:#fff;border-color:var(--brand)}

/* The main the dig is going down to, found on the map rather than typed. */
.dw-main{margin-top:7px;font-size:11px;color:var(--ink-2);background:var(--surface-2);
  border:1px solid var(--line);border-radius:8px;padding:5px 8px}
