JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html>
<html>
<head>
<title>China in 5 - Featured Cities</title>
<script src='https://api.mapbox.com/mapbox-gl-js/v3.8.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v3.8.0/mapbox-gl.css' rel='stylesheet' />
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="map-title">China in 5 - Featured Cities</div>
<div class="city-counter">67 Cities Featured</div>
<div class="season-badge">Season 2</div>
<div id='map'></div>
<div class="map-legend">
<div class="legend-item"><div class="legend-color" style="background-color: #ff3366;"></div><span>Featured Cities</span></div>
<div class="legend-item"><div class="legend-color" style="background-color: #00cc66;"></div><span>Latest Addition (Yangzhou)</span></div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS
/* ===== BASE STYLES ===== */
body {
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #1a2a6c 0%, #b21f1f 50%, #fdbb2d 100%);
}
#map {
height: 100vh;
width: 100%;
}
/* ===== POPUP STYLES ===== */
.mapboxgl-popup-content {
background: #fff;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
max-width: 280px;
}
.mapboxgl-popup-content h3 {
margin: 0 0 10px 0;
color: #333;
font-size: 18px;
border-bottom: 1px solid #eee;
padding-bottom: 8px;
}
.mapboxgl-popup-content a {
display: block;
margin: 8px 0;
color: #0066cc;
text-decoration: none;
padding: 5px 8px;
border-radius: 4px;
transition: background-color 0.2s;
}
.mapboxgl-popup-content a:hover {
background-color: #f5f9ff;
}
/* ===== CUSTOM MARKER STYLES ===== */
.custom-marker { position: relative; cursor: pointer; }
.marker-dot {
width: 18px;
height: 18px;
border-radius: 50%;
border: 3px solid white;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
.marker-pulse { animation: pulse 2s infinite; }
.marker-red { background-color: #ff3366; }
.marker-green {
background-color: #00cc66;
box-shadow: 0 0 15px rgba(0, 204, 102, 0.7), 0 2px 8px rgba(0,0,0,0.3) !important;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
/* ===== MAP CONTROLS ===== */
.map-title {
position: absolute;
top: 20px;
left: 20px;
background: rgba(255,255,255,0.9);
padding: 10px 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 1;
font-size: 16px;
font-weight: 600;
color: #333;
}
.map-legend {
position: absolute;
bottom: 20px;
left: 20px;
background:...
JavaScript
// ===== INITIALIZE MAP =====
mapboxgl.accessToken = 'pk.eyJ1IjoiY2hpbmFpbjUiLCJhIjoiY21nb3o5cGp0MDc4djJqcXRiMzNrcGxiciJ9.NnIoptkfIvQLLziNYk1zvQ';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v11',
center: [119.4215, 32.3935],
zoom: 7
});
// ===== CITIES DATA =====
const cities = [
// Season 1 - Cities 1-34 (with City 7 corrected to Chongzuo)
{city: "Hefei", coordinates: [117.2272, 31.8206], deepdive: "https://open.substack.com/pub/chinain5/p/hefeis-1400-year-debugged-code-how", principle: "The State's Gambit"},
{city: "Xiong'an", coordinates: [115.9386, 39.0438], deepdive: "https://open.substack.com/pub/chinain5/p/xiongan-beijings-floodplain-metropolis", principle: "The Future-First Advantage"},
{city: "Wanzhou", coordinates: [108.4087, 30.8079], deepdive: "https://open.substack.com/pub/chinain5/p/beneath-the-reservoir-wanzhous-submerged", principle: "The Phoenix Principle"},
{city: "Quanzhou", coordinates: [118.6757, 24.8739], deepdive: "https://open.substack.com/pub/chinain5/p/quanzhous-pirate-code-how-rebel-tycoons", principle: "The Opportunism Engine"},
{city: "Xiahe", coordinates: [102.5206, 35.2025], deepdive: "https://chinain5.substack.com/p/from-sacred-herds-to-luxury-brands", principle: "The Value Alchemy Principle"},
{city: "Jiangmen", coordinates: [113.0815, 22.5787], deepdive: "https://chinain5.substack.com/p/how-jiangmen-china-outsmarted-the-world", principle: "The Uncontested Market Strategy"},
{city: "Chongzuo", coordinates: [107.3645, 22.3765], deepdive: "https://open.substack.com/pub/chinain5/p/chongzuo-china-how-one-city-cornered", principle: "The IP Moonshot"},
{city: "Qiandongnan", coordinates: [107.9813, 26.5834], deepdive: "https://open.substack.com/pub/chinain5/p/qiandongnan-chinas-cultural-capital", principle: "The Native IP Alchemy Principle"},
{city: "Qionghai", coordinates: [110.4746, 19.2592], deepdive:...