/* ============================================================
   MASAR SCADA — map.css
   Leaflet skin, vehicle markers, overlays, HUD panels
   ============================================================ */

.maproot{position:absolute;inset:0}
#lmapMount{position:absolute;inset:0}
#lmap{position:absolute;inset:0;background:#eaf1f9}
body.dark #lmap{background:#0a1424}

/* --- map unavailable / degraded --- */
.map-offline{position:absolute;inset:0;display:grid;place-items:center;padding:28px;
  background:var(--surface-2)}
.map-offline .mo-card{max-width:420px;text-align:center;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:28px 26px;box-shadow:var(--sh-2)}
.map-offline .mo-ic{width:52px;height:52px;margin:0 auto 14px;border-radius:16px;display:grid;place-items:center;
  background:var(--surface-3);color:var(--dim);font-size:24px}
.map-offline b{display:block;font-size:15px;margin-bottom:8px}
.map-offline p{font-size:12.5px;line-height:1.7;color:var(--muted)}
.map-offline .mo-hint{margin-top:10px;font-size:11.5px;color:var(--dim)}
.map-banner{position:absolute;left:50%;top:14px;transform:translateX(-50%);z-index:600;
  display:flex;align-items:center;gap:8px;padding:8px 14px;border-radius:100px;font-size:11.5px;font-weight:600;
  background:color-mix(in srgb,var(--surface) 94%,transparent);border:1px solid var(--line);
  box-shadow:var(--sh-2);color:var(--text);backdrop-filter:blur(10px)}

/* soften basemap into the blue theme */
/* A basemap with a real dark variant of its own needs no filter, and
   inverting satellite imagery turns the desert purple. So the filter
   is opt-in per style rather than applied to whatever is underneath. */
.leaflet-tile-pane{filter:saturate(.72) brightness(1.03) contrast(.98)}
body.dark .tf-dark-invert .leaflet-tile-pane{filter:invert(1) hue-rotate(185deg) saturate(.62) brightness(.92) contrast(1.06)}
.tf-none .leaflet-tile-pane{filter:none}
body.dark .tf-none .leaflet-tile-pane{filter:none}
/* Trap Leaflet's 200-700 pane z-indexes inside the map so they cannot
   paint over the app's own panels. Without this the inspector, the
   alarm drawer and the search dropdown all render underneath the map. */
.leaflet-container{isolation:isolate;z-index:var(--z-map);font-family:var(--f);background:transparent}
.leaflet-control-zoom{border:0 !important;box-shadow:var(--sh-2) !important;border-radius:11px !important;overflow:hidden}
.leaflet-control-zoom a{background:var(--surface) !important;color:var(--text) !important;border-bottom:1px solid var(--line) !important;
  width:32px !important;height:32px !important;line-height:31px !important;font-size:16px !important}
.leaflet-control-zoom a:hover{background:var(--surface-2) !important;color:var(--b600) !important}
.leaflet-control-attribution{background:color-mix(in srgb,var(--surface) 80%,transparent) !important;
  color:var(--dim) !important;font-size:9.5px !important;border-radius:7px 0 0 0;padding:2px 7px !important}
.leaflet-control-attribution a{color:var(--muted) !important}
.leaflet-bar{border:0 !important}
/* the assistant button is fixed to the bottom-right corner, so the zoom
   control is raised above it instead of sharing the same 60px of screen */
/* the zoom control clears the fleet panel; the attribution keeps the
   opposite corner to itself */
.leaflet-bottom.leaflet-left{left:312px}
body.rail .leaflet-bottom.leaflet-left{left:312px}
@media(max-width:1100px){ .leaflet-bottom.leaflet-left{left:14px} }

/* ---------------- vehicle marker ----------------
   The mark itself is ONE self-contained <svg> written by
   js/map/markers.js with pixel width/height — everything below is
   polish (shadow, halo, label chip). If this file ever fails to load
   the marker still draws correctly; it just loses its shadow.
   ------------------------------------------------ */
.veh-ic,.pin-ic,.dia-ic,.clu-ic{background:none !important;border:0 !important}

