diff --git a/index.html b/index.html
index 941353f..36c251d 100644
--- a/index.html
+++ b/index.html
@@ -176,7 +176,12 @@
}
/* ── Live vehicle DOM marker (locked look) ─────────────────────────── */
- .veh-marker { position: relative; cursor: pointer; will-change: transform; }
+ /* NOTE: never set position on .veh-marker — MapLibre's own .maplibregl-marker
+ class supplies position:absolute and drives placement. The plate's
+ positioning context is the inner wrapper below, so a class change can't
+ reflow the markers. */
+ .veh-marker { cursor: pointer; will-change: transform; }
+ .veh-inner { position: relative; width: 32px; height: 32px; }
.veh-pin {
width: 32px; height: 32px; border-radius: 50%;
background: var(--c, var(--parked));
@@ -507,7 +512,7 @@ function upsertLiveMarker(p, coords, feature) {
if (!m) {
const el = document.createElement('div');
el.className = 'veh-marker';
- el.innerHTML = `
`;
+ el.innerHTML = ``;
el.addEventListener('mouseenter', () => { cancelPopupClose(); openPopupImei = p.imei; const f = currentLiveFeature(p.imei); if (f) showLivePopup(f); });
el.addEventListener('mouseleave', () => { if (!popupStuck) schedulePopupClose(); });
el.addEventListener('click', e => {
@@ -520,9 +525,13 @@ function upsertLiveMarker(p, coords, feature) {
} else {
m.setLngLat(coords);
}
- // Style the (possibly reused) element to current state
+ // Style the (possibly reused) element to current state. Use classList so we
+ // never wipe MapLibre's own `maplibregl-marker` class (doing so dropped
+ // position:absolute and made markers stack in document flow — FIX).
const el = m.getElement();
- el.className = 'veh-marker ' + state;
+ el.classList.add('veh-marker');
+ el.classList.remove('active', 'parked', 'offline');
+ el.classList.add(state);
const pin = el.querySelector('.veh-pin');
pin.style.setProperty('--c', color);
const glyph = el.querySelector('.glyph');