Skip to content

Commit 14f8e20

Browse files
feat: make #1 venue unmissable on the map
- #1 marker is larger (32px) with pulsing green glow animation - Floating venue name label above #1 marker (always visible) - Lower-ranked markers are faded (opacity 0.5–0.65) - #1 result card highlighted with green border in panel - Venue markers now use child elements for rank number + label
1 parent 31386d4 commit 14f8e20

2 files changed

Lines changed: 84 additions & 20 deletions

File tree

docs/demo.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,20 @@ function addVenueMarkers(venues) {
201201
el.className = 'marker-venue'
202202
el.title = v.name
203203

204+
// Rank number
205+
const num = document.createElement('span')
206+
num.className = 'venue-num'
207+
el.appendChild(num)
208+
209+
// Floating name label (visible only on #1)
210+
const label = document.createElement('span')
211+
label.className = 'venue-label'
212+
label.textContent = v.name
213+
el.appendChild(label)
214+
204215
const marker = new maplibregl.Marker({ element: el })
205216
.setLngLat([v.lon, v.lat])
206-
.setPopup(new maplibregl.Popup({ offset: 10 }).setHTML(
217+
.setPopup(new maplibregl.Popup({ offset: 18 }).setHTML(
207218
`<b>${esc(v.name)}</b><br><small>${esc(v.venueType)}</small>`,
208219
))
209220
.addTo(map)
@@ -226,7 +237,7 @@ function updateVenueRanks() {
226237
const rank = rankByName.get(venue.name) ?? 99
227238
const el = marker.getElement()
228239
el.dataset.rank = String(rank)
229-
el.textContent = String(rank)
240+
el.querySelector('.venue-num').textContent = String(rank)
230241
}
231242
}
232243

docs/style.css

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,15 @@ select:focus:not(:focus-visible) { outline: none; }
229229

230230
.result-card:hover { border-color: var(--text-muted); }
231231

232+
.result-card:first-child {
233+
border-color: var(--score);
234+
box-shadow: 0 0 8px rgba(128, 255, 128, 0.15);
235+
}
236+
237+
.result-card:first-child .result-rank {
238+
color: var(--score);
239+
}
240+
232241
.result-rank {
233242
font-size: 18px;
234243
font-weight: 700;
@@ -305,56 +314,100 @@ footer {
305314
.marker-participant:hover { transform: scale(1.3); }
306315

307316
.marker-venue {
317+
position: relative;
308318
border-radius: 50%;
309319
background: var(--venue);
310-
border: 2px solid rgba(255, 255, 255, 0.8);
311-
box-shadow: 0 0 6px var(--venue);
320+
border: 2px solid rgba(255, 255, 255, 0.5);
321+
box-shadow: 0 0 4px var(--venue);
312322
cursor: pointer;
313323
transition: all 0.3s;
314324
display: flex;
315325
align-items: center;
316326
justify-content: center;
317327
font-family: var(--font);
318328
font-weight: 700;
319-
color: #fff;
320-
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
329+
color: rgba(255, 255, 255, 0.7);
330+
opacity: 0.5;
331+
}
332+
333+
.marker-venue .venue-label {
334+
display: none;
321335
}
322336

323337
.marker-venue[data-rank="1"] {
324-
width: 28px;
325-
height: 28px;
326-
font-size: 14px;
338+
width: 32px;
339+
height: 32px;
340+
font-size: 15px;
327341
background: var(--score);
328-
border-color: #fff;
329-
box-shadow: 0 0 12px var(--score), 0 0 24px rgba(128, 255, 128, 0.3);
342+
border: 3px solid #fff;
343+
box-shadow: 0 0 16px var(--score), 0 0 32px rgba(128, 255, 128, 0.4);
330344
z-index: 10;
331345
color: var(--bg);
332-
text-shadow: none;
346+
opacity: 1;
347+
animation: pulse-winner 2s ease-in-out infinite;
348+
}
349+
350+
.marker-venue[data-rank="1"] .venue-label {
351+
display: block;
352+
position: absolute;
353+
bottom: calc(100% + 6px);
354+
left: 50%;
355+
transform: translateX(-50%);
356+
white-space: nowrap;
357+
background: var(--score);
358+
color: var(--bg);
359+
padding: 3px 8px;
360+
border-radius: 4px;
361+
font-size: 11px;
362+
font-weight: 600;
363+
letter-spacing: 0.3px;
364+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
365+
pointer-events: none;
366+
}
367+
368+
.marker-venue[data-rank="1"] .venue-label::after {
369+
content: '';
370+
position: absolute;
371+
top: 100%;
372+
left: 50%;
373+
transform: translateX(-50%);
374+
border: 5px solid transparent;
375+
border-top-color: var(--score);
376+
}
377+
378+
@keyframes pulse-winner {
379+
0%, 100% { box-shadow: 0 0 16px var(--score), 0 0 32px rgba(128, 255, 128, 0.4); }
380+
50% { box-shadow: 0 0 24px var(--score), 0 0 48px rgba(128, 255, 128, 0.6); }
333381
}
334382

335383
.marker-venue[data-rank="2"] {
336-
width: 22px;
337-
height: 22px;
384+
width: 24px;
385+
height: 24px;
338386
font-size: 12px;
339387
background: var(--accent);
388+
border-color: rgba(255, 255, 255, 0.8);
340389
box-shadow: 0 0 8px var(--accent);
341390
color: var(--bg);
342-
text-shadow: none;
391+
opacity: 0.85;
343392
}
344393

345394
.marker-venue[data-rank="3"] {
346-
width: 18px;
347-
height: 18px;
395+
width: 20px;
396+
height: 20px;
348397
font-size: 11px;
398+
opacity: 0.65;
349399
}
350400

351401
.marker-venue:not([data-rank="1"]):not([data-rank="2"]):not([data-rank="3"]) {
352-
width: 14px;
353-
height: 14px;
402+
width: 16px;
403+
height: 16px;
354404
font-size: 10px;
355405
}
356406

357-
.marker-venue:hover { transform: scale(1.3); }
407+
.marker-venue:hover {
408+
transform: scale(1.3);
409+
opacity: 1;
410+
}
358411

359412
/* MapLibre popup overrides */
360413
.maplibregl-popup-content {

0 commit comments

Comments
 (0)