.veh{position:relative;filter:drop-shadow(0 2px 4px rgba(10,25,50,.3))}
.veh svg{display:block;overflow:visible}
.veh.dim{opacity:.4;filter:none}
.veh.parked{filter:drop-shadow(0 1px 3px rgba(10,25,50,.22))}
.veh.sel{filter:drop-shadow(0 3px 9px color-mix(in srgb,var(--vc) 60%,transparent));z-index:600}

/* selection halo pulses behind the mark */
.veh .halo{position:absolute;inset:-8px;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,color-mix(in srgb,var(--vc) 34%,transparent),transparent 68%);
  opacity:0;transition:opacity .2s}
.veh.sel .halo{opacity:1;animation:vhalo 2.1s ease-out infinite}
@keyframes vhalo{0%{transform:scale(.78);opacity:.9}100%{transform:scale(1.6);opacity:0}}

/* alarms pulse; the count chip is inline-styled so it survives without css */
.veh.alarm .badge{animation:vbadge 1.6s ease-in-out infinite;
  box-shadow:0 1px 4px rgba(224,36,36,.5)}
@keyframes vbadge{0%,100%{transform:scale(1)}50%{transform:scale(1.14)}}

/* label chip — only for vehicles the declutterer allows */
.veh .lbl{letter-spacing:.2px;pointer-events:none;box-shadow:0 1px 4px rgba(0,0,0,.32)}
.veh.dim .lbl{background:rgba(15,30,53,.42)}
.veh.sel .lbl{background:var(--vc);box-shadow:0 2px 8px rgba(0,0,0,.3)}

/* the low-zoom stand-in */
.veh.dot-only{filter:none}
.veh .vd{box-shadow:0 1px 3px rgba(0,0,0,.35)}

/* ---------------- place pins (teardrop) ---------------- */
.mpin{position:relative;width:30px;height:39px;cursor:pointer}
.mpin .mp-shadow{position:absolute;left:50%;bottom:-3px;transform:translateX(-50%);
  width:16px;height:5px;border-radius:50%;background:rgba(15,30,53,.28);filter:blur(1.5px)}
.mpin .mp-body{position:absolute;inset:0;filter:drop-shadow(0 3px 5px rgba(10,25,50,.3))}
.mpin .mp-ic{position:absolute;left:0;right:0;top:8px;display:grid;place-items:center;pointer-events:none}
.mpin .mp-ic svg{width:15px;height:15px;stroke-width:1.9}
/* At city scale a dozen facility names collide with each other and
   with the vehicles; the pins still show, the names return on zoom. */
.z-far .mpin .mp-lbl,.z-mid .mpin .mp-lbl{display:none}
.mpin:hover .mp-lbl,.z-far .mpin:hover .mp-lbl,.z-mid .mpin:hover .mp-lbl{display:block;z-index:3}
.mpin .mp-lbl{position:absolute;left:50%;top:40px;transform:translateX(-50%);
  font-size:10px;font-weight:700;color:var(--ink);background:color-mix(in srgb,var(--surface) 92%,transparent);
  border:1px solid var(--line);padding:2px 7px;border-radius:100px;white-space:nowrap;
  box-shadow:var(--sh-1);pointer-events:none;letter-spacing:.1px}
.mpin:hover{z-index:600}
.mpin:hover .mp-body{transform:translateY(-2px);transition:transform .15s}

/* ---------------- incidents (diamond) ---------------- */
.mdia{position:relative;width:22px;height:22px;cursor:pointer;
  filter:drop-shadow(0 2px 3px rgba(10,25,50,.3))}
