<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>Conic (Albers) World Map SVG</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <style>
    html, body { margin:0; padding:0; background:#111; }
    #wrap { display:flex; align-items:center; justify-content:center; min-height:100vh; }
    /* Page background is dark so the white outlines pop while previewing.
       The exported SVG itself has a light background rectangle you can delete if you want transparent. */
  </style>
</head>
<body>
<div id="wrap">
  <!-- We create the SVG via JS so you can just save-as SVG from the browser -->
  <svg id="map" width="1400" height="800" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Albers Equal-Area Conic World Map"></svg>
</div>

<!-- D3 + TopoJSON (from official CDNs) -->
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3"></script>

<script>
(async function () {
  const width = 1400, height = 800;
  const svg = d3.select("#map")
    .attr("viewBox", `0 0 ${width} ${height}`)
    .attr("preserveAspectRatio", "xMidYMid meet");

  // Background (remove this rect if you want a transparent SVG)
  svg.append("rect")
    .attr("x", 0).attr("y", 0)
    .attr("width", width).attr("height", height)
    .attr("fill", "#f2f2f2");

  // Albers equal-area conic (global-ish setup)
  // Standard parallels picked to minimize distortion across mid-latitudes
  const projection = d3.geoAlbers()
    .parallels([20, 50])     // tweak if you like
    .rotate([0, 0])          // center longitudes
    .center([0, 10])         // slight north bias to fit Antarctica
    .translate([width / 2, height / 2])
    .scale(300);             // adjust size

  const path = d3.geoPath(projection);

  // Load world countries (Natural Earth via world-atlas)
  // 110m keeps paths light; switch to 50m for more detail if needed
  const world = await fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json").then(r => r.json());
  const { countries, land } = world.objects;

  const geoCountries = topojson.feature(world, countries);
  const geoLand = topojson.feature(world, land);

  // Optional graticule for reference (comment out if you want it ultra clean)
  // const graticule = d3.geoGraticule10();
  // svg.append("path").attr("d", path(graticule))
  //   .attr("fill", "none").attr("stroke", "#ddd").attr("stroke-width", 0.6);

  // Land fill (flat gray)
  svg.append("path")
    .datum(geoLand)
    .attr("d", path)
    .attr("fill", "#c8c8c8");

  // Country outlines (thin white)
  svg.append("g")
    .selectAll("path")
    .data(geoCountries.features)
    .join("path")
    .attr("d", path)
    .attr("fill", "none")
    .attr("stroke", "#ffffff")
    .attr("stroke-width", 0.6)
    .attr("vector-effect", "non-scaling-stroke"); // keep hairline look when resizing

  // Optional neatline boundary of the projection (comment out if not needed)
  // svg.append("path")
  //   .datum({type: "Sphere"})
  //   .attr("d", path)
  //   .attr("fill", "none")
  //   .attr("stroke", "#bbb")
  //   .attr("stroke-width", 0.8);

  // Title metadata inside SVG (safe to delete)
  svg.append("metadata").text(`
    Projection: Albers Equal-Area (conic)
    Fill: #c8c8c8, Stroke: #ffffff
    Data: Natural Earth via world-atlas TopoJSON
  `);
})();
</script>
</body>
</html>
