---
title: "点阵地球访客地图"
summary: "three.js 点阵地球：各国访客数立成红色光柱，蓝色弧线带着光点飞向同一个目的地，可拖动、可点光柱看数字。"
category: "visual (图表与 3D)"
origin: "original"
stack: ["html","css","three.js"]
tags: ["3D","地球","数据可视化","地图"]
demo: "https://zhuoqidev.com/design/demos/dot-globe-visitors/"
url: "https://zhuoqidev.com/design/dot-globe-visitors/"
license: "MIT"
added: "2026-10-14"
translation: "https://zhuoqidev.com/en/design/dot-globe-visitors/index.md"
---

# 点阵地球访客地图

> three.js 点阵地球：各国访客数立成红色光柱，蓝色弧线带着光点飞向同一个目的地，可拖动、可点光柱看数字。

## 看点

- **点阵陆地**：在球面上用斐波那契螺旋均匀撒 5.2 万个点，只留落在陆地上的（约 1.5 万个），一个 `Points` 一次画完。陆地数据是 0.5° 的位图，只有「哪里是陆地」，不画国界。
- **点往边缘淡出**：点的着色器算「这个点朝不朝向镜头」，越靠球的边缘越透明，球看起来有体积；背面的点被一个略小的不透明球挡住。
- **光柱**：所有国家共用一个 `InstancedMesh`，每根柱子是同一个单位圆柱，按国家的位置、朝向和高度摆放。高度按访客数开平方，小国家也看得见；柱子从地面长出来。
- **弧线 + 流动光点**：每条弧是一段二次贝塞尔管子，顶点在大圆中点上方，路越远拱得越高；全部合成一个几何体，光点在片元着色器里按 `t` 和时间算，不用逐帧改顶点。
- **跟着主题走**：颜色都从 CSS 变量读，切换深浅色时重读一次；浅色背景上弧线改用普通混合（叠加光在纸色上看不见）。
- **省电**：离开视口、没东西在动时就停掉渲染循环；偏好减少动效时不自转、不流动、柱子直接到位。

## 怎么用

1. 把 `index.html` 里的 `.stage` 结构、样式和 `<script type="module">` 拷过去，`geo.js` 放同一目录（普通 `<script>` 引入，`file://` 也能打开）。
2. 把示例里的 `VISITORS`（ISO 两位国家码 → 访客数）换成你统计里的真实数字，`HOME` 改成弧线要飞向的城市经纬度。
3. 想换更细或更粗的陆地：从 Natural Earth 下载陆地 GeoJSON，`node build-land.mjs ne_50m_land.geojson`，把输出贴进 `geo.js` 的 `land`。
4. 页面首屏很重要的话，可以等用户第一次滚动或移动鼠标再 `import` three.js 和建地球，首屏先放一张静态图。

## 坑

- 地理数据来自 Natural Earth（公有领域）：陆地位图由 1:50m 陆地多边形生成，国家点是 1:50m 国家图层的标注点（`LABEL_X / LABEL_Y`）。故意不画国界，避免地图在边界问题上表态。
- 浅色背景上 `AdditiveBlending` 几乎看不见，必须按主题切混合模式，并把 `needsUpdate` 设成 `true`。
- 离目的地太近（小于 4°）的国家不画弧线，否则弧线缩成一个点还会穿进地面。
- 手机上 canvas 要设 `touch-action: pan-y`，否则竖着滑会被地球吃掉，页面滚不动。
- 拖动时别弹提示框，要区分「点了一下」和「拖了一段」（这里按移动距离小于 6px 算点击）。

## 参考实现（完整源码）

在线演示：https://zhuoqidev.com/design/demos/dot-globe-visitors/。共 3 个文件，第一个是演示页本身。

### index.html