.mdia.urgent{animation:dpulse 1.5s ease-in-out infinite}
@keyframes dpulse{0%,100%{transform:scale(1)}50%{transform:scale(1.16)}}
.mdia .mdia-n{position:absolute;right:-5px;top:-5px;min-width:14px;height:14px;border-radius:100px;
  background:var(--ink);color:#fff;font-family:var(--mono);font-size:8.5px;font-weight:700;
  display:grid;place-items:center;border:1.5px solid #fff}
.mdia:hover{transform:scale(1.14)}

/* ---------------- zone cluster bubble ---------------- */
.mclu{position:relative;display:grid;place-items:center;border-radius:50%;cursor:pointer;
  background:color-mix(in srgb,var(--cc) 88%,#fff);border:3px solid #fff;
  box-shadow:0 3px 10px rgba(10,25,50,.3);transform:translate(-50%,-50%);transition:transform .16s}
.mclu b{font-family:var(--mono);font-size:14px;font-weight:700;color:#fff;letter-spacing:-.5px}
.mclu:hover{transform:translate(-50%,-50%) scale(1.08)}
.mclu .mclu-a{position:absolute;right:-3px;top:-3px;min-width:17px;height:17px;border-radius:100px;
  background:var(--bad);color:#fff;font-family:var(--mono);font-size:9.5px;font-weight:700;font-style:normal;
  display:grid;place-items:center;border:2px solid #fff}

/* ---------------- hover card ---------------- */
.mhover{position:absolute;left:0;top:0;z-index:620;width:208px;pointer-events:none;
  background:color-mix(in srgb,var(--surface) 96%,transparent);border:1px solid var(--line);
  border-radius:var(--r);box-shadow:var(--sh-3);padding:10px 12px;backdrop-filter:blur(12px);
  opacity:0;transition:opacity .14s;will-change:transform}
.mhover.on{opacity:1}
.mhover .mh-h{display:flex;align-items:center;gap:6px;margin-bottom:2px}
.mhover .mh-h b{font-family:var(--mono);font-size:12.5px}
.mhover .mh-st{margin-left:auto;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.4px}
.mhover .mh-d{font-size:11px;color:var(--muted);margin-bottom:7px}
.mhover .mh-r{display:flex;justify-content:space-between;font-size:11.5px;padding:2.5px 0}
.mhover .mh-r span{color:var(--muted)}
.mhover .mh-r b{font-family:var(--mono);font-size:11.5px}
.mhover .mh-al{margin-top:6px;font-size:10.5px;font-weight:700;color:var(--bad);
  background:var(--bad-bg);padding:3px 7px;border-radius:6px;text-align:center}
.mhover .mh-f{margin-top:8px;padding-top:7px;border-top:1px dashed var(--line);
  font-size:10px;color:var(--dim);text-align:center}

/* leaflet tooltip / popup restyle */
.leaflet-tooltip.mas-tip{background:var(--ink);color:#fff;border:0;border-radius:8px;font-size:11px;
  font-weight:600;padding:4px 9px;box-shadow:var(--sh-2)}
.leaflet-tooltip.mas-tip::before{border-top-color:var(--ink)}
.leaflet-popup-content-wrapper{border-radius:var(--r) !important;box-shadow:var(--sh-3) !important;
  background:var(--surface) !important;color:var(--text) !important;padding:0 !important;border:1px solid var(--line)}
.leaflet-popup-content{margin:0 !important;width:288px !important;font-size:12px}
.leaflet-popup-tip{background:var(--surface) !important;box-shadow:none !important}
.leaflet-popup-close-button{color:var(--dim) !important;padding:8px 8px 0 0 !important;z-index:5}

/* The Leaflet-bound vehicle popup that used to live here is gone —
   the live map now draws its own anchored card, and that card owns
   .vpop, .vp-h and .vp-b in css/live.css. The old rules outranked the
   new ones (.vpop .vp-h beats .vp-h) and painted the card's header
   navy; leaving them here would break it again the next time. */

/* ---------------- HUD panels over map ---------------- */
.hud{position:absolute;z-index:var(--z-hud);pointer-events:none}
.hud > *{pointer-events:auto}

.hud-left{top:14px;left:14px;bottom:14px;width:298px;display:flex;flex-direction:column;gap:11px}
.hud-right{top:14px;right:14px;width:292px;display:flex;flex-direction:column;gap:11px;max-height:calc(100% - 28px)}
.hud-bottom{left:50%;bottom:16px;transform:translateX(-50%);display:flex;gap:9px;align-items:center}

.glass{background:color-mix(in srgb,var(--surface) 92%,transparent);backdrop-filter:blur(16px) saturate(1.4);
  border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-3)}

.hud-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);border-radius:var(--r);overflow:hidden;flex:0 0 auto}
.hud-stats > div{background:color-mix(in srgb,var(--surface) 94%,transparent);padding:9px 6px;text-align:center}
.hud-stats .h-v{font-family:var(--mono);font-size:16px;font-weight:700;color:var(--ink);line-height:1;letter-spacing:-.8px}
.hud-stats .h-l{font-size:9px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin-top:4px;font-weight:600}
.hud-stats .h-v.ok{color:var(--ok)}.hud-stats .h-v.warn{color:var(--warn)}.hud-stats .h-v.bad{color:var(--bad)}

.vlist{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}
.vlist-h{display:flex;align-items:center;gap:7px;padding:10px 12px;border-bottom:1px solid var(--line);flex:0 0 auto}
.vlist-h b{font-size:12px}
.vlist-f{display:flex;gap:4px;padding:8px 10px;border-bottom:1px solid var(--line);flex:0 0 auto;flex-wrap:wrap}
.vlist-f::-webkit-scrollbar{height:0}
.vlist-b{flex:1;overflow-y:auto;padding:7px}

.vrow{display:flex;gap:9px;padding:9px;border-radius:10px;cursor:pointer;transition:.14s;align-items:center;border:1px solid transparent}
.vrow:hover{background:var(--surface-2)}
.vrow.on{background:var(--b50);border-color:var(--b200)}
body.dark .vrow.on{background:rgba(59,130,246,.13);border-color:rgba(59,130,246,.3)}
.vrow .vr-ic{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;flex:0 0 auto;position:relative}
.vrow .vr-ic svg{width:17px;height:17px}
.vrow .vr-x{flex:1;min-width:0}
.vrow .vr-1{display:flex;align-items:center;gap:6px}
.vrow .vr-1 b{font-family:var(--mono);font-size:11.8px;font-weight:700;color:var(--ink)}
.vrow .vr-2{font-size:10.5px;color:var(--muted);margin-top:2px;display:flex;align-items:center;gap:5px}
.vrow .vr-2 .sep{opacity:.4}
.vrow .vr-r{text-align:right;flex:0 0 auto}
.vrow .vr-r .sp{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--ink);line-height:1}
.vrow .vr-r .un{font-size:8.5px;color:var(--dim);letter-spacing:.4px}
.vrow .vr-bar{height:3px;border-radius:3px;background:var(--surface-3);margin-top:5px;overflow:hidden}
.vrow .vr-bar i{display:block;height:100%;border-radius:3px}

.maptools{display:flex;flex-direction:column;gap:1px;background:var(--line);border-radius:11px;overflow:hidden;box-shadow:var(--sh-2)}
.maptools button{width:34px;height:34px;background:var(--surface);color:var(--muted);display:grid;place-items:center;font-size:14px;transition:.14s}
.maptools button:hover{background:var(--surface-2);color:var(--b600)}
/* an enabled layer is a tinted cell with a coloured icon and a small
   rail, not a filled block — six filled blocks stacked read as one
   heavy column and stop saying which layers are actually on */
.maptools button.on{background:var(--b50);color:var(--b700)}
.maptools button.on::before{content:"";position:absolute;left:0;top:6px;bottom:6px;width:2.5px;
  border-radius:0 3px 3px 0;background:var(--b600)}
.maptools button{position:relative}
body.dark .maptools button.on{background:color-mix(in srgb,var(--b500) 20%,transparent);color:var(--b200)}
/* The strip has to clear the right panel AND that panel's fold tab,
   which hangs 26px off its left edge. 14 (panel gap) + 292 (panel) +
   26 (tab) + 14 (breathing room) = 346. At 318 the tab sat on top of
   the strip and the two read as one jammed column. */
.hud-tools{position:absolute;top:14px;right:346px;z-index:var(--z-hud);transition:right .26s cubic-bezier(.4,0,.2,1)}
.hud-tools.wide{right:14px}
/* right panel folded away, or replaced by the inspector */
#hudRight.folded ~ .hud-tools,.hud-tools.wide{right:14px}

.legend-box,.mapkey{padding:10px 12px;font-size:10.5px}
.legend-box .lg-t,.mapkey .lg-t{font-size:10px;font-weight:700;letter-spacing:.7px;color:var(--muted);text-transform:uppercase;margin-bottom:7px}
.legend-box .lg-r,.mapkey .lg-r{display:flex;align-items:center;gap:7px;padding:2.5px 0;color:var(--text)}
.legend-box .lg-r .sw,.mapkey .lg-r .sw{width:11px;height:11px;border-radius:3px;flex:0 0 auto}

