Skip to content

Commit 05a436d

Browse files
committed
feat: world map + radar hover, bubbles fix, hover hints, enriched geo data
2 parents bc099b1 + 1707c59 commit 05a436d

14 files changed

Lines changed: 871 additions & 41 deletions

.ground_truth.sha256

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
af5dba38c4e66d61cff1ead52ef0349759f23eb77ab03553a8aad85492d0c3f1 GROUND_TRUTH_BRAINSTORM.md
2+
ca6d9eee1b2f20bcea50d46f905a0b76f1b3dde1b684dfbe5ef36726d9a525ef GROUND_TRUTH_DOCS.md
3+
ce23c9872560589d278ca2e1b993a83d2f2c6cf108bf6c256f2a1775b0c52f4b GROUND_TRUTH_HEALTH.md

GROUND_TRUTH_BRAINSTORM.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Ground Truth: Approach
2+
3+
## Map approach: D3 choropleth with TopoJSON (CHOSEN)
4+
- CDN: world-atlas@2/countries-110m.json + topojson-client@3
5+
- d3.geoNaturalEarth1() projection
6+
- Integrated two-panel layout: map left, radar right
7+
- Hover on country → radar shows that region
8+
9+
## Alternative rejected: Leaflet/Mapbox
10+
Over-engineered for this use case. D3 native geo is sufficient.
11+
12+
## Radar refactor approach
13+
Expose window.drawGeoRadarChart(containerId, geoData, options) from geo-radar.js.
14+
geo-map.js calls it to update the side panel. Keep backward compat with scrollama onStep.
15+
16+
## Bubble fix
17+
Simple constant change — BUBBLE_RADIUS_RANGE and TOP_N. No architectural change.

GROUND_TRUTH_DOCS.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Ground Truth: Interfaces
2+
3+
## geo_data.json schema
4+
```json
5+
{
6+
"regions": [
7+
{"name": "Europe", "countries": [...], "count": 15874,
8+
"families": {"floral": N, "woody": N, ...},
9+
"topNotes": [{"note": "musk", "count": N}]}
10+
],
11+
"families": ["floral","woody","citrus","spicy","fresh","sweet","musky","fruity"]
12+
}
13+
```
14+
15+
## geo-radar.js current exports
16+
- window.initGeoRadar(containerId, dataPath) → {onStep}
17+
- REGION_COLORS = {Europe:'#7b9ec9', 'North America':'#c97b7b', Asia:'#7bc9a3', 'Middle East':'#c9b67b', 'South America':'#9b7bc9'}
18+
- normalizeRegion(region) → proportions array
19+
20+
## TopoJSON world-atlas structure
21+
- topojson.feature(world, world.objects.countries) → GeoJSON FeatureCollection
22+
- Each feature.properties.name = country name
23+
- feature.id = ISO numeric code
24+
25+
## CSS variables
26+
--bg-primary:#0a0a0a --accent-gold:#c9a96e --text-primary:#e8e0d4
27+
--text-secondary:#9a9088 --text-muted:#6b6460
28+
--font-heading:'Cormorant Garamond' --font-body:'DM Sans'

GROUND_TRUTH_HEALTH.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Ground Truth: Codebase Health
2+
3+
## Current state (post geo-radar addition)
4+
- 9 viz files in docs/js/visualizations/ (beeswarm, radar, bubbles, timeline, price, chord, sankey, heatmap, geo-radar)
5+
- 8 JSON data files in docs/data/
6+
- geo-radar.js: 376 lines, single overlaid radar, scrollama-driven
7+
- bubbles.js: 365 lines, BUBBLE_RADIUS_RANGE [5,38], TOP_N 40
8+
- main.js: 259 lines, vizConfigs has 9 entries
9+
- index.html: ~280 lines, 8 sections + hero + footer
10+
- style.css: 595 lines
11+
12+
## Key interfaces
13+
- vizConfigs array in main.js: {initFn, containerId, dataPath, scrollyId}
14+
- All vizs: window.initXxx(containerId, dataPath) → {onStep(idx, dir)}
15+
- Shared: NOTE_FAMILIES, getNoteFamily, getNoteColor, FAMILY_COLORS
16+
- Shared: showTooltip, hideTooltip, escapeHtml
17+
18+
## Tech debt
19+
- price.js at 516 lines (over 400 limit)
20+
- No resize handling except heatmap
21+
- geo-radar.js REGION_COLORS defined locally, should be shared if geo-map.js also needs them

TODO.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# TODO — Night Shift geo-map
2+
3+
- [ ] T1: Fix bubbles.js — smaller dots, fewer notes
4+
- [ ] T3: Add "hover to explore" hints in CSS + HTML
5+
- [ ] T4: Enrich geo data — add Indonesia, Malaysia, Lebanon, Egypt
6+
- [ ] T2a: Refactor geo-radar.js — expose reusable drawRadarForRegion
7+
- [ ] T2b: Create geo-map.js — world choropleth + radar integration
8+
- [ ] T2c: Update index.html — two-panel layout, topojson CDN
9+
- [ ] T2d: Update main.js — new vizConfig for geo-map
10+
- [ ] T5: Visual QA — test all sections, screenshots
11+
- [ ] T6: Commit, push, deploy

docs/css/style.css

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,74 @@ strong {
325325
border: none;
326326
}
327327

