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:...