.ticker{display:flex;align-items:center;gap:9px;padding:0 13px;height:36px;font-size:11.5px;max-width:640px;overflow:hidden}
.ticker .tk-x{flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--text)}
.ticker .tk-x b{font-family:var(--mono);font-size:11px}

.followbar{display:flex;align-items:center;gap:9px;padding:7px 9px 7px 13px;font-size:11.5px}
.followbar b{font-family:var(--mono);font-size:12px}

/* geofence / route styling helpers rendered via JS options */
.route-pulse{animation:rp 2s linear infinite}
@keyframes rp{to{stroke-dashoffset:-24}}

@media(max-width:1280px){ .hud-right{display:none} .hud-tools{right:14px} }
@media(max-width:900px){ .hud-left{width:calc(100% - 28px);bottom:auto;max-height:46%} .hud-bottom{display:none} }

@media(max-width:640px){
  .hud-left{width:calc(100% - 20px);left:10px;top:10px;max-height:56%}
  .hud-stats{grid-template-columns:repeat(2,1fr)}
  .hud-tools{right:10px;top:auto;bottom:86px}
  .maptools{flex-direction:row}
  .maptools button.on::before{left:6px;right:6px;top:auto;bottom:0;width:auto;height:2.5px;border-radius:3px 3px 0 0}
}

/* ---------------- collapsible HUD columns ---------------- */
.hud-fold{position:absolute;top:0;width:20px;height:26px;border-radius:7px;z-index:2;
  background:color-mix(in srgb,var(--surface) 92%,transparent);border:1px solid var(--line);
  color:var(--muted);font-size:12px;line-height:1;display:grid;place-items:center;
  box-shadow:var(--sh-1);transition:.15s;backdrop-filter:blur(10px)}
.hud-fold:hover{color:var(--b600);border-color:var(--b300)}
#foldLeft{right:-26px}
#foldRight{left:-26px}
.hud-left,.hud-right{transition:transform .26s cubic-bezier(.4,0,.2,1),opacity .2s}
.hud-left.folded{transform:translateX(calc(-100% - 18px))}
.hud-right.folded{transform:translateX(calc(100% + 18px))}
.hud-left.folded .hud-fold,.hud-right.folded .hud-fold{pointer-events:auto}
.hud-left.folded > :not(.hud-fold),.hud-right.folded > :not(.hud-fold){opacity:0;pointer-events:none}
.hud-left.folded #foldLeft{right:calc(-100% - 44px)}
.hud-right.folded #foldRight{left:calc(-100% - 44px)}

/* the map tool strip now holds real icons */
.maptools button svg{width:16px;height:16px}
.maptools button.on svg{stroke-width:2.1}

/* ============================================================
   v4 — MAP FILTER PANEL
   Docked to the left edge of the map, over the fleet HUD's gutter.
   Collapsed it is a tab that carries the active-filter count, so a
   narrowed view can never look like a full one.
   ============================================================ */
.mt-sep{display:block;height:1px;background:var(--line);margin:0}

.fp-wrap{position:absolute;left:12px;top:12px;z-index:var(--z-hud,520);display:flex;align-items:flex-start;gap:8px;pointer-events:none}
.fp-wrap>*{pointer-events:auto}

.fp-tab{position:relative;width:38px;height:38px;display:grid;place-items:center;
  background:var(--surface);color:var(--muted);border:1px solid var(--line);border-radius:11px;
  box-shadow:var(--sh-2);transition:.15s}