328+
/* ============================================
329+
GEO MAP + RADAR LAYOUT
330+
============================================ */
331+
332+
.geo-section-layout {
333+
max-width: var(--content-width);
334+
margin: 0 auto;
335+
padding: 0 2.5rem;
336+
}
337+
338+
.geo-layout {
339+
display: flex;
340+
gap: 1.5rem;
341+
width: 100%;
342+
height: 500px;
343+
}
344+
345+
.geo-map-container {
346+
flex: 1.3;
347+
min-width: 0;
348+
position: relative;
349+
background: var(--bg-card);
350+
border: 1px solid var(--border-subtle);
351+
border-radius: 16px;
352+
overflow: hidden;
353+
}
354+
355+
.geo-radar-container {
356+
flex: 0.7;
357+
min-width: 0;
358+
background: var(--bg-card);
359+
border: 1px solid var(--border-subtle);
360+
border-radius: 16px;
361+
display: flex;
362+
align-items: center;
363+
justify-content: center;
364+
}
365+
366+
.geo-steps {
367+
display: flex;
368+
gap: 1rem;
369+
margin-top: 1.5rem;
370+
}
371+
372+
.geo-steps .step {
373+
flex: 1;
374+
padding: 1.5rem;
375+
margin-bottom: 0;
376+
background: var(--bg-card);
377+
border: 1px solid var(--border-subtle);
378+
border-radius: 12px;
379+
opacity: 0.5;
380+
transition: opacity 0.4s ease, border-color 0.4s ease;
381+
cursor: pointer;
382+
}
383+
384+
.geo-steps .step.is-active {
385+
opacity: 1;
386+
border-color: var(--border-active);
387+
}
388+
389+
.geo-steps .step p {
390+
font-size: 0.9rem;
391+
font-weight: 300;
392+
line-height: 1.7;
393+
color: var(--text-primary);
394+
}
395+
328396
/* ============================================
329397
DEEP DIVE GRID
330398
============================================ */
@@ -455,6 +523,17 @@ strong {
455523
color: var(--text-secondary);
456524
}
457525

526+
/* Hover hints */
527+
.hover-hint {
528+
text-align: center;
529+
font-size: 0.7rem;
530+
letter-spacing: 0.12em;
531+
text-transform: uppercase;
532+
color: var(--text-muted);
533+
margin-top: 0.8rem;
534+
opacity: 0.5;
535+
}
536+
458537
/* ============================================
459538
ANIMATIONS
460539
============================================ */
@@ -527,6 +606,18 @@ strong {
527606
grid-template-columns: 1fr;
528607
}
529608

609+
.geo-layout {
610+
flex-direction: column;
611+
}
612+
613+
.geo-radar-container {
614+
min-height: 300px;
615+
}
616+
617+
.geo-steps {
618+
flex-direction: column;
619+
}
620+
530621
.nav-links {
531622
display: none;
532623
}

docs/data/geo_data.json

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -100,39 +100,44 @@
100100
"Japan",
101101
"South Korea",
102102
"India",
103-
"Thailand"
103+
"Thailand",
104+
"Indonesia",
105+
"Malaysia",
106+
"China",
107+
"Hong Kong",
108+
"Pakistan"
104109
],
105-
"count": 385,
110+
"count": 426,
106111
"families": {
107-
"floral": 727,
108-
"woody": 460,
109-
"citrus": 422,
110-
"spicy": 241,
111-
"fresh": 139,
112-
"sweet": 207,
113-
"musky": 377,
114-
"fruity": 207
112+
"floral": 804,
113+
"woody": 513,
114+
"citrus": 454,
115+
"spicy": 259,
116+
"fresh": 159,
117+
"sweet": 230,
118+
"musky": 441,
119+
"fruity": 225
115120
},
116121
"topNotes": [
117122
{
118123
"note": "musk",
119-
"count": 145
124+
"count": 169
120125
},
121126
{
122127
"note": "bergamot",
123-
"count": 140
128+
"count": 153
124129
},
125130
{
126131
"note": "sandalwood",
127-
"count": 123
132+
"count": 138
128133
},
129134
{
130-
"note": "rose",
131-
"count": 119
135+
"note": "jasmine",
136+
"count": 132
132137
},
133138
{
134-
"note": "jasmine",
135-
"count": 118
139+
"note": "rose",
140+
"count": 130
136141
}
137142
]
138143
},
@@ -143,39 +148,44 @@
143148
"Oman",
144149
"Arabia saudi",
145150
"Bahrain",
146-
"Turkey"
151+
"Turkey",
152+
"Lebanon",
153+
"Egypt",
154+
"Kuwait",
155+
"Qatar",
156+
"Iran"
147157
],
148-
"count": 1618,
158+
"count": 1659,
149159
"families": {
150-
"floral": 2521,
151-
"woody": 2186,
152-
"citrus": 1422,
153-
"spicy": 1268,
154-
"fresh": 529,
155-
"sweet": 1098,
156-
"musky": 2134,
157-
"fruity": 856
160+
"floral": 2562,
161+
"woody": 2228,
162+
"citrus": 1467,
163+
"spicy": 1311,
164+
"fresh": 548,
165+
"sweet": 1144,
166+
"musky": 2176,
167+
"fruity": 875
158168
},
159169
"topNotes": [
160170
{
161171
"note": "musk",
162-
"count": 859
172+
"count": 874
163173
},
164174
{
165175
"note": "amber",
166-
"count": 693
176+
"count": 708
167177
},
168178
{
169179
"note": "vanilla",
170-
"count": 626
180+
"count": 646
171181
},
172182
{
173183
"note": "patchouli",
174-
"count": 603
184+
"count": 617
175185
},
176186
{
177187
"note": "sandalwood",
178-
"count": 596
188+
"count": 603
179189
}
180190
]
181191
},

0 commit comments

Comments
 (0)