```html
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>点阵地球访客地图</title>
    <style>
      :root {
        --paper: #fbf8f1;
        --paper-2: #f3eee2;
        --card: #fffdf8;
        --ink: #1c2230;
        --ink-2: #4a5163;
        --ink-3: #636877;
        --line: #e6dfd0;
        --dot: #d8d0bf;
        --blue: #2f5bd3;
        --blue-soft: #e8eefc;
        --seal: #c0391f;
        --hi: #ffe066;
        --shadow: 0 1px 0 rgba(28, 34, 48, 0.04), 0 10px 28px -14px rgba(28, 34, 48, 0.28);
        --f-sans: system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
        --f-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
        color-scheme: light;
      }
      @media (prefers-color-scheme: dark) {
        :root {
          --paper: #14161b;
          --paper-2: #1c1f26;
          --card: #1e2129;
          --ink: #ece7dc;
          --ink-2: #bab6ac;
          --ink-3: #959aa8;
          --line: #31353f;
          --dot: #2c3039;
          --blue: #8eaaff;
          --blue-soft: #1f2a47;
          --seal: #f0694e;
          --hi: #7d6416;
          --shadow: 0 1px 0 rgba(0, 0, 0, 0.25), 0 10px 28px -14px rgba(0, 0, 0, 0.8);
          color-scheme: dark;
        }
      }
      * {
        box-sizing: border-box;
      }
      body {
        margin: 0;
        min-height: 100vh;
        background: var(--paper) radial-gradient(var(--dot) 1px, transparent 1.2px) 0 0 / 22px 22px;
        color: var(--ink);
        font: 16px/1.7 var(--f-sans);
      }
      main {
        max-width: 1120px;
        margin: 0 auto;
        padding: 28px 24px 40px;
      }
      .kicker {
        margin: 0;
        font: 500 12px/1.6 var(--f-mono);
        letter-spacing: 0.08em;
        color: var(--seal);
      }
      h1 {
        margin: 2px 0 4px;
        font-size: 28px;
        line-height: 1.3;
      }
      .hint {
        margin: 0 0 18px;
        font-size: 14.5px;
        color: var(--ink-2);
      }

      /* ---------- globe + ranked list ---------- */
      .grid {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 300px;
        gap: 24px;
        align-items: start;
      }
      .stage {
        position: relative;
        height: clamp(340px, calc(100vh - 170px), 640px);
        background: var(--card);
        border: 1px solid var(--line);
        border-radius: 14px;
        box-shadow: var(--shadow);
        overflow: hidden;
      }
      .stage canvas {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        cursor: grab;
        touch-action: pan-y; /* a vertical swipe still scrolls the page on a phone */
      }
      .stage canvas:active {
        cursor: grabbing;
      }
      .legend {
        position: absolute;
        left: 14px;
        bottom: 12px;
        display: flex;
        gap: 14px;
        margin: 0;
        font: 400 12px/1.6 var(--f-mono);
        color: var(--ink-3);
        pointer-events: none;
      }
      .legend i {
        display: inline-block;
        width: 10px;
        height: 10px;
        margin-right: 5px;
        vertical-align: -1px;
        border-radius: 2px;
        background: var(--seal);
      }
      .legend .arc i {
        height: 2px;
        vertical-align: 3px;
        background: var(--blue);
      }
      .nogl {
        display: grid;
        place-items: center;
        height: 100%;
        margin: 0;
        padding: 24px;
        text-align: center;
        color: var(--ink-3);
      }
      .tip {
        position: absolute;
        z-index: 2;
        translate: -50% calc(-100% - 12px);
        padding: 6px 10px;
        border: 1.5px solid var(--ink);
        border-radius: 10px;
        background: var(--card);
        box-shadow: 2px 3px 0 rgba(28, 34, 48, 0.18);
        font: 500 13px/1.45 var(--f-sans);
        white-space: nowrap;
        pointer-events: none;
      }
      .tip span {
        display: block;
        font: 400 12px/1.5 var(--f-mono);
        color: var(--ink-2);
      }
      .side h2 {
        margin: 0 0 8px;
        font-size: 15px;
      }
      .kpis {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 8px;
        margin: 0 0 18px;
      }
      .kpis div {
        padding: 8px 10px;
        background: var(--card);
        border: 1px solid var(--line);
        border-radius: 10px;
      }
      .kpis dt {
        font-size: 12px;
        color: var(--ink-3);
      }
      .kpis dd {
        margin: 0;
        font: 600 18px/1.4 var(--f-mono);
      }
      .list {
        list-style: none;
        margin: 0;
        padding: 0;
        font-size: 14px;
      }
      .list li {
        position: relative;
        display: flex;
        justify-content: space-between;
        gap: 8px;
        z-index: 0;
        padding: 4px 8px;
        border-radius: 6px;
      }
      /* The bar behind each row is as wide as its share of the top row. */
      .list li::before {
        content: "";
        position: absolute;
        inset: 0 auto 0 0;
        width: var(--w);
        border-radius: 6px;
        background: var(--blue-soft);
        z-index: -1;
      }
      .list .v {
        font-family: var(--f-mono);
        color: var(--ink-2);
      }
      .note {
        margin: 12px 0 0;
        font-size: 12px;
        color: var(--ink-3);
      }
      @media (max-width: 820px) {
        main {
          padding: 20px 16px 32px;
        }
        h1 {
          font-size: 24px;
        }
        .grid {
          grid-template-columns: minmax(0, 1fr);
        }
        .stage {
          height: min(92vw, 520px);
        }
      }
    </style>
  </head>
  <body>
    <main>
      <p class="kicker">VISITORS · 示例数据</p>
      <h1>访客从哪来</h1>
      <p class="hint">拖动地球转着看；红色光柱越高，那个国家的访客越多，蓝色弧线飞向目的地。数字都是编的。</p>
      <div class="grid">
        <div class="stage" data-stage>
          <div class="tip" data-tip hidden></div>
          <p class="legend" aria-hidden="true">
            <span><i></i>访客数</span><span class="arc"><i></i>飞向目的地</span>
          </p>
        </div>
        <aside class="side">
          <dl class="kpis">
            <div>
              <dt>访客</dt>
              <dd data-kpi="visitors">–</dd>
            </div>
            <div>
              <dt>国家 / 地区</dt>
              <dd data-kpi="countries">–</dd>
            </div>
            <div>
              <dt>目的地</dt>
              <dd data-kpi="home">–</dd>
            </div>
          </dl>
          <h2>访客最多的地方</h2>
          <ol class="list" data-list></ol>
          <p class="note">点地球上的光柱（或鼠标悬停）看具体数字。</p>
        </aside>
      </div>
    </main>

    <!-- window.GEO: land bitmap + one point per country (Natural Earth, public domain). -->
    <script src="geo.js"></script>
    <script type="importmap">
      {
        "imports": {
          "three": "https://cdn.jsdelivr.net/npm/three@0.186.1/build/three.module.js",
          "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.186.1/examples/jsm/"
        }
      }
    </script>
    <script type="module">
      import {
        AdditiveBlending,
        BackSide,
        BufferAttribute,
        BufferGeometry,
        Color,
        CylinderGeometry,
        Group,
        InstancedMesh,
        Matrix4,
        Mesh,
        MeshBasicMaterial,
        NormalBlending,
        PerspectiveCamera,
        Points,
        Quaternion,
        QuadraticBezierCurve3,
        RingGeometry,
        Scene,
        ShaderMaterial,
        SphereGeometry,
        SRGBColorSpace,
        TubeGeometry,
        Vector3,
        WebGLRenderer,
      } from "three";
      import { mergeGeometries } from "three/addons/utils/BufferGeometryUtils.js";

      // ---------- sample data (made up) ----------
      // Visitors per country, keyed by ISO 3166-1 alpha-2 code; in a real site this comes from your
      // analytics. HOME is where every arc lands.
      const HOME = { name: "上海", lat: 31.23, lon: 121.47 };
      const VISITORS = {
        CN: 4210,
        US: 1830,
        JP: 920,
        SG: 640,
        DE: 520,
        GB: 480,
        KR: 450,
        CA: 360,
        AU: 300,
        FR: 280,
        IN: 260,
        NL: 180,
        BR: 150,
        RU: 140,
        MY: 130,
        TH: 110,
        VN: 100,
        ID: 90,
        ES: 80,
        IT: 70,
        SE: 60,
        AE: 50,
        TR: 45,
        MX: 40,
        ZA: 40,
        NZ: 30,
        AR: 25,
        EG: 20,
        KE: 15,
        CL: 12,
      };

      const D = Math.PI / 180;
      const DOTS = 52000; // dots over the whole sphere; about 30% land on land
      const MAX_ARCS = 48;
      const ARC_STEPS = 40;
      const UP = new Vector3(0, 1, 0);
      const { land, points: POINTS } = window.GEO;
      const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
      const darkQuery = matchMedia("(prefers-color-scheme: dark)");

      let regionNames = null;
      try {
        regionNames = new Intl.DisplayNames(["zh-CN"], { type: "region" });
      } catch {}
      const nameOf = (code) => regionNames?.of(code) ?? code;
      const rows = Object.entries(VISITORS)
        .map(([code, visitors]) => ({ code, name: nameOf(code), visitors }))
        .sort((a, b) => b.visitors - a.visitors);

      // ---------- the side panel ----------
      const num = new Intl.NumberFormat("zh-CN");
      document.querySelector('[data-kpi="visitors"]').textContent = num.format(
        rows.reduce((s, r) => s + r.visitors, 0),
      );
      document.querySelector('[data-kpi="countries"]').textContent = rows.length;
      document.querySelector('[data-kpi="home"]').textContent = HOME.name;
      const max0 = rows[0].visitors;
      document.querySelector("[data-list]").replaceChildren(
        ...rows.slice(0, 10).map((r) => {
          const li = document.createElement("li");
          li.style.setProperty("--w", `${(r.visitors / max0) * 100}%`);
          const n = document.createElement("span");
          n.textContent = r.name;
          const v = document.createElement("span");
          v.className = "v";
          v.textContent = num.format(r.visitors);
          li.append(n, v);
          return li;
        }),
      );

      // ---------- the globe ----------
      /** lat/lon in degrees to a point on a sphere of radius r; longitude 0 faces +z. */
      function vec(lat, lon, r = 1) {
        const la = lat * D;
        const lo = lon * D;
        return new Vector3(r * Math.cos(la) * Math.sin(lo), r * Math.sin(la), r * Math.cos(la) * Math.cos(lo));
      }

      // Evenly spread dots (a Fibonacci sphere), keeping the ones that fall on land.
      function landDots() {
        const bits = Uint8Array.from(atob(land.bits), (c) => c.charCodeAt(0));
        const isLand = (lat, lon) => {
          const x = Math.min(land.w - 1, Math.floor((lon + 180) * 2));
          const y = Math.min(land.h - 1, Math.floor((90 - lat) * 2));
          const n = y * land.w + x;
          return (bits[n >> 3] >> (n & 7)) & 1;
        };
        const out = [];
        const golden = Math.PI * (3 - Math.sqrt(5));
        for (let i = 0; i < DOTS; i++) {
          const y = 1 - (2 * (i + 0.5)) / DOTS;
          const r = Math.sqrt(1 - y * y);
          const x = Math.cos(golden * i) * r;
          const z = Math.sin(golden * i) * r;
          if (isLand(Math.asin(y) / D, Math.atan2(x, z) / D)) out.push(x * 1.002, y * 1.002, z * 1.002);
        }
        return new Float32Array(out);
      }

      function slerp(a, b, angle, t) {
        const s = Math.sin(angle);
        return a
          .clone()
          .multiplyScalar(Math.sin((1 - t) * angle) / s)
          .add(b.clone().multiplyScalar(Math.sin(t * angle) / s));
      }

      const css = (name) =>
        new Color(getComputedStyle(document.documentElement).getPropertyValue(name).trim() || "#888");

      function mountGlobe(stage, tip) {
        const canvas = document.createElement("canvas");
        canvas.setAttribute("aria-hidden", "true");
        // Throws without WebGL; the caller then shows a note and keeps the list.
        const renderer = new WebGLRenderer({ canvas, antialias: true, alpha: true, powerPreference: "low-power" });
        const dpr = Math.min(window.devicePixelRatio, 2);
        renderer.setPixelRatio(dpr);
        renderer.outputColorSpace = SRGBColorSpace;

        const scene = new Scene();
        const camera = new PerspectiveCamera(30, 1, 0.1, 50);
        camera.position.set(0, 0, 5);
        const tilt = new Group(); // leans the north towards the reader
        const spin = new Group(); // turns about the poles
        tilt.rotation.x = 0.42;
        spin.rotation.y = -(HOME.lon - 10) * D; // start with the destination a little right of centre
        tilt.add(spin);
        scene.add(tilt);

        // An opaque sphere just under the dots hides the dots on the far side.
        const body = new MeshBasicMaterial();
        spin.add(new Mesh(new SphereGeometry(0.995, 72, 48), body));

        // A soft rim of light around the edge (a back-facing sphere, brightest at the silhouette).
        const halo = new ShaderMaterial({
          uniforms: { uColor: { value: new Color() }, uStrength: { value: 0.5 } },
          vertexShader: `varying vec3 vN; void main() { vN = normalize(normalMatrix * normal); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
          fragmentShader: `uniform vec3 uColor; uniform float uStrength; varying vec3 vN;
            void main() { float a = pow(clamp(0.62 + vN.z, 0.0, 1.0), 4.0); gl_FragColor = vec4(uColor, a * uStrength); }`,
          side: BackSide,
          transparent: true,
          depthWrite: false,
        });
        tilt.add(new Mesh(new SphereGeometry(1.09, 64, 32), halo));

        // Land dots, fading out towards the edge of the disc.
        const dotGeo = new BufferGeometry();
        dotGeo.setAttribute("position", new BufferAttribute(landDots(), 3));
        const dots = new ShaderMaterial({
          uniforms: { uColor: { value: new Color() }, uSize: { value: 1.9 * dpr }, uAlpha: { value: 0.8 } },
          vertexShader: `uniform float uSize; varying float vFace;
            void main() {
              vec4 mv = modelViewMatrix * vec4(position, 1.0);
              vFace = dot(normalize(normalMatrix * position), normalize(-mv.xyz));
              gl_PointSize = uSize;
              gl_Position = projectionMatrix * mv;
            }`,
          fragmentShader: `uniform vec3 uColor; uniform float uAlpha; varying float vFace;
            void main() {
              if (length(gl_PointCoord - 0.5) > 0.5) discard;
              gl_FragColor = vec4(uColor, uAlpha * smoothstep(-0.05, 0.45, vFace));
            }`,
          transparent: true,
        });
        spin.add(new Points(dotGeo, dots));

        // Pillars: one unit cylinder standing on its base, placed and stretched per country (one draw call).
        const beamGeo = new CylinderGeometry(1, 1, 1, 10, 1, false).translate(0, 0.5, 0);
        const beamMat = new MeshBasicMaterial({ transparent: true, opacity: 0.92 });
        const beams = new InstancedMesh(beamGeo, beamMat, rows.length);
        spin.add(beams);

        // Arcs: thin tubes from each country to HOME, merged into one geometry; `t` runs 0 → 1 along each,
        // and a pulse runs along it in the shader.
        const arcMat = new ShaderMaterial({
          uniforms: { uColor: { value: new Color() }, uTime: { value: 0 }, uBase: { value: 0.22 } },
          vertexShader: `attribute float t; attribute float seed; varying float vT; varying float vSeed;
            void main() { vT = t; vSeed = seed; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
          fragmentShader: `uniform vec3 uColor; uniform float uTime; uniform float uBase; varying float vT; varying float vSeed;
            void main() {
              float head = fract(uTime * 0.22 + vSeed);
              float d = head - vT;
              float pulse = d >= 0.0 && d < 0.22 ? 1.0 - d / 0.22 : 0.0;
              gl_FragColor = vec4(uColor, uBase + pulse * 0.85);
            }`,
          transparent: true,
          depthWrite: false,
          blending: AdditiveBlending,
        });
        const arcs = new Mesh(new BufferGeometry(), arcMat);
        spin.add(arcs);

        // HOME: a dot and a ring that keeps spreading out from it.
        const homeN = vec(HOME.lat, HOME.lon);
        const homeQ = new Quaternion().setFromUnitVectors(new Vector3(0, 0, 1), homeN);
        const homeMat = new MeshBasicMaterial({ transparent: true });
        const ringMat = new MeshBasicMaterial({ transparent: true, depthWrite: false });
        const homeDot = new Mesh(new RingGeometry(0, 0.016, 24), homeMat);
        const ring = new Mesh(new RingGeometry(0.02, 0.026, 40), ringMat);
        for (const m of [homeDot, ring]) {
          m.position.copy(homeN).multiplyScalar(1.004);
          m.quaternion.copy(homeQ);
          spin.add(m);
        }

        // Colours come from the page's CSS tokens, so the globe follows light / dark like the rest.
        const theme = () => {
          const dark = darkQuery.matches;
          body.color = css("--paper-2");
          dots.uniforms.uColor.value = css("--ink-3");
          dots.uniforms.uAlpha.value = dark ? 0.75 : 0.65;
          halo.uniforms.uColor.value = css("--blue");
          halo.uniforms.uStrength.value = dark ? 0.45 : 0.22;
          beamMat.color = css("--seal");
          arcMat.uniforms.uColor.value = css("--blue");
          arcMat.blending = dark ? AdditiveBlending : NormalBlending; // adding light shows nothing on paper
          arcMat.uniforms.uBase.value = dark ? 0.2 : 0.28;
          arcMat.needsUpdate = true;
          homeMat.color = css("--seal");
          ringMat.color = css("--seal");
          wake();
        };

        // Pillars grow from the ground towards their height; the tallest is the busiest country.
        const max = Math.max(1, ...rows.map((r) => r.visitors));
        const shown = rows
          .filter((r) => POINTS[r.code])
          .map((row) => {
            const [lon, lat] = POINTS[row.code];
            const n = vec(lat, lon);
            return {
              row,
              n,
              q: new Quaternion().setFromUnitVectors(UP, n),
              h: 0,
              to: 0.04 + 0.42 * Math.sqrt(row.visitors / max), // sqrt, so small countries still show
            };
          });
        const m4 = new Matrix4();
        const sc = new Vector3();
        const W = 0.011;
        const placeBeams = () => {
          let moving = false;
          shown.forEach((b, i) => {
            const step = reduced ? b.to - b.h : (b.to - b.h) * 0.08;
            b.h = Math.abs(step) < 1e-4 ? b.to : b.h + step;
            if (b.h !== b.to) moving = true;
            m4.compose(b.n, b.q, sc.set(W, Math.max(b.h, 1e-4), W));
            beams.setMatrixAt(i, m4);
          });
          beams.count = shown.length;
          beams.instanceMatrix.needsUpdate = true;
          return moving;
        };

        // Each arc rises from the country, peaks over the middle of the great circle (higher for
        // longer trips) and comes down at HOME. Countries too close to HOME get no arc.
        const tubes = [];
        for (const b of shown) {
          if (tubes.length >= MAX_ARCS) break;
          const angle = b.n.angleTo(homeN);
          if (angle < 4 * D) continue;
          const mid = slerp(b.n, homeN, angle, 0.5).multiplyScalar(1 + 0.12 + 0.7 * (angle / Math.PI));
          const tube = new TubeGeometry(new QuadraticBezierCurve3(b.n, mid, homeN), ARC_STEPS, 0.0032, 5, false);
          const uv = tube.getAttribute("uv");
          const t = new Float32Array(uv.count);
          for (let i = 0; i < uv.count; i++) t[i] = uv.getX(i);
          tube.setAttribute("t", new BufferAttribute(t, 1));
          tube.setAttribute(
            "seed",
            new BufferAttribute(new Float32Array(uv.count).fill((tubes.length * 0.618) % 1), 1),
          );
          tube.deleteAttribute("normal");
          tube.deleteAttribute("uv");
          tubes.push(tube);
        }
        arcs.geometry = mergeGeometries(tubes);
        for (const g of tubes) g.dispose();

        // Dragging spins the globe (and, with a mouse, tilts it a little); a flick keeps it turning.
        let dragging = false;
        let moved = 0;
        let lastX = 0;
        let lastY = 0;
        let vel = 0;
        let idleSince = performance.now();
        canvas.addEventListener("pointerdown", (e) => {
          dragging = true;
          moved = 0;
          lastX = e.clientX;
          lastY = e.clientY;
          vel = 0;
          canvas.setPointerCapture(e.pointerId);
          wake();
        });
        canvas.addEventListener("pointermove", (e) => {
          if (!dragging) {
            if (e.pointerType === "mouse") hover(e.clientX, e.clientY);
            return;
          }
          const dx = e.clientX - lastX;
          const dy = e.clientY - lastY;
          moved += Math.abs(dx) + Math.abs(dy);
          lastX = e.clientX;
          lastY = e.clientY;
          vel = dx * 0.006;
          spin.rotation.y += vel;
          if (e.pointerType === "mouse") tilt.rotation.x = Math.min(1.1, Math.max(-0.5, tilt.rotation.x + dy * 0.004));
          showTip(null);
          wake();
        });
        const end = (e) => {
          if (!dragging) return;
          dragging = false;
          idleSince = performance.now();
          if (moved < 6) hover(e.clientX, e.clientY); // a tap, not a drag: show that pillar's numbers
        };
        canvas.addEventListener("pointerup", end);
        canvas.addEventListener("pointercancel", () => (dragging = false));
        canvas.addEventListener("pointerleave", (e) => {
          if (e.pointerType === "mouse" && !dragging) showTip(null);
        });

        function showTip(b, x, y) {
          if (!b) {
            tip.hidden = true;
            return;
          }
          tip.replaceChildren(b.row.name);
          const v = document.createElement("span");
          v.textContent = `${num.format(b.row.visitors)} 位访客`;
          tip.append(v);
          tip.style.left = `${x}px`;
          tip.style.top = `${y}px`;
          tip.hidden = false;
        }

        // The pillar whose top is nearest the pointer (within 16px), on the side facing the reader.
        const top = new Vector3();
        const face = new Vector3();
        const q = new Quaternion();
        function hover(x, y) {
          const r = canvas.getBoundingClientRect();
          spin.getWorldQuaternion(q);
          let best = null;
          let bestD = 16 * 16;
          let at = [0, 0];
          for (const b of shown) {
            face.copy(b.n).applyQuaternion(q);
            if (face.z < 0.1) continue;
            top.copy(b.n).multiplyScalar(1 + b.h);
            spin.localToWorld(top).project(camera);
            const sx = r.left + ((top.x + 1) / 2) * r.width;
            const sy = r.top + ((1 - top.y) / 2) * r.height;
            const d = (sx - x) ** 2 + (sy - y) ** 2;
            if (d < bestD) {
              bestD = d;
              best = b;
              at = [sx - r.left, sy - r.top];
            }
          }
          showTip(best, at[0], at[1]);
        }

        stage.prepend(canvas);
        new ResizeObserver(([entry]) => {
          const { width, height } = entry.contentRect;
          renderer.setSize(width, height, false);
          camera.aspect = width / Math.max(1, height);
          // Keep the whole globe in view on tall, narrow screens.
          camera.position.z = camera.aspect < 1 ? 5 / camera.aspect ** 0.8 : 5;
          camera.updateProjectionMatrix();
          wake();
        }).observe(stage);

        // Render only while on screen and while something moves.
        let visible = false;
        let running = false;
        let last = performance.now();
        function frame(now) {
          const dt = Math.min(0.05, (now - last) / 1000);
          last = now;
          let busy = placeBeams() || dragging;
          if (!dragging && Math.abs(vel) > 1e-4) {
            spin.rotation.y += vel;
            vel *= 0.94;
            busy = true;
          }
          if (!reduced) {
            if (!dragging && now - idleSince > 2500) spin.rotation.y += dt * 0.08;
            arcMat.uniforms.uTime.value += dt;
            const p = (now / 1600) % 1;
            ring.scale.setScalar(1 + p * 2.4);
            ringMat.opacity = 1 - p;
            busy = true;
          }
          renderer.render(scene, camera);
          if (!busy || !visible) stop();
        }
        function wake() {
          if (running || !visible) return;
          running = true;
          last = performance.now();
          renderer.setAnimationLoop(frame);
        }
        function stop() {
          running = false;
          renderer.setAnimationLoop(null);
        }
        new IntersectionObserver(([e]) => {
          visible = e.isIntersecting;
          if (visible) wake();
        }).observe(stage);
        darkQuery.addEventListener("change", theme);
        theme();
      }

      const stage = document.querySelector("[data-stage]");
      try {
        mountGlobe(stage, stage.querySelector("[data-tip]"));
      } catch {
        const p = document.createElement("p");
        p.className = "nogl";
        p.textContent = "这个浏览器没开 WebGL，地球画不出来；右边的列表照样能看。";
        stage.replaceChildren(p);
      }
    </script>
  </body>
</html>
```

### geo.js

```js
// Map data for the globe, loaded as a plain <script> so the demo also opens from file://.
// Both parts come from Natural Earth 1:50m (public domain, naturalearthdata.com), v5.1.2.
//
// GEO.land   where the land is, as a 0.5-degree bitmap: 720 x 360 cells, row 0 at 90N, column 0 at
//            180W, one bit per cell (bit n of the decoded bytes is cell n = y * 720 + x, low bit first).
//            Land only, no borders. build-land.mjs rebuilds it from ne_50m_land.geojson.
// GEO.points one [longitude, latitude] per ISO 3166-1 alpha-2 code: Natural Earth's label point
//            (LABEL_X / LABEL_Y of ne_50m_admin_0_countries), where that country's pillar stands.
window.GEO = {
  land: {
    w: 720,
    h: 360,
    bits: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMT5//8PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD7///kBAAAA4OP/////DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw8f////8fAE74sP////8fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7//////3/A9/////////9/PoAfAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8MDP//f//x/A////////////z/9/AAAAAAAAAAAAAAAAAAAAAIAPAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/IP7//j/f+D///////////////8HAAAAAAAAAAAAAAAAAABgfeCHzwEAAAAAAAD8DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/7/5/P//D/z//////////////30AAAAAAAAAAEAjBwAAAADAA08bAAAAAAAAAAD/AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///zz//fAcD//////////////wwAAAAAAADgL8/8HwAAAAAAAAAAAAAAAAAAAADz/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AMAgP+///8BAOD//////////////wMAAAAAAABAfz/AAAAAAAAAAAAAAAAAAAAAAADgPzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP444P/9//8H8P//////////////PwAAAAAAAAAg//8HAAAAAAAAAAAAAAAAAAAAAAAAAP4DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODxAVf+//+B////////////////HwIAAAAAAAAAhD8cAAAAAAAAAAAAAAAAAAAAAAAAgD8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgPADgAHwDv/w8A+P///////////////xEAAAAAAAAAAB/4AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gEAYAAAAAj8bwAAwP///////////////wUAAAAAAAAA4AcAAAAAAAAAAAAAAAAAAAAAAAQAAPgHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA/xhgAADAP/j//w8A4P//////////////FwAAAAAAAAAAAAMAAAAAAAAAAAAAAPADAAAAAAAAAPw/AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAD4Ay/wALYfwD8AwAAAwH/5////////////fwQAAAAAAAAAAAAAAAAAAAAAAAAAzP8AAAAAAACAg////wUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzP/BH/gPAD8APwAAAAAA/P///////////wEAAAAAAAAAAAAAAAAAAAAAAADg/wEAAAAAAAD+/////w0AAAAAgPj9AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P//zwEPn////wEAAAAA8P//////////fw0AAAAAAAAAAAAAAAAAAAAAAAD8AwAAAAAAAP7//////wcAAAAAAPzf8wUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAHAAAAHP///QAAAAAAwP//////////vwEAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAA0P///////wAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/GAAAAAAAAAAAAAAAAAAAgP///////////wAAAAAAAAAAAAAAAAAAAAAAAMAfAAAAAAAA4P//////DwMAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAAMMA//Ac+QAAAAAAAAP/////////ffwAAAAAAAAAAAAAAAAAAAAAAAPAHAAAAAAAAuv//////2QQAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/fw4AdYAP/sHPv38AAAAAAP7////////nAQAAAAAAAAAAAAAAAAAAAAAAAPgAAABwAAD+7/////8P//8fgP8BAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMD/9+cxH5g/zuDnfwAAAAAAAPv////////3DwAAAAAAAAAAAAAAAAAAAAAAAH4AAAD8QUD+//////////v///8DAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD/8f9/P8B/DPDHP+8DAAAAAP7/////////DAAAAAAAAAAAAAAAAAAAAAAAAH4AAAD+QfDw//////////////8GAMD//AMAAAAAAAAAAAAAAAAAAAAAAAAAAIB//P//fgA+DvDv//8TAAAAAN7/////////DwAAAAAAAAAAAAAAAAAAAAAAgH8AAAD+ef+n//////////////8HAoD/8wMAAAAAAAAAHwAAAADAAAAAAAAAAAAOwP//fwCAP4Cf////AwAAAND///////+fHwAAAAAAAAAAAAAAAAAAAAAAAPoAAMD/+fDf//////////////8H//f//38AAAAAAADAAAAAAAD9fwAAAAAAAAAA8P///wCAf8D/////OwAAADj+//////8eHwAAAAAAAAAAAABA1gYAAAAAAOAHAID/8f+/////////////////////////fwAAAAAAAAAAAOD///8AAAAAAAIAAL7//x+A/wH4//v/nwAAANj///////9zAAAAAAAAAAAAAACw+z8AAAAAAABgAMD/8f/f/////////////////////////wAAAAAAAAAAAPz/////HwAA90ccwP///zcYfgDggMH//wIAAPz6////////AQAAAAAAAAAAAGD//7cDAAAAAACAH8D/+f///////////////////////////wAA5/8BAAAAAP7//////wd/////A/D/+w/46CPgHyT+/wcAAAD8//////8/AAAAAAAAAAAAAPz///9fAAAADgAA/gP/8f//////////////////////////////wf9/AwAA8P///////////////+c/HBD44ffAH4D4fwAAAAD8//////8PAAAAAAAAAAAA4Pn/////BwAAAgxw/j/84/v///////////////////////////v/////HwAA8P///////////////wOAOQB4+H/0B4Dj/wsAAID+/////w8AAAAAAAAAAAAAKP//////PwAP4Nf/////4/f//////////////////////////////////wEAgP///////////////wcf/8fN/v/4D+CD/38AACD9////PwAAAAAAAAAAAAAAwP///////wEH/P//////4////////////////////////////////////wMAAP///////////////////v/////9H0AA//8DAPD/////HwAAAAAAAAAAAAAAgP///////wMH////////8P////////////////////////////////////MBAPj//////////////////v////9/DwDA//8fAMD/////DwAAAAAAAAAAAAAA+P/////z/wP+//////9z/P///////////////////////////////////f8P8MD///////////////////////9PAAD4//kHAOD////vAQAADIADAAAAAAAA9P////8P/HD/////////////////////////////////////////////+f8H/v///////////////////////893AADg/+AHAMD9//8fAAAAnv8HAAAAAAAA/v8f/v8/AP7/////////////////////////////////////////////AX8A+P/////////////////////////xAOD//8MBAID///8AAAAA+P8fAAAAAAAA/P8H+P8fAP//////////////////////////////////////////////ADgA+M/////////////////////////5B/D7/xcAAADx/38AAAAA+f8PAAAAAACA//8D/v8/Pv///////////////////////////////////////////789AAAAAMD////////////////////////4H0DA/x8AAAD+/18AAAAA8P8BAAAAAADg//8D////8P////////////////////////////////////////////8fAAAAAMD/////////////////////fw/8eACA/38AAAD+/38AAAAAgB8AAAAAAAD6///B//////////////////////////////////////////////////8fAAB4APj//////////////////////wcgABgAfjwAAAD8/z8AAAAAAAAAAAAAAAD//z/w//////////////////////////////////////////////////8/AAAAwP//////////////////////fwAADgAA5CMAAAD4/w8AAAAAAAAAAAAAAID//w/8//////////////////////////////////////////////////97AAAA4P//////////////////////PwAAAvE7gA8AAADg/wcAAAAAAAAAAAQAAPj//wf4/////////////////////////////////////////////z////8AAAAA8P//////////////////////HwAAAPH/AAAAAADg/wcAAAAAAAAAAAAAAPz//wf4////////////////////////////////////////////Bz7//w8AAAAA4P////P/////////////////DwAAAOD/AQAAAACA/wcAAAAAAAAAAAAAAPz//wP4////////////////////////////////////////////AQf//wEAAAAAQP7//374////////////////BwAAAOD/HwAAAAAA8QcAAAAAAAAAAAAAAPz//wf4////////////////////////////////////////////AMH/fwAAAAAAnP//f/6D////////////////BwAAAOD/n0AAAAAAYAMAAAAAAAAAAAAgAPz//5/wB/z///////////////////////////////////////8/APAnEAAAAAAAAPD/Pw8AwP7/////////////AwAAAOD/H+AAAAAAAAAAAAAAAAAAAAAAAPT//z8AAP7///////////////////////////////////////8fAHwAAAAAAAAAAPD/DwMAAPz/////////////AwAAAPD/H+ABAAAAAAAAAAAAAAAAAAAAAPTf/x+A//////////////////////////////////////8fEAA/AD8AAAAAAAAAABDaHwAAAHD/////////////FwAAAPj/b/gDAAAAAAAAAAAAAAAAAAAAAPjH/wOA//////////////////////////////////////8PAAAAgJ8AAAAAAAAAAADgzwAAAAD7////////////PwAAAOD///8DAAAAAAAAAAAAAAAAAOQBAOCB/wEQ/v////////////////////////////////////8BAAAA4A8AAAAAAAAAAADgcQAAAADp////////////fwAAAMD///8PAAAAAAAAAAAAAAAAAOAAAACA/yEA/v////////////////////////////////////8AAAAA/D8AAAAAAAAAAAB4OAAAAADr////////////fwAAAID///8PAAAAAAAAAAAAAAAAAPgPAAAY/xE4/v///////////////////////////////////z8AAAAA/D8AAAAAAAAAAAAcAAAAAACM/////////////38AAID///8fAAAAAAAAAAAAAAAAAPAHAAAe/gP8/////////////////////////////////////x8AAAAA/z8AAAAAAAAAAIAHAAAAAACk//////////////8AAIb///8fAAAAAAAAAAAAAAAAAOAHAAA//AD8/////////////////////////////////////w8AAAAA/38AAAAAAAAAAPAAAAAAAABg/v////////////8HAMD///9/AAAAAAAAAAAAAAAAAMgPAAAPDQD8/////////////////////////////////////wMAAACA/w8AAAAAAAAAAEwAAAAAAADg////////////////AfD///9/AQAAAAAAAAAAAAAAAMIfAAD2IQD8/////////////////////////////////////wAAAACA/w8AAAAAAAAAgAMAAAAAAABA8P//////////////D/7/////DwAAAAAAAAAAAAAAgB8eAADOABj/////////////////////////////////////PwgAAACA/w+AAAAAAAAAAAAAAAAAAAAA8P//////////////B/7/////BwAAAAAAAAAAAAAA8B9+AAA8A////////////////////////////////////////6MgAAAA/wAAAAAAAAAABAAAAAAAAABA+P//////////////D/z/////fAAAAAAAAAAAAAAA8A/8AAD+7////////////////////////////////////////+chAAAA/wAAAAAAAACAAAAAAAAAAACAoP//////////////D/z//////wAAAAAAAAAAAAAA4I//Afj///////////////////////////////////////////83AAAA/wAAAAAAAAAAAAAAAAAAAAAAof//////////////T/z//////wAAAAAAAAAAAAAA4A//B/7///////////////////////////////////////////93AAAAHwAAAAAAAAgAAAAAAAAAAAAAAv7/////////////D/j//////wEAAAAAAAAAAAAA+If/B/7///////////////////////////////////////////8/AAAAHgAAAAAAYAAAAAAAAAAAAAAAAP//////////////f/z/////fwAAAAAAAAAAAAAAcMD/A/////////////////////////////////////////////9zAAAADgAAAAAAAAAAAAAAAAAAAAAAAP7///////////////7/////xwAAAAAAAAAAAAAAAAD8x/////////////////////////////////////////////9xAAAABgAAAAAAAAAAAAAAAAAAAAAAgPn/////////////////////wwAAAAAAAAAAAAAAAIA/+P////////////////////////////////////////////9xAAAAAQAAAAAAAAAAAAAAAAAAAAAAAP///////////////////w/yYAAAAAAAAAAAAAAAACAB+P/////////////////////////////////////////////xAADAAAAAAAAAAAAAAAAAAAAAAAAAADz//////////////////wMDsAAAAAAAAAAAAAAAAAAA/v/////////////////////////////////////////////xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD8/////////////////wAM8B0AAAAAAAAAAAAAAADg//////////////////////////////////////////////8xAQAAAAAAAAAAAAAAAAAAAAAAAAAAAMD5////////////////P38A+A8AAAAAAAAAAAAAAADi//////////////////////////////////////////////8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID4////////////////338A/B8AAAAAAAAAAAAAAID///////////////////////////////////////////////8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID7////////////////7z8A/mcAAAAAAAAAAAAAAAD+/////////////////////////////////////////////38QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7/////////////////z8AADIAAAAAAAAAAAAAAADw////////////3////////////////////////////////z8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////////79AACAAAAAAAAAAAAAAAADw////////////4///D/z//////////////////////////x9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+//////////////+//3/mAAAAAAAAAAAAAAAAAADA/////////59/4P//A/z//////////////////////////w8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////////+jAAAAAAAAAAAAAAAAAADA////+////w888P//APz//////////////////////////wcAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAD////////////////3/w8/AAAAAAAAAAAAAAAAAADA////+P///wf8/f9/gP///////////////////////////wMYAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////////+cDAAAAAAAAAAAAAAAAAADA////wf///wMY+P8/wP///////////////////////////wEwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////P3AAAAAAAAAAAAAAAAAAAADg///5wf///wEAwP8/4P///////////////////////////wB4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////DzAAAAAAAAAAAAAAAAAAAADg/3/gA////wEAgP9/wP//////////////////////////fwD4AwAAAAAAAAAAAAAAAAAAAAAAAAAAAID/////////////////BwAAAAAAAAAAAAAAAAAAwP//fxjgD/z//wAAAP5/gP//////////////////////////HgD4BwAAAAAAAAAAAAAAAAAAAAAAAAAAAID/////////////////AwAAAAAAAAAAAAAAAAAAwP//PwDQD/D//wAAAPh/AP7///////////////////////9/BAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/////////////////AwAAAAAAAAAAAAAAAAAAgP//PwCGH8D//wAAAPj/AP7///////////////////////8fAABhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////BwAAAAAAAAAAAAAAAAAAwP//PwAG/oD//wB+APj/AfL///////////////////////8PAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////8/AAAAAAAAAAAAAAAAAAAAgP//DwAA+IH//4P/A/z/A+D///////////////////////8HAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////8/AAAAAAAAAAAAAAAAAAAAgP//AwAH4If/cvD/////B+T/////////////////////8/8HAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID///////////////8PAAAAAAAAAAAAAAAAAAAAwP//AQAGwJPf4f//////B/7/////////////////////8f8BAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////8PAAAAAAAAAAAAAAAAAAAAwP//YAAGAIE/8P//////B/j///////////////////9/eH4AAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////38FAAAAAAAAAAAAAAAAAAAA4P9/AAAGAAN+8P//////B/j///////////////////8/CHgAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+/////////////38DAAAAAAAAAAAAAAACAAAA4P//AAAAAAE8wP//////A/D///////////////////8HAPgAAIAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/////////////z8DAAAAAAAAAAAAAAAAAAAAwP9/AAAAgAHI4f//////A/D///////////////////8PAPwBAIADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw/////////////38BAAAAAAAAAAAAAAAgAAAAwP8/AAAAPgA64P//////A/D///////////////////8/AuADAMADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4/////////////38AAAAAAAAAAAAAAAAAAAAAwP8PAAAIOAA4gP//////H/D///////////////////8/H8AHAOADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw//////////////8AAAAAAAAAAAAAAAAAAAAAAPgEwPs/IAAAgJ9f////P/z/////////////////////B/AHAP4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw//////////////8AAAAAAAAAAAAAAAAAAAAAABAA/v8fAAAAAAgO////////////////////////////AeAHBP8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg//////////////8BAAAAAAAAAAAAAAAAAAAAABCA//8/AAAAAAAA////////////////////////////AOAHAP8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA/////////////38AAAAAAAAAAAAAAAAAAAAAAHDh//8/AACAFwAM//////////////////////////9/AOAH/j8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA/////////////38AAAAAAAAAAAAAAAAAAAAAAPj///9/AAAAAAAG//////////////////////////8/ACAA3xkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///////////w8AAAAAAAAAAAAAAAAAAAAAAPj///8PAAAAAACA////////////////////////////AQDE+QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P///////////wMAAAAAAAAAAAAAAAAAAAAAAP7///8/AAAAAACA////////////////////////////AQAongAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P///////////wEAAAAAAAAAAAAAAAAAAAAAgP////8/AAAAAADA////////////////////////////ARD4AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P///////////wAAAAAAAAAAAAAAAAAAAEAAwP//////DwAcAADA////////////////////////////AwDyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP//////////fwAAAAAAAAAAAAAAAAAAAAAA4P//////fwA/AADA////////////////////////////BwBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgP//////////PwAAAAAAAAAAAAAAAAAAAAAA4P//////fwD/AwDg////////////////////////////DwB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgMP/////////HwAAAAAAAAAAAAAAAAAAAAAA8P///////wH/f/Dx////////////////////////////BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMf/////////HwAAAAAAAAAAAAAAAAAAAAAA8P///////w//////////////////////////////////BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMf//////5fwHwAAAAAAAAAAAAAAAAAAAAAA4P//////////////////////////////////////////BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI7/////yx8gPgAAAAAAAAAAAAAAAAAAAAAA8P//////////////////4f//////////////////////DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz/////AywAPAAAAAAAAAAAAAAAAAAAAAAA+P/////////////d////4P//////////////////////DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADj/////AQAAeAAAAAAAAAAAAAAAAAAAABAA/P/////////////f////wf//////////////////////BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADL+//8/AAAAeAAAAAAAAAAAAAAAAAAAAEAA/v/////////////7////gf//////////////////////AwAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHT4//8fAAAAfAAAAAAAAAAAAAAAAAAAAADA//////////////+H////A///////////////////////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPj4//8fAAAA+AAAAAAAAAAAAAAAAAAAAADg//////////////8P////B/z/////////////////////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDx//8fAAAA8AAAAAAAAAAAAAAAAAAAAADg//////////////8P////D7j8//////////////////9/AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIDh//8fAAAA8AAAAAAAAAAAAAAAAAAAAAD4//////////////8P/v//DwD8//////////////////9/AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADh//8/AAAA4AAAAAAAAAAAAAAAAAAAAAD4//////////////8f/P//TwD5//////////////////9/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD//8fAAAAQAAAAAAAAAAAAAAAAAAAAAD8//////////////8//P//X4ABXOD///////////////9/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//8fAAAAAAgAAAAAAAAAAAAAAAAAAAD8//////////////8//P//f+ABAMD///////////////8fDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO/v8fAAAAABAAAAAAAAAAAAAAAAAAAAD+//////////////9/+P///+ADAID///////////////8PBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY/P8fAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////9/4P////8PAAD///////////////8HBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ+P8PAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////9/4P////8/AAD+//////////////8BBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P8PAAAA/wEIAAAAAAAAAAAAAAAAAID/////////////////wP////9/AADg/////9///////z8AAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P8PAACA8QcAAAAAAAAAAAAAAAAAAID/////////////////wf//////AAD8/P///z///////wcAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P8fAAAABB8AAAAAAAAAAAAAAAAAAMD/////////////////w/////9/AAD4/v///wf//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP8fAPADAHgAAAAAAAAAAAAAAAAAAMD/////////////////w/////8/AADw/v//PwD///9/EAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAA4P8/APgDAPAAAAAAAAAAAAAAAAAAAID/////////////////g/////8fAAAg/P//PwD+//8/EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P8/APgBAOAPAAAAAAAAAAAAAAAAAAD/////////////////A/////8vAAAA/P//HwD8//8fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAA4P9/APgBAADgBgAAAAAAAAAAAAAAAID/////////////////B/z///8HAAAA/v//AwD4//8POAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAwP//APwBAADAPwAAAAAAAAAAAAAAAID/////////////////B/z///8PAAAA/P//AwD4//8PHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AP4BAACAfwAAAAAAAAAAAAAAAAD/////////////////B/z///8DAAAA/P//AQDw//8HHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz/9/8AAHjwSxwAAAAAAAAAAAAAAAD/////////////////H/j///8BAAAA/P//AADg//8PAAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD///8AAAAAAEAAAAAAAAAAAAAAAAD/////////////////H/D//38AAAAA/P9/AADg//8fAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMD//38AAAAAAAAAAAAAAAAAAAAAAAD/////////////////P+D//z8AAAAA/P8fAADg//8/AAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+/38AAAAAAAAAAAAAAAAAAAAAAID/////////////////P+D//wcAAAAA+P8fAADg+v9/AAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4+38AAAAAAAAwAAAAAAAAAAAAAID/////////////////P8D//wEAAAAA+P8DAADw+P//AAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA4H//AAAAAAAAAAAAAAAAAAAAAID/////////////////f+D//wAAAAAA+P8BAAAA+P//AQAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP//AAAAAAAAAAAAAAAAAAAAAcD/////////////////f+D/fwAAAAAA8P8AAAAA8P//AwAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgP//AQAAAAAAAAAAAAAAAAAAAOD//////////////////8P/BwAAAAAA8P8AAAAA8P//AwAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AwAAAAAAAAAAAAAAAAAAAMD//////////////////8f/AwAAAAAA4P8AAAAA8P//AwAAJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD/AQAAAAAAAAAAAAAAAAAAAID//////////////////69/AAAAAAAA4P8AAAAA8P//AwAA1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID+AQAAAAAgAAAAAAAAAAAAAMD//////////////////98HAAAAAAAA4P8BAAAA4Pz/BwAAhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+AQAAAAAAAAAAAAAAAAAAAMD//////////////////78BAAAAAAAAwP8AAAAC4Pz/BwAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8AQAAAwAAAAAAAAAAAAAAAID//////////////////38AAAAAAAAAwP8AAAAA4OD/AwAAxAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AQCAAQAAAAAAAAAAAAAAAAD+/////////////////z8AIAAAAAAAgP8AAAAC4MD/AwAAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAADweAAAAAAAAAAAAAAAAAD//////////////////38APgAAAAAAAP8AAAAAYMD/AwAAsAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAQD+fwAgAAAAAAAAAAAAAAD4///////////////////4PwAAAAAAAP8AAAAAcMD/AAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAQD+/o8nAAAAAAAAAAAAAAD4////////////////////PwAAAAAAAH8AAAAAIAAeAABAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAwD+/P8fAAAAAAAAAAAAAADg////////////////////PwAAAAAAAD4BAAAAIAAcAAAgIAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABw///P8/AAAAAAAAAAAAAADg////////////////////HwAAAAAAAH4DAAAA4AAMAAAQQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/pn///8/AAAAAAAAAAAAAADA////////////////////HwAAAAAAAA4DAAAA8AAAAAAIABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcPj/////AQAAAAAAAAAAAADA////////////////////DwAAAAAAAAwHAAAA4AEAAAAAwB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4Pj/////AwAAAAAAAAAAAACA////////////////////DwAAAAAAAAAHAAAAwAAAAAAAUB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQPD/////BwAAAAAAAAAAAAAA////////////////////BwAAAAAAAAAPAAAAgAEAAAAEEBcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD/////DwAAAAAAAAAAAAAA/v//////////////////AwAAAAAAAAAPAAAAAAcAAAAGAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD/////HwAAAAAAAAAAAAAA+P//D/7/////////////AwAAAAAAAAAHAAAAAA8AAAAHAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD//////w8AAAAAAAAAAAAA8P//APz/////////////AwAAAAAAAAAAAAAAAB4AAAAfAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD//////38AAAAAAAAAAAAA4P89APj/////////////AQAAAAAAAAAAAADAAz4AAIB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD///////8AAAAAAAAAAAAAgAcAAPj/////////////AAAAAAAAAAAAAACAD34AAOAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD///////8BAAAAAAAAAAAAAAAAAAD8////////////AAAAAAAAAAAAAAAAH34AAPAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMD///////8DAAAAAAAAAAAAAAAAAAD6//////////9/AAAAAAAAAAAAAAAAPnwAAfgHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD///////8DAAAAAAAAAAAAAAAAAADw//////////8/AAAAAAAAAAAAAAAAfHgAAPwHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD///////8DAAAAAAAAAAAAAAAAAADw//////////8fAAAAAAAAAAAAAACA+HgAgP8PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPj///////8HAAAAAAAAAAAAAAAAAADw//////////8HAAAAAAAAAAAAAAAA8PEAwP8PAAABAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAPz///////8PAAAAAAAAAAAAAAAAAAD4//////////8DAAAAAAAAAAAAAAAA4McAyP8PAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz///////8PAAAAAAAAAAAAAAAAAAD4//////////8AAAAAAAAAAAAAAAAAxB8A/P8fBIIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////8HAAAAAAAAAAAAAAAAAAD4/////////38AAAAAAAAAAAAAAAAAyB8A/P8P/4EBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////8XAAAAAAAAAAAAAAAAAAD4/////////z8AAAAAAAAAAAAAAAAAgF8A/P8HAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAgP////////95AAAAAAAAAAAAAAAAAAD4/////////x8AAAAAAAAAAAAAAAAAAH8A/P+HAIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAgP////////9/AwAAAAAAAAAAAAAAAAD8/////////w8AAAAAAAAAAAAAAAAAAH8A+P+HQMCBjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP////////+/DwAAAAAAAAAAAAAAAAD8/////////w8AAAAAAAAAAAAAAAAAIP4B8P+DHQDADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP/////////ffwAAAAAAAAAAAAAAAAD4/////////wcAAAAAAAAAAAAAAAAAAP4J8P+BDwIQDxsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP//////////fwAAAAAAAAAAAAAAAAD4/////////wMAAAAAAAAAAAAAAAAAgPwD8P/BDwAAAn4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wcAAAAAAAAAAAAAAADw/////////wAAAAAAAAAAAAAAAAAAAPif8P/BDQAAHf8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8BAAAAAAAAAAAAAADg/////////wAAAAAAAAAAAAAAAAAAAPgPAPvAHTAevv8fAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP////////////8HAAAAAAAAAAAAAADA/////////wAAAAAAAAAAAAAAAAAAAPAPAGCBHSAg9P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP////////////8PAAAAAAAAAAAAAACA////////fwAAAAAAAAAAAAAAAAAAAOAPAACAOQAAwP//A4ACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4P////////////8fAAAAAAAAAAAAAAAA////////PwAAAAAAAAAAAAAAAAAAAIAPAACACQAAAP7/B4ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP//////////////AQAAAAAAAAAAAAAA////////vwAAAAAAAAAAAAAAAAAAAAAPAACAIQAAAPj/D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP//////////////AwAAAAAAAAAAAAAA////////PwAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAEvD/H34gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP//////////////AwAAAAAAAAAAAAAA/v//////fwAAAAAAAAAAAAAAAAAAAADwAAAAAAAAEOD/fxhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AwAAAAAAAAAAAAAA/v//////fwAAAAAAAAAAAAAAAAAAAAD4YQAAAAAAEMD/PwCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7/////////////AwAAAAAAAAAAAAAA/P//////fwAAAAAAAAAAAAAAAAAAAADg/wEAAAAAAMD/PwAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7/////////////AwAAAAAAAAAAAAAA/P//////fwAAAAAAAAAAAAAAAAAAAAAA+R8AABBAAPD/fAAAIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz/////////////AwAAAAAAAAAAAAAA+P//////fwAAAAAAAAAAAAAAAAAAAAAAwH8AwAMAADh/8AAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz/////////////AwAAAAAAAAAAAAAA+P//////fwAAAAAAAAAAAAAAAAAAAAAAAEAdDzwAAAB+4AEAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPj/////////////AQAAAAAAAAAAAAAA/P//////fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAgwBMAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPj/////////////AAAAAAAAAAAAAAAA/P//////fwAAAAAAAAAAAAAAAAAAAAAAAACAgQMAAAAAgA8AAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD/////////////AAAAAAAAAAAAAAAA+P///////wAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD///////////8/AAAAAAAAAAAAAAAA+P///////wEAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD///////////8/AAAAAAAAAAAAAAAA8P///////wEAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMD///////////8fAAAAAAAAAAAAAAAA8P///////0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAwBgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMD///////////8PAAAAAAAAAAAAAAAA+P///////wEABAAAAAAAAAAAAAAAAAAAAAAAAABA/wI4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID///////////8PAAAAAAAAAAAAAAAA/P///////wEABAAAAAAAAAAAAAAAAAAAAAAAAADg/wFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID///////////8DAAAAAAAAAAAAAAAA/v///////wEADAAAAAAAAAAAAAAAAAAAAAAAAADw/wB4AAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8DAAAAAAAAAAAAAAAA/v///////wEADwAAAAAAAAAAAAAAAAAAAAAAAADw/wF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8DAAAAAAAAAAAAAAAA/v///////wEADwAAAAAAAAAAAAAAAAAAAAAAAHD4/wJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8DAAAAAAAAAAAAAAAA/////////wOADwAAAAAAAAAAAAAAAAAAAAAAAPz4fwD4AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8//////////8DAAAAAAAAAAAAAAAA/////////wHAHwAAAAAAAAAAAAAAAAAAAAAAAPz+/wD4BwAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4//////////8DAAAAAAAAAAAAAAAA/////////wHgFwAAAAAAAAAAAAAAAAAAAAAAAP7//wH4BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg//////////8DAAAAAAAAAAAAAAAA/////////wD+DwAAAAAAAAAAAAAAAAAAAAAAgP7//wf4BwAAAAAAAQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA//////////8DAAAAAAAAAAAAAAAA////////fwD+BwAAAAAAAAAAAAAAAAAAAAAAoP///x/8BwAAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////////8DAAAAAAAAAAAAAACA////////DwD/BwAAAAAAAAAAAAAAAAAAAAAA8P///z/8DwAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA/P////////8DAAAAAAAAAAAAAACA////////AwD/BwAAAAAAAAAAAAAAAAAAAAAA8P//////DwAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P////////8BAAAAAAAAAAAAAAAA////////AwD/BwAAAAAAAAAAAAAAAAAAAAAA8P//////HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P////////8BAAAAAAAAAAAAAAAA/v//////AQD/AwAAAAAAAAAAAAAAAAAAAAAA+P//////HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P////////8BAAAAAAAAAAAAAAAA/v////9/AAD+AwAAAAAAAAAAAAAAAAAAAAAA+P//////PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P////////8AAAAAAAAAAAAAAAAA/P////8fAAD+AwAAAAAAAAAAAAAAAAAAAAAA/v//////fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P///////38AAAAAAAAAAAAAAAAA/P////8fAAD+AQAIAAAAAAAAAAAAAAAAAADA/////////wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P///////38AAAAAAAAAAAAAAAAA+P////8/AAD/AQAAAAAAAAAAAAAAAAAAAAD+/////////wMAAABCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P///////z8AAAAAAAAAAAAAAAAA+P////8/AID/AYAAAAAAAAAAAAAAAAAAAAD//////////wMAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P///////z8AAAAAAAAAAAAAAAAA8P////9/AID/AAAAAAAAAAAAAAAAAAAAAMD//////////wcAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P///////x8AAAAAAAAAAAAAAAAA4P////9/AID/AAAAAAAAAAAAAAAAAAAAAOD//////////wcAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P///////w8AAAAAAAAAAAAAAAAA4P////9/AID/AAAAAAAAAAAAAAAAAAAAAPj//////////z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P//////fwAAAAAAAAAAAAAAAAAA4P////9/AIB/AAAAAAAAAAAAAAAAAAAAAPD//////////z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P//////HwAAAAAAAAAAAAAAAAAA4P////9/AIB/AAAAAAAAAAAAAAAAAAAAAPj//////////38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P//////AwAAAAAAAAAAAAAAAAAA4P////9/AIB/AAAAAAAAAAAAAAAAAAAAAPj///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P//////AQAAAAAAAAAAAAAAAAAA4P////8/AAA/AAAAAAAAAAAAAAAAAAAAAPj///////////8FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P//////AAAAAAAAAAAAAAAAAAAAwP////8HAAAOAAAAAAAAAAAAAAAAAAAAAPD///////////8FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P////9/AAAAAAAAAAAAAAAAAAAAwP////8DAAAAAAAAAAAAAAAAAAAAAAAAAPD///////////8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+P////9/AAAAAAAAAAAAAAAAAAAAwP////8DAAAAAAAAAAAAAAAAAAAAAAAAAPT///////////8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P////9/AAAAAAAAAAAAAAAAAAAAwP////8DAAAAAAAAAAAAAAAAAAAAAAAAAPj///////////8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P////9/AAAAAAAAAAAAAAAAAAAAgP////8DAAAAAAAAAAAAAAAAAAAAAAAAAPD///////////8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P////9/AAAAAAAAAAAAAAAAAAAAgP////8BAAAAAAAAAAAAAAAAAAAAAAAAAPD///////////8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P////9/AAAAAAAAAAAAAAAAAAAAAP////8BAAAAAAAAAAAAAAAAAAAAAAAAAOD///////////8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////8/AAAAAAAAAAAAAAAAAAAAAP7///8AAAAAAAAAAAAAAAAAAAAAAAAAAOD///////////8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////8fAAAAAAAAAAAAAAAAAAAAAPz//38AAAAAAAAAAAAAAAAAAAAAAAAAAMD///////////8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////8PAAAAAAAAAAAAAAAAAAAAAPz//z8AAAAAAAAAAAAAAAAAAAAAAAAAAMD///////////8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////8NAAAAAAAAAAAAAAAAAAAAAPj//z8AAAAAAAAAAAAAAAAAAAAAAAAAAMD///////////8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////8BAAAAAAAAAAAAAAAAAAAAAPj//x8AAAAAAAAAAAAAAAAAAAAAAAAAAMD///////////8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////8BAAAAAAAAAAAAAAAAAAAAAPD//w8AAAAAAAAAAAAAAAAAAAAAAAAAAID///////////8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////8AAAAAAAAAAAAAAAAAAAAAAPD//wcAAAAAAAAAAAAAAAAAAAAAAAAAAID///8D//////8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////8AAAAAAAAAAAAAAAAAAAAAAOD//wMAAAAAAAAAAAAAAAAAAAAAAAAAAID//38A+P////8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///38AAAAAAAAAAAAAAAAAAAAAAPD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAID//wMA8P////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///38AAAAAAAAAAAAAAAAAAAAAAPD/fwAAAAAAAAAAAAAAAAAAAAAAAAAAAID//wAA4Pf//38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////x8AAAAAAAAAAAAAAAAAAAAAAOD/DwAAAAAAAAAAAAAAAAAAAAAAAAAAAMD/fwAAwPv//38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////9x8AAAAAAAAAAAAAAAAAAAAAAMAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMB/AAAAgPn//z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////jwcAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfAAAAgOj//z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA////HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD//x8AAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA////HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMb//w8AAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA////PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID//w8AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA////fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//w8AAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg////PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//w8AAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg////HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+/wcAAAAAAMAZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg////DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4fQAAAAAAAOAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA//8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg//8PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg//8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw//8HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAMABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw/z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gEAAAAAAPsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg/z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AEAAAAAgB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ//8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAgA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ/z8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAwAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADY/z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAA8AEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA/x8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA/x8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADo/x8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw/wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4/w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADo/w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/wcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6fwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0XwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAegAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABg8wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4gMAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6L8AAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOQXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwP8AAAAAAAAAAAAAAPwH4A8AAADgzwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4v8BAAAAAAAAAOD/////8X8AwD/4//8DAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P8/AAAAAAAA/////////48//v//////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/////w8AAAD4////////////////////HgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD///////8PAMD/////////////////////PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHxBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAP7///////8HAPD//////////////////////785AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+gP////////8HAPz/////////////////////////HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACn/8HAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAD8i/////////8DAP///////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMP8HAAAAAAAAAAAAAAAAAAAABAEEBCEAMMD//////////38A/v///////////////////////////wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcfP4PAAAAAAAAAAAAAAAAABAGAP5//z+cAf////////////8D//////////////////////////////c/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAf/4/AAAAAAAAAAAAAAAAOA4A/v////////////////////+B////////////////////////////////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+//w/AAAAAAAAAAAAAAAA/v///////////////////////3/A////////////////////////////////PwAAAAAAAAAAAAAAAAAAAAAAAAAAAIC/AQAAAAAAevx/AAAAAAAAAAAAAAAA/v///////////////////////3/y////////////////////////////////DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAEIAAAAAAP5/AAAAAAAAAAAAAADI/////////////////////////z//////////////////////////////////DwAAAAAAAAAAAAAAAAAAAAAAAAAAAPw/9vkRgAMX8P/PAAAAAAAAAAAAAAD//////////////////////////7////////////////////////////////8/AAAAAAAAAAAAAAAAAAAAAAg+AAAAALz/////5z////8/AAAAAAAAAAAAQAD///////////////////////////////////////////////////////////8PAAAAAAAAAAAAAAAAAAAAAAA8ABwDAOD///////////8PAAAAAAAAAAAAQAD8//////////////////////////////////////////////////////////8DAAAAAAAAAAAAAAAAAAAHAP/g/w8GAAD///////////8LAAAAAAAAAAAAAPD//////////////////////////////////////////////////////////58AAAAAAAAAAAAAAAAAAP////////9/8B/4//////////8AAAAAAAAAAAAAAPj//////////////////////////////////////////////////////////wcAAAAAAAAAAAAAAACA/////////////////////////z8AAAAAAAAAAAAA/////////////////////////////////////////////////////////////x8AAAAAAAAAAAAAAMD3////////////////////////fwAAAAAAAAAAAAD//////////////////////////////////////////////////////////////x8AAAAAAAAAAAAAAGzg/////////////////////z8AAQAAAAAAAAAAAPj//////////////////////////////////////////////////////////////z8AAAAAAAAAAADwD8Lg/////////////////////38AAAAAAAAAAAAAwP///////////////////////////////////////////////////////////////38gAAAAAAAAAAD4/+////////////////////////8/AAAAAAAAAAAA+P////////////////////////////////////////////////////////////////8gAAAAAAAAAAAA+P///////////////////////QcAAAAAAADg/wAA//////////////////////////////////////////////////////////////////81AAAAAAAAAAYA////////////////////////wQcA4AEAAAD4HwAA/////////////////////////////////////////////////////////////////3cAAAAAAAAAgH8AAP//////////////////////HwAAHgMAAAD4/wOAD/D//////////////////////////////////////////////////////////////wEAAAAAAAAAAOADAID///////////////////////8AAAwAAAD8/wMAAAXg/////////////////////////////////////////////////////////////wAAAAAAAAAAAAAAAPj///////////////////////8AAAjgAeD/fwAAAPD/////////////////////////////////////////////////////////////PwAAAAAAAAAAAAAAAMD///////////////////////8BBwD8APgfAAAA/v///////////////////////////////////////////////////////////////wEAAAAAAAAAAADA/////////////////////////////wMAAAAAAOD//////////////////////////////////////////////////////////////////wEAAAAAAAAAAAAA8P///////////////////////////x8AAAAAAPj//////////////////////////////////////////////////////////////////x8AAAAAAAAAAAAA4P///////////////////////////w9gAPD/D/7//////////////////////////////////////////////////////////////////z8AAAAAAAAAAAAA+P////////////////////////////8HwP////////////////////////////////////////////////////////////////////////8fAAAAAAD8HwDA//////////////////////////////8f/P////////////////////////////////////////////////////////////////////////9/AAAAAAAA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////wcAAAAAAP////////////////////////////////////////////////////////////////////////////////////////////////////////////////9/////AAD8////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////",
  },
  points: {
    AD: [1.54, 42.55],
    AE: [54.55, 23.47],
    AF: [66.5, 34.16],
    AG: [-61.79, 17.35],
    AI: [-63.03, 18.24],
    AL: [20.11, 40.65],
    AM: [44.8, 40.46],
    AO: [17.98, -12.18],
    AQ: [35.89, -79.84],
    AR: [-64.17, -33.5],
    AS: [-170.75, -14.33],
    AT: [14.13, 47.52],
    AU: [134.05, -24.13],
    AW: [-69.97, 12.52],
    AX: [19.87, 60.16],
    AZ: [47.21, 40.4],
    BA: [18.07, 44.09],
    BB: [-59.57, 13.16],
    BD: [89.68, 24.21],
    BE: [4.8, 50.79],
    BF: [-1.36, 12.67],
    BG: [25.16, 42.51],
    BH: [50.55, 26.06],
    BI: [29.92, -3.33],
    BJ: [2.35, 10.32],
    BL: [-62.83, 17.9],
    BM: [-64.76, 32.3],
    BN: [114.55, 4.45],
    BO: [-64.59, -16.67],
    BR: [-49.56, -12.1],
    BS: [-77.15, 26.4],
    BT: [90.04, 27.54],
    BW: [24.18, -22.1],
    BY: [28.42, 53.82],
    BZ: [-88.71, 17.2],
    CA: [-101.91, 60.32],
    CD: [23.46, -1.86],
    CF: [20.91, 6.99],
    CG: [15.9, 0.14],
    CH: [7.46, 46.72],
    CI: [-5.57, 7.49],
    CK: [-159.79, -21.22],
    CL: [-72.32, -38.15],
    CM: [12.47, 4.59],
    CN: [106.34, 32.5],
    CO: [-73.17, 3.37],
    CR: [-84.08, 10.07],
    CU: [-77.98, 21.33],
    CV: [-23.64, 15.07],
    CW: [-68.92, 12.15],
    CY: [33.08, 34.91],
    CZ: [15.38, 49.88],
    DE: [9.68, 50.96],
    DJ: [42.5, 11.98],
    DK: [9.02, 55.97],
    DM: [-61.34, 15.46],
    DO: [-70.65, 19.1],
    DZ: [2.81, 27.4],
    EC: [-78.19, -1.26],
    EE: [25.87, 58.72],
    EG: [29.45, 26.19],
    EH: [-12.63, 23.97],
    ER: [38.29, 15.79],
    ES: [-3.46, 40.09],
    ET: [39.09, 8.03],
    FI: [27.28, 63.25],
    FJ: [177.98, -17.83],
    FK: [-58.74, -51.61],
    FM: [158.23, 6.89],
    FO: [-7.06, 62.19],
    FR: [2.55, 46.7],
    GA: [11.84, -0.44],
    GB: [-2.12, 54.4],
    GD: [-61.68, 12.11],
    GE: [43.74, 41.87],
    GG: [-2.56, 49.46],
    GH: [-1.04, 7.72],
    GL: [-39.34, 74.32],
    GM: [-15, 13.64],
    GN: [-10.02, 10.62],
    GQ: [8.99, 2.33],
    GR: [21.73, 39.49],
    GS: [-31.06, -55.68],
    GT: [-90.5, 14.98],
    GU: [144.7, 13.35],
    GW: [-14.52, 12.16],
    GY: [-58.94, 5.12],
    HK: [114.1, 22.45],
    HM: [73.51, -53.1],
    HN: [-86.89, 14.79],
    HR: [16.37, 45.81],
    HT: [-72.22, 19.26],
    HU: [19.45, 47.09],
    ID: [101.89, -0.95],
    IE: [-7.8, 53.08],
    IL: [34.85, 30.91],
    IM: [-4.53, 54.22],
    IN: [79.36, 22.69],
    IO: [71.35, -6.19],
    IQ: [43.26, 33.09],
    IR: [54.93, 32.17],
    IS: [-18.67, 64.78],
    IT: [11.08, 44.73],
    JE: [-2.09, 49.22],
    JM: [-77.32, 18.14],
    JO: [36.38, 30.81],
    JP: [138.44, 36.14],
    KE: [37.91, 0.55],
    KG: [74.53, 41.67],
    KH: [104.5, 12.65],
    KI: [-157.38, 1.82],
    KM: [43.32, -11.73],
    KN: [-62.76, 17.34],
    KP: [126.44, 39.89],
    KR: [128.13, 36.38],
    KW: [47.31, 29.41],
    KY: [-81.24, 19.32],
    KZ: [68.69, 49.05],
    LA: [102.53, 19.43],
    LB: [35.99, 34.13],
    LC: [-60.98, 13.89],
    LI: [9.56, 47.11],
    LK: [80.7, 7.58],
    LR: [-9.46, 6.45],
    LS: [28.25, -29.48],
    LT: [24.09, 55.1],
    LU: [6.08, 49.73],
    LV: [25.46, 57.07],
    LY: [18.01, 26.64],
    MA: [-7.19, 31.65],
    MC: [7.4, 43.74],
    MD: [28.49, 47.43],
    ME: [19.14, 42.8],
    MF: [-63.05, 18.08],
    MG: [46.7, -18.63],
    MH: [171.19, 7.08],
    MK: [21.56, 41.56],
    ML: [-2.04, 18.69],
    MM: [95.8, 21.57],
    MN: [104.15, 46],
    MO: [113.56, 22.13],
    MP: [145.73, 15.19],
    MR: [-9.74, 19.59],
    MS: [-62.19, 16.74],
    MT: [14.43, 35.89],
    MU: [57.57, -20.3],
    MV: [73.51, 4.17],
    MW: [33.61, -13.39],
    MX: [-102.29, 23.92],
    MY: [113.84, 2.53],
    MZ: [37.84, -13.94],
    NA: [17.11, -20.58],
    NC: [165.08, -21.06],
    NE: [9.5, 17.45],
    NF: [167.95, -29.03],
    NG: [7.5, 9.44],
    NI: [-85.07, 12.67],
    NL: [5.61, 52.42],
    NO: [9.68, 61.36],
    NP: [83.64, 28.3],
    NR: [166.93, -0.52],
    NU: [-169.86, -19.05],
    NZ: [172.79, -39.76],
    OM: [57.34, 22.12],
    PA: [-80.35, 8.72],
    PE: [-72.9, -12.98],
    PF: [-149.46, -17.63],
    PG: [143.91, -5.7],
    PH: [122.47, 11.2],
    PK: [68.55, 29.33],
    PL: [19.49, 51.99],
    PM: [-56.33, 47.04],
    PN: [-128.32, -24.36],
    PR: [-66.48, 18.23],
    PS: [35.29, 32.05],
    PT: [-8.27, 39.61],
    PW: [134.58, 7.52],
    PY: [-60.15, -21.67],
    QA: [51.14, 25.24],
    RO: [24.97, 45.73],
    RS: [20.79, 44.19],
    RU: [44.69, 58.25],
    RW: [30.1, -1.9],
    SA: [44.7, 23.81],
    SB: [159.17, -8.03],
    SC: [55.48, -4.68],
    SD: [29.26, 16.33],
    SE: [19.02, 65.86],
    SG: [103.82, 1.37],
    SH: [-5.71, -15.95],
    SI: [14.92, 46.06],
    SK: [19.05, 48.73],
    SL: [-11.76, 8.62],
    SM: [12.44, 43.93],
    SN: [-14.78, 15.14],
    SO: [45.19, 3.57],
    SR: [-55.91, 4.14],
    SS: [30.39, 7.23],
    ST: [7.02, 0.97],
    SV: [-88.89, 13.69],
    SX: [-63.07, 18.04],
    SY: [38.28, 35.01],
    SZ: [31.47, -26.53],
    TC: [-71.75, 21.82],
    TD: [18.65, 15.14],
    TF: [69.12, -49.3],
    TG: [1.06, 8.81],
    TH: [101.07, 15.46],
    TJ: [72.59, 38.2],
    TL: [125.85, -8.8],
    TM: [58.68, 39.86],
    TN: [9.01, 33.69],
    TO: [-175.16, -21.21],
    TR: [34.51, 39.35],
    TT: [-60.92, 11],
    TV: [179.21, -8.51],
    TW: [120.87, 23.65],
    TZ: [34.96, -6.05],
    UA: [32.14, 49.72],
    UG: [32.95, 1.97],
    US: [-97.48, 39.54],
    UY: [-55.97, -32.96],
    UZ: [64.01, 41.69],
    VA: [12.45, 41.9],
    VC: [-61.34, 13.09],
    VE: [-64.6, 7.18],
    VG: [-64.64, 18.43],
    VI: [-64.78, 17.75],
    VN: [105.39, 21.72],
    VU: [166.91, -15.37],
    WF: [-178.14, -14.29],
    WS: [-172.44, -13.64],
    XK: [20.86, 42.59],
    YE: [45.87, 15.33],
    ZA: [23.67, -29.71],
    ZM: [26.4, -14.66],
    ZW: [29.93, -18.91],
  },
};
```

### build-land.mjs

```js
// Rebuilds GEO.land in geo.js: a 0.5-degree land bitmap from any land polygons in GeoJSON.
//
//   1. Download ne_50m_land.geojson from Natural Earth (public domain), e.g. from
//      https://github.com/nvkelso/natural-earth-vector/tree/master/geojson
//   2. node build-land.mjs ne_50m_land.geojson > land.json
//   3. Paste the output after `land:` in geo.js.
//
// Cell (x, y) covers longitude -180 + x / 2 … and latitude 90 - y / 2 …; a cell is land when its centre
// is. Each row is filled as a scanline (even-odd over every ring), which is exact in this plate carrée
// grid and takes well under a second.
import { readFileSync } from "node:fs";

const file = process.argv[2];
if (!file) {
  console.error("usage: node build-land.mjs <land.geojson>");
  process.exit(1);
}
const land = JSON.parse(readFileSync(file, "utf8"));
const W = 720;
const H = 360;
const bits = new Uint8Array((W * H) / 8);
const rings = land.features.flatMap((f) =>
  f.geometry.type === "Polygon" ? f.geometry.coordinates : f.geometry.coordinates.flat(),
);
for (let y = 0; y < H; y++) {
  const lat = 90 - (y + 0.5) / 2;
  const xs = [];
  for (const ring of rings) {
    for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
      const [x1, y1] = ring[i];
      const [x2, y2] = ring[j];
      if (y1 > lat !== y2 > lat) xs.push(x1 + ((lat - y1) / (y2 - y1)) * (x2 - x1));
    }
  }
  xs.sort((a, b) => a - b);
  for (let k = 0; k + 1 < xs.length; k += 2) {
    for (let x = Math.max(0, Math.ceil((xs[k] + 180) * 2 - 0.5)); x < W && (x + 0.5) / 2 - 180 < xs[k + 1]; x++) {
      const n = y * W + x;
      bits[n >> 3] |= 1 << (n & 7);
    }
  }
}
process.stdout.write(`${JSON.stringify({ w: W, h: H, bits: Buffer.from(bits).toString("base64") })}\n`);
```