.fp-tab:hover{color:var(--text);border-color:var(--line-2)}
.fp-tab.on,.fp-tab.active{background:var(--b600);color:#fff;border-color:transparent}
.fp-tab.active:not(.on){background:var(--b50);color:var(--b600);border-color:var(--b600)}
.fp-tab-n{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;padding:0 4px;border-radius:100px;
  background:var(--b600);color:#fff;font:700 9.5px/16px var(--mono);text-align:center;border:2px solid var(--surface)}
.fp-tab.on .fp-tab-n{background:var(--warn);color:#3a2600;border-color:var(--b600)}
.fp-tab-n.off{display:none}

.fp{width:326px;max-height:calc(100vh - 150px);display:flex;flex-direction:column;border-radius:13px;overflow:hidden}
.fp-head{display:flex;align-items:center;gap:8px;padding:10px 10px 10px 13px;border-bottom:1px solid var(--line)}
.fp-head b{font-size:12.5px;letter-spacing:.01em}
.fp-count{font:600 11px/1 var(--mono);color:var(--muted);white-space:nowrap}
.fp-count.narrowed{color:var(--b600)}
.fp-views{display:flex;gap:6px;padding:8px 10px;border-bottom:1px solid var(--line)}
.fp-views select{flex:1;height:28px;border:1px solid var(--line);border-radius:8px;background:var(--surface);
  color:var(--text);font-size:11.5px;padding:0 8px}
.fp-body{padding:4px 0 10px;overflow-y:auto}

.fp-sec{padding:9px 12px 4px}
.fp-st{display:flex;align-items:center;gap:6px;margin-bottom:7px}
.fp-st b{font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--muted)}
.fp-mini{height:19px;padding:0 6px;border-radius:6px;border:1px solid var(--line);background:transparent;
  color:var(--muted);font-size:10px;font-weight:600;transition:.13s}
.fp-mini:hover{color:var(--b600);border-color:var(--b600)}
.fp-mini.go{color:var(--b600);border-color:var(--b600)}
.fp-rule{height:1px;background:var(--line);margin:10px 12px 4px}

.fchips{display:flex;flex-wrap:wrap;gap:4px}
.fchip{display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 7px;border-radius:7px;
  border:1px solid var(--line);background:var(--surface);color:var(--text);font-size:11px;font-weight:600;transition:.13s}
.fchip:hover{border-color:var(--line-2);background:var(--surface-2)}
.fchip.on{background:var(--b600);border-color:var(--b600);color:#fff}
.fchip.nil{opacity:.42}
.fchip.nil.on{opacity:1}
.fc-dot{width:7px;height:7px;border-radius:100px;flex:none}
.fchip.on .fc-dot{box-shadow:0 0 0 1.5px rgba(255,255,255,.6)}
.fc-ic{display:grid;place-items:center;opacity:.75}
.fchip.on .fc-ic{opacity:1}
.fc-n{font:700 9.5px/1 var(--mono);opacity:.6;min-width:10px;text-align:right}
.fchip.on .fc-n{opacity:.9}

.segbar{display:flex;gap:2px;background:var(--surface-2);border:1px solid var(--line);border-radius:8px;padding:2px}
.segbar .seg{flex:1;height:24px;border-radius:6px;font-size:11px;font-weight:600;color:var(--muted);transition:.13s}
.segbar .seg:hover{color:var(--text)}
.segbar .seg.on{background:var(--surface);color:var(--b600);box-shadow:var(--sh-1)}

.fp-range{display:flex;flex-direction:column;gap:5px}
.fp-range label{display:grid;grid-template-columns:26px 1fr 34px;align-items:center;gap:7px}
.fp-range label>span{font-size:10px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
.fp-range label>b{font:700 10.5px/1 var(--mono);color:var(--text);text-align:right}
.fp-range input[type=range]{width:100%;height:16px;accent-color:var(--b600);background:transparent}

.fp-in{width:100%;height:28px;border:1px solid var(--line);border-radius:8px;background:var(--surface);
  color:var(--text);font-size:11.5px;padding:0 9px;margin-bottom:5px}
.fp-in:focus{outline:none;border-color:var(--b600);box-shadow:var(--ring)}

.fp-lays{display:grid;grid-template-columns:1fr 1fr;gap:2px}
.fp-lay{display:flex;align-items:center;gap:6px;height:26px;padding:0 5px;border-radius:7px;cursor:pointer;transition:.12s}
.fp-lay:hover{background:var(--surface-2)}
.fp-lay input{accent-color:var(--b600);width:13px;height:13px;flex:none}
.fl-ic{display:grid;place-items:center;color:var(--muted);flex:none}
.fp-lay input:checked~.fl-ic{color:var(--b600)}
.fl-t{font-size:10.5px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* active-filter strip along the top of the map */
.fltbar{position:absolute;left:62px;right:360px;top:14px;z-index:var(--z-hud,520);
  display:flex;flex-wrap:wrap;gap:5px;pointer-events:none}
.fltbar.off{display:none}
.fltbar>*{pointer-events:auto}
.fbchip{display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 5px 0 9px;border-radius:100px;
  background:var(--b600);color:#fff;font-size:11px;font-weight:600;box-shadow:var(--sh-2);transition:.13s}
.fbchip .x{display:grid;place-items:center;width:15px;height:15px;border-radius:100px;background:rgba(255,255,255,.22)}
.fbchip:hover .x{background:rgba(255,255,255,.4)}
.fbchip.clear{background:var(--surface);color:var(--muted);padding:0 10px;border:1px solid var(--line)}
.fbchip.clear:hover{color:var(--bad);border-color:var(--bad)}

/* service-request pins */
.mreq{filter:drop-shadow(0 3px 5px rgba(15,30,53,.28))}
.mr-ic{position:absolute;left:0;right:0;top:7px;display:grid;place-items:center;pointer-events:none}
.mr-b{position:absolute;right:-3px;top:-3px;width:14px;height:14px;border-radius:100px;background:#e02424;color:#fff;
  font:800 10px/14px var(--mono);text-align:center;border:2px solid #fff}
.mreq.breach{animation:reqpulse 1.9s ease-in-out infinite}
@keyframes reqpulse{0%,100%{filter:drop-shadow(0 3px 5px rgba(224,36,36,.35))}50%{filter:drop-shadow(0 3px 11px rgba(224,36,36,.7))}}

@media (max-width:1280px){ .fp{width:290px} .fltbar{right:120px} }
@media (max-width:1024px){ .fp{width:82vw;max-width:320px} .fltbar{left:14px;right:14px;top:60px} }

/* dark: the active-tab tint must not be a near-white block */
body.dark .fp-tab.active:not(.on){background:rgba(37,99,235,.18);color:#93c5fd;border-color:#2563eb}

/* the panel sits beside the fleet HUD, not on top of it; when that
   panel is folded away the filter slides across into the space */
.fp-wrap{left:318px;transition:left .28s cubic-bezier(.4,0,.2,1)}
.maproot.lfold .fp-wrap{left:56px}
@media (max-width:1280px){ .fp-wrap{left:300px} .maproot.lfold .fp-wrap{left:56px} }
@media (max-width:1024px){ .fp-wrap{left:14px} }

/* ---- v4.1: tabs at the top of the filter panel ---- */
.fp-tabs{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--line)}
.fp-tabs button{position:relative;flex:1;display:flex;align-items:center;justify-content:center;gap:5px;
  height:28px;border-radius:8px;font-size:11.5px;font-weight:600;color:var(--muted);transition:.13s}
.fp-tabs button:hover{color:var(--text);background:var(--surface-2)}
.fp-tabs button.on{background:var(--b600);color:#fff}
.fp-tn{min-width:15px;height:15px;padding:0 4px;border-radius:100px;background:var(--b600);color:#fff;
  font:700 9px/15px var(--mono);font-style:normal;text-align:center}
.fp-tabs button.on .fp-tn{background:rgba(255,255,255,.28)}
.fp-tn.off{display:none}
.fp-lay.dim{opacity:.5}
.fp-lay-x{display:flex;gap:5px;flex-wrap:wrap;margin-top:9px;padding-top:9px;border-top:1px solid var(--line)}

/* ============================================================
   v4.1 — a quieter map

   The map is the point. Every panel on top of it is a tax, so the
   two that were pure reference — the tool strip and the colour key —
   are off by default and the key is a button instead of a box.
   ============================================================ */
.mapkey-btn{position:absolute;left:358px;bottom:14px;z-index:var(--z-hud,520);
  transition:left .28s cubic-bezier(.4,0,.2,1);
  display:flex;align-items:center;gap:6px;height:30px;padding:0 11px;border-radius:9px;
  background:var(--surface);border:1px solid var(--line);color:var(--muted);
  font-size:11.5px;font-weight:600;box-shadow:var(--sh-2);transition:.14s}
.mapkey-btn:hover{color:var(--ink);border-color:var(--line-2)}
.mapkey-btn.on{background:var(--b600);color:#fff;border-color:transparent}
.mapkey{position:absolute;left:358px;bottom:52px;z-index:var(--z-hud,520);
  padding:11px 13px;border-radius:12px;min-width:178px;
  transition:left .28s cubic-bezier(.4,0,.2,1)}
.maproot.lfold .mapkey-btn,.maproot.lfold .mapkey{left:96px}

/* Zoom and the colour key share the bottom-left corner, clear of the
   fleet panel and shifting with it when it folds — the zoom control
   used to sit underneath that panel where nothing could reach it. */
.maproot .leaflet-bottom.leaflet-left{left:310px;bottom:6px;transition:left .28s cubic-bezier(.4,0,.2,1)}
.maproot.lfold .leaflet-bottom.leaflet-left{left:48px}

@media (max-width:1280px){ .mapkey-btn,.mapkey{left:340px} .maproot .leaflet-bottom.leaflet-left{left:292px} }
@media (max-width:1024px){ .mapkey-btn{left:60px} .mapkey{left:14px}
  .maproot .leaflet-bottom.leaflet-left{left:8px} }

/* ---- v4.1: the service picker inside the filter panel ---- */
.svsels{display:flex;flex-direction:column;gap:3px}
.svsel{display:grid;grid-template-columns:24px minmax(0,1fr) auto;align-items:center;gap:8px;
  padding:6px 7px;border-radius:8px;border:1px solid transparent;text-align:left;transition:.12s}
.svsel:hover{background:var(--surface-2)}
.svsel.on{background:color-mix(in srgb,var(--c) 12%,transparent);border-color:var(--c)}
body.dark .svsel.on{background:color-mix(in srgb,var(--c) 22%,transparent)}
.svs-ic{width:22px;height:22px;border-radius:7px;display:grid;place-items:center;
  background:color-mix(in srgb,var(--c) 14%,transparent);color:var(--c)}
.svsel.on .svs-ic{background:var(--c);color:#fff}
.svs-t{min-width:0;display:flex;flex-direction:column;gap:0}
.svs-t b{font-size:11px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.svsel.on .svs-t b{color:var(--ink)}
.svs-t i{font-size:10px;font-style:normal;color:var(--muted);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;unicode-bidi:plaintext}
.svs-n{text-align:right}
.svs-n b{display:block;font:700 12px/1 var(--mono);color:var(--ink)}
.svs-n i{font-size:9px;font-style:normal;color:var(--muted)}
.fp-note{font-size:10.5px;line-height:1.6;color:var(--muted)}
.fp-sec[data-sec="svcnote"] .fp-st{display:none}

/* ============================================================
   v4.2 — MAP DIAGNOSTIC

   Shown only when the map genuinely has nothing to draw. An empty
   rectangle is the same picture for four different faults, so this
   names which one it is and offers the single control that fixes it.
   ============================================================ */
.mapdiag{position:absolute;inset:0;z-index:var(--z-hud,520);display:grid;place-items:center;
  background:color-mix(in srgb,var(--bg) 72%,transparent);backdrop-filter:blur(3px);
  animation:mdIn .22s cubic-bezier(.4,0,.2,1)}
@keyframes mdIn{from{opacity:0}to{opacity:1}}
.md-card{width:min(400px,86%);display:flex;flex-direction:column;align-items:center;gap:11px;
  text-align:center;padding:26px 26px 20px;border-radius:16px;
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--sh-3)}
.md-ic{width:52px;height:52px;border-radius:16px;display:grid;place-items:center;
  background:var(--warn-bg);color:var(--warn)}
.md-card b{font-size:15px;color:var(--ink);line-height:1.35}
.md-card p{font-size:12px;line-height:1.7;color:var(--muted)}
.md-build{font:600 10px/1 var(--mono);color:var(--dim);letter-spacing:.04em}

/* ---- v4.3: basemap picker inside the Key popover ---- */
.mapkey{min-width:212px}
.bmpick{display:grid;grid-template-columns:1fr 1fr;gap:3px;margin-bottom:2px}
.bm{height:25px;padding:0 8px;border-radius:7px;border:1px solid var(--line);background:var(--surface);
  color:var(--text);font-size:10.5px;font-weight:600;text-align:center;transition:.13s;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bm:hover{border-color:var(--line-2);background:var(--surface-2)}
.bm.on{background:var(--b600);border-color:var(--b600);color:#fff}
.bm.risky:not(.on){color:var(--muted)}
.bm.risky.on{background:var(--warn);border-color:var(--warn);color:#3a2600}
