]> git.openstreetmap.org Git - rails.git/blobdiff - vendor/assets/iD/iD.js
Merge remote-tracking branch 'upstream/pull/4092'
[rails.git] / vendor / assets / iD / iD.js
index e391c7aa25c1abdbc6f1855c207e7c51f6f4c3e9..ad4c204939ea18982bc0a0b4b6cb38f9e5c07498 100644 (file)
     return to;
   };
   var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
+    // If the importer is in node compatibility mode or this is not an ESM
+    // file that has been converted to a CommonJS file using a Babel-
+    // compatible transform (i.e. "__esModule" has not been set), then set
+    // "default" to the CommonJS "module.exports" for node compatibility.
     isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
     mod
   ));
         [69216, 69247],
         [126064, 126143],
         [126464, 126719]
+        // Mathematical Alphabetic symbols https://www.unicode.org/charts/PDF/U1EE00.pdf
       ];
       function isArabic(char) {
         if (char.length > 1) {
           }
           this._adjustParentBBoxes(bbox2, insertPath, level);
         },
+        // split overflowed node into two
         _split: function(insertPath, level) {
           var node = insertPath[level], M = node.children.length, m = this._minEntries;
           this._chooseSplitAxis(node, m, M);
           }
           return index;
         },
+        // sorts node children by the best axis for split
         _chooseSplitAxis: function(node, m, M) {
           var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX, compareMinY = node.leaf ? this.compareMinY : compareNodeMinY, xMargin = this._allDistMargin(node, m, M, compareMinX), yMargin = this._allDistMargin(node, m, M, compareMinY);
           if (xMargin < yMargin)
             node.children.sort(compareMinX);
         },
+        // total margin of all possible split distributions where each node is at least m full
         _allDistMargin: function(node, m, M, compare) {
           node.children.sort(compare);
           var toBBox = this.toBBox, leftBBox = distBBox(node, 0, m, toBBox), rightBBox = distBBox(node, M - m, M, toBBox), margin = bboxMargin(leftBBox) + bboxMargin(rightBBox), i2, child;
         return result;
       }
       function intersect2(a, b, edge, bbox2) {
-        return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox2[3] - a[1]) / (b[1] - a[1]), bbox2[3]] : edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox2[1] - a[1]) / (b[1] - a[1]), bbox2[1]] : edge & 2 ? [bbox2[2], a[1] + (b[1] - a[1]) * (bbox2[2] - a[0]) / (b[0] - a[0])] : edge & 1 ? [bbox2[0], a[1] + (b[1] - a[1]) * (bbox2[0] - a[0]) / (b[0] - a[0])] : null;
+        return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox2[3] - a[1]) / (b[1] - a[1]), bbox2[3]] : (
+          // top
+          edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox2[1] - a[1]) / (b[1] - a[1]), bbox2[1]] : (
+            // bottom
+            edge & 2 ? [bbox2[2], a[1] + (b[1] - a[1]) * (bbox2[2] - a[0]) / (b[0] - a[0])] : (
+              // right
+              edge & 1 ? [bbox2[0], a[1] + (b[1] - a[1]) * (bbox2[0] - a[0]) / (b[0] - a[0])] : (
+                // left
+                null
+              )
+            )
+          )
+        );
       }
       function bitCode2(p, bbox2) {
         var code = 0;
         var bboxes = [];
         for (var i2 = 0; i2 < data.features.length; i2++) {
           var feature3 = data.features[i2];
+          if (!feature3.geometry)
+            continue;
           var coords = feature3.geometry.coordinates;
           if (feature3.geometry.type === "Polygon") {
             bboxes.push(treeItem(coords, feature3.properties));
             _defineProperties(Constructor, staticProps);
           return Constructor;
         }
-        var Node = function() {
-          function Node2(key, data) {
-            this.next = null;
-            this.key = key;
-            this.data = data;
-            this.left = null;
-            this.right = null;
-          }
-          return Node2;
-        }();
+        var Node = (
+          /** @class */
+          function() {
+            function Node2(key, data) {
+              this.next = null;
+              this.key = key;
+              this.data = data;
+              this.left = null;
+              this.right = null;
+            }
+            return Node2;
+          }()
+        );
         function DEFAULT_COMPARE(a, b) {
           return a > b ? 1 : a < b ? -1 : 0;
         }
             right
           };
         }
-        function merge3(left, right, comparator) {
+        function merge2(left, right, comparator) {
           if (right === null)
             return left;
           if (left === null)
               printRow(root3.right, indent2, true, out, printNode);
           }
         }
-        var Tree = function() {
-          function Tree2(comparator) {
-            if (comparator === void 0) {
-              comparator = DEFAULT_COMPARE;
-            }
-            this._root = null;
-            this._size = 0;
-            this._comparator = comparator;
-          }
-          Tree2.prototype.insert = function(key, data) {
-            this._size++;
-            return this._root = insert(key, data, this._root, this._comparator);
-          };
-          Tree2.prototype.add = function(key, data) {
-            var node = new Node(key, data);
-            if (this._root === null) {
-              node.left = node.right = null;
-              this._size++;
-              this._root = node;
-            }
-            var comparator = this._comparator;
-            var t = splay(key, this._root, comparator);
-            var cmp2 = comparator(key, t.key);
-            if (cmp2 === 0)
-              this._root = t;
-            else {
-              if (cmp2 < 0) {
-                node.left = t.left;
-                node.right = t;
-                t.left = null;
-              } else if (cmp2 > 0) {
-                node.right = t.right;
-                node.left = t;
-                t.right = null;
+        var Tree = (
+          /** @class */
+          function() {
+            function Tree2(comparator) {
+              if (comparator === void 0) {
+                comparator = DEFAULT_COMPARE;
               }
-              this._size++;
-              this._root = node;
+              this._root = null;
+              this._size = 0;
+              this._comparator = comparator;
             }
-            return this._root;
-          };
-          Tree2.prototype.remove = function(key) {
-            this._root = this._remove(key, this._root, this._comparator);
-          };
-          Tree2.prototype._remove = function(i2, t, comparator) {
-            var x;
-            if (t === null)
-              return null;
-            t = splay(i2, t, comparator);
-            var cmp2 = comparator(i2, t.key);
-            if (cmp2 === 0) {
-              if (t.left === null) {
-                x = t.right;
-              } else {
-                x = splay(i2, t.left, comparator);
-                x.right = t.right;
-              }
-              this._size--;
-              return x;
-            }
-            return t;
-          };
-          Tree2.prototype.pop = function() {
-            var node = this._root;
-            if (node) {
-              while (node.left) {
-                node = node.left;
+            Tree2.prototype.insert = function(key, data) {
+              this._size++;
+              return this._root = insert(key, data, this._root, this._comparator);
+            };
+            Tree2.prototype.add = function(key, data) {
+              var node = new Node(key, data);
+              if (this._root === null) {
+                node.left = node.right = null;
+                this._size++;
+                this._root = node;
               }
-              this._root = splay(node.key, this._root, this._comparator);
-              this._root = this._remove(node.key, this._root, this._comparator);
-              return {
-                key: node.key,
-                data: node.data
-              };
-            }
-            return null;
-          };
-          Tree2.prototype.findStatic = function(key) {
-            var current = this._root;
-            var compare = this._comparator;
-            while (current) {
-              var cmp2 = compare(key, current.key);
+              var comparator = this._comparator;
+              var t = splay(key, this._root, comparator);
+              var cmp2 = comparator(key, t.key);
               if (cmp2 === 0)
-                return current;
-              else if (cmp2 < 0)
-                current = current.left;
-              else
-                current = current.right;
-            }
-            return null;
-          };
-          Tree2.prototype.find = function(key) {
-            if (this._root) {
-              this._root = splay(key, this._root, this._comparator);
-              if (this._comparator(key, this._root.key) !== 0)
+                this._root = t;
+              else {
+                if (cmp2 < 0) {
+                  node.left = t.left;
+                  node.right = t;
+                  t.left = null;
+                } else if (cmp2 > 0) {
+                  node.right = t.right;
+                  node.left = t;
+                  t.right = null;
+                }
+                this._size++;
+                this._root = node;
+              }
+              return this._root;
+            };
+            Tree2.prototype.remove = function(key) {
+              this._root = this._remove(key, this._root, this._comparator);
+            };
+            Tree2.prototype._remove = function(i2, t, comparator) {
+              var x;
+              if (t === null)
                 return null;
-            }
-            return this._root;
-          };
-          Tree2.prototype.contains = function(key) {
-            var current = this._root;
-            var compare = this._comparator;
-            while (current) {
-              var cmp2 = compare(key, current.key);
-              if (cmp2 === 0)
-                return true;
-              else if (cmp2 < 0)
-                current = current.left;
-              else
-                current = current.right;
-            }
-            return false;
-          };
-          Tree2.prototype.forEach = function(visitor, ctx) {
-            var current = this._root;
-            var Q = [];
-            var done = false;
-            while (!done) {
-              if (current !== null) {
-                Q.push(current);
-                current = current.left;
-              } else {
-                if (Q.length !== 0) {
-                  current = Q.pop();
-                  visitor.call(ctx, current);
-                  current = current.right;
-                } else
-                  done = true;
+              t = splay(i2, t, comparator);
+              var cmp2 = comparator(i2, t.key);
+              if (cmp2 === 0) {
+                if (t.left === null) {
+                  x = t.right;
+                } else {
+                  x = splay(i2, t.left, comparator);
+                  x.right = t.right;
+                }
+                this._size--;
+                return x;
               }
-            }
-            return this;
-          };
-          Tree2.prototype.range = function(low, high, fn, ctx) {
-            var Q = [];
-            var compare = this._comparator;
-            var node = this._root;
-            var cmp2;
-            while (Q.length !== 0 || node) {
+              return t;
+            };
+            Tree2.prototype.pop = function() {
+              var node = this._root;
               if (node) {
-                Q.push(node);
-                node = node.left;
-              } else {
-                node = Q.pop();
-                cmp2 = compare(node.key, high);
-                if (cmp2 > 0) {
-                  break;
-                } else if (compare(node.key, low) >= 0) {
-                  if (fn.call(ctx, node))
-                    return this;
+                while (node.left) {
+                  node = node.left;
                 }
-                node = node.right;
+                this._root = splay(node.key, this._root, this._comparator);
+                this._root = this._remove(node.key, this._root, this._comparator);
+                return {
+                  key: node.key,
+                  data: node.data
+                };
               }
-            }
-            return this;
-          };
-          Tree2.prototype.keys = function() {
-            var keys = [];
-            this.forEach(function(_a) {
-              var key = _a.key;
-              return keys.push(key);
-            });
-            return keys;
-          };
-          Tree2.prototype.values = function() {
-            var values = [];
-            this.forEach(function(_a) {
-              var data = _a.data;
-              return values.push(data);
-            });
-            return values;
-          };
-          Tree2.prototype.min = function() {
-            if (this._root)
-              return this.minNode(this._root).key;
-            return null;
-          };
-          Tree2.prototype.max = function() {
-            if (this._root)
-              return this.maxNode(this._root).key;
-            return null;
-          };
-          Tree2.prototype.minNode = function(t) {
-            if (t === void 0) {
-              t = this._root;
-            }
-            if (t)
-              while (t.left) {
-                t = t.left;
+              return null;
+            };
+            Tree2.prototype.findStatic = function(key) {
+              var current = this._root;
+              var compare = this._comparator;
+              while (current) {
+                var cmp2 = compare(key, current.key);
+                if (cmp2 === 0)
+                  return current;
+                else if (cmp2 < 0)
+                  current = current.left;
+                else
+                  current = current.right;
               }
-            return t;
-          };
-          Tree2.prototype.maxNode = function(t) {
-            if (t === void 0) {
-              t = this._root;
-            }
-            if (t)
-              while (t.right) {
-                t = t.right;
+              return null;
+            };
+            Tree2.prototype.find = function(key) {
+              if (this._root) {
+                this._root = splay(key, this._root, this._comparator);
+                if (this._comparator(key, this._root.key) !== 0)
+                  return null;
               }
-            return t;
-          };
-          Tree2.prototype.at = function(index2) {
-            var current = this._root;
-            var done = false;
-            var i2 = 0;
-            var Q = [];
-            while (!done) {
-              if (current) {
-                Q.push(current);
-                current = current.left;
-              } else {
-                if (Q.length > 0) {
-                  current = Q.pop();
-                  if (i2 === index2)
-                    return current;
-                  i2++;
+              return this._root;
+            };
+            Tree2.prototype.contains = function(key) {
+              var current = this._root;
+              var compare = this._comparator;
+              while (current) {
+                var cmp2 = compare(key, current.key);
+                if (cmp2 === 0)
+                  return true;
+                else if (cmp2 < 0)
+                  current = current.left;
+                else
                   current = current.right;
-                } else
-                  done = true;
               }
-            }
-            return null;
-          };
-          Tree2.prototype.next = function(d) {
-            var root3 = this._root;
-            var successor = null;
-            if (d.right) {
-              successor = d.right;
-              while (successor.left) {
-                successor = successor.left;
+              return false;
+            };
+            Tree2.prototype.forEach = function(visitor, ctx) {
+              var current = this._root;
+              var Q = [];
+              var done = false;
+              while (!done) {
+                if (current !== null) {
+                  Q.push(current);
+                  current = current.left;
+                } else {
+                  if (Q.length !== 0) {
+                    current = Q.pop();
+                    visitor.call(ctx, current);
+                    current = current.right;
+                  } else
+                    done = true;
+                }
+              }
+              return this;
+            };
+            Tree2.prototype.range = function(low, high, fn, ctx) {
+              var Q = [];
+              var compare = this._comparator;
+              var node = this._root;
+              var cmp2;
+              while (Q.length !== 0 || node) {
+                if (node) {
+                  Q.push(node);
+                  node = node.left;
+                } else {
+                  node = Q.pop();
+                  cmp2 = compare(node.key, high);
+                  if (cmp2 > 0) {
+                    break;
+                  } else if (compare(node.key, low) >= 0) {
+                    if (fn.call(ctx, node))
+                      return this;
+                  }
+                  node = node.right;
+                }
+              }
+              return this;
+            };
+            Tree2.prototype.keys = function() {
+              var keys2 = [];
+              this.forEach(function(_a) {
+                var key = _a.key;
+                return keys2.push(key);
+              });
+              return keys2;
+            };
+            Tree2.prototype.values = function() {
+              var values = [];
+              this.forEach(function(_a) {
+                var data = _a.data;
+                return values.push(data);
+              });
+              return values;
+            };
+            Tree2.prototype.min = function() {
+              if (this._root)
+                return this.minNode(this._root).key;
+              return null;
+            };
+            Tree2.prototype.max = function() {
+              if (this._root)
+                return this.maxNode(this._root).key;
+              return null;
+            };
+            Tree2.prototype.minNode = function(t) {
+              if (t === void 0) {
+                t = this._root;
+              }
+              if (t)
+                while (t.left) {
+                  t = t.left;
+                }
+              return t;
+            };
+            Tree2.prototype.maxNode = function(t) {
+              if (t === void 0) {
+                t = this._root;
+              }
+              if (t)
+                while (t.right) {
+                  t = t.right;
+                }
+              return t;
+            };
+            Tree2.prototype.at = function(index2) {
+              var current = this._root;
+              var done = false;
+              var i2 = 0;
+              var Q = [];
+              while (!done) {
+                if (current) {
+                  Q.push(current);
+                  current = current.left;
+                } else {
+                  if (Q.length > 0) {
+                    current = Q.pop();
+                    if (i2 === index2)
+                      return current;
+                    i2++;
+                    current = current.right;
+                  } else
+                    done = true;
+                }
+              }
+              return null;
+            };
+            Tree2.prototype.next = function(d) {
+              var root3 = this._root;
+              var successor = null;
+              if (d.right) {
+                successor = d.right;
+                while (successor.left) {
+                  successor = successor.left;
+                }
+                return successor;
+              }
+              var comparator = this._comparator;
+              while (root3) {
+                var cmp2 = comparator(d.key, root3.key);
+                if (cmp2 === 0)
+                  break;
+                else if (cmp2 < 0) {
+                  successor = root3;
+                  root3 = root3.left;
+                } else
+                  root3 = root3.right;
               }
               return successor;
-            }
-            var comparator = this._comparator;
-            while (root3) {
-              var cmp2 = comparator(d.key, root3.key);
-              if (cmp2 === 0)
-                break;
-              else if (cmp2 < 0) {
-                successor = root3;
-                root3 = root3.left;
-              } else
-                root3 = root3.right;
-            }
-            return successor;
-          };
-          Tree2.prototype.prev = function(d) {
-            var root3 = this._root;
-            var predecessor = null;
-            if (d.left !== null) {
-              predecessor = d.left;
-              while (predecessor.right) {
-                predecessor = predecessor.right;
+            };
+            Tree2.prototype.prev = function(d) {
+              var root3 = this._root;
+              var predecessor = null;
+              if (d.left !== null) {
+                predecessor = d.left;
+                while (predecessor.right) {
+                  predecessor = predecessor.right;
+                }
+                return predecessor;
+              }
+              var comparator = this._comparator;
+              while (root3) {
+                var cmp2 = comparator(d.key, root3.key);
+                if (cmp2 === 0)
+                  break;
+                else if (cmp2 < 0)
+                  root3 = root3.left;
+                else {
+                  predecessor = root3;
+                  root3 = root3.right;
+                }
               }
               return predecessor;
-            }
-            var comparator = this._comparator;
-            while (root3) {
-              var cmp2 = comparator(d.key, root3.key);
-              if (cmp2 === 0)
-                break;
-              else if (cmp2 < 0)
-                root3 = root3.left;
-              else {
-                predecessor = root3;
-                root3 = root3.right;
+            };
+            Tree2.prototype.clear = function() {
+              this._root = null;
+              this._size = 0;
+              return this;
+            };
+            Tree2.prototype.toList = function() {
+              return toList(this._root);
+            };
+            Tree2.prototype.load = function(keys2, values, presort) {
+              if (values === void 0) {
+                values = [];
               }
-            }
-            return predecessor;
-          };
-          Tree2.prototype.clear = function() {
-            this._root = null;
-            this._size = 0;
-            return this;
-          };
-          Tree2.prototype.toList = function() {
-            return toList(this._root);
-          };
-          Tree2.prototype.load = function(keys, values, presort) {
-            if (values === void 0) {
-              values = [];
-            }
-            if (presort === void 0) {
-              presort = false;
-            }
-            var size = keys.length;
-            var comparator = this._comparator;
-            if (presort)
-              sort(keys, values, 0, size - 1, comparator);
-            if (this._root === null) {
-              this._root = loadRecursive(keys, values, 0, size);
-              this._size = size;
-            } else {
-              var mergedList = mergeLists(this.toList(), createList(keys, values), comparator);
-              size = this._size + size;
-              this._root = sortedListToBST({
-                head: mergedList
-              }, 0, size);
-            }
-            return this;
-          };
-          Tree2.prototype.isEmpty = function() {
-            return this._root === null;
-          };
-          Object.defineProperty(Tree2.prototype, "size", {
-            get: function get4() {
-              return this._size;
-            },
-            enumerable: true,
-            configurable: true
-          });
-          Object.defineProperty(Tree2.prototype, "root", {
-            get: function get4() {
-              return this._root;
-            },
-            enumerable: true,
-            configurable: true
-          });
-          Tree2.prototype.toString = function(printNode) {
-            if (printNode === void 0) {
-              printNode = function printNode2(n2) {
-                return String(n2.key);
-              };
-            }
-            var out = [];
-            printRow(this._root, "", true, function(v) {
-              return out.push(v);
-            }, printNode);
-            return out.join("");
-          };
-          Tree2.prototype.update = function(key, newKey, newData) {
-            var comparator = this._comparator;
-            var _a = split(key, this._root, comparator), left = _a.left, right = _a.right;
-            if (comparator(key, newKey) < 0) {
-              right = insert(newKey, newData, right, comparator);
-            } else {
-              left = insert(newKey, newData, left, comparator);
-            }
-            this._root = merge3(left, right, comparator);
-          };
-          Tree2.prototype.split = function(key) {
-            return split(key, this._root, this._comparator);
-          };
-          return Tree2;
-        }();
-        function loadRecursive(keys, values, start2, end) {
+              if (presort === void 0) {
+                presort = false;
+              }
+              var size = keys2.length;
+              var comparator = this._comparator;
+              if (presort)
+                sort(keys2, values, 0, size - 1, comparator);
+              if (this._root === null) {
+                this._root = loadRecursive(keys2, values, 0, size);
+                this._size = size;
+              } else {
+                var mergedList = mergeLists(this.toList(), createList(keys2, values), comparator);
+                size = this._size + size;
+                this._root = sortedListToBST({
+                  head: mergedList
+                }, 0, size);
+              }
+              return this;
+            };
+            Tree2.prototype.isEmpty = function() {
+              return this._root === null;
+            };
+            Object.defineProperty(Tree2.prototype, "size", {
+              get: function get4() {
+                return this._size;
+              },
+              enumerable: true,
+              configurable: true
+            });
+            Object.defineProperty(Tree2.prototype, "root", {
+              get: function get4() {
+                return this._root;
+              },
+              enumerable: true,
+              configurable: true
+            });
+            Tree2.prototype.toString = function(printNode) {
+              if (printNode === void 0) {
+                printNode = function printNode2(n2) {
+                  return String(n2.key);
+                };
+              }
+              var out = [];
+              printRow(this._root, "", true, function(v) {
+                return out.push(v);
+              }, printNode);
+              return out.join("");
+            };
+            Tree2.prototype.update = function(key, newKey, newData) {
+              var comparator = this._comparator;
+              var _a = split(key, this._root, comparator), left = _a.left, right = _a.right;
+              if (comparator(key, newKey) < 0) {
+                right = insert(newKey, newData, right, comparator);
+              } else {
+                left = insert(newKey, newData, left, comparator);
+              }
+              this._root = merge2(left, right, comparator);
+            };
+            Tree2.prototype.split = function(key) {
+              return split(key, this._root, this._comparator);
+            };
+            return Tree2;
+          }()
+        );
+        function loadRecursive(keys2, values, start2, end) {
           var size = end - start2;
           if (size > 0) {
             var middle = start2 + Math.floor(size / 2);
-            var key = keys[middle];
+            var key = keys2[middle];
             var data = values[middle];
             var node = new Node(key, data);
-            node.left = loadRecursive(keys, values, start2, middle);
-            node.right = loadRecursive(keys, values, middle + 1, end);
+            node.left = loadRecursive(keys2, values, start2, middle);
+            node.right = loadRecursive(keys2, values, middle + 1, end);
             return node;
           }
           return null;
         }
-        function createList(keys, values) {
+        function createList(keys2, values) {
           var head = new Node(null, null);
           var p = head;
-          for (var i2 = 0; i2 < keys.length; i2++) {
-            p = p.next = new Node(keys[i2], values[i2]);
+          for (var i2 = 0; i2 < keys2.length; i2++) {
+            p = p.next = new Node(keys2[i2], values[i2]);
           }
           p.next = null;
           return head.next;
           }
           return head.next;
         }
-        function sort(keys, values, left, right, compare) {
+        function sort(keys2, values, left, right, compare) {
           if (left >= right)
             return;
-          var pivot = keys[left + right >> 1];
+          var pivot = keys2[left + right >> 1];
           var i2 = left - 1;
           var j2 = right + 1;
           while (true) {
             do {
               i2++;
-            } while (compare(keys[i2], pivot) < 0);
+            } while (compare(keys2[i2], pivot) < 0);
             do {
               j2--;
-            } while (compare(keys[j2], pivot) > 0);
+            } while (compare(keys2[j2], pivot) > 0);
             if (i2 >= j2)
               break;
-            var tmp = keys[i2];
-            keys[i2] = keys[j2];
-            keys[j2] = tmp;
+            var tmp = keys2[i2];
+            keys2[i2] = keys2[j2];
+            keys2[j2] = tmp;
             tmp = values[i2];
             values[i2] = values[j2];
             values[j2] = tmp;
           }
-          sort(keys, values, left, j2, compare);
-          sort(keys, values, j2 + 1, right, compare);
+          sort(keys2, values, left, j2, compare);
+          sort(keys2, values, j2 + 1, right, compare);
         }
         var isInBbox = function isInBbox2(bbox2, point2) {
           return bbox2.ll.x <= point2.x && point2.x <= bbox2.ur.x && bbox2.ll.y <= point2.y && point2.y <= bbox2.ur.y;
         var SweepEvent = /* @__PURE__ */ function() {
           _createClass(SweepEvent2, null, [{
             key: "compare",
+            // for ordering sweep events in the sweep event queue
             value: function compare(a, b) {
               var ptCmp = SweepEvent2.comparePoints(a.point, b.point);
               if (ptCmp !== 0)
                 return a.isLeft ? 1 : -1;
               return Segment.compare(a.segment, b.segment);
             }
+            // for ordering points in sweep line order
           }, {
             key: "comparePoints",
             value: function comparePoints(aPt, bPt) {
                 return 1;
               return 0;
             }
+            // Warning: 'point' input will be modified and re-used (for performance)
           }]);
           function SweepEvent2(point2, isLeft) {
             _classCallCheck(this, SweepEvent2);
               }
               this.checkForConsuming();
             }
+            /* Do a pass over our linked events and check to see if any pair
+             * of segments match, and should be consumed. */
           }, {
             key: "checkForConsuming",
             value: function checkForConsuming() {
               }
               return events;
             }
+            /**
+             * Returns a comparator function for sorting linked events that will
+             * favor the event that will give us the smallest left-side angle.
+             * All ring construction starts as low as possible heading to the right,
+             * so by always turning left as sharp as possible we'll get polygons
+             * without uncessary loops & holes.
+             *
+             * The comparator function has a compute cache such that it avoids
+             * re-computing already-computed values.
+             */
           }, {
             key: "getLeftmostComparator",
             value: function getLeftmostComparator(baseEvent) {
         var Segment = /* @__PURE__ */ function() {
           _createClass(Segment2, null, [{
             key: "compare",
+            /* This compare() function is for ordering segments in the sweep
+             * line tree, and does so according to the following criteria:
+             *
+             * Consider the vertical line that lies an infinestimal step to the
+             * right of the right-more of the two left endpoints of the input
+             * segments. Imagine slowly moving a point up from negative infinity
+             * in the increasing y direction. Which of the two segments will that
+             * point intersect first? That segment comes 'before' the other one.
+             *
+             * If neither segment would be intersected by such a line, (if one
+             * or more of the segments are vertical) then the line to be considered
+             * is directly on the right-more of the two left inputs.
+             */
             value: function compare(a, b) {
               var alx = a.leftSE.point.x;
               var blx = b.leftSE.point.x;
                 return 1;
               return 0;
             }
+            /* Warning: a reference to ringWindings input will be stored,
+             *  and possibly will be later modified */
           }]);
           function Segment2(leftSE, rightSE, rings, windings) {
             _classCallCheck(this, Segment2);
           }
           _createClass(Segment2, [{
             key: "replaceRightSE",
+            /* When a segment is split, the rightSE is replaced with a new sweep event */
             value: function replaceRightSE(newRightSE) {
               this.rightSE = newRightSE;
               this.rightSE.segment = this;
                 }
               };
             }
+            /* A vector from the left point to the right */
           }, {
             key: "vector",
             value: function vector() {
             value: function isAnEndpoint(pt) {
               return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y;
             }
+            /* Compare this segment with a point.
+             *
+             * A point P is considered to be colinear to a segment if there
+             * exists a distance D such that if we travel along the segment
+             * from one * endpoint towards the other a distance D, we find
+             * ourselves at point P.
+             *
+             * Return value indicates:
+             *
+             *   1: point lies above the segment (to the left of vertical)
+             *   0: point is colinear to segment
+             *  -1: point lies below the segment (to the right of vertical)
+             */
           }, {
             key: "comparePoint",
             value: function comparePoint(point2) {
                 return 0;
               return point2.y < yFromXDist ? -1 : 1;
             }
+            /**
+             * Given another segment, returns the first non-trivial intersection
+             * between the two segments (in terms of sweep line ordering), if it exists.
+             *
+             * A 'non-trivial' intersection is one that will cause one or both of the
+             * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
+             *
+             *   * endpoint of segA with endpoint of segB --> trivial
+             *   * endpoint of segA with point along segB --> non-trivial
+             *   * endpoint of segB with point along segA --> non-trivial
+             *   * point along segA with point along segB --> non-trivial
+             *
+             * If no non-trivial intersection exists, return null
+             * Else, return null.
+             */
           }, {
             key: "getIntersection",
             value: function getIntersection(other) {
                 return null;
               return rounder.round(pt.x, pt.y);
             }
+            /**
+             * Split the given segment into multiple segments on the given points.
+             *  * Each existing segment will retain its leftSE and a new rightSE will be
+             *    generated for it.
+             *  * A new segment will be generated which will adopt the original segment's
+             *    rightSE, and a new leftSE will be generated for it.
+             *  * If there are more than two points given to split on, new segments
+             *    in the middle will be generated with new leftSE and rightSE's.
+             *  * An array of the newly generated SweepEvents will be returned.
+             *
+             * Warning: input array of points is modified
+             */
           }, {
             key: "split",
             value: function split2(point2) {
               }
               return newEvents;
             }
+            /* Swap which event is left and right */
           }, {
             key: "swapEvents",
             value: function swapEvents() {
                 this.windings[i2] *= -1;
               }
             }
+            /* Consume another segment. We take their rings under our wing
+             * and mark them as consumed. Use for perfectly overlapping segments */
           }, {
             key: "consume",
             value: function consume(other) {
               consumee.leftSE.consumedBy = consumer.leftSE;
               consumee.rightSE.consumedBy = consumer.rightSE;
             }
+            /* The first segment previous segment chain that is in the result */
           }, {
             key: "prevInResult",
             value: function prevInResult() {
               }
               return this._afterState;
             }
+            /* Is this segment part of the final result? */
           }, {
             key: "isInResult",
             value: function isInResult() {
         var RingOut = /* @__PURE__ */ function() {
           _createClass(RingOut2, null, [{
             key: "factory",
+            /* Given the segments from the sweep line pass, compute & return a series
+             * of closed rings from all the segments marked to be part of the result */
             value: function factory(allSegments) {
               var ringsOut = [];
               for (var i2 = 0, iMax = allSegments.length; i2 < iMax; i2++) {
               }
               return this._enclosingRing;
             }
+            /* Returns the ring that encloses this one, if any */
           }, {
             key: "_calcEnclosingRing",
             value: function _calcEnclosingRing() {
               }
               return newEvents;
             }
+            /* Safely split a segment that is currently in the datastructures
+             * IE - a segment other than the one that is currently being processed. */
           }, {
             key: "_splitSafely",
             value: function _splitSafely(seg, pt) {
           }
           _createClass(Operation2, [{
             key: "run",
-            value: function run(type3, geom, moreGeoms) {
-              operation.type = type3;
+            value: function run(type2, geom, moreGeoms) {
+              operation.type = type2;
               rounder.reset();
               var multipolys = [new MultiPolyIn(geom, true)];
               for (var i2 = 0, iMax = moreGeoms.length; i2 < iMax; i2++) {
     }
   });
 
-  // node_modules/fast-deep-equal/index.js
-  var require_fast_deep_equal = __commonJS({
-    "node_modules/fast-deep-equal/index.js"(exports2, module2) {
-      "use strict";
-      module2.exports = function equal(a, b) {
-        if (a === b)
-          return true;
-        if (a && b && typeof a == "object" && typeof b == "object") {
-          if (a.constructor !== b.constructor)
-            return false;
-          var length, i2, keys;
-          if (Array.isArray(a)) {
-            length = a.length;
-            if (length != b.length)
-              return false;
-            for (i2 = length; i2-- !== 0; )
-              if (!equal(a[i2], b[i2]))
-                return false;
-            return true;
-          }
-          if (a.constructor === RegExp)
-            return a.source === b.source && a.flags === b.flags;
-          if (a.valueOf !== Object.prototype.valueOf)
-            return a.valueOf() === b.valueOf();
-          if (a.toString !== Object.prototype.toString)
-            return a.toString() === b.toString();
-          keys = Object.keys(a);
-          length = keys.length;
-          if (length !== Object.keys(b).length)
-            return false;
-          for (i2 = length; i2-- !== 0; )
-            if (!Object.prototype.hasOwnProperty.call(b, keys[i2]))
-              return false;
-          for (i2 = length; i2-- !== 0; ) {
-            var key = keys[i2];
-            if (!equal(a[key], b[key]))
-              return false;
-          }
-          return true;
-        }
-        return a !== a && b !== b;
-      };
-    }
-  });
-
   // node_modules/lodash/lodash.js
   var require_lodash = __commonJS({
     "node_modules/lodash/lodash.js"(exports2, module2) {
       (function() {
         var undefined2;
         var VERSION = "4.17.21";
-        var LARGE_ARRAY_SIZE = 200;
+        var LARGE_ARRAY_SIZE2 = 200;
         var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT3 = "Expected a function", INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`";
-        var HASH_UNDEFINED = "__lodash_hash_undefined__";
+        var HASH_UNDEFINED4 = "__lodash_hash_undefined__";
         var MAX_MEMOIZE_SIZE = 500;
         var PLACEHOLDER = "__lodash_placeholder__";
         var CLONE_DEEP_FLAG = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG = 4;
-        var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
+        var COMPARE_PARTIAL_FLAG5 = 1, COMPARE_UNORDERED_FLAG3 = 2;
         var WRAP_BIND_FLAG = 1, WRAP_BIND_KEY_FLAG = 2, WRAP_CURRY_BOUND_FLAG = 4, WRAP_CURRY_FLAG = 8, WRAP_CURRY_RIGHT_FLAG = 16, WRAP_PARTIAL_FLAG = 32, WRAP_PARTIAL_RIGHT_FLAG = 64, WRAP_ARY_FLAG = 128, WRAP_REARG_FLAG = 256, WRAP_FLIP_FLAG = 512;
         var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "...";
         var HOT_COUNT = 800, HOT_SPAN = 16;
         var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3;
-        var INFINITY2 = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 17976931348623157e292, NAN2 = 0 / 0;
+        var INFINITY2 = 1 / 0, MAX_SAFE_INTEGER3 = 9007199254740991, MAX_INTEGER = 17976931348623157e292, NAN2 = 0 / 0;
         var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
         var wrapFlags = [
           ["ary", WRAP_ARY_FLAG],
           ["partialRight", WRAP_PARTIAL_RIGHT_FLAG],
           ["rearg", WRAP_REARG_FLAG]
         ];
-        var argsTag = "[object Arguments]", arrayTag = "[object Array]", asyncTag = "[object AsyncFunction]", boolTag = "[object Boolean]", dateTag = "[object Date]", domExcTag = "[object DOMException]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", nullTag2 = "[object Null]", objectTag = "[object Object]", promiseTag = "[object Promise]", proxyTag = "[object Proxy]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag2 = "[object Symbol]", undefinedTag2 = "[object Undefined]", weakMapTag = "[object WeakMap]", weakSetTag = "[object WeakSet]";
-        var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]";
+        var argsTag4 = "[object Arguments]", arrayTag3 = "[object Array]", asyncTag2 = "[object AsyncFunction]", boolTag3 = "[object Boolean]", dateTag3 = "[object Date]", domExcTag = "[object DOMException]", errorTag3 = "[object Error]", funcTag3 = "[object Function]", genTag2 = "[object GeneratorFunction]", mapTag4 = "[object Map]", numberTag3 = "[object Number]", nullTag2 = "[object Null]", objectTag4 = "[object Object]", promiseTag2 = "[object Promise]", proxyTag2 = "[object Proxy]", regexpTag3 = "[object RegExp]", setTag4 = "[object Set]", stringTag3 = "[object String]", symbolTag3 = "[object Symbol]", undefinedTag2 = "[object Undefined]", weakMapTag3 = "[object WeakMap]", weakSetTag = "[object WeakSet]";
+        var arrayBufferTag3 = "[object ArrayBuffer]", dataViewTag4 = "[object DataView]", float32Tag2 = "[object Float32Array]", float64Tag2 = "[object Float64Array]", int8Tag2 = "[object Int8Array]", int16Tag2 = "[object Int16Array]", int32Tag2 = "[object Int32Array]", uint8Tag2 = "[object Uint8Array]", uint8ClampedTag2 = "[object Uint8ClampedArray]", uint16Tag2 = "[object Uint16Array]", uint32Tag2 = "[object Uint32Array]";
         var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
         var reEscapedHtml2 = /&(?:amp|lt|gt|quot|#39);/g, reUnescapedHtml2 = /[&<>"']/g, reHasEscapedHtml2 = RegExp(reEscapedHtml2.source), reHasUnescapedHtml2 = RegExp(reUnescapedHtml2.source);
         var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g;
         var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
-        var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source);
+        var reRegExpChar2 = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar2.source);
         var reTrimStart2 = /^\s+/;
         var reWhitespace2 = /\s/;
         var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, reSplitDetails = /,? & /;
         var reFlags = /\w*$/;
         var reIsBadHex2 = /^[-+]0x[0-9a-f]+$/i;
         var reIsBinary2 = /^0b[01]+$/i;
-        var reIsHostCtor = /^\[object .+?Constructor\]$/;
+        var reIsHostCtor2 = /^\[object .+?Constructor\]$/;
         var reIsOctal2 = /^0o[0-7]+$/i;
-        var reIsUint = /^(?:0|[1-9]\d*)$/;
+        var reIsUint2 = /^(?:0|[1-9]\d*)$/;
         var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
         var reNoMatch = /($^)/;
         var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
           "setTimeout"
         ];
         var templateCounter = -1;
-        var typedArrayTags = {};
-        typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
-        typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
+        var typedArrayTags2 = {};
+        typedArrayTags2[float32Tag2] = typedArrayTags2[float64Tag2] = typedArrayTags2[int8Tag2] = typedArrayTags2[int16Tag2] = typedArrayTags2[int32Tag2] = typedArrayTags2[uint8Tag2] = typedArrayTags2[uint8ClampedTag2] = typedArrayTags2[uint16Tag2] = typedArrayTags2[uint32Tag2] = true;
+        typedArrayTags2[argsTag4] = typedArrayTags2[arrayTag3] = typedArrayTags2[arrayBufferTag3] = typedArrayTags2[boolTag3] = typedArrayTags2[dataViewTag4] = typedArrayTags2[dateTag3] = typedArrayTags2[errorTag3] = typedArrayTags2[funcTag3] = typedArrayTags2[mapTag4] = typedArrayTags2[numberTag3] = typedArrayTags2[objectTag4] = typedArrayTags2[regexpTag3] = typedArrayTags2[setTag4] = typedArrayTags2[stringTag3] = typedArrayTags2[weakMapTag3] = false;
         var cloneableTags = {};
-        cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag2] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
-        cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
+        cloneableTags[argsTag4] = cloneableTags[arrayTag3] = cloneableTags[arrayBufferTag3] = cloneableTags[dataViewTag4] = cloneableTags[boolTag3] = cloneableTags[dateTag3] = cloneableTags[float32Tag2] = cloneableTags[float64Tag2] = cloneableTags[int8Tag2] = cloneableTags[int16Tag2] = cloneableTags[int32Tag2] = cloneableTags[mapTag4] = cloneableTags[numberTag3] = cloneableTags[objectTag4] = cloneableTags[regexpTag3] = cloneableTags[setTag4] = cloneableTags[stringTag3] = cloneableTags[symbolTag3] = cloneableTags[uint8Tag2] = cloneableTags[uint8ClampedTag2] = cloneableTags[uint16Tag2] = cloneableTags[uint32Tag2] = true;
+        cloneableTags[errorTag3] = cloneableTags[funcTag3] = cloneableTags[weakMapTag3] = false;
         var deburredLetters = {
+          // Latin-1 Supplement block.
           "\xC0": "A",
           "\xC1": "A",
           "\xC2": "A",
           "\xDE": "Th",
           "\xFE": "th",
           "\xDF": "ss",
+          // Latin Extended-A block.
           "\u0100": "A",
           "\u0102": "A",
           "\u0104": "A",
         var freeGlobal2 = typeof global == "object" && global && global.Object === Object && global;
         var freeSelf2 = typeof self == "object" && self && self.Object === Object && self;
         var root3 = freeGlobal2 || freeSelf2 || Function("return this")();
-        var freeExports = typeof exports2 == "object" && exports2 && !exports2.nodeType && exports2;
-        var freeModule = freeExports && typeof module2 == "object" && module2 && !module2.nodeType && module2;
-        var moduleExports = freeModule && freeModule.exports === freeExports;
-        var freeProcess = moduleExports && freeGlobal2.process;
-        var nodeUtil = function() {
+        var freeExports3 = typeof exports2 == "object" && exports2 && !exports2.nodeType && exports2;
+        var freeModule3 = freeExports3 && typeof module2 == "object" && module2 && !module2.nodeType && module2;
+        var moduleExports3 = freeModule3 && freeModule3.exports === freeExports3;
+        var freeProcess2 = moduleExports3 && freeGlobal2.process;
+        var nodeUtil2 = function() {
           try {
-            var types = freeModule && freeModule.require && freeModule.require("util").types;
+            var types = freeModule3 && freeModule3.require && freeModule3.require("util").types;
             if (types) {
               return types;
             }
-            return freeProcess && freeProcess.binding && freeProcess.binding("util");
+            return freeProcess2 && freeProcess2.binding && freeProcess2.binding("util");
           } catch (e) {
           }
         }();
-        var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, nodeIsDate = nodeUtil && nodeUtil.isDate, nodeIsMap = nodeUtil && nodeUtil.isMap, nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, nodeIsSet = nodeUtil && nodeUtil.isSet, nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
+        var nodeIsArrayBuffer = nodeUtil2 && nodeUtil2.isArrayBuffer, nodeIsDate = nodeUtil2 && nodeUtil2.isDate, nodeIsMap = nodeUtil2 && nodeUtil2.isMap, nodeIsRegExp = nodeUtil2 && nodeUtil2.isRegExp, nodeIsSet = nodeUtil2 && nodeUtil2.isSet, nodeIsTypedArray2 = nodeUtil2 && nodeUtil2.isTypedArray;
         function apply(func, thisArg, args) {
           switch (args.length) {
             case 0:
           }
           return true;
         }
-        function arrayFilter(array2, predicate) {
+        function arrayFilter2(array2, predicate) {
           var index = -1, length = array2 == null ? 0 : array2.length, resIndex = 0, result = [];
           while (++index < length) {
             var value = array2[index];
           }
           return result;
         }
-        function arrayPush(array2, values) {
+        function arrayPush2(array2, values) {
           var index = -1, length = values.length, offset = array2.length;
           while (++index < length) {
             array2[offset + index] = values[index];
           }
           return accumulator;
         }
-        function arraySome(array2, predicate) {
+        function arraySome2(array2, predicate) {
           var index = -1, length = array2 == null ? 0 : array2.length;
           while (++index < length) {
             if (predicate(array2[index], index, array2)) {
           }
           return result;
         }
-        function baseTimes(n2, iteratee) {
+        function baseTimes2(n2, iteratee) {
           var index = -1, result = Array(n2);
           while (++index < n2) {
             result[index] = iteratee(index);
         function baseTrim2(string) {
           return string ? string.slice(0, trimmedEndIndex2(string) + 1).replace(reTrimStart2, "") : string;
         }
-        function baseUnary(func) {
+        function baseUnary2(func) {
           return function(value) {
             return func(value);
           };
             return object[key];
           });
         }
-        function cacheHas(cache, key) {
+        function cacheHas2(cache, key) {
           return cache.has(key);
         }
         function charsStartIndex(strSymbols, chrSymbols) {
         function escapeStringChar(chr) {
           return "\\" + stringEscapes[chr];
         }
-        function getValue(object, key) {
+        function getValue2(object, key) {
           return object == null ? undefined2 : object[key];
         }
         function hasUnicode(string) {
           }
           return result;
         }
-        function mapToArray(map2) {
+        function mapToArray2(map2) {
           var index = -1, result = Array(map2.size);
           map2.forEach(function(value, key) {
             result[++index] = [key, value];
           });
           return result;
         }
-        function overArg(func, transform2) {
+        function overArg2(func, transform2) {
           return function(arg) {
             return func(transform2(arg));
           };
           }
           return result;
         }
-        function setToArray(set3) {
+        function setToArray2(set3) {
           var index = -1, result = Array(set3.size);
           set3.forEach(function(value) {
             result[++index] = value;
         var runInContext = function runInContext2(context) {
           context = context == null ? root3 : _.defaults(root3.Object(), context, _.pick(root3, contextProps));
           var Array2 = context.Array, Date2 = context.Date, Error2 = context.Error, Function2 = context.Function, Math2 = context.Math, Object2 = context.Object, RegExp2 = context.RegExp, String2 = context.String, TypeError2 = context.TypeError;
-          var arrayProto = Array2.prototype, funcProto = Function2.prototype, objectProto3 = Object2.prototype;
-          var coreJsData = context["__core-js_shared__"];
-          var funcToString = funcProto.toString;
-          var hasOwnProperty2 = objectProto3.hasOwnProperty;
+          var arrayProto2 = Array2.prototype, funcProto3 = Function2.prototype, objectProto13 = Object2.prototype;
+          var coreJsData2 = context["__core-js_shared__"];
+          var funcToString3 = funcProto3.toString;
+          var hasOwnProperty10 = objectProto13.hasOwnProperty;
           var idCounter = 0;
-          var maskSrcKey = function() {
-            var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || "");
+          var maskSrcKey2 = function() {
+            var uid = /[^.]+$/.exec(coreJsData2 && coreJsData2.keys && coreJsData2.keys.IE_PROTO || "");
             return uid ? "Symbol(src)_1." + uid : "";
           }();
-          var nativeObjectToString3 = objectProto3.toString;
-          var objectCtorString = funcToString.call(Object2);
+          var nativeObjectToString3 = objectProto13.toString;
+          var objectCtorString = funcToString3.call(Object2);
           var oldDash = root3._;
-          var reIsNative = RegExp2(
-            "^" + funcToString.call(hasOwnProperty2).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
+          var reIsNative2 = RegExp2(
+            "^" + funcToString3.call(hasOwnProperty10).replace(reRegExpChar2, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
           );
-          var Buffer2 = moduleExports ? context.Buffer : undefined2, Symbol3 = context.Symbol, Uint8Array2 = context.Uint8Array, allocUnsafe = Buffer2 ? Buffer2.allocUnsafe : undefined2, getPrototype = overArg(Object2.getPrototypeOf, Object2), objectCreate = Object2.create, propertyIsEnumerable = objectProto3.propertyIsEnumerable, splice = arrayProto.splice, spreadableSymbol = Symbol3 ? Symbol3.isConcatSpreadable : undefined2, symIterator = Symbol3 ? Symbol3.iterator : undefined2, symToStringTag3 = Symbol3 ? Symbol3.toStringTag : undefined2;
+          var Buffer3 = moduleExports3 ? context.Buffer : undefined2, Symbol3 = context.Symbol, Uint8Array3 = context.Uint8Array, allocUnsafe = Buffer3 ? Buffer3.allocUnsafe : undefined2, getPrototype = overArg2(Object2.getPrototypeOf, Object2), objectCreate = Object2.create, propertyIsEnumerable3 = objectProto13.propertyIsEnumerable, splice2 = arrayProto2.splice, spreadableSymbol = Symbol3 ? Symbol3.isConcatSpreadable : undefined2, symIterator = Symbol3 ? Symbol3.iterator : undefined2, symToStringTag3 = Symbol3 ? Symbol3.toStringTag : undefined2;
           var defineProperty = function() {
             try {
-              var func = getNative(Object2, "defineProperty");
+              var func = getNative2(Object2, "defineProperty");
               func({}, "", {});
               return func;
             } catch (e) {
             }
           }();
           var ctxClearTimeout = context.clearTimeout !== root3.clearTimeout && context.clearTimeout, ctxNow = Date2 && Date2.now !== root3.Date.now && Date2.now, ctxSetTimeout = context.setTimeout !== root3.setTimeout && context.setTimeout;
-          var nativeCeil = Math2.ceil, nativeFloor = Math2.floor, nativeGetSymbols = Object2.getOwnPropertySymbols, nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : undefined2, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, nativeKeys = overArg(Object2.keys, Object2), nativeMax2 = Math2.max, nativeMin2 = Math2.min, nativeNow = Date2.now, nativeParseInt = context.parseInt, nativeRandom = Math2.random, nativeReverse = arrayProto.reverse;
-          var DataView2 = getNative(context, "DataView"), Map2 = getNative(context, "Map"), Promise2 = getNative(context, "Promise"), Set2 = getNative(context, "Set"), WeakMap = getNative(context, "WeakMap"), nativeCreate = getNative(Object2, "create");
-          var metaMap = WeakMap && new WeakMap();
+          var nativeCeil = Math2.ceil, nativeFloor = Math2.floor, nativeGetSymbols2 = Object2.getOwnPropertySymbols, nativeIsBuffer2 = Buffer3 ? Buffer3.isBuffer : undefined2, nativeIsFinite = context.isFinite, nativeJoin = arrayProto2.join, nativeKeys2 = overArg2(Object2.keys, Object2), nativeMax2 = Math2.max, nativeMin2 = Math2.min, nativeNow = Date2.now, nativeParseInt = context.parseInt, nativeRandom = Math2.random, nativeReverse = arrayProto2.reverse;
+          var DataView3 = getNative2(context, "DataView"), Map3 = getNative2(context, "Map"), Promise3 = getNative2(context, "Promise"), Set3 = getNative2(context, "Set"), WeakMap2 = getNative2(context, "WeakMap"), nativeCreate2 = getNative2(Object2, "create");
+          var metaMap = WeakMap2 && new WeakMap2();
           var realNames = {};
-          var dataViewCtorString = toSource(DataView2), mapCtorString = toSource(Map2), promiseCtorString = toSource(Promise2), setCtorString = toSource(Set2), weakMapCtorString = toSource(WeakMap);
-          var symbolProto2 = Symbol3 ? Symbol3.prototype : undefined2, symbolValueOf = symbolProto2 ? symbolProto2.valueOf : undefined2, symbolToString2 = symbolProto2 ? symbolProto2.toString : undefined2;
+          var dataViewCtorString2 = toSource2(DataView3), mapCtorString2 = toSource2(Map3), promiseCtorString2 = toSource2(Promise3), setCtorString2 = toSource2(Set3), weakMapCtorString2 = toSource2(WeakMap2);
+          var symbolProto3 = Symbol3 ? Symbol3.prototype : undefined2, symbolValueOf2 = symbolProto3 ? symbolProto3.valueOf : undefined2, symbolToString2 = symbolProto3 ? symbolProto3.toString : undefined2;
           function lodash(value) {
             if (isObjectLike2(value) && !isArray2(value) && !(value instanceof LazyWrapper)) {
               if (value instanceof LodashWrapper) {
                 return value;
               }
-              if (hasOwnProperty2.call(value, "__wrapped__")) {
+              if (hasOwnProperty10.call(value, "__wrapped__")) {
                 return wrapperClone(value);
               }
             }
             this.__values__ = undefined2;
           }
           lodash.templateSettings = {
+            /**
+             * Used to detect `data` property values to be HTML-escaped.
+             *
+             * @memberOf _.templateSettings
+             * @type {RegExp}
+             */
             "escape": reEscape,
+            /**
+             * Used to detect code to be evaluated.
+             *
+             * @memberOf _.templateSettings
+             * @type {RegExp}
+             */
             "evaluate": reEvaluate,
+            /**
+             * Used to detect `data` property values to inject.
+             *
+             * @memberOf _.templateSettings
+             * @type {RegExp}
+             */
             "interpolate": reInterpolate,
+            /**
+             * Used to reference the data object in the template text.
+             *
+             * @memberOf _.templateSettings
+             * @type {string}
+             */
             "variable": "",
+            /**
+             * Used to import variables into the compiled template.
+             *
+             * @memberOf _.templateSettings
+             * @type {Object}
+             */
             "imports": {
+              /**
+               * A reference to the `lodash` function.
+               *
+               * @memberOf _.templateSettings.imports
+               * @type {Function}
+               */
               "_": lodash
             }
           };
                 index += dir;
                 var iterIndex = -1, value = array2[index];
                 while (++iterIndex < iterLength) {
-                  var data = iteratees[iterIndex], iteratee2 = data.iteratee, type3 = data.type, computed = iteratee2(value);
-                  if (type3 == LAZY_MAP_FLAG) {
+                  var data = iteratees[iterIndex], iteratee2 = data.iteratee, type2 = data.type, computed = iteratee2(value);
+                  if (type2 == LAZY_MAP_FLAG) {
                     value = computed;
                   } else if (!computed) {
-                    if (type3 == LAZY_FILTER_FLAG) {
+                    if (type2 == LAZY_FILTER_FLAG) {
                       continue outer;
                     } else {
                       break outer;
           }
           LazyWrapper.prototype = baseCreate(baseLodash.prototype);
           LazyWrapper.prototype.constructor = LazyWrapper;
-          function Hash(entries) {
+          function Hash2(entries) {
             var index = -1, length = entries == null ? 0 : entries.length;
             this.clear();
             while (++index < length) {
               this.set(entry[0], entry[1]);
             }
           }
-          function hashClear() {
-            this.__data__ = nativeCreate ? nativeCreate(null) : {};
+          function hashClear2() {
+            this.__data__ = nativeCreate2 ? nativeCreate2(null) : {};
             this.size = 0;
           }
-          function hashDelete(key) {
+          function hashDelete2(key) {
             var result2 = this.has(key) && delete this.__data__[key];
             this.size -= result2 ? 1 : 0;
             return result2;
           }
-          function hashGet(key) {
+          function hashGet2(key) {
             var data = this.__data__;
-            if (nativeCreate) {
+            if (nativeCreate2) {
               var result2 = data[key];
-              return result2 === HASH_UNDEFINED ? undefined2 : result2;
+              return result2 === HASH_UNDEFINED4 ? undefined2 : result2;
             }
-            return hasOwnProperty2.call(data, key) ? data[key] : undefined2;
+            return hasOwnProperty10.call(data, key) ? data[key] : undefined2;
           }
-          function hashHas(key) {
+          function hashHas2(key) {
             var data = this.__data__;
-            return nativeCreate ? data[key] !== undefined2 : hasOwnProperty2.call(data, key);
+            return nativeCreate2 ? data[key] !== undefined2 : hasOwnProperty10.call(data, key);
           }
-          function hashSet(key, value) {
+          function hashSet2(key, value) {
             var data = this.__data__;
             this.size += this.has(key) ? 0 : 1;
-            data[key] = nativeCreate && value === undefined2 ? HASH_UNDEFINED : value;
+            data[key] = nativeCreate2 && value === undefined2 ? HASH_UNDEFINED4 : value;
             return this;
           }
-          Hash.prototype.clear = hashClear;
-          Hash.prototype["delete"] = hashDelete;
-          Hash.prototype.get = hashGet;
-          Hash.prototype.has = hashHas;
-          Hash.prototype.set = hashSet;
-          function ListCache(entries) {
+          Hash2.prototype.clear = hashClear2;
+          Hash2.prototype["delete"] = hashDelete2;
+          Hash2.prototype.get = hashGet2;
+          Hash2.prototype.has = hashHas2;
+          Hash2.prototype.set = hashSet2;
+          function ListCache2(entries) {
             var index = -1, length = entries == null ? 0 : entries.length;
             this.clear();
             while (++index < length) {
               this.set(entry[0], entry[1]);
             }
           }
-          function listCacheClear() {
+          function listCacheClear2() {
             this.__data__ = [];
             this.size = 0;
           }
-          function listCacheDelete(key) {
-            var data = this.__data__, index = assocIndexOf(data, key);
+          function listCacheDelete2(key) {
+            var data = this.__data__, index = assocIndexOf2(data, key);
             if (index < 0) {
               return false;
             }
             if (index == lastIndex) {
               data.pop();
             } else {
-              splice.call(data, index, 1);
+              splice2.call(data, index, 1);
             }
             --this.size;
             return true;
           }
-          function listCacheGet(key) {
-            var data = this.__data__, index = assocIndexOf(data, key);
+          function listCacheGet2(key) {
+            var data = this.__data__, index = assocIndexOf2(data, key);
             return index < 0 ? undefined2 : data[index][1];
           }
-          function listCacheHas(key) {
-            return assocIndexOf(this.__data__, key) > -1;
+          function listCacheHas2(key) {
+            return assocIndexOf2(this.__data__, key) > -1;
           }
-          function listCacheSet(key, value) {
-            var data = this.__data__, index = assocIndexOf(data, key);
+          function listCacheSet2(key, value) {
+            var data = this.__data__, index = assocIndexOf2(data, key);
             if (index < 0) {
               ++this.size;
               data.push([key, value]);
             }
             return this;
           }
-          ListCache.prototype.clear = listCacheClear;
-          ListCache.prototype["delete"] = listCacheDelete;
-          ListCache.prototype.get = listCacheGet;
-          ListCache.prototype.has = listCacheHas;
-          ListCache.prototype.set = listCacheSet;
-          function MapCache(entries) {
+          ListCache2.prototype.clear = listCacheClear2;
+          ListCache2.prototype["delete"] = listCacheDelete2;
+          ListCache2.prototype.get = listCacheGet2;
+          ListCache2.prototype.has = listCacheHas2;
+          ListCache2.prototype.set = listCacheSet2;
+          function MapCache2(entries) {
             var index = -1, length = entries == null ? 0 : entries.length;
             this.clear();
             while (++index < length) {
               this.set(entry[0], entry[1]);
             }
           }
-          function mapCacheClear() {
+          function mapCacheClear2() {
             this.size = 0;
             this.__data__ = {
-              "hash": new Hash(),
-              "map": new (Map2 || ListCache)(),
-              "string": new Hash()
+              "hash": new Hash2(),
+              "map": new (Map3 || ListCache2)(),
+              "string": new Hash2()
             };
           }
-          function mapCacheDelete(key) {
-            var result2 = getMapData(this, key)["delete"](key);
+          function mapCacheDelete2(key) {
+            var result2 = getMapData2(this, key)["delete"](key);
             this.size -= result2 ? 1 : 0;
             return result2;
           }
-          function mapCacheGet(key) {
-            return getMapData(this, key).get(key);
+          function mapCacheGet2(key) {
+            return getMapData2(this, key).get(key);
           }
-          function mapCacheHas(key) {
-            return getMapData(this, key).has(key);
+          function mapCacheHas2(key) {
+            return getMapData2(this, key).has(key);
           }
-          function mapCacheSet(key, value) {
-            var data = getMapData(this, key), size2 = data.size;
+          function mapCacheSet2(key, value) {
+            var data = getMapData2(this, key), size2 = data.size;
             data.set(key, value);
             this.size += data.size == size2 ? 0 : 1;
             return this;
           }
-          MapCache.prototype.clear = mapCacheClear;
-          MapCache.prototype["delete"] = mapCacheDelete;
-          MapCache.prototype.get = mapCacheGet;
-          MapCache.prototype.has = mapCacheHas;
-          MapCache.prototype.set = mapCacheSet;
-          function SetCache(values2) {
+          MapCache2.prototype.clear = mapCacheClear2;
+          MapCache2.prototype["delete"] = mapCacheDelete2;
+          MapCache2.prototype.get = mapCacheGet2;
+          MapCache2.prototype.has = mapCacheHas2;
+          MapCache2.prototype.set = mapCacheSet2;
+          function SetCache2(values2) {
             var index = -1, length = values2 == null ? 0 : values2.length;
-            this.__data__ = new MapCache();
+            this.__data__ = new MapCache2();
             while (++index < length) {
               this.add(values2[index]);
             }
           }
-          function setCacheAdd(value) {
-            this.__data__.set(value, HASH_UNDEFINED);
+          function setCacheAdd2(value) {
+            this.__data__.set(value, HASH_UNDEFINED4);
             return this;
           }
-          function setCacheHas(value) {
+          function setCacheHas2(value) {
             return this.__data__.has(value);
           }
-          SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
-          SetCache.prototype.has = setCacheHas;
-          function Stack(entries) {
-            var data = this.__data__ = new ListCache(entries);
+          SetCache2.prototype.add = SetCache2.prototype.push = setCacheAdd2;
+          SetCache2.prototype.has = setCacheHas2;
+          function Stack2(entries) {
+            var data = this.__data__ = new ListCache2(entries);
             this.size = data.size;
           }
-          function stackClear() {
-            this.__data__ = new ListCache();
+          function stackClear2() {
+            this.__data__ = new ListCache2();
             this.size = 0;
           }
-          function stackDelete(key) {
+          function stackDelete2(key) {
             var data = this.__data__, result2 = data["delete"](key);
             this.size = data.size;
             return result2;
           }
-          function stackGet(key) {
+          function stackGet2(key) {
             return this.__data__.get(key);
           }
-          function stackHas(key) {
+          function stackHas2(key) {
             return this.__data__.has(key);
           }
-          function stackSet(key, value) {
+          function stackSet2(key, value) {
             var data = this.__data__;
-            if (data instanceof ListCache) {
+            if (data instanceof ListCache2) {
               var pairs = data.__data__;
-              if (!Map2 || pairs.length < LARGE_ARRAY_SIZE - 1) {
+              if (!Map3 || pairs.length < LARGE_ARRAY_SIZE2 - 1) {
                 pairs.push([key, value]);
                 this.size = ++data.size;
                 return this;
               }
-              data = this.__data__ = new MapCache(pairs);
+              data = this.__data__ = new MapCache2(pairs);
             }
             data.set(key, value);
             this.size = data.size;
             return this;
           }
-          Stack.prototype.clear = stackClear;
-          Stack.prototype["delete"] = stackDelete;
-          Stack.prototype.get = stackGet;
-          Stack.prototype.has = stackHas;
-          Stack.prototype.set = stackSet;
-          function arrayLikeKeys(value, inherited) {
-            var isArr = isArray2(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer(value), isType = !isArr && !isArg && !isBuff && isTypedArray(value), skipIndexes = isArr || isArg || isBuff || isType, result2 = skipIndexes ? baseTimes(value.length, String2) : [], length = result2.length;
+          Stack2.prototype.clear = stackClear2;
+          Stack2.prototype["delete"] = stackDelete2;
+          Stack2.prototype.get = stackGet2;
+          Stack2.prototype.has = stackHas2;
+          Stack2.prototype.set = stackSet2;
+          function arrayLikeKeys2(value, inherited) {
+            var isArr = isArray2(value), isArg = !isArr && isArguments2(value), isBuff = !isArr && !isArg && isBuffer2(value), isType = !isArr && !isArg && !isBuff && isTypedArray2(value), skipIndexes = isArr || isArg || isBuff || isType, result2 = skipIndexes ? baseTimes2(value.length, String2) : [], length = result2.length;
             for (var key in value) {
-              if ((inherited || hasOwnProperty2.call(value, key)) && !(skipIndexes && (key == "length" || isBuff && (key == "offset" || key == "parent") || isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || isIndex(key, length)))) {
+              if ((inherited || hasOwnProperty10.call(value, key)) && !(skipIndexes && // Safari 9 has enumerable `arguments.length` in strict mode.
+              (key == "length" || // Node.js 0.10 has enumerable non-index properties on buffers.
+              isBuff && (key == "offset" || key == "parent") || // PhantomJS 2 has enumerable non-index properties on typed arrays.
+              isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || // Skip index properties.
+              isIndex2(key, length)))) {
                 result2.push(key);
               }
             }
             return shuffleSelf(copyArray(array2));
           }
           function assignMergeValue(object, key, value) {
-            if (value !== undefined2 && !eq(object[key], value) || value === undefined2 && !(key in object)) {
+            if (value !== undefined2 && !eq2(object[key], value) || value === undefined2 && !(key in object)) {
               baseAssignValue(object, key, value);
             }
           }
           function assignValue(object, key, value) {
             var objValue = object[key];
-            if (!(hasOwnProperty2.call(object, key) && eq(objValue, value)) || value === undefined2 && !(key in object)) {
+            if (!(hasOwnProperty10.call(object, key) && eq2(objValue, value)) || value === undefined2 && !(key in object)) {
               baseAssignValue(object, key, value);
             }
           }
-          function assocIndexOf(array2, key) {
+          function assocIndexOf2(array2, key) {
             var length = array2.length;
             while (length--) {
-              if (eq(array2[length][0], key)) {
+              if (eq2(array2[length][0], key)) {
                 return length;
               }
             }
             return accumulator;
           }
           function baseAssign(object, source) {
-            return object && copyObject(source, keys(source), object);
+            return object && copyObject(source, keys2(source), object);
           }
           function baseAssignIn(object, source) {
             return object && copyObject(source, keysIn(source), object);
                 return copyArray(value, result2);
               }
             } else {
-              var tag = getTag(value), isFunc = tag == funcTag || tag == genTag;
-              if (isBuffer(value)) {
+              var tag = getTag2(value), isFunc = tag == funcTag3 || tag == genTag2;
+              if (isBuffer2(value)) {
                 return cloneBuffer(value, isDeep);
               }
-              if (tag == objectTag || tag == argsTag || isFunc && !object) {
+              if (tag == objectTag4 || tag == argsTag4 || isFunc && !object) {
                 result2 = isFlat || isFunc ? {} : initCloneObject(value);
                 if (!isDeep) {
                   return isFlat ? copySymbolsIn(value, baseAssignIn(result2, value)) : copySymbols(value, baseAssign(result2, value));
                 result2 = initCloneByTag(value, tag, isDeep);
               }
             }
-            stack || (stack = new Stack());
+            stack || (stack = new Stack2());
             var stacked = stack.get(value);
             if (stacked) {
               return stacked;
                 result2.set(key2, baseClone(subValue, bitmask, customizer, key2, value, stack));
               });
             }
-            var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
+            var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys2 : isFlat ? keysIn : keys2;
             var props = isArr ? undefined2 : keysFunc(value);
             arrayEach(props || value, function(subValue, key2) {
               if (props) {
             return result2;
           }
           function baseConforms(source) {
-            var props = keys(source);
+            var props = keys2(source);
             return function(object) {
               return baseConformsTo(object, source, props);
             };
               return result2;
             }
             if (iteratee2) {
-              values2 = arrayMap2(values2, baseUnary(iteratee2));
+              values2 = arrayMap2(values2, baseUnary2(iteratee2));
             }
             if (comparator) {
               includes2 = arrayIncludesWith;
               isCommon = false;
-            } else if (values2.length >= LARGE_ARRAY_SIZE) {
-              includes2 = cacheHas;
+            } else if (values2.length >= LARGE_ARRAY_SIZE2) {
+              includes2 = cacheHas2;
               isCommon = false;
-              values2 = new SetCache(values2);
+              values2 = new SetCache2(values2);
             }
             outer:
               while (++index < length) {
                 if (depth > 1) {
                   baseFlatten(value, depth - 1, predicate, isStrict, result2);
                 } else {
-                  arrayPush(result2, value);
+                  arrayPush2(result2, value);
                 }
               } else if (!isStrict) {
                 result2[result2.length] = value;
           var baseFor = createBaseFor();
           var baseForRight = createBaseFor(true);
           function baseForOwn(object, iteratee2) {
-            return object && baseFor(object, iteratee2, keys);
+            return object && baseFor(object, iteratee2, keys2);
           }
           function baseForOwnRight(object, iteratee2) {
-            return object && baseForRight(object, iteratee2, keys);
+            return object && baseForRight(object, iteratee2, keys2);
           }
           function baseFunctions(object, props) {
-            return arrayFilter(props, function(key) {
-              return isFunction(object[key]);
+            return arrayFilter2(props, function(key) {
+              return isFunction2(object[key]);
             });
           }
           function baseGet(object, path) {
             }
             return index && index == length ? object : undefined2;
           }
-          function baseGetAllKeys(object, keysFunc, symbolsFunc) {
+          function baseGetAllKeys2(object, keysFunc, symbolsFunc) {
             var result2 = keysFunc(object);
-            return isArray2(object) ? result2 : arrayPush(result2, symbolsFunc(object));
+            return isArray2(object) ? result2 : arrayPush2(result2, symbolsFunc(object));
           }
           function baseGetTag2(value) {
             if (value == null) {
             return value > other;
           }
           function baseHas(object, key) {
-            return object != null && hasOwnProperty2.call(object, key);
+            return object != null && hasOwnProperty10.call(object, key);
           }
           function baseHasIn(object, key) {
             return object != null && key in Object2(object);
             while (othIndex--) {
               var array2 = arrays[othIndex];
               if (othIndex && iteratee2) {
-                array2 = arrayMap2(array2, baseUnary(iteratee2));
+                array2 = arrayMap2(array2, baseUnary2(iteratee2));
               }
               maxLength = nativeMin2(array2.length, maxLength);
-              caches[othIndex] = !comparator && (iteratee2 || length >= 120 && array2.length >= 120) ? new SetCache(othIndex && array2) : undefined2;
+              caches[othIndex] = !comparator && (iteratee2 || length >= 120 && array2.length >= 120) ? new SetCache2(othIndex && array2) : undefined2;
             }
             array2 = arrays[0];
             var index = -1, seen = caches[0];
               while (++index < length && result2.length < maxLength) {
                 var value = array2[index], computed = iteratee2 ? iteratee2(value) : value;
                 value = comparator || value !== 0 ? value : 0;
-                if (!(seen ? cacheHas(seen, computed) : includes2(result2, computed, comparator))) {
+                if (!(seen ? cacheHas2(seen, computed) : includes2(result2, computed, comparator))) {
                   othIndex = othLength;
                   while (--othIndex) {
                     var cache = caches[othIndex];
-                    if (!(cache ? cacheHas(cache, computed) : includes2(arrays[othIndex], computed, comparator))) {
+                    if (!(cache ? cacheHas2(cache, computed) : includes2(arrays[othIndex], computed, comparator))) {
                       continue outer;
                     }
                   }
             var func = object == null ? object : object[toKey(last(path))];
             return func == null ? undefined2 : apply(func, object, args);
           }
-          function baseIsArguments(value) {
-            return isObjectLike2(value) && baseGetTag2(value) == argsTag;
+          function baseIsArguments2(value) {
+            return isObjectLike2(value) && baseGetTag2(value) == argsTag4;
           }
           function baseIsArrayBuffer(value) {
-            return isObjectLike2(value) && baseGetTag2(value) == arrayBufferTag;
+            return isObjectLike2(value) && baseGetTag2(value) == arrayBufferTag3;
           }
           function baseIsDate(value) {
-            return isObjectLike2(value) && baseGetTag2(value) == dateTag;
+            return isObjectLike2(value) && baseGetTag2(value) == dateTag3;
           }
-          function baseIsEqual(value, other, bitmask, customizer, stack) {
+          function baseIsEqual2(value, other, bitmask, customizer, stack) {
             if (value === other) {
               return true;
             }
             if (value == null || other == null || !isObjectLike2(value) && !isObjectLike2(other)) {
               return value !== value && other !== other;
             }
-            return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
+            return baseIsEqualDeep2(value, other, bitmask, customizer, baseIsEqual2, stack);
           }
-          function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
-            var objIsArr = isArray2(object), othIsArr = isArray2(other), objTag = objIsArr ? arrayTag : getTag(object), othTag = othIsArr ? arrayTag : getTag(other);
-            objTag = objTag == argsTag ? objectTag : objTag;
-            othTag = othTag == argsTag ? objectTag : othTag;
-            var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag;
-            if (isSameTag && isBuffer(object)) {
-              if (!isBuffer(other)) {
+          function baseIsEqualDeep2(object, other, bitmask, customizer, equalFunc, stack) {
+            var objIsArr = isArray2(object), othIsArr = isArray2(other), objTag = objIsArr ? arrayTag3 : getTag2(object), othTag = othIsArr ? arrayTag3 : getTag2(other);
+            objTag = objTag == argsTag4 ? objectTag4 : objTag;
+            othTag = othTag == argsTag4 ? objectTag4 : othTag;
+            var objIsObj = objTag == objectTag4, othIsObj = othTag == objectTag4, isSameTag = objTag == othTag;
+            if (isSameTag && isBuffer2(object)) {
+              if (!isBuffer2(other)) {
                 return false;
               }
               objIsArr = true;
               objIsObj = false;
             }
             if (isSameTag && !objIsObj) {
-              stack || (stack = new Stack());
-              return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
+              stack || (stack = new Stack2());
+              return objIsArr || isTypedArray2(object) ? equalArrays2(object, other, bitmask, customizer, equalFunc, stack) : equalByTag2(object, other, objTag, bitmask, customizer, equalFunc, stack);
             }
-            if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
-              var objIsWrapped = objIsObj && hasOwnProperty2.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty2.call(other, "__wrapped__");
+            if (!(bitmask & COMPARE_PARTIAL_FLAG5)) {
+              var objIsWrapped = objIsObj && hasOwnProperty10.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty10.call(other, "__wrapped__");
               if (objIsWrapped || othIsWrapped) {
                 var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other;
-                stack || (stack = new Stack());
+                stack || (stack = new Stack2());
                 return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
               }
             }
             if (!isSameTag) {
               return false;
             }
-            stack || (stack = new Stack());
-            return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
+            stack || (stack = new Stack2());
+            return equalObjects2(object, other, bitmask, customizer, equalFunc, stack);
           }
           function baseIsMap(value) {
-            return isObjectLike2(value) && getTag(value) == mapTag;
+            return isObjectLike2(value) && getTag2(value) == mapTag4;
           }
           function baseIsMatch(object, source, matchData, customizer) {
             var index = matchData.length, length = index, noCustomizer = !customizer;
                   return false;
                 }
               } else {
-                var stack = new Stack();
+                var stack = new Stack2();
                 if (customizer) {
                   var result2 = customizer(objValue, srcValue, key, object, source, stack);
                 }
-                if (!(result2 === undefined2 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result2)) {
+                if (!(result2 === undefined2 ? baseIsEqual2(srcValue, objValue, COMPARE_PARTIAL_FLAG5 | COMPARE_UNORDERED_FLAG3, customizer, stack) : result2)) {
                   return false;
                 }
               }
             }
             return true;
           }
-          function baseIsNative(value) {
-            if (!isObject3(value) || isMasked(value)) {
+          function baseIsNative2(value) {
+            if (!isObject3(value) || isMasked2(value)) {
               return false;
             }
-            var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
-            return pattern.test(toSource(value));
+            var pattern = isFunction2(value) ? reIsNative2 : reIsHostCtor2;
+            return pattern.test(toSource2(value));
           }
           function baseIsRegExp(value) {
-            return isObjectLike2(value) && baseGetTag2(value) == regexpTag;
+            return isObjectLike2(value) && baseGetTag2(value) == regexpTag3;
           }
           function baseIsSet(value) {
-            return isObjectLike2(value) && getTag(value) == setTag;
+            return isObjectLike2(value) && getTag2(value) == setTag4;
           }
-          function baseIsTypedArray(value) {
-            return isObjectLike2(value) && isLength(value.length) && !!typedArrayTags[baseGetTag2(value)];
+          function baseIsTypedArray2(value) {
+            return isObjectLike2(value) && isLength2(value.length) && !!typedArrayTags2[baseGetTag2(value)];
           }
           function baseIteratee(value) {
             if (typeof value == "function") {
             }
             return property(value);
           }
-          function baseKeys(object) {
-            if (!isPrototype(object)) {
-              return nativeKeys(object);
+          function baseKeys2(object) {
+            if (!isPrototype2(object)) {
+              return nativeKeys2(object);
             }
             var result2 = [];
             for (var key in Object2(object)) {
-              if (hasOwnProperty2.call(object, key) && key != "constructor") {
+              if (hasOwnProperty10.call(object, key) && key != "constructor") {
                 result2.push(key);
               }
             }
             if (!isObject3(object)) {
               return nativeKeysIn(object);
             }
-            var isProto = isPrototype(object), result2 = [];
+            var isProto = isPrototype2(object), result2 = [];
             for (var key in object) {
-              if (!(key == "constructor" && (isProto || !hasOwnProperty2.call(object, key)))) {
+              if (!(key == "constructor" && (isProto || !hasOwnProperty10.call(object, key)))) {
                 result2.push(key);
               }
             }
             return value < other;
           }
           function baseMap(collection, iteratee2) {
-            var index = -1, result2 = isArrayLike(collection) ? Array2(collection.length) : [];
+            var index = -1, result2 = isArrayLike2(collection) ? Array2(collection.length) : [];
             baseEach(collection, function(value, key, collection2) {
               result2[++index] = iteratee2(value, key, collection2);
             });
             }
             return function(object) {
               var objValue = get4(object, path);
-              return objValue === undefined2 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
+              return objValue === undefined2 && objValue === srcValue ? hasIn(object, path) : baseIsEqual2(srcValue, objValue, COMPARE_PARTIAL_FLAG5 | COMPARE_UNORDERED_FLAG3);
             };
           }
           function baseMerge(object, source, srcIndex, customizer, stack) {
               return;
             }
             baseFor(source, function(srcValue, key) {
-              stack || (stack = new Stack());
+              stack || (stack = new Stack2());
               if (isObject3(srcValue)) {
                 baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
               } else {
             var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : undefined2;
             var isCommon = newValue === undefined2;
             if (isCommon) {
-              var isArr = isArray2(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue);
+              var isArr = isArray2(srcValue), isBuff = !isArr && isBuffer2(srcValue), isTyped = !isArr && !isBuff && isTypedArray2(srcValue);
               newValue = srcValue;
               if (isArr || isBuff || isTyped) {
                 if (isArray2(objValue)) {
                 } else {
                   newValue = [];
                 }
-              } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+              } else if (isPlainObject(srcValue) || isArguments2(srcValue)) {
                 newValue = objValue;
-                if (isArguments(objValue)) {
+                if (isArguments2(objValue)) {
                   newValue = toPlainObject(objValue);
-                } else if (!isObject3(objValue) || isFunction(objValue)) {
+                } else if (!isObject3(objValue) || isFunction2(objValue)) {
                   newValue = initCloneObject(srcValue);
                 }
               } else {
               return;
             }
             n2 += n2 < 0 ? length : 0;
-            return isIndex(n2, length) ? array2[n2] : undefined2;
+            return isIndex2(n2, length) ? array2[n2] : undefined2;
           }
           function baseOrderBy(collection, iteratees, orders) {
             if (iteratees.length) {
               iteratees = [identity4];
             }
             var index = -1;
-            iteratees = arrayMap2(iteratees, baseUnary(getIteratee()));
+            iteratees = arrayMap2(iteratees, baseUnary2(getIteratee()));
             var result2 = baseMap(collection, function(value, key, collection2) {
               var criteria = arrayMap2(iteratees, function(iteratee2) {
                 return iteratee2(value);
               values2 = copyArray(values2);
             }
             if (iteratee2) {
-              seen = arrayMap2(array2, baseUnary(iteratee2));
+              seen = arrayMap2(array2, baseUnary2(iteratee2));
             }
             while (++index < length) {
               var fromIndex = 0, value = values2[index], computed = iteratee2 ? iteratee2(value) : value;
               while ((fromIndex = indexOf2(seen, computed, fromIndex, comparator)) > -1) {
                 if (seen !== array2) {
-                  splice.call(seen, fromIndex, 1);
+                  splice2.call(seen, fromIndex, 1);
                 }
-                splice.call(array2, fromIndex, 1);
+                splice2.call(array2, fromIndex, 1);
               }
             }
             return array2;
               var index = indexes[length];
               if (length == lastIndex || index !== previous) {
                 var previous = index;
-                if (isIndex(index)) {
-                  splice.call(array2, index, 1);
+                if (isIndex2(index)) {
+                  splice2.call(array2, index, 1);
                 } else {
                   baseUnset(array2, index);
                 }
           }
           function baseRepeat(string, n2) {
             var result2 = "";
-            if (!string || n2 < 1 || n2 > MAX_SAFE_INTEGER) {
+            if (!string || n2 < 1 || n2 > MAX_SAFE_INTEGER3) {
               return result2;
             }
             do {
                 var objValue = nested[key];
                 newValue = customizer ? customizer(objValue, key, nested) : undefined2;
                 if (newValue === undefined2) {
-                  newValue = isObject3(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {};
+                  newValue = isObject3(objValue) ? objValue : isIndex2(path[index + 1]) ? [] : {};
                 }
               }
               assignValue(nested, key, newValue);
             var index = -1, length = array2.length, resIndex = 0, result2 = [];
             while (++index < length) {
               var value = array2[index], computed = iteratee2 ? iteratee2(value) : value;
-              if (!index || !eq(computed, seen)) {
+              if (!index || !eq2(computed, seen)) {
                 var seen = computed;
                 result2[resIndex++] = value === 0 ? 0 : value;
               }
             if (comparator) {
               isCommon = false;
               includes2 = arrayIncludesWith;
-            } else if (length >= LARGE_ARRAY_SIZE) {
+            } else if (length >= LARGE_ARRAY_SIZE2) {
               var set4 = iteratee2 ? null : createSet(array2);
               if (set4) {
-                return setToArray(set4);
+                return setToArray2(set4);
               }
               isCommon = false;
-              includes2 = cacheHas;
-              seen = new SetCache();
+              includes2 = cacheHas2;
+              seen = new SetCache2();
             } else {
               seen = iteratee2 ? [] : result2;
             }
               result2 = result2.value();
             }
             return arrayReduce(actions, function(result3, action) {
-              return action.func.apply(action.thisArg, arrayPush([result3], action.args));
+              return action.func.apply(action.thisArg, arrayPush2([result3], action.args));
             }, result2);
           }
           function baseXor(arrays, iteratee2, comparator) {
           }
           function cloneArrayBuffer(arrayBuffer) {
             var result2 = new arrayBuffer.constructor(arrayBuffer.byteLength);
-            new Uint8Array2(result2).set(new Uint8Array2(arrayBuffer));
+            new Uint8Array3(result2).set(new Uint8Array3(arrayBuffer));
             return result2;
           }
           function cloneDataView(dataView, isDeep) {
             return result2;
           }
           function cloneSymbol(symbol) {
-            return symbolValueOf ? Object2(symbolValueOf.call(symbol)) : {};
+            return symbolValueOf2 ? Object2(symbolValueOf2.call(symbol)) : {};
           }
           function cloneTypedArray(typedArray, isDeep) {
             var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
             return object;
           }
           function copySymbols(source, object) {
-            return copyObject(source, getSymbols(source), object);
+            return copyObject(source, getSymbols2(source), object);
           }
           function copySymbolsIn(source, object) {
             return copyObject(source, getSymbolsIn(source), object);
               if (collection == null) {
                 return collection;
               }
-              if (!isArrayLike(collection)) {
+              if (!isArrayLike2(collection)) {
                 return eachFunc(collection, iteratee2);
               }
               var length = collection.length, index = fromRight ? length : -1, iterable = Object2(collection);
           function createFind(findIndexFunc) {
             return function(collection, predicate, fromIndex) {
               var iterable = Object2(collection);
-              if (!isArrayLike(collection)) {
+              if (!isArrayLike2(collection)) {
                 var iteratee2 = getIteratee(predicate, 3);
-                collection = keys(collection);
+                collection = keys2(collection);
                 predicate = function(key) {
                   return iteratee2(iterable[key], key, iterable);
                 };
           }
           function createOver(arrayFunc) {
             return flatRest(function(iteratees) {
-              iteratees = arrayMap2(iteratees, baseUnary(getIteratee()));
+              iteratees = arrayMap2(iteratees, baseUnary2(getIteratee()));
               return baseRest(function(args) {
                 var thisArg = this;
                 return arrayFunc(iteratees, function(iteratee2) {
           function createRelationalOperation(operator) {
             return function(value, other) {
               if (!(typeof value == "string" && typeof other == "string")) {
-                value = toNumber2(value);
-                other = toNumber2(other);
+                value = toNumber3(value);
+                other = toNumber3(other);
               }
               return operator(value, other);
             };
           function createRound(methodName) {
             var func = Math2[methodName];
             return function(number3, precision2) {
-              number3 = toNumber2(number3);
+              number3 = toNumber3(number3);
               precision2 = precision2 == null ? 0 : nativeMin2(toInteger(precision2), 292);
               if (precision2 && nativeIsFinite(number3)) {
                 var pair2 = (toString2(number3) + "e").split("e"), value = func(pair2[0] + "e" + (+pair2[1] + precision2));
               return func(number3);
             };
           }
-          var createSet = !(Set2 && 1 / setToArray(new Set2([, -0]))[1] == INFINITY2) ? noop3 : function(values2) {
-            return new Set2(values2);
+          var createSet = !(Set3 && 1 / setToArray2(new Set3([, -0]))[1] == INFINITY2) ? noop3 : function(values2) {
+            return new Set3(values2);
           };
           function createToPairs(keysFunc) {
             return function(object) {
-              var tag = getTag(object);
-              if (tag == mapTag) {
-                return mapToArray(object);
+              var tag = getTag2(object);
+              if (tag == mapTag4) {
+                return mapToArray2(object);
               }
-              if (tag == setTag) {
+              if (tag == setTag4) {
                 return setToPairs(object);
               }
               return baseToPairs(object, keysFunc(object));
             return setWrapToString(setter(result2, newData), func, bitmask);
           }
           function customDefaultsAssignIn(objValue, srcValue, key, object) {
-            if (objValue === undefined2 || eq(objValue, objectProto3[key]) && !hasOwnProperty2.call(object, key)) {
+            if (objValue === undefined2 || eq2(objValue, objectProto13[key]) && !hasOwnProperty10.call(object, key)) {
               return srcValue;
             }
             return objValue;
           function customOmitClone(value) {
             return isPlainObject(value) ? undefined2 : value;
           }
-          function equalArrays(array2, other, bitmask, customizer, equalFunc, stack) {
-            var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array2.length, othLength = other.length;
+          function equalArrays2(array2, other, bitmask, customizer, equalFunc, stack) {
+            var isPartial = bitmask & COMPARE_PARTIAL_FLAG5, arrLength = array2.length, othLength = other.length;
             if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
               return false;
             }
             if (arrStacked && othStacked) {
               return arrStacked == other && othStacked == array2;
             }
-            var index = -1, result2 = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined2;
+            var index = -1, result2 = true, seen = bitmask & COMPARE_UNORDERED_FLAG3 ? new SetCache2() : undefined2;
             stack.set(array2, other);
             stack.set(other, array2);
             while (++index < arrLength) {
                 break;
               }
               if (seen) {
-                if (!arraySome(other, function(othValue2, othIndex) {
-                  if (!cacheHas(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) {
+                if (!arraySome2(other, function(othValue2, othIndex) {
+                  if (!cacheHas2(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) {
                     return seen.push(othIndex);
                   }
                 })) {
             stack["delete"](other);
             return result2;
           }
-          function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
+          function equalByTag2(object, other, tag, bitmask, customizer, equalFunc, stack) {
             switch (tag) {
-              case dataViewTag:
+              case dataViewTag4:
                 if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
                   return false;
                 }
                 object = object.buffer;
                 other = other.buffer;
-              case arrayBufferTag:
-                if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array2(object), new Uint8Array2(other))) {
+              case arrayBufferTag3:
+                if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array3(object), new Uint8Array3(other))) {
                   return false;
                 }
                 return true;
-              case boolTag:
-              case dateTag:
-              case numberTag:
-                return eq(+object, +other);
-              case errorTag:
+              case boolTag3:
+              case dateTag3:
+              case numberTag3:
+                return eq2(+object, +other);
+              case errorTag3:
                 return object.name == other.name && object.message == other.message;
-              case regexpTag:
-              case stringTag:
+              case regexpTag3:
+              case stringTag3:
                 return object == other + "";
-              case mapTag:
-                var convert = mapToArray;
-              case setTag:
-                var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
-                convert || (convert = setToArray);
+              case mapTag4:
+                var convert = mapToArray2;
+              case setTag4:
+                var isPartial = bitmask & COMPARE_PARTIAL_FLAG5;
+                convert || (convert = setToArray2);
                 if (object.size != other.size && !isPartial) {
                   return false;
                 }
                 if (stacked) {
                   return stacked == other;
                 }
-                bitmask |= COMPARE_UNORDERED_FLAG;
+                bitmask |= COMPARE_UNORDERED_FLAG3;
                 stack.set(object, other);
-                var result2 = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
+                var result2 = equalArrays2(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
                 stack["delete"](object);
                 return result2;
-              case symbolTag2:
-                if (symbolValueOf) {
-                  return symbolValueOf.call(object) == symbolValueOf.call(other);
+              case symbolTag3:
+                if (symbolValueOf2) {
+                  return symbolValueOf2.call(object) == symbolValueOf2.call(other);
                 }
             }
             return false;
           }
-          function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
-            var isPartial = bitmask & COMPARE_PARTIAL_FLAG, objProps = getAllKeys(object), objLength = objProps.length, othProps = getAllKeys(other), othLength = othProps.length;
+          function equalObjects2(object, other, bitmask, customizer, equalFunc, stack) {
+            var isPartial = bitmask & COMPARE_PARTIAL_FLAG5, objProps = getAllKeys2(object), objLength = objProps.length, othProps = getAllKeys2(other), othLength = othProps.length;
             if (objLength != othLength && !isPartial) {
               return false;
             }
             var index = objLength;
             while (index--) {
               var key = objProps[index];
-              if (!(isPartial ? key in other : hasOwnProperty2.call(other, key))) {
+              if (!(isPartial ? key in other : hasOwnProperty10.call(other, key))) {
                 return false;
               }
             }
           function flatRest(func) {
             return setToString(overRest(func, undefined2, flatten2), func + "");
           }
-          function getAllKeys(object) {
-            return baseGetAllKeys(object, keys, getSymbols);
+          function getAllKeys2(object) {
+            return baseGetAllKeys2(object, keys2, getSymbols2);
           }
           function getAllKeysIn(object) {
-            return baseGetAllKeys(object, keysIn, getSymbolsIn);
+            return baseGetAllKeys2(object, keysIn, getSymbolsIn);
           }
           var getData = !metaMap ? noop3 : function(func) {
             return metaMap.get(func);
           };
           function getFuncName(func) {
-            var result2 = func.name + "", array2 = realNames[result2], length = hasOwnProperty2.call(realNames, result2) ? array2.length : 0;
+            var result2 = func.name + "", array2 = realNames[result2], length = hasOwnProperty10.call(realNames, result2) ? array2.length : 0;
             while (length--) {
               var data = array2[length], otherFunc = data.func;
               if (otherFunc == null || otherFunc == func) {
             return result2;
           }
           function getHolder(func) {
-            var object = hasOwnProperty2.call(lodash, "placeholder") ? lodash : func;
+            var object = hasOwnProperty10.call(lodash, "placeholder") ? lodash : func;
             return object.placeholder;
           }
           function getIteratee() {
             result2 = result2 === iteratee ? baseIteratee : result2;
             return arguments.length ? result2(arguments[0], arguments[1]) : result2;
           }
-          function getMapData(map3, key) {
+          function getMapData2(map3, key) {
             var data = map3.__data__;
-            return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
+            return isKeyable2(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
           }
           function getMatchData(object) {
-            var result2 = keys(object), length = result2.length;
+            var result2 = keys2(object), length = result2.length;
             while (length--) {
               var key = result2[length], value = object[key];
               result2[length] = [key, value, isStrictComparable(value)];
             }
             return result2;
           }
-          function getNative(object, key) {
-            var value = getValue(object, key);
-            return baseIsNative(value) ? value : undefined2;
+          function getNative2(object, key) {
+            var value = getValue2(object, key);
+            return baseIsNative2(value) ? value : undefined2;
           }
           function getRawTag2(value) {
-            var isOwn = hasOwnProperty2.call(value, symToStringTag3), tag = value[symToStringTag3];
+            var isOwn = hasOwnProperty10.call(value, symToStringTag3), tag = value[symToStringTag3];
             try {
               value[symToStringTag3] = undefined2;
               var unmasked = true;
             }
             return result2;
           }
-          var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
+          var getSymbols2 = !nativeGetSymbols2 ? stubArray2 : function(object) {
             if (object == null) {
               return [];
             }
             object = Object2(object);
-            return arrayFilter(nativeGetSymbols(object), function(symbol) {
-              return propertyIsEnumerable.call(object, symbol);
+            return arrayFilter2(nativeGetSymbols2(object), function(symbol) {
+              return propertyIsEnumerable3.call(object, symbol);
             });
           };
-          var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
+          var getSymbolsIn = !nativeGetSymbols2 ? stubArray2 : function(object) {
             var result2 = [];
             while (object) {
-              arrayPush(result2, getSymbols(object));
+              arrayPush2(result2, getSymbols2(object));
               object = getPrototype(object);
             }
             return result2;
           };
-          var getTag = baseGetTag2;
-          if (DataView2 && getTag(new DataView2(new ArrayBuffer(1))) != dataViewTag || Map2 && getTag(new Map2()) != mapTag || Promise2 && getTag(Promise2.resolve()) != promiseTag || Set2 && getTag(new Set2()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) {
-            getTag = function(value) {
-              var result2 = baseGetTag2(value), Ctor = result2 == objectTag ? value.constructor : undefined2, ctorString = Ctor ? toSource(Ctor) : "";
+          var getTag2 = baseGetTag2;
+          if (DataView3 && getTag2(new DataView3(new ArrayBuffer(1))) != dataViewTag4 || Map3 && getTag2(new Map3()) != mapTag4 || Promise3 && getTag2(Promise3.resolve()) != promiseTag2 || Set3 && getTag2(new Set3()) != setTag4 || WeakMap2 && getTag2(new WeakMap2()) != weakMapTag3) {
+            getTag2 = function(value) {
+              var result2 = baseGetTag2(value), Ctor = result2 == objectTag4 ? value.constructor : undefined2, ctorString = Ctor ? toSource2(Ctor) : "";
               if (ctorString) {
                 switch (ctorString) {
-                  case dataViewCtorString:
-                    return dataViewTag;
-                  case mapCtorString:
-                    return mapTag;
-                  case promiseCtorString:
-                    return promiseTag;
-                  case setCtorString:
-                    return setTag;
-                  case weakMapCtorString:
-                    return weakMapTag;
+                  case dataViewCtorString2:
+                    return dataViewTag4;
+                  case mapCtorString2:
+                    return mapTag4;
+                  case promiseCtorString2:
+                    return promiseTag2;
+                  case setCtorString2:
+                    return setTag4;
+                  case weakMapCtorString2:
+                    return weakMapTag3;
                 }
               }
               return result2;
               return result2;
             }
             length = object == null ? 0 : object.length;
-            return !!length && isLength(length) && isIndex(key, length) && (isArray2(object) || isArguments(object));
+            return !!length && isLength2(length) && isIndex2(key, length) && (isArray2(object) || isArguments2(object));
           }
           function initCloneArray(array2) {
             var length = array2.length, result2 = new array2.constructor(length);
-            if (length && typeof array2[0] == "string" && hasOwnProperty2.call(array2, "index")) {
+            if (length && typeof array2[0] == "string" && hasOwnProperty10.call(array2, "index")) {
               result2.index = array2.index;
               result2.input = array2.input;
             }
             return result2;
           }
           function initCloneObject(object) {
-            return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
+            return typeof object.constructor == "function" && !isPrototype2(object) ? baseCreate(getPrototype(object)) : {};
           }
           function initCloneByTag(object, tag, isDeep) {
             var Ctor = object.constructor;
             switch (tag) {
-              case arrayBufferTag:
+              case arrayBufferTag3:
                 return cloneArrayBuffer(object);
-              case boolTag:
-              case dateTag:
+              case boolTag3:
+              case dateTag3:
                 return new Ctor(+object);
-              case dataViewTag:
+              case dataViewTag4:
                 return cloneDataView(object, isDeep);
-              case float32Tag:
-              case float64Tag:
-              case int8Tag:
-              case int16Tag:
-              case int32Tag:
-              case uint8Tag:
-              case uint8ClampedTag:
-              case uint16Tag:
-              case uint32Tag:
+              case float32Tag2:
+              case float64Tag2:
+              case int8Tag2:
+              case int16Tag2:
+              case int32Tag2:
+              case uint8Tag2:
+              case uint8ClampedTag2:
+              case uint16Tag2:
+              case uint32Tag2:
                 return cloneTypedArray(object, isDeep);
-              case mapTag:
+              case mapTag4:
                 return new Ctor();
-              case numberTag:
-              case stringTag:
+              case numberTag3:
+              case stringTag3:
                 return new Ctor(object);
-              case regexpTag:
+              case regexpTag3:
                 return cloneRegExp(object);
-              case setTag:
+              case setTag4:
                 return new Ctor();
-              case symbolTag2:
+              case symbolTag3:
                 return cloneSymbol(object);
             }
           }
             return source.replace(reWrapComment, "{\n/* [wrapped with " + details + "] */\n");
           }
           function isFlattenable(value) {
-            return isArray2(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
+            return isArray2(value) || isArguments2(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
           }
-          function isIndex(value, length) {
-            var type3 = typeof value;
-            length = length == null ? MAX_SAFE_INTEGER : length;
-            return !!length && (type3 == "number" || type3 != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
+          function isIndex2(value, length) {
+            var type2 = typeof value;
+            length = length == null ? MAX_SAFE_INTEGER3 : length;
+            return !!length && (type2 == "number" || type2 != "symbol" && reIsUint2.test(value)) && (value > -1 && value % 1 == 0 && value < length);
           }
           function isIterateeCall(value, index, object) {
             if (!isObject3(object)) {
               return false;
             }
-            var type3 = typeof index;
-            if (type3 == "number" ? isArrayLike(object) && isIndex(index, object.length) : type3 == "string" && index in object) {
-              return eq(object[index], value);
+            var type2 = typeof index;
+            if (type2 == "number" ? isArrayLike2(object) && isIndex2(index, object.length) : type2 == "string" && index in object) {
+              return eq2(object[index], value);
             }
             return false;
           }
             if (isArray2(value)) {
               return false;
             }
-            var type3 = typeof value;
-            if (type3 == "number" || type3 == "symbol" || type3 == "boolean" || value == null || isSymbol2(value)) {
+            var type2 = typeof value;
+            if (type2 == "number" || type2 == "symbol" || type2 == "boolean" || value == null || isSymbol2(value)) {
               return true;
             }
             return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object2(object);
           }
-          function isKeyable(value) {
-            var type3 = typeof value;
-            return type3 == "string" || type3 == "number" || type3 == "symbol" || type3 == "boolean" ? value !== "__proto__" : value === null;
+          function isKeyable2(value) {
+            var type2 = typeof value;
+            return type2 == "string" || type2 == "number" || type2 == "symbol" || type2 == "boolean" ? value !== "__proto__" : value === null;
           }
           function isLaziable(func) {
             var funcName = getFuncName(func), other = lodash[funcName];
             var data = getData(other);
             return !!data && func === data[0];
           }
-          function isMasked(func) {
-            return !!maskSrcKey && maskSrcKey in func;
+          function isMasked2(func) {
+            return !!maskSrcKey2 && maskSrcKey2 in func;
           }
-          var isMaskable = coreJsData ? isFunction : stubFalse;
-          function isPrototype(value) {
-            var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto3;
+          var isMaskable = coreJsData2 ? isFunction2 : stubFalse2;
+          function isPrototype2(value) {
+            var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto13;
             return value === proto;
           }
           function isStrictComparable(value) {
             var arrLength = array2.length, length = nativeMin2(indexes.length, arrLength), oldArray = copyArray(array2);
             while (length--) {
               var index = indexes[length];
-              array2[length] = isIndex(index, arrLength) ? oldArray[index] : undefined2;
+              array2[length] = isIndex2(index, arrLength) ? oldArray[index] : undefined2;
             }
             return array2;
           }
             var result2 = value + "";
             return result2 == "0" && 1 / value == -INFINITY2 ? "-0" : result2;
           }
-          function toSource(func) {
+          function toSource2(func) {
             if (func != null) {
               try {
-                return funcToString.call(func);
+                return funcToString3.call(func);
               } catch (e) {
               }
               try {
             while (index--) {
               args[index - 1] = arguments[index];
             }
-            return arrayPush(isArray2(array2) ? copyArray(array2) : [array2], baseFlatten(args, 1));
+            return arrayPush2(isArray2(array2) ? copyArray(array2) : [array2], baseFlatten(args, 1));
           }
           var difference = baseRest(function(array2, values2) {
             return isArrayLikeObject(array2) ? baseDifference(array2, baseFlatten(values2, 1, isArrayLikeObject, true)) : [];
           var pullAt = flatRest(function(array2, indexes) {
             var length = array2 == null ? 0 : array2.length, result2 = baseAt(array2, indexes);
             basePullAt(array2, arrayMap2(indexes, function(index) {
-              return isIndex(index, length) ? +index : index;
+              return isIndex2(index, length) ? +index : index;
             }).sort(compareAscending));
             return result2;
           });
             var length = array2 == null ? 0 : array2.length;
             if (length) {
               var index = baseSortedIndex(array2, value);
-              if (index < length && eq(array2[index], value)) {
+              if (index < length && eq2(array2[index], value)) {
                 return index;
               }
             }
             var length = array2 == null ? 0 : array2.length;
             if (length) {
               var index = baseSortedIndex(array2, value, true) - 1;
-              if (eq(array2[index], value)) {
+              if (eq2(array2[index], value)) {
                 return index;
               }
             }
               return [];
             }
             var length = 0;
-            array2 = arrayFilter(array2, function(group) {
+            array2 = arrayFilter2(array2, function(group) {
               if (isArrayLikeObject(group)) {
                 length = nativeMax2(group.length, length);
                 return true;
               }
             });
-            return baseTimes(length, function(index) {
+            return baseTimes2(length, function(index) {
               return arrayMap2(array2, baseProperty(index));
             });
           }
             return isArrayLikeObject(array2) ? baseDifference(array2, values2) : [];
           });
           var xor = baseRest(function(arrays) {
-            return baseXor(arrayFilter(arrays, isArrayLikeObject));
+            return baseXor(arrayFilter2(arrays, isArrayLikeObject));
           });
           var xorBy = baseRest(function(arrays) {
             var iteratee2 = last(arrays);
             if (isArrayLikeObject(iteratee2)) {
               iteratee2 = undefined2;
             }
-            return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee2, 2));
+            return baseXor(arrayFilter2(arrays, isArrayLikeObject), getIteratee(iteratee2, 2));
           });
           var xorWith = baseRest(function(arrays) {
             var comparator = last(arrays);
             comparator = typeof comparator == "function" ? comparator : undefined2;
-            return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined2, comparator);
+            return baseXor(arrayFilter2(arrays, isArrayLikeObject), undefined2, comparator);
           });
           var zip = baseRest(unzip);
           function zipObject(props, values2) {
             var length = paths.length, start2 = length ? paths[0] : 0, value = this.__wrapped__, interceptor = function(object) {
               return baseAt(object, paths);
             };
-            if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start2)) {
+            if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex2(start2)) {
               return this.thru(interceptor);
             }
             value = value.slice(start2, +start2 + (length ? 1 : 0));
             return baseWrapperValue(this.__wrapped__, this.__actions__);
           }
           var countBy = createAggregator(function(result2, value, key) {
-            if (hasOwnProperty2.call(result2, key)) {
+            if (hasOwnProperty10.call(result2, key)) {
               ++result2[key];
             } else {
               baseAssignValue(result2, key, 1);
             return func(collection, getIteratee(predicate, 3));
           }
           function filter2(collection, predicate) {
-            var func = isArray2(collection) ? arrayFilter : baseFilter;
+            var func = isArray2(collection) ? arrayFilter2 : baseFilter;
             return func(collection, getIteratee(predicate, 3));
           }
           var find2 = createFind(findIndex);
             return func(collection, getIteratee(iteratee2, 3));
           }
           var groupBy = createAggregator(function(result2, value, key) {
-            if (hasOwnProperty2.call(result2, key)) {
+            if (hasOwnProperty10.call(result2, key)) {
               result2[key].push(value);
             } else {
               baseAssignValue(result2, key, [value]);
             }
           });
           function includes(collection, value, fromIndex, guard) {
-            collection = isArrayLike(collection) ? collection : values(collection);
+            collection = isArrayLike2(collection) ? collection : values(collection);
             fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0;
             var length = collection.length;
             if (fromIndex < 0) {
             return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
           }
           var invokeMap = baseRest(function(collection, path, args) {
-            var index = -1, isFunc = typeof path == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : [];
+            var index = -1, isFunc = typeof path == "function", result2 = isArrayLike2(collection) ? Array2(collection.length) : [];
             baseEach(collection, function(value) {
               result2[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
             });
             return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEachRight);
           }
           function reject(collection, predicate) {
-            var func = isArray2(collection) ? arrayFilter : baseFilter;
+            var func = isArray2(collection) ? arrayFilter2 : baseFilter;
             return func(collection, negate(getIteratee(predicate, 3)));
           }
           function sample(collection) {
             if (collection == null) {
               return 0;
             }
-            if (isArrayLike(collection)) {
+            if (isArrayLike2(collection)) {
               return isString(collection) ? stringSize(collection) : collection.length;
             }
-            var tag = getTag(collection);
-            if (tag == mapTag || tag == setTag) {
+            var tag = getTag2(collection);
+            if (tag == mapTag4 || tag == setTag4) {
               return collection.size;
             }
-            return baseKeys(collection).length;
+            return baseKeys2(collection).length;
           }
           function some(collection, predicate, guard) {
-            var func = isArray2(collection) ? arraySome : baseSome;
+            var func = isArray2(collection) ? arraySome2 : baseSome;
             if (guard && isIterateeCall(collection, predicate, guard)) {
               predicate = undefined2;
             }
             if (typeof func != "function") {
               throw new TypeError2(FUNC_ERROR_TEXT3);
             }
-            wait = toNumber2(wait) || 0;
+            wait = toNumber3(wait) || 0;
             if (isObject3(options2)) {
               leading = !!options2.leading;
               maxing = "maxWait" in options2;
-              maxWait = maxing ? nativeMax2(toNumber2(options2.maxWait) || 0, wait) : maxWait;
+              maxWait = maxing ? nativeMax2(toNumber3(options2.maxWait) || 0, wait) : maxWait;
               trailing = "trailing" in options2 ? !!options2.trailing : trailing;
             }
             function invokeFunc(time) {
             return baseDelay(func, 1, args);
           });
           var delay = baseRest(function(func, wait, args) {
-            return baseDelay(func, toNumber2(wait) || 0, args);
+            return baseDelay(func, toNumber3(wait) || 0, args);
           });
           function flip(func) {
             return createWrap(func, WRAP_FLIP_FLAG);
               memoized.cache = cache.set(key, result2) || cache;
               return result2;
             };
-            memoized.cache = new (memoize.Cache || MapCache)();
+            memoized.cache = new (memoize.Cache || MapCache2)();
             return memoized;
           }
-          memoize.Cache = MapCache;
+          memoize.Cache = MapCache2;
           function negate(predicate) {
             if (typeof predicate != "function") {
               throw new TypeError2(FUNC_ERROR_TEXT3);
             return before(2, func);
           }
           var overArgs = castRest(function(func, transforms) {
-            transforms = transforms.length == 1 && isArray2(transforms[0]) ? arrayMap2(transforms[0], baseUnary(getIteratee())) : arrayMap2(baseFlatten(transforms, 1), baseUnary(getIteratee()));
+            transforms = transforms.length == 1 && isArray2(transforms[0]) ? arrayMap2(transforms[0], baseUnary2(getIteratee())) : arrayMap2(baseFlatten(transforms, 1), baseUnary2(getIteratee()));
             var funcsLength = transforms.length;
             return baseRest(function(args) {
               var index = -1, length = nativeMin2(args.length, funcsLength);
             return baseRest(function(args) {
               var array2 = args[start2], otherArgs = castSlice(args, 0, start2);
               if (array2) {
-                arrayPush(otherArgs, array2);
+                arrayPush2(otherArgs, array2);
               }
               return apply(func, this, otherArgs);
             });
             return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
           }
           function conformsTo(object, source) {
-            return source == null || baseConformsTo(object, source, keys(source));
+            return source == null || baseConformsTo(object, source, keys2(source));
           }
-          function eq(value, other) {
+          function eq2(value, other) {
             return value === other || value !== value && other !== other;
           }
           var gt = createRelationalOperation(baseGt);
           var gte = createRelationalOperation(function(value, other) {
             return value >= other;
           });
-          var isArguments = baseIsArguments(function() {
+          var isArguments2 = baseIsArguments2(function() {
             return arguments;
-          }()) ? baseIsArguments : function(value) {
-            return isObjectLike2(value) && hasOwnProperty2.call(value, "callee") && !propertyIsEnumerable.call(value, "callee");
+          }()) ? baseIsArguments2 : function(value) {
+            return isObjectLike2(value) && hasOwnProperty10.call(value, "callee") && !propertyIsEnumerable3.call(value, "callee");
           };
           var isArray2 = Array2.isArray;
-          var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
-          function isArrayLike(value) {
-            return value != null && isLength(value.length) && !isFunction(value);
+          var isArrayBuffer = nodeIsArrayBuffer ? baseUnary2(nodeIsArrayBuffer) : baseIsArrayBuffer;
+          function isArrayLike2(value) {
+            return value != null && isLength2(value.length) && !isFunction2(value);
           }
           function isArrayLikeObject(value) {
-            return isObjectLike2(value) && isArrayLike(value);
+            return isObjectLike2(value) && isArrayLike2(value);
           }
           function isBoolean(value) {
-            return value === true || value === false || isObjectLike2(value) && baseGetTag2(value) == boolTag;
+            return value === true || value === false || isObjectLike2(value) && baseGetTag2(value) == boolTag3;
           }
-          var isBuffer = nativeIsBuffer || stubFalse;
-          var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
+          var isBuffer2 = nativeIsBuffer2 || stubFalse2;
+          var isDate = nodeIsDate ? baseUnary2(nodeIsDate) : baseIsDate;
           function isElement2(value) {
             return isObjectLike2(value) && value.nodeType === 1 && !isPlainObject(value);
           }
             if (value == null) {
               return true;
             }
-            if (isArrayLike(value) && (isArray2(value) || typeof value == "string" || typeof value.splice == "function" || isBuffer(value) || isTypedArray(value) || isArguments(value))) {
+            if (isArrayLike2(value) && (isArray2(value) || typeof value == "string" || typeof value.splice == "function" || isBuffer2(value) || isTypedArray2(value) || isArguments2(value))) {
               return !value.length;
             }
-            var tag = getTag(value);
-            if (tag == mapTag || tag == setTag) {
+            var tag = getTag2(value);
+            if (tag == mapTag4 || tag == setTag4) {
               return !value.size;
             }
-            if (isPrototype(value)) {
-              return !baseKeys(value).length;
+            if (isPrototype2(value)) {
+              return !baseKeys2(value).length;
             }
             for (var key in value) {
-              if (hasOwnProperty2.call(value, key)) {
+              if (hasOwnProperty10.call(value, key)) {
                 return false;
               }
             }
             return true;
           }
-          function isEqual(value, other) {
-            return baseIsEqual(value, other);
+          function isEqual4(value, other) {
+            return baseIsEqual2(value, other);
           }
           function isEqualWith(value, other, customizer) {
             customizer = typeof customizer == "function" ? customizer : undefined2;
             var result2 = customizer ? customizer(value, other) : undefined2;
-            return result2 === undefined2 ? baseIsEqual(value, other, undefined2, customizer) : !!result2;
+            return result2 === undefined2 ? baseIsEqual2(value, other, undefined2, customizer) : !!result2;
           }
           function isError(value) {
             if (!isObjectLike2(value)) {
               return false;
             }
             var tag = baseGetTag2(value);
-            return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value);
+            return tag == errorTag3 || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value);
           }
           function isFinite2(value) {
             return typeof value == "number" && nativeIsFinite(value);
           }
-          function isFunction(value) {
+          function isFunction2(value) {
             if (!isObject3(value)) {
               return false;
             }
             var tag = baseGetTag2(value);
-            return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
+            return tag == funcTag3 || tag == genTag2 || tag == asyncTag2 || tag == proxyTag2;
           }
           function isInteger(value) {
             return typeof value == "number" && value == toInteger(value);
           }
-          function isLength(value) {
-            return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+          function isLength2(value) {
+            return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER3;
           }
           function isObject3(value) {
-            var type3 = typeof value;
-            return value != null && (type3 == "object" || type3 == "function");
+            var type2 = typeof value;
+            return value != null && (type2 == "object" || type2 == "function");
           }
           function isObjectLike2(value) {
             return value != null && typeof value == "object";
           }
-          var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
+          var isMap = nodeIsMap ? baseUnary2(nodeIsMap) : baseIsMap;
           function isMatch(object, source) {
             return object === source || baseIsMatch(object, source, getMatchData(source));
           }
             if (isMaskable(value)) {
               throw new Error2(CORE_ERROR_TEXT);
             }
-            return baseIsNative(value);
+            return baseIsNative2(value);
           }
           function isNull(value) {
             return value === null;
             return value == null;
           }
           function isNumber2(value) {
-            return typeof value == "number" || isObjectLike2(value) && baseGetTag2(value) == numberTag;
+            return typeof value == "number" || isObjectLike2(value) && baseGetTag2(value) == numberTag3;
           }
           function isPlainObject(value) {
-            if (!isObjectLike2(value) || baseGetTag2(value) != objectTag) {
+            if (!isObjectLike2(value) || baseGetTag2(value) != objectTag4) {
               return false;
             }
             var proto = getPrototype(value);
             if (proto === null) {
               return true;
             }
-            var Ctor = hasOwnProperty2.call(proto, "constructor") && proto.constructor;
-            return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
+            var Ctor = hasOwnProperty10.call(proto, "constructor") && proto.constructor;
+            return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString3.call(Ctor) == objectCtorString;
           }
-          var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
+          var isRegExp = nodeIsRegExp ? baseUnary2(nodeIsRegExp) : baseIsRegExp;
           function isSafeInteger(value) {
-            return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
+            return isInteger(value) && value >= -MAX_SAFE_INTEGER3 && value <= MAX_SAFE_INTEGER3;
           }
-          var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
+          var isSet = nodeIsSet ? baseUnary2(nodeIsSet) : baseIsSet;
           function isString(value) {
-            return typeof value == "string" || !isArray2(value) && isObjectLike2(value) && baseGetTag2(value) == stringTag;
+            return typeof value == "string" || !isArray2(value) && isObjectLike2(value) && baseGetTag2(value) == stringTag3;
           }
           function isSymbol2(value) {
-            return typeof value == "symbol" || isObjectLike2(value) && baseGetTag2(value) == symbolTag2;
+            return typeof value == "symbol" || isObjectLike2(value) && baseGetTag2(value) == symbolTag3;
           }
-          var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
+          var isTypedArray2 = nodeIsTypedArray2 ? baseUnary2(nodeIsTypedArray2) : baseIsTypedArray2;
           function isUndefined(value) {
             return value === undefined2;
           }
           function isWeakMap(value) {
-            return isObjectLike2(value) && getTag(value) == weakMapTag;
+            return isObjectLike2(value) && getTag2(value) == weakMapTag3;
           }
           function isWeakSet(value) {
             return isObjectLike2(value) && baseGetTag2(value) == weakSetTag;
             if (!value) {
               return [];
             }
-            if (isArrayLike(value)) {
+            if (isArrayLike2(value)) {
               return isString(value) ? stringToArray(value) : copyArray(value);
             }
             if (symIterator && value[symIterator]) {
               return iteratorToArray(value[symIterator]());
             }
-            var tag = getTag(value), func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values;
+            var tag = getTag2(value), func = tag == mapTag4 ? mapToArray2 : tag == setTag4 ? setToArray2 : values;
             return func(value);
           }
           function toFinite(value) {
             if (!value) {
               return value === 0 ? value : 0;
             }
-            value = toNumber2(value);
+            value = toNumber3(value);
             if (value === INFINITY2 || value === -INFINITY2) {
               var sign2 = value < 0 ? -1 : 1;
               return sign2 * MAX_INTEGER;
           function toLength(value) {
             return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
           }
-          function toNumber2(value) {
+          function toNumber3(value) {
             if (typeof value == "number") {
               return value;
             }
             return copyObject(value, keysIn(value));
           }
           function toSafeInteger(value) {
-            return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0;
+            return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER3, MAX_SAFE_INTEGER3) : value === 0 ? value : 0;
           }
           function toString2(value) {
             return value == null ? "" : baseToString2(value);
           }
           var assign = createAssigner(function(object, source) {
-            if (isPrototype(source) || isArrayLike(source)) {
-              copyObject(source, keys(source), object);
+            if (isPrototype2(source) || isArrayLike2(source)) {
+              copyObject(source, keys2(source), object);
               return;
             }
             for (var key in source) {
-              if (hasOwnProperty2.call(source, key)) {
+              if (hasOwnProperty10.call(source, key)) {
                 assignValue(object, key, source[key]);
               }
             }
             copyObject(source, keysIn(source), object, customizer);
           });
           var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
-            copyObject(source, keys(source), object, customizer);
+            copyObject(source, keys2(source), object, customizer);
           });
           var at = flatRest(baseAt);
           function create2(prototype, properties) {
               while (++propsIndex < propsLength) {
                 var key = props[propsIndex];
                 var value = object[key];
-                if (value === undefined2 || eq(value, objectProto3[key]) && !hasOwnProperty2.call(object, key)) {
+                if (value === undefined2 || eq2(value, objectProto13[key]) && !hasOwnProperty10.call(object, key)) {
                   object[key] = source[key];
                 }
               }
             return object && baseForOwnRight(object, getIteratee(iteratee2, 3));
           }
           function functions(object) {
-            return object == null ? [] : baseFunctions(object, keys(object));
+            return object == null ? [] : baseFunctions(object, keys2(object));
           }
           function functionsIn(object) {
             return object == null ? [] : baseFunctions(object, keysIn(object));
             if (value != null && typeof value.toString != "function") {
               value = nativeObjectToString3.call(value);
             }
-            if (hasOwnProperty2.call(result2, value)) {
+            if (hasOwnProperty10.call(result2, value)) {
               result2[value].push(key);
             } else {
               result2[value] = [key];
             }
           }, getIteratee);
           var invoke = baseRest(baseInvoke);
-          function keys(object) {
-            return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
+          function keys2(object) {
+            return isArrayLike2(object) ? arrayLikeKeys2(object) : baseKeys2(object);
           }
           function keysIn(object) {
-            return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
+            return isArrayLike2(object) ? arrayLikeKeys2(object, true) : baseKeysIn(object);
           }
           function mapKeys(object, iteratee2) {
             var result2 = {};
             });
             return result2;
           }
-          var merge3 = createAssigner(function(object, source, srcIndex) {
+          var merge2 = createAssigner(function(object, source, srcIndex) {
             baseMerge(object, source, srcIndex);
           });
           var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
                 index = length;
                 value = defaultValue;
               }
-              object = isFunction(value) ? value.call(object) : value;
+              object = isFunction2(value) ? value.call(object) : value;
             }
             return object;
           }
             customizer = typeof customizer == "function" ? customizer : undefined2;
             return object == null ? object : baseSet(object, path, value, customizer);
           }
-          var toPairs = createToPairs(keys);
+          var toPairs = createToPairs(keys2);
           var toPairsIn = createToPairs(keysIn);
           function transform2(object, iteratee2, accumulator) {
-            var isArr = isArray2(object), isArrLike = isArr || isBuffer(object) || isTypedArray(object);
+            var isArr = isArray2(object), isArrLike = isArr || isBuffer2(object) || isTypedArray2(object);
             iteratee2 = getIteratee(iteratee2, 4);
             if (accumulator == null) {
               var Ctor = object && object.constructor;
               if (isArrLike) {
                 accumulator = isArr ? new Ctor() : [];
               } else if (isObject3(object)) {
-                accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
+                accumulator = isFunction2(Ctor) ? baseCreate(getPrototype(object)) : {};
               } else {
                 accumulator = {};
               }
             return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
           }
           function values(object) {
-            return object == null ? [] : baseValues(object, keys(object));
+            return object == null ? [] : baseValues(object, keys2(object));
           }
           function valuesIn(object) {
             return object == null ? [] : baseValues(object, keysIn(object));
               lower2 = undefined2;
             }
             if (upper !== undefined2) {
-              upper = toNumber2(upper);
+              upper = toNumber3(upper);
               upper = upper === upper ? upper : 0;
             }
             if (lower2 !== undefined2) {
-              lower2 = toNumber2(lower2);
+              lower2 = toNumber3(lower2);
               lower2 = lower2 === lower2 ? lower2 : 0;
             }
-            return baseClamp(toNumber2(number3), lower2, upper);
+            return baseClamp(toNumber3(number3), lower2, upper);
           }
           function inRange(number3, start2, end) {
             start2 = toFinite(start2);
             } else {
               end = toFinite(end);
             }
-            number3 = toNumber2(number3);
+            number3 = toNumber3(number3);
             return baseInRange(number3, start2, end);
           }
           function random(lower2, upper, floating) {
           }
           function escapeRegExp(string) {
             string = toString2(string);
-            return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, "\\$&") : string;
+            return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar2, "\\$&") : string;
           }
           var kebabCase = createCompounder(function(result2, word, index) {
             return result2 + (index ? "-" : "") + word.toLowerCase();
             }
             string = toString2(string);
             options2 = assignInWith({}, options2, settings, customDefaultsAssignIn);
-            var imports = assignInWith({}, options2.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys);
+            var imports = assignInWith({}, options2.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys2(imports), importsValues = baseValues(imports, importsKeys);
             var isEscaping, isEvaluating, index = 0, interpolate = options2.interpolate || reNoMatch, source = "__p += '";
             var reDelimiters = RegExp2(
               (options2.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options2.evaluate || reNoMatch).source + "|$",
               "g"
             );
-            var sourceURL = "//# sourceURL=" + (hasOwnProperty2.call(options2, "sourceURL") ? (options2.sourceURL + "").replace(/\s/g, " ") : "lodash.templateSources[" + ++templateCounter + "]") + "\n";
+            var sourceURL = "//# sourceURL=" + (hasOwnProperty10.call(options2, "sourceURL") ? (options2.sourceURL + "").replace(/\s/g, " ") : "lodash.templateSources[" + ++templateCounter + "]") + "\n";
             string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
               interpolateValue || (interpolateValue = esTemplateValue);
               source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
               return match;
             });
             source += "';\n";
-            var variable = hasOwnProperty2.call(options2, "variable") && options2.variable;
+            var variable = hasOwnProperty10.call(options2, "variable") && options2.variable;
             if (!variable) {
               source = "with (obj) {\n" + source + "\n}\n";
             } else if (reForbiddenIdentifierChars.test(variable)) {
             };
           });
           function mixin(object, source, options2) {
-            var props = keys(source), methodNames = baseFunctions(source, props);
+            var props = keys2(source), methodNames = baseFunctions(source, props);
             if (options2 == null && !(isObject3(source) && (methodNames.length || !props.length))) {
               options2 = source;
               source = object;
               object = this;
-              methodNames = baseFunctions(source, keys(source));
+              methodNames = baseFunctions(source, keys2(source));
             }
-            var chain2 = !(isObject3(options2) && "chain" in options2) || !!options2.chain, isFunc = isFunction(object);
+            var chain2 = !(isObject3(options2) && "chain" in options2) || !!options2.chain, isFunc = isFunction2(object);
             arrayEach(methodNames, function(methodName) {
               var func = source[methodName];
               object[methodName] = func;
                     result2.__chain__ = chainAll;
                     return result2;
                   }
-                  return func.apply(object, arrayPush([this.value()], arguments));
+                  return func.apply(object, arrayPush2([this.value()], arguments));
                 };
               }
             });
           }
           var over = createOver(arrayMap2);
           var overEvery = createOver(arrayEvery);
-          var overSome = createOver(arraySome);
+          var overSome = createOver(arraySome2);
           function property(path) {
             return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
           }
           }
           var range3 = createRange();
           var rangeRight = createRange(true);
-          function stubArray() {
+          function stubArray2() {
             return [];
           }
-          function stubFalse() {
+          function stubFalse2() {
             return false;
           }
           function stubObject() {
           }
           function times(n2, iteratee2) {
             n2 = toInteger(n2);
-            if (n2 < 1 || n2 > MAX_SAFE_INTEGER) {
+            if (n2 < 1 || n2 > MAX_SAFE_INTEGER3) {
               return [];
             }
             var index = MAX_ARRAY_LENGTH, length = nativeMin2(n2, MAX_ARRAY_LENGTH);
             iteratee2 = getIteratee(iteratee2);
             n2 -= MAX_ARRAY_LENGTH;
-            var result2 = baseTimes(length, iteratee2);
+            var result2 = baseTimes2(length, iteratee2);
             while (++index < n2) {
               iteratee2(index);
             }
           lodash.invokeMap = invokeMap;
           lodash.iteratee = iteratee;
           lodash.keyBy = keyBy;
-          lodash.keys = keys;
+          lodash.keys = keys2;
           lodash.keysIn = keysIn;
           lodash.map = map2;
           lodash.mapKeys = mapKeys;
           lodash.matches = matches;
           lodash.matchesProperty = matchesProperty;
           lodash.memoize = memoize;
-          lodash.merge = merge3;
+          lodash.merge = merge2;
           lodash.mergeWith = mergeWith;
           lodash.method = method;
           lodash.methodOf = methodOf;
           lodash.defaultTo = defaultTo;
           lodash.divide = divide;
           lodash.endsWith = endsWith;
-          lodash.eq = eq;
+          lodash.eq = eq2;
           lodash.escape = escape6;
           lodash.escapeRegExp = escapeRegExp;
           lodash.every = every;
           lodash.indexOf = indexOf;
           lodash.inRange = inRange;
           lodash.invoke = invoke;
-          lodash.isArguments = isArguments;
+          lodash.isArguments = isArguments2;
           lodash.isArray = isArray2;
           lodash.isArrayBuffer = isArrayBuffer;
-          lodash.isArrayLike = isArrayLike;
+          lodash.isArrayLike = isArrayLike2;
           lodash.isArrayLikeObject = isArrayLikeObject;
           lodash.isBoolean = isBoolean;
-          lodash.isBuffer = isBuffer;
+          lodash.isBuffer = isBuffer2;
           lodash.isDate = isDate;
           lodash.isElement = isElement2;
           lodash.isEmpty = isEmpty;
-          lodash.isEqual = isEqual;
+          lodash.isEqual = isEqual4;
           lodash.isEqualWith = isEqualWith;
           lodash.isError = isError;
           lodash.isFinite = isFinite2;
-          lodash.isFunction = isFunction;
+          lodash.isFunction = isFunction2;
           lodash.isInteger = isInteger;
-          lodash.isLength = isLength;
+          lodash.isLength = isLength2;
           lodash.isMap = isMap;
           lodash.isMatch = isMatch;
           lodash.isMatchWith = isMatchWith;
           lodash.isSet = isSet;
           lodash.isString = isString;
           lodash.isSymbol = isSymbol2;
-          lodash.isTypedArray = isTypedArray;
+          lodash.isTypedArray = isTypedArray2;
           lodash.isUndefined = isUndefined;
           lodash.isWeakMap = isWeakMap;
           lodash.isWeakSet = isWeakSet;
           lodash.meanBy = meanBy;
           lodash.min = min3;
           lodash.minBy = minBy;
-          lodash.stubArray = stubArray;
-          lodash.stubFalse = stubFalse;
+          lodash.stubArray = stubArray2;
+          lodash.stubFalse = stubFalse2;
           lodash.stubObject = stubObject;
           lodash.stubString = stubString;
           lodash.stubTrue = stubTrue;
           lodash.toInteger = toInteger;
           lodash.toLength = toLength;
           lodash.toLower = toLower;
-          lodash.toNumber = toNumber2;
+          lodash.toNumber = toNumber3;
           lodash.toSafeInteger = toSafeInteger;
           lodash.toString = toString2;
           lodash.toUpper = toUpper;
           mixin(lodash, function() {
             var source = {};
             baseForOwn(lodash, function(func, methodName) {
-              if (!hasOwnProperty2.call(lodash.prototype, methodName)) {
+              if (!hasOwnProperty10.call(lodash.prototype, methodName)) {
                 source[methodName] = func;
               }
             });
             };
           });
           arrayEach(["filter", "map", "takeWhile"], function(methodName, index) {
-            var type3 = index + 1, isFilter = type3 == LAZY_FILTER_FLAG || type3 == LAZY_WHILE_FLAG;
+            var type2 = index + 1, isFilter = type2 == LAZY_FILTER_FLAG || type2 == LAZY_WHILE_FLAG;
             LazyWrapper.prototype[methodName] = function(iteratee2) {
               var result2 = this.clone();
               result2.__iteratees__.push({
                 "iteratee": getIteratee(iteratee2, 3),
-                "type": type3
+                "type": type2
               });
               result2.__filtered__ = result2.__filtered__ || isFilter;
               return result2;
             lodash.prototype[methodName] = function() {
               var value = this.__wrapped__, args = isTaker ? [1] : arguments, isLazy = value instanceof LazyWrapper, iteratee2 = args[0], useLazy = isLazy || isArray2(value);
               var interceptor = function(value2) {
-                var result3 = lodashFunc.apply(lodash, arrayPush([value2], args));
+                var result3 = lodashFunc.apply(lodash, arrayPush2([value2], args));
                 return isTaker && chainAll ? result3[0] : result3;
               };
               if (useLazy && checkIteratee && typeof iteratee2 == "function" && iteratee2.length != 1) {
             };
           });
           arrayEach(["pop", "push", "shift", "sort", "splice", "unshift"], function(methodName) {
-            var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName);
+            var func = arrayProto2[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName);
             lodash.prototype[methodName] = function() {
               var args = arguments;
               if (retUnwrapped && !this.__chain__) {
             var lodashFunc = lodash[methodName];
             if (lodashFunc) {
               var key = lodashFunc.name + "";
-              if (!hasOwnProperty2.call(realNames, key)) {
+              if (!hasOwnProperty10.call(realNames, key)) {
                 realNames[key] = [];
               }
               realNames[key].push({ "name": methodName, "func": lodashFunc });
           define(function() {
             return _;
           });
-        } else if (freeModule) {
-          (freeModule.exports = _)._ = _;
-          freeExports._ = _;
+        } else if (freeModule3) {
+          (freeModule3.exports = _)._ = _;
+          freeExports3._ = _;
         } else {
           root3._ = _;
         }
     }
   });
 
+  // node_modules/fast-deep-equal/index.js
+  var require_fast_deep_equal = __commonJS({
+    "node_modules/fast-deep-equal/index.js"(exports2, module2) {
+      "use strict";
+      module2.exports = function equal(a, b) {
+        if (a === b)
+          return true;
+        if (a && b && typeof a == "object" && typeof b == "object") {
+          if (a.constructor !== b.constructor)
+            return false;
+          var length, i2, keys2;
+          if (Array.isArray(a)) {
+            length = a.length;
+            if (length != b.length)
+              return false;
+            for (i2 = length; i2-- !== 0; )
+              if (!equal(a[i2], b[i2]))
+                return false;
+            return true;
+          }
+          if (a.constructor === RegExp)
+            return a.source === b.source && a.flags === b.flags;
+          if (a.valueOf !== Object.prototype.valueOf)
+            return a.valueOf() === b.valueOf();
+          if (a.toString !== Object.prototype.toString)
+            return a.toString() === b.toString();
+          keys2 = Object.keys(a);
+          length = keys2.length;
+          if (length !== Object.keys(b).length)
+            return false;
+          for (i2 = length; i2-- !== 0; )
+            if (!Object.prototype.hasOwnProperty.call(b, keys2[i2]))
+              return false;
+          for (i2 = length; i2-- !== 0; ) {
+            var key = keys2[i2];
+            if (!equal(a[key], b[key]))
+              return false;
+          }
+          return true;
+        }
+        return a !== a && b !== b;
+      };
+    }
+  });
+
   // node_modules/rbush/rbush.min.js
   var require_rbush_min = __commonJS({
     "node_modules/rbush/rbush.min.js"(exports2, module2) {
         destroy: function() {
           this.buf = null;
         },
+        // === READING =================================================================
         readFields: function(readField, result, end) {
           end = end || this.length;
           while (this.pos < end) {
           this.pos += 4;
           return val;
         },
+        // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
         readFixed64: function() {
           var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
           this.pos += 8;
           this.pos = end;
           return buffer;
         },
+        // verbose for performance reasons; doesn't affect gzipped size
         readPackedVarint: function(arr, isSigned) {
           if (this.type !== Pbf.Bytes)
             return arr.push(this.readVarint(isSigned));
           return arr;
         },
         skip: function(val) {
-          var type3 = val & 7;
-          if (type3 === Pbf.Varint)
+          var type2 = val & 7;
+          if (type2 === Pbf.Varint)
             while (this.buf[this.pos++] > 127) {
             }
-          else if (type3 === Pbf.Bytes)
+          else if (type2 === Pbf.Bytes)
             this.pos = this.readVarint() + this.pos;
-          else if (type3 === Pbf.Fixed32)
+          else if (type2 === Pbf.Fixed32)
             this.pos += 4;
-          else if (type3 === Pbf.Fixed64)
+          else if (type2 === Pbf.Fixed64)
             this.pos += 8;
           else
-            throw new Error("Unimplemented type: " + type3);
+            throw new Error("Unimplemented type: " + type2);
         },
-        writeTag: function(tag, type3) {
-          this.writeVarint(tag << 3 | type3);
+        // === WRITING =================================================================
+        writeTag: function(tag, type2) {
+          this.writeVarint(tag << 3 | type2);
         },
         realloc: function(min3) {
           var length = this.length || 16;
         this.y = y;
       }
       Point.prototype = {
+        /**
+         * Clone this point, returning a new point that can be modified
+         * without affecting the old one.
+         * @return {Point} the clone
+         */
         clone: function() {
           return new Point(this.x, this.y);
         },
+        /**
+         * Add this point's x & y coordinates to another point,
+         * yielding a new point.
+         * @param {Point} p the other point
+         * @return {Point} output point
+         */
         add: function(p) {
           return this.clone()._add(p);
         },
+        /**
+         * Subtract this point's x & y coordinates to from point,
+         * yielding a new point.
+         * @param {Point} p the other point
+         * @return {Point} output point
+         */
         sub: function(p) {
           return this.clone()._sub(p);
         },
+        /**
+         * Multiply this point's x & y coordinates by point,
+         * yielding a new point.
+         * @param {Point} p the other point
+         * @return {Point} output point
+         */
         multByPoint: function(p) {
           return this.clone()._multByPoint(p);
         },
+        /**
+         * Divide this point's x & y coordinates by point,
+         * yielding a new point.
+         * @param {Point} p the other point
+         * @return {Point} output point
+         */
         divByPoint: function(p) {
           return this.clone()._divByPoint(p);
         },
+        /**
+         * Multiply this point's x & y coordinates by a factor,
+         * yielding a new point.
+         * @param {Point} k factor
+         * @return {Point} output point
+         */
         mult: function(k) {
           return this.clone()._mult(k);
         },
+        /**
+         * Divide this point's x & y coordinates by a factor,
+         * yielding a new point.
+         * @param {Point} k factor
+         * @return {Point} output point
+         */
         div: function(k) {
           return this.clone()._div(k);
         },
+        /**
+         * Rotate this point around the 0, 0 origin by an angle a,
+         * given in radians
+         * @param {Number} a angle to rotate around, in radians
+         * @return {Point} output point
+         */
         rotate: function(a) {
           return this.clone()._rotate(a);
         },
+        /**
+         * Rotate this point around p point by an angle a,
+         * given in radians
+         * @param {Number} a angle to rotate around, in radians
+         * @param {Point} p Point to rotate around
+         * @return {Point} output point
+         */
         rotateAround: function(a, p) {
           return this.clone()._rotateAround(a, p);
         },
+        /**
+         * Multiply this point by a 4x1 transformation matrix
+         * @param {Array<Number>} m transformation matrix
+         * @return {Point} output point
+         */
         matMult: function(m) {
           return this.clone()._matMult(m);
         },
+        /**
+         * Calculate this point but as a unit vector from 0, 0, meaning
+         * that the distance from the resulting point to the 0, 0
+         * coordinate will be equal to 1 and the angle from the resulting
+         * point to the 0, 0 coordinate will be the same as before.
+         * @return {Point} unit vector point
+         */
         unit: function() {
           return this.clone()._unit();
         },
+        /**
+         * Compute a perpendicular point, where the new y coordinate
+         * is the old x coordinate and the new x coordinate is the old y
+         * coordinate multiplied by -1
+         * @return {Point} perpendicular point
+         */
         perp: function() {
           return this.clone()._perp();
         },
+        /**
+         * Return a version of this point with the x & y coordinates
+         * rounded to integers.
+         * @return {Point} rounded point
+         */
         round: function() {
           return this.clone()._round();
         },
+        /**
+         * Return the magitude of this point: this is the Euclidean
+         * distance from the 0, 0 coordinate to this point's x and y
+         * coordinates.
+         * @return {Number} magnitude
+         */
         mag: function() {
           return Math.sqrt(this.x * this.x + this.y * this.y);
         },
+        /**
+         * Judge whether this point is equal to another point, returning
+         * true or false.
+         * @param {Point} other the other point
+         * @return {boolean} whether the points are equal
+         */
         equals: function(other) {
           return this.x === other.x && this.y === other.y;
         },
+        /**
+         * Calculate the distance from this point to another point
+         * @param {Point} p the other point
+         * @return {Number} distance
+         */
         dist: function(p) {
           return Math.sqrt(this.distSqr(p));
         },
+        /**
+         * Calculate the distance from this point to another point,
+         * without the square root step. Useful if you're comparing
+         * relative distances.
+         * @param {Point} p the other point
+         * @return {Number} distance
+         */
         distSqr: function(p) {
           var dx = p.x - this.x, dy = p.y - this.y;
           return dx * dx + dy * dy;
         },
+        /**
+         * Get the angle from the 0, 0 coordinate to this point, in radians
+         * coordinates.
+         * @return {Number} angle
+         */
         angle: function() {
           return Math.atan2(this.y, this.x);
         },
+        /**
+         * Get the angle from this point to another point, in radians
+         * @param {Point} b the other point
+         * @return {Number} angle
+         */
         angleTo: function(b) {
           return Math.atan2(this.y - b.y, this.x - b.x);
         },
+        /**
+         * Get the angle between this point and another point, in radians
+         * @param {Point} b the other point
+         * @return {Number} angle
+         */
         angleWith: function(b) {
           return this.angleWithSep(b.x, b.y);
         },
+        /*
+         * Find the angle of the two vectors, solving the formula for
+         * the cross product a x b = |a||b|sin(θ) for θ.
+         * @param {Number} x the x-coordinate
+         * @param {Number} y the y-coordinate
+         * @return {Number} the angle in radians
+         */
         angleWithSep: function(x, y) {
           return Math.atan2(
             this.x * y - this.y * x,
       "use strict";
       var Point = require_point_geometry();
       module2.exports = VectorTileFeature;
-      function VectorTileFeature(pbf, end, extent, keys, values) {
+      function VectorTileFeature(pbf, end, extent, keys2, values) {
         this.properties = {};
         this.extent = extent;
         this.type = 0;
         this._pbf = pbf;
         this._geometry = -1;
-        this._keys = keys;
+        this._keys = keys2;
         this._values = values;
         pbf.readFields(readFeature, this, end);
       }
         return [x12, y12, x2, y2];
       };
       VectorTileFeature.prototype.toGeoJSON = function(x, y, z) {
-        var size = this.extent * Math.pow(2, z), x05 = this.extent * x, y05 = this.extent * y, coords = this.loadGeometry(), type3 = VectorTileFeature.types[this.type], i2, j2;
+        var size = this.extent * Math.pow(2, z), x05 = this.extent * x, y05 = this.extent * y, coords = this.loadGeometry(), type2 = VectorTileFeature.types[this.type], i2, j2;
         function project(line) {
           for (var j3 = 0; j3 < line.length; j3++) {
             var p = line[j3], y2 = 180 - (p.y + y05) * 360 / size;
         if (coords.length === 1) {
           coords = coords[0];
         } else {
-          type3 = "Multi" + type3;
+          type2 = "Multi" + type2;
         }
         var result = {
           type: "Feature",
           geometry: {
-            type: type3,
+            type: type2,
             coordinates: coords
           },
           properties: this.properties
             throw new TypeError("Converting circular structure to JSON");
           }
           var seenIndex = seen.push(node) - 1;
-          var keys = Object.keys(node).sort(cmp && cmp(node));
+          var keys2 = Object.keys(node).sort(cmp && cmp(node));
           out = "";
-          for (i2 = 0; i2 < keys.length; i2++) {
-            var key = keys[i2];
+          for (i2 = 0; i2 < keys2.length; i2++) {
+            var key = keys2[i2];
             var value = stringify3(node[key]);
             if (!value)
               continue;
         map: map2,
         pluck,
         isList,
-        isFunction,
+        isFunction: isFunction2,
         isObject: isObject3,
         Global
       };
       function isList(val) {
         return val != null && typeof val != "function" && typeof val.length == "number";
       }
-      function isFunction(val) {
+      function isFunction2(val) {
         return val && {}.toString.call(val) === "[object Function]";
       }
       function isObject3(val) {
       var bind = util.bind;
       var create2 = util.create;
       var isList = util.isList;
-      var isFunction = util.isFunction;
+      var isFunction2 = util.isFunction;
       var isObject3 = util.isObject;
       module2.exports = {
         createStore
       var storeAPI = {
         version: "2.0.12",
         enabled: false,
+        // get returns the value of the given key. If that value
+        // is undefined, it returns optionalDefaultValue instead.
         get: function(key, optionalDefaultValue) {
           var data = this.storage.read(this._namespacePrefix + key);
           return this._deserialize(data, optionalDefaultValue);
         },
+        // set will store the given value at key and returns value.
+        // Calling set with value === undefined is equivalent to calling remove.
         set: function(key, value) {
           if (value === void 0) {
             return this.remove(key);
           this.storage.write(this._namespacePrefix + key, this._serialize(value));
           return value;
         },
+        // remove deletes the key and value stored at the given key.
         remove: function(key) {
           this.storage.remove(this._namespacePrefix + key);
         },
+        // each will call the given callback once for each key-value pair
+        // in this store.
         each: function(callback) {
           var self2 = this;
           this.storage.each(function(val, namespacedKey) {
             callback.call(self2, self2._deserialize(val), (namespacedKey || "").replace(self2._namespaceRegexp, ""));
           });
         },
+        // clearAll will remove all the stored key-value pairs in this store.
         clearAll: function() {
           this.storage.clearAll();
         },
+        // additional functionality that can't live in plugins
+        // ---------------------------------------------------
+        // hasNamespace returns true if this store instance has the given namespace.
         hasNamespace: function(namespace) {
           return this._namespacePrefix == "__storejs_" + namespace + "_";
         },
+        // createStore creates a store.js instance with the first
+        // functioning storage in the list of storage candidates,
+        // and applies the the given mixins to the instance.
         createStore: function() {
           return createStore.apply(this, arguments);
         },
               return;
             }
             this.plugins.push(plugin);
-            if (!isFunction(plugin)) {
+            if (!isFunction2(plugin)) {
               throw new Error("Plugins must be function values that return objects");
             }
             var pluginProperties = plugin.call(this);
               throw new Error("Plugins must return an object of function properties");
             }
             each(pluginProperties, function(pluginFnProp, propName) {
-              if (!isFunction(pluginFnProp)) {
+              if (!isFunction2(pluginFnProp)) {
                 throw new Error("Bad plugin property: " + propName + " from plugin " + plugin.name + ". Plugins should only return functions.");
               }
               self2._assignPluginFnProp(pluginFnProp, propName);
             });
           },
+          // Put deprecated properties in the private API, so as to not expose it to accidential
+          // discovery through inspection of the store object.
+          // Deprecated: addStorage
           addStorage: function(storage) {
             _warn("store.addStorage(storage) is deprecated. Use createStore([storages])");
             this._addStorage(storage);
         });
         store2.raw = {};
         each(store2, function(prop, propName) {
-          if (isFunction(prop)) {
+          if (isFunction2(prop)) {
             store2.raw[propName] = bind(store2, prop);
           }
         });
   var require_all = __commonJS({
     "node_modules/store/storages/all.js"(exports2, module2) {
       module2.exports = [
+        // Listed in order of usage preference
         require_localStorage(),
         require_oldFF_globalStorage(),
         require_oldIE_userDataStorage(),
         }
         if (typeof JSON.stringify !== "function") {
           meta = {
+            // table of character substitutions
             "\b": "\\b",
             "  ": "\\t",
             "\n": "\\n",
       if (options2.cache === "no-store" || options2.cache === "no-cache") {
         var reParamSearch = /([?&])_=[^&]*/;
         if (reParamSearch.test(this.url)) {
-          this.url = this.url.replace(reParamSearch, "$1_=" + new Date().getTime());
+          this.url = this.url.replace(reParamSearch, "$1_=" + (/* @__PURE__ */ new Date()).getTime());
         } else {
           var reQueryString = /\?/;
-          this.url += (reQueryString.test(this.url) ? "&" : "?") + "_=" + new Date().getTime();
+          this.url += (reQueryString.test(this.url) ? "&" : "?") + "_=" + (/* @__PURE__ */ new Date()).getTime();
         }
       }
     }
         _defineProperties(Constructor.prototype, protoProps);
       if (staticProps)
         _defineProperties(Constructor, staticProps);
+      Object.defineProperty(Constructor, "prototype", {
+        writable: false
+      });
       return Constructor;
     }
     function _inherits(subClass, superClass) {
           configurable: true
         }
       });
+      Object.defineProperty(subClass, "prototype", {
+        writable: false
+      });
       if (superClass)
         _setPrototypeOf(subClass, superClass);
     }
     function _getPrototypeOf(o) {
-      _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf2(o2) {
+      _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf2(o2) {
         return o2.__proto__ || Object.getPrototypeOf(o2);
       };
       return _getPrototypeOf(o);
     }
     function _setPrototypeOf(o, p) {
-      _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf2(o2, p2) {
+      _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf2(o2, p2) {
         o2.__proto__ = p2;
         return o2;
       };
     function _possibleConstructorReturn(self2, call) {
       if (call && (typeof call === "object" || typeof call === "function")) {
         return call;
+      } else if (call !== void 0) {
+        throw new TypeError("Derived constructors may only return object or undefined");
       }
       return _assertThisInitialized(self2);
     }
       }
       return object;
     }
-    function _get(target, property, receiver) {
+    function _get() {
       if (typeof Reflect !== "undefined" && Reflect.get) {
-        _get = Reflect.get;
+        _get = Reflect.get.bind();
       } else {
-        _get = function _get2(target2, property2, receiver2) {
-          var base = _superPropBase(target2, property2);
+        _get = function _get2(target, property, receiver) {
+          var base = _superPropBase(target, property);
           if (!base)
             return;
-          var desc = Object.getOwnPropertyDescriptor(base, property2);
+          var desc = Object.getOwnPropertyDescriptor(base, property);
           if (desc.get) {
-            return desc.get.call(receiver2);
+            return desc.get.call(arguments.length < 3 ? target : receiver);
           }
           return desc.value;
         };
       }
-      return _get(target, property, receiver || target);
+      return _get.apply(this, arguments);
     }
     var Emitter = /* @__PURE__ */ function() {
       function Emitter2() {
       }
       _createClass(Emitter2, [{
         key: "addEventListener",
-        value: function addEventListener(type3, callback, options2) {
-          if (!(type3 in this.listeners)) {
-            this.listeners[type3] = [];
+        value: function addEventListener(type2, callback, options2) {
+          if (!(type2 in this.listeners)) {
+            this.listeners[type2] = [];
           }
-          this.listeners[type3].push({
+          this.listeners[type2].push({
             callback,
             options: options2
           });
         }
       }, {
         key: "removeEventListener",
-        value: function removeEventListener(type3, callback) {
-          if (!(type3 in this.listeners)) {
+        value: function removeEventListener(type2, callback) {
+          if (!(type2 in this.listeners)) {
             return;
           }
-          var stack = this.listeners[type3];
+          var stack = this.listeners[type2];
           for (var i2 = 0, l = stack.length; i2 < l; i2++) {
             if (stack[i2].callback === callback) {
               stack.splice(i2, 1);
           writable: true,
           configurable: true
         });
+        Object.defineProperty(_assertThisInitialized(_this), "reason", {
+          value: void 0,
+          writable: true,
+          configurable: true
+        });
         return _this;
       }
       _createClass(AbortSignal2, [{
       }
       _createClass(AbortController3, [{
         key: "abort",
-        value: function abort() {
+        value: function abort(reason) {
           var event;
           try {
             event = new Event("abort");
               };
             }
           }
+          var signalReason = reason;
+          if (signalReason === void 0) {
+            if (typeof document === "undefined") {
+              signalReason = new Error("This operation was aborted");
+              signalReason.name = "AbortError";
+            } else {
+              try {
+                signalReason = new DOMException("signal is aborted without reason");
+              } catch (err) {
+                signalReason = new Error("This operation was aborted");
+                signalReason.name = "AbortError";
+              }
+            }
+          }
+          this.signal.reason = signalReason;
           this.signal.dispatchEvent(event);
         }
       }, {
     geoVecSubtract: () => geoVecSubtract,
     geoViewportEdge: () => geoViewportEdge,
     geoZoomToScale: () => geoZoomToScale,
+    likelyRawNumberFormat: () => likelyRawNumberFormat,
     localizer: () => _mainLocalizer,
     locationManager: () => _sharedLocationManager,
     modeAddArea: () => modeAddArea,
     uiFieldCheck: () => uiFieldCheck,
     uiFieldColour: () => uiFieldText,
     uiFieldCombo: () => uiFieldCombo,
-    uiFieldCycleway: () => uiFieldCycleway,
     uiFieldDefaultCheck: () => uiFieldCheck,
+    uiFieldDirectionalCombo: () => uiFieldDirectionalCombo,
     uiFieldEmail: () => uiFieldText,
     uiFieldHelp: () => uiFieldHelp,
     uiFieldIdentifier: () => uiFieldText,
     uiKeepRightEditor: () => uiKeepRightEditor,
     uiKeepRightHeader: () => uiKeepRightHeader,
     uiLasso: () => uiLasso,
+    uiLengthIndicator: () => uiLengthIndicator,
     uiLoading: () => uiLoading,
     uiMapInMap: () => uiMapInMap,
     uiModal: () => uiModal,
     utilArrayUniq: () => utilArrayUniq,
     utilArrayUniqBy: () => utilArrayUniqBy,
     utilAsyncMap: () => utilAsyncMap,
+    utilCleanOsmString: () => utilCleanOsmString,
     utilCleanTags: () => utilCleanTags,
     utilCombinedTags: () => utilCombinedTags,
     utilCompareIDs: () => utilCompareIDs,
       } else if (options2 && options2.reverseOneway && key === "oneway") {
         return onewayReplacements[value] || value;
       } else if (includeAbsolute && directionKey.test(key)) {
-        if (compassReplacements[value])
-          return compassReplacements[value];
-        var degrees3 = parseFloat(value);
-        if (typeof degrees3 === "number" && !isNaN(degrees3)) {
-          if (degrees3 < 180) {
-            degrees3 += 180;
+        return value.split(";").map((value2) => {
+          if (compassReplacements[value2])
+            return compassReplacements[value2];
+          var degrees3 = Number(value2);
+          if (isFinite(degrees3)) {
+            if (degrees3 < 180) {
+              degrees3 += 180;
+            } else {
+              degrees3 -= 180;
+            }
+            return degrees3.toString();
           } else {
-            degrees3 -= 180;
+            return valueReplacements[value2] || value2;
           }
-          return degrees3.toString();
-        }
+        }).join(";");
       }
       return valueReplacements[value] || value;
     }
 
   // modules/osm/tags.js
   function osmIsInterestingTag(key) {
-    return key !== "attribution" && key !== "created_by" && key !== "source" && key !== "odbl" && key.indexOf("source:") !== 0 && key.indexOf("source_ref") !== 0 && key.indexOf("tiger:") !== 0;
+    return key !== "attribution" && key !== "created_by" && key !== "source" && key !== "odbl" && key.indexOf("source:") !== 0 && key.indexOf("source_ref") !== 0 && // purposely exclude colon
+    key.indexOf("tiger:") !== 0;
   }
   var osmLifecyclePrefixes = {
+    // nonexistent, might be built
     proposed: true,
     planned: true,
+    // under maintentance or between groundbreaking and opening
     construction: true,
+    // existent but not functional
     disused: true,
+    // dilapidated to nonexistent
     abandoned: true,
     was: true,
+    // nonexistent, still may appear in imagery
     dismantled: true,
     razed: true,
     demolished: true,
     destroyed: true,
     removed: true,
     obliterated: true,
+    // existent occasionally, e.g. stormwater drainage basin
     intermittent: true
   };
   function osmRemoveLifecyclePrefix(key) {
       turntable: true,
       wash: true
     },
+    traffic_calming: {
+      island: true
+    },
     waterway: {
       dam: true
     }
     var returnTags = {};
     for (var realKey in tags) {
       const key = osmRemoveLifecyclePrefix(realKey);
-      if (key in osmAreaKeys && !(tags[key] in osmAreaKeys[key])) {
+      if (key in osmAreaKeys && !(tags[realKey] in osmAreaKeys[key])) {
         returnTags[realKey] = tags[realKey];
         return returnTags;
       }
-      if (key in osmAreaKeysExceptions && tags[key] in osmAreaKeysExceptions[key]) {
+      if (key in osmAreaKeysExceptions && tags[realKey] in osmAreaKeysExceptions[key]) {
         returnTags[realKey] = tags[realKey];
         return returnTags;
       }
       "yes": true
     },
     "seamark:type": {
+      "two-way_route": true,
+      "recommended_traffic_lane": true,
       "separation_lane": true,
       "separation_roundabout": true
     },
       "ditch": true,
       "drain": true,
       "fish_pass": true,
+      "pressurised": true,
       "river": true,
+      "spillway": true,
       "stream": true,
       "tidal_channel": true
     }
       "city_wall": true
     },
     "man_made": {
-      "embankment": true
+      "embankment": true,
+      "quay": true
     },
     "waterway": {
       "weir": true
     stream: true,
     tidal_channel: true
   };
+  var allowUpperCaseTagValues = /network|taxon|genus|species|brand|grape_variety|royal_cypher|listed_status|booth|rating|stars|:output|_hours|_times|_ref|manufacturer|country|target|brewery|cai_scale|traffic_sign/;
 
   // node_modules/d3-array/src/ascending.js
   function ascending(a, b) {
       streamGeometry(object.geometry, stream);
     },
     FeatureCollection: function(object, stream) {
-      var features2 = object.features, i2 = -1, n2 = features2.length;
+      var features = object.features, i2 = -1, n2 = features.length;
       while (++i2 < n2)
-        streamGeometry(features2[i2].geometry, stream);
+        streamGeometry(features[i2].geometry, stream);
     }
   };
   var streamGeometryType = {
             stream.lineEnd();
           point0 = null;
         },
+        // Rejoin first and last segments if there were intersections and the first
+        // and last points were visible.
         clean: function() {
           return clean2 | (v00 && v0) << 1;
         }
         copy2[t] = _[t].slice();
       return new Dispatch(copy2);
     },
-    call: function(type3, that) {
+    call: function(type2, that) {
       if ((n2 = arguments.length - 2) > 0)
         for (var args = new Array(n2), i2 = 0, n2, t; i2 < n2; ++i2)
           args[i2] = arguments[i2 + 2];
-      if (!this._.hasOwnProperty(type3))
-        throw new Error("unknown type: " + type3);
-      for (t = this._[type3], i2 = 0, n2 = t.length; i2 < n2; ++i2)
+      if (!this._.hasOwnProperty(type2))
+        throw new Error("unknown type: " + type2);
+      for (t = this._[type2], i2 = 0, n2 = t.length; i2 < n2; ++i2)
         t[i2].value.apply(that, args);
     },
-    apply: function(type3, that, args) {
-      if (!this._.hasOwnProperty(type3))
-        throw new Error("unknown type: " + type3);
-      for (var t = this._[type3], i2 = 0, n2 = t.length; i2 < n2; ++i2)
+    apply: function(type2, that, args) {
+      if (!this._.hasOwnProperty(type2))
+        throw new Error("unknown type: " + type2);
+      for (var t = this._[type2], i2 = 0, n2 = t.length; i2 < n2; ++i2)
         t[i2].value.apply(that, args);
     }
   };
-  function get(type3, name) {
-    for (var i2 = 0, n2 = type3.length, c; i2 < n2; ++i2) {
-      if ((c = type3[i2]).name === name) {
+  function get(type2, name) {
+    for (var i2 = 0, n2 = type2.length, c; i2 < n2; ++i2) {
+      if ((c = type2[i2]).name === name) {
         return c.value;
       }
     }
   }
-  function set(type3, name, callback) {
-    for (var i2 = 0, n2 = type3.length; i2 < n2; ++i2) {
-      if (type3[i2].name === name) {
-        type3[i2] = noop2, type3 = type3.slice(0, i2).concat(type3.slice(i2 + 1));
+  function set(type2, name, callback) {
+    for (var i2 = 0, n2 = type2.length; i2 < n2; ++i2) {
+      if (type2[i2].name === name) {
+        type2[i2] = noop2, type2 = type2.slice(0, i2).concat(type2.slice(i2 + 1));
         break;
       }
     }
     if (callback != null)
-      type3.push({ name, value: callback });
-    return type3;
+      type2.push({ name, value: callback });
+    return type2;
   }
   var dispatch_default = dispatch;
 
   function merge_default(context) {
     var selection2 = context.selection ? context.selection() : context;
     for (var groups0 = this._groups, groups1 = selection2._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j2 = 0; j2 < m; ++j2) {
-      for (var group0 = groups0[j2], group1 = groups1[j2], n2 = group0.length, merge3 = merges[j2] = new Array(n2), node, i2 = 0; i2 < n2; ++i2) {
+      for (var group0 = groups0[j2], group1 = groups1[j2], n2 = group0.length, merge2 = merges[j2] = new Array(n2), node, i2 = 0; i2 < n2; ++i2) {
         if (node = group0[i2] || group1[i2]) {
-          merge3[i2] = node;
+          merge2[i2] = node;
         }
       }
     }
   }
 
   // node_modules/d3-selection/src/selection/dispatch.js
-  function dispatchEvent(node, type3, params) {
+  function dispatchEvent(node, type2, params) {
     var window2 = window_default(node), event = window2.CustomEvent;
     if (typeof event === "function") {
-      event = new event(type3, params);
+      event = new event(type2, params);
     } else {
       event = window2.document.createEvent("Event");
       if (params)
-        event.initEvent(type3, params.bubbles, params.cancelable), event.detail = params.detail;
+        event.initEvent(type2, params.bubbles, params.cancelable), event.detail = params.detail;
       else
-        event.initEvent(type3, false, false);
+        event.initEvent(type2, false, false);
     }
     node.dispatchEvent(event);
   }
-  function dispatchConstant(type3, params) {
+  function dispatchConstant(type2, params) {
     return function() {
-      return dispatchEvent(this, type3, params);
+      return dispatchEvent(this, type2, params);
     };
   }
-  function dispatchFunction(type3, params) {
+  function dispatchFunction(type2, params) {
     return function() {
-      return dispatchEvent(this, type3, params.apply(this, arguments));
+      return dispatchEvent(this, type2, params.apply(this, arguments));
     };
   }
-  function dispatch_default2(type3, params) {
-    return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type3, params));
+  function dispatch_default2(type2, params) {
+    return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type2, params));
   }
 
   // node_modules/d3-selection/src/selection/iterator.js
   var constant_default2 = (x) => () => x;
 
   // node_modules/d3-drag/src/event.js
-  function DragEvent(type3, {
+  function DragEvent(type2, {
     sourceEvent,
     subject,
     target,
     dispatch: dispatch10
   }) {
     Object.defineProperties(this, {
-      type: { value: type3, enumerable: true, configurable: true },
+      type: { value: type2, enumerable: true, configurable: true },
       sourceEvent: { value: sourceEvent, enumerable: true, configurable: true },
       subject: { value: subject, enumerable: true, configurable: true },
       target: { value: target, enumerable: true, configurable: true },
         return;
       dx = s.x - p[0] || 0;
       dy = s.y - p[1] || 0;
-      return function gesture(type3, event2, touch2) {
+      return function gesture(type2, event2, touch2) {
         var p02 = p, n2;
-        switch (type3) {
+        switch (type2) {
           case "start":
             gestures[identifier] = gesture, n2 = active++;
             break;
             break;
         }
         dispatch10.call(
-          type3,
+          type2,
           that,
-          new DragEvent(type3, {
+          new DragEvent(type2, {
             sourceEvent: event2,
             subject: s,
             target: drag,
       return this.rgb().displayable();
     },
     hex: color_formatHex,
+    // Deprecated! Use color.formatHex.
     formatHex: color_formatHex,
     formatHex8: color_formatHex8,
     formatHsl: color_formatHsl,
       return -0.5 <= this.r && this.r < 255.5 && (-0.5 <= this.g && this.g < 255.5) && (-0.5 <= this.b && this.b < 255.5) && (0 <= this.opacity && this.opacity <= 1);
     },
     hex: rgb_formatHex,
+    // Deprecated! Use color.formatHex.
     formatHex: rgb_formatHex,
     formatHex8: rgb_formatHex8,
     formatRgb: rgb_formatRgb,
 
   // node_modules/d3-interpolate/src/date.js
   function date_default(a, b) {
-    var d = new Date();
+    var d = /* @__PURE__ */ new Date();
     return a = +a, b = +b, function(t) {
       return d.setTime(a * (1 - t) + b * t), d;
     };
     create(node, id2, {
       name,
       index,
+      // For context during callback.
       group,
+      // For context during callback.
       on: emptyOn,
       tween: emptyTween,
       time: timing.time,
     if (transition2._id !== this._id)
       throw new Error();
     for (var groups0 = this._groups, groups1 = transition2._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j2 = 0; j2 < m; ++j2) {
-      for (var group0 = groups0[j2], group1 = groups1[j2], n2 = group0.length, merge3 = merges[j2] = new Array(n2), node, i2 = 0; i2 < n2; ++i2) {
+      for (var group0 = groups0[j2], group1 = groups1[j2], n2 = group0.length, merge2 = merges[j2] = new Array(n2), node, i2 = 0; i2 < n2; ++i2) {
         if (node = group0[i2] || group1[i2]) {
-          merge3[i2] = node;
+          merge2[i2] = node;
         }
       }
     }
   // node_modules/d3-transition/src/selection/transition.js
   var defaultTiming = {
     time: null,
+    // Set on use.
     delay: 0,
     duration: 250,
     ease: cubicInOut
   var constant_default4 = (x) => () => x;
 
   // node_modules/d3-zoom/src/event.js
-  function ZoomEvent(type3, {
+  function ZoomEvent(type2, {
     sourceEvent,
     target,
     transform: transform2,
     dispatch: dispatch10
   }) {
     Object.defineProperties(this, {
-      type: { value: type3, enumerable: true, configurable: true },
+      type: { value: type2, enumerable: true, configurable: true },
       sourceEvent: { value: sourceEvent, enumerable: true, configurable: true },
       target: { value: target, enumerable: true, configurable: true },
       transform: { value: transform2, enumerable: true, configurable: true },
         }
         return this;
       },
-      emit: function(type3) {
+      emit: function(type2) {
         var d = select_default2(this.that).datum();
         listeners.call(
-          type3,
+          type2,
           this.that,
-          new ZoomEvent(type3, {
+          new ZoomEvent(type2, {
             sourceEvent: this.sourceEvent,
             target: zoom,
-            type: type3,
+            type: type2,
             transform: this.that.__zoom,
             dispatch: listeners
           }),
   var ociCdnUrl = "https://cdn.jsdelivr.net/npm/osm-community-index@{version}/";
   var wmfSitematrixCdnUrl = "https://cdn.jsdelivr.net/npm/wmf-sitematrix@{version}/";
   var nsiCdnUrl = "https://cdn.jsdelivr.net/npm/name-suggestion-index@{version}/";
-  var osmApiConnections = [
-    {
+  var defaultOsmApiConnections = {
+    live: {
       url: "https://www.openstreetmap.org",
       client_id: "0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc",
       client_secret: "BTlNrNxIPitHdL4sP2clHw5KLoee9aKkA7dQbc0Bj7Q"
     },
-    {
+    dev: {
       url: "https://api06.dev.openstreetmap.org",
       client_id: "Ee1wWJ6UlpERbF6BfTNOpwn0R8k_06mvMXdDUkeHMgw",
       client_secret: "OnfWFC-JkZNHyYdr_viNn_h_RTZXRslKcUxllOXqf5g"
     }
-  ];
+  };
+  var osmApiConnections = [];
+  if (false) {
+    osmApiConnections.push({
+      url: null,
+      client_id: null,
+      client_secret: null
+    });
+  } else if (false) {
+    osmApiConnections.push(defaultOsmApiConnections[null]);
+  } else {
+    osmApiConnections.push(defaultOsmApiConnections.live);
+    osmApiConnections.push(defaultOsmApiConnections.dev);
+  }
   var taginfoApiUrl = "https://taginfo.openstreetmap.org/api/4/";
   var nominatimApiUrl = "https://nominatim.openstreetmap.org/";
 
   // package.json
   var package_default = {
     name: "iD",
-    version: "2.23.2",
+    version: "2.26.2",
     description: "A friendly editor for OpenStreetMap",
     main: "dist/iD.min.js",
     repository: "github:openstreetmap/iD",
       build: "run-s build:css build:data build:js",
       "build:css": "node scripts/build_css.js",
       "build:data": "shx mkdir -p dist/data && node scripts/build_data.js",
-      "build:stats": "esbuild-visualizer --metadata dist/esbuild.json --exclude *.png --filename docs/statistics.html",
+      "build:stats": "node config/esbuild.config.mjs --stats && esbuild-visualizer --metadata dist/esbuild.json --exclude *.png --filename docs/statistics.html && shx rm dist/esbuild.json",
       "build:js": "node config/esbuild.config.mjs",
       "build:js:watch": "node config/esbuild.config.mjs --watch",
       clean: "shx rm -f dist/esbuild.json dist/*.js dist/*.map dist/*.css dist/img/*.svg",
       "dist:svg:maki": 'svg-sprite --symbol --symbol-dest . --shape-id-generator "maki-%s" --symbol-sprite dist/img/maki-sprite.svg node_modules/@mapbox/maki/icons/*.svg',
       "dist:svg:mapillary:signs": "svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/mapillary-sprite.svg node_modules/mapillary_sprite_source/package_signs/*.svg",
       "dist:svg:mapillary:objects": "svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/mapillary-object-sprite.svg node_modules/mapillary_sprite_source/package_objects/*.svg",
-      "dist:svg:temaki": 'svg-sprite --symbol --symbol-dest . --shape-id-generator "temaki-%s" --symbol-sprite dist/img/temaki-sprite.svg node_modules/@ideditor/temaki/icons/*.svg',
+      "dist:svg:roentgen": 'svg-sprite --shape-id-generator "roentgen-%s" --shape-dim-width 16 --shape-dim-height 16 --symbol --symbol-dest . --symbol-sprite dist/img/roentgen-sprite.svg svg/roentgen/*.svg',
+      "dist:svg:temaki": 'svg-sprite --symbol --symbol-dest . --shape-id-generator "temaki-%s" --symbol-sprite dist/img/temaki-sprite.svg node_modules/@rapideditor/temaki/icons/*.svg',
       imagery: "node scripts/update_imagery.js",
-      lint: "eslint scripts test/spec modules",
+      lint: "eslint config scripts test/spec modules --ext js,mjs",
       "lint:fix": "eslint scripts test/spec modules --fix",
-      start: "run-s build:js start:server",
+      start: "run-s start:watch",
+      "start:single-build": "run-p build:js start:server",
       "start:watch": "run-p build:js:watch start:server",
       "start:server": "node scripts/server.js",
       test: "npm-run-all -s lint build test:spec",
       translations: "node scripts/update_locales.js"
     },
     dependencies: {
-      "@ideditor/country-coder": "~5.0.3",
-      "@ideditor/location-conflation": "~1.0.2",
+      "@rapideditor/country-coder": "~5.2.0",
+      "@rapideditor/location-conflation": "~1.2.0",
       "@mapbox/geojson-area": "^0.2.2",
       "@mapbox/sexagesimal": "1.2.0",
       "@mapbox/vector-tile": "^1.3.1",
-      "@tmcw/togeojson": "^5.2.1",
+      "@tmcw/togeojson": "^5.6.2",
       "@turf/bbox": "^6.0.0",
       "@turf/bbox-clip": "^6.0.0",
-      "abortcontroller-polyfill": "^1.4.0",
+      "abortcontroller-polyfill": "^1.7.5",
       "aes-js": "^3.1.2",
       "alif-toolkit": "^1.2.9",
-      "core-js-bundle": "^3.19.0",
+      "core-js-bundle": "^3.31.1",
       diacritics: "1.3.0",
       "fast-deep-equal": "~3.1.1",
       "fast-json-stable-stringify": "2.1.0",
       "lodash-es": "~4.17.15",
-      marked: "~4.2.2",
+      marked: "~5.1.1",
       "node-diff3": "~3.1.0",
-      "osm-auth": "~2.0.0",
+      "osm-auth": "~2.1.0",
       pannellum: "2.5.6",
       pbf: "^3.2.1",
       "polygon-clipping": "~0.15.1",
       rbush: "3.0.1",
       "whatwg-fetch": "^3.4.1",
-      "which-polygon": "2.2.0"
+      "which-polygon": "2.2.1"
     },
     devDependencies: {
-      "@fortawesome/fontawesome-svg-core": "~6.2.0",
-      "@fortawesome/free-brands-svg-icons": "~6.2.0",
-      "@fortawesome/free-regular-svg-icons": "~6.2.0",
-      "@fortawesome/free-solid-svg-icons": "~6.2.0",
-      "@ideditor/temaki": "~5.2.0",
-      "@mapbox/maki": "^8.0.0",
-      "@openstreetmap/id-tagging-schema": "^5.0.1",
-      autoprefixer: "^10.0.1",
-      btoa: "^1.2.1",
-      chai: "^4.3.4",
+      "@fortawesome/fontawesome-svg-core": "~6.4.0",
+      "@fortawesome/free-brands-svg-icons": "~6.4.0",
+      "@fortawesome/free-regular-svg-icons": "~6.4.0",
+      "@fortawesome/free-solid-svg-icons": "~6.4.0",
+      "@rapideditor/temaki": "~5.4.0",
+      "@mapbox/maki": "^8.0.1",
+      "@openstreetmap/id-tagging-schema": "^6.3.0",
+      "@transifex/api": "^5.4.0",
+      autoprefixer: "^10.4.14",
+      chai: "^4.3.7",
       chalk: "^4.1.2",
-      "cldr-core": "^41.0.0",
-      "cldr-localenames-full": "^41.0.0",
+      "cldr-core": "^43.0.0",
+      "cldr-localenames-full": "^43.1.0",
       "concat-files": "^0.1.1",
-      d3: "~7.6.1",
+      d3: "~7.8.5",
+      dotenv: "^16.3.1",
       "editor-layer-index": "github:osmlab/editor-layer-index#gh-pages",
-      esbuild: "^0.15.7",
-      "esbuild-visualizer": "^0.3.1",
-      eslint: "^8.8.0",
+      esbuild: "^0.18.11",
+      "esbuild-visualizer": "^0.4.1",
+      eslint: "^8.44.0",
       "fetch-mock": "^9.11.0",
       gaze: "^1.1.3",
-      glob: "^8.0.3",
+      glob: "^10.3.3",
       happen: "^0.3.2",
       "js-yaml": "^4.0.0",
       "json-stringify-pretty-compact": "^3.0.0",
-      karma: "^6.3.5",
-      "karma-chrome-launcher": "^3.1.0",
+      karma: "^6.4.2",
+      "karma-chrome-launcher": "^3.2.0",
       "karma-coverage": "2.1.1",
       "karma-mocha": "^2.0.1",
       "karma-remap-istanbul": "^0.6.0",
       mapillary_sprite_source: "^1.8.0",
       "mapillary-js": "4.1.1",
-      minimist: "^1.2.3",
-      mocha: "^10.0.0",
+      minimist: "^1.2.8",
+      mocha: "^10.2.0",
       "name-suggestion-index": "~6.0",
-      "node-fetch": "^2.6.1",
+      "node-fetch": "^2.6.11",
       "npm-run-all": "^4.0.0",
-      "osm-community-index": "~5.3.0",
-      postcss: "^8.1.1",
+      "osm-community-index": "~5.5.3",
+      postcss: "^8.4.25",
       "postcss-selector-prepend": "^0.5.0",
       shelljs: "^0.8.0",
       shx: "^0.3.0",
       "sinon-chai": "^3.7.0",
       smash: "0.0",
       "static-server": "^2.2.1",
-      "svg-sprite": "2.0.1",
+      "svg-sprite": "2.0.2",
       vparse: "~1.1.0"
     },
     engines: {
     return _this;
   }
 
-  // node_modules/@ideditor/country-coder/dist/country-coder.mjs
+  // node_modules/@rapideditor/country-coder/dist/country-coder.mjs
   var import_which_polygon = __toESM(require_which_polygon(), 1);
-  var type = "FeatureCollection";
-  var features = [
+  var borders_default = { type: "FeatureCollection", features: [
     { type: "Feature", properties: { wikidata: "Q21", nameEn: "England", aliases: ["GB-ENG"], country: "GB", groups: ["Q23666", "Q3336843", "154", "150", "UN"], driveSide: "left", roadSpeedUnit: "mph", roadHeightUnit: "ft", callingCodes: ["44"] }, geometry: { type: "MultiPolygon", coordinates: [[[[-6.03913, 51.13217], [-7.74976, 48.64773], [1.17405, 50.74239], [2.18458, 51.52087], [2.56575, 51.85301], [0.792, 57.56437], [-2.30613, 55.62698], [-2.17058, 55.45916], [-2.6095, 55.28488], [-2.63532, 55.19452], [-3.02906, 55.04606], [-3.09361, 54.94924], [-3.38407, 54.94278], [-4.1819, 54.57861], [-3.5082, 53.54318], [-3.08228, 53.25526], [-3.03675, 53.25092], [-2.92329, 53.19383], [-2.92022, 53.17685], [-2.98598, 53.15589], [-2.90649, 53.10964], [-2.87469, 53.12337], [-2.89131, 53.09374], [-2.83133, 52.99184], [-2.7251, 52.98389], [-2.72221, 52.92969], [-2.80549, 52.89428], [-2.85897, 52.94487], [-2.92401, 52.93836], [-2.97243, 52.9651], [-3.13576, 52.895], [-3.15744, 52.84947], [-3.16105, 52.79599], [-3.08734, 52.77504], [-3.01001, 52.76636], [-2.95581, 52.71794], [-3.01724, 52.72083], [-3.04398, 52.65435], [-3.13648, 52.58208], [-3.12926, 52.5286], [-3.09746, 52.53077], [-3.08662, 52.54811], [-3.00929, 52.57774], [-2.99701, 52.551], [-3.03603, 52.49969], [-3.13359, 52.49174], [-3.22971, 52.45344], [-3.22754, 52.42526], [-3.04687, 52.34504], [-2.95364, 52.3501], [-2.99701, 52.323], [-3.00785, 52.2753], [-3.09289, 52.20546], [-3.12638, 52.08114], [-2.97111, 51.90456], [-2.8818, 51.93196], [-2.78742, 51.88833], [-2.74277, 51.84367], [-2.66234, 51.83555], [-2.66336, 51.59504], [-3.20563, 51.31615], [-6.03913, 51.13217]]]] } },
     { type: "Feature", properties: { wikidata: "Q22", nameEn: "Scotland", aliases: ["GB-SCT"], country: "GB", groups: ["Q23666", "Q3336843", "154", "150", "UN"], driveSide: "left", roadSpeedUnit: "mph", roadHeightUnit: "ft", callingCodes: ["44"] }, geometry: { type: "MultiPolygon", coordinates: [[[[0.792, 57.56437], [-0.3751, 61.32236], [-14.78497, 57.60709], [-6.82333, 55.83103], [-4.69044, 54.3629], [-3.38407, 54.94278], [-3.09361, 54.94924], [-3.02906, 55.04606], [-2.63532, 55.19452], [-2.6095, 55.28488], [-2.17058, 55.45916], [-2.30613, 55.62698], [0.792, 57.56437]]]] } },
     { type: "Feature", properties: { wikidata: "Q25", nameEn: "Wales", aliases: ["GB-WLS"], country: "GB", groups: ["Q23666", "Q3336843", "154", "150", "UN"], driveSide: "left", roadSpeedUnit: "mph", roadHeightUnit: "ft", callingCodes: ["44"] }, geometry: { type: "MultiPolygon", coordinates: [[[[-3.5082, 53.54318], [-5.37267, 53.63269], [-6.03913, 51.13217], [-3.20563, 51.31615], [-2.66336, 51.59504], [-2.66234, 51.83555], [-2.74277, 51.84367], [-2.78742, 51.88833], [-2.8818, 51.93196], [-2.97111, 51.90456], [-3.12638, 52.08114], [-3.09289, 52.20546], [-3.00785, 52.2753], [-2.99701, 52.323], [-2.95364, 52.3501], [-3.04687, 52.34504], [-3.22754, 52.42526], [-3.22971, 52.45344], [-3.13359, 52.49174], [-3.03603, 52.49969], [-2.99701, 52.551], [-3.00929, 52.57774], [-3.08662, 52.54811], [-3.09746, 52.53077], [-3.12926, 52.5286], [-3.13648, 52.58208], [-3.04398, 52.65435], [-3.01724, 52.72083], [-2.95581, 52.71794], [-3.01001, 52.76636], [-3.08734, 52.77504], [-3.16105, 52.79599], [-3.15744, 52.84947], [-3.13576, 52.895], [-2.97243, 52.9651], [-2.92401, 52.93836], [-2.85897, 52.94487], [-2.80549, 52.89428], [-2.72221, 52.92969], [-2.7251, 52.98389], [-2.83133, 52.99184], [-2.89131, 53.09374], [-2.87469, 53.12337], [-2.90649, 53.10964], [-2.98598, 53.15589], [-2.92022, 53.17685], [-2.92329, 53.19383], [-3.03675, 53.25092], [-3.08228, 53.25526], [-3.5082, 53.54318]]]] } },
     { type: "Feature", properties: { iso1A2: "CD", iso1A3: "COD", iso1N3: "180", wikidata: "Q974", nameEn: "Democratic Republic of the Congo", aliases: ["ZR"], groups: ["017", "202", "002", "UN"], callingCodes: ["243"] }, geometry: { type: "MultiPolygon", coordinates: [[[[27.44012, 5.07349], [27.09575, 5.22305], [26.93064, 5.13535], [26.85579, 5.03887], [26.74572, 5.10685], [26.48595, 5.04984], [26.13371, 5.25594], [25.86073, 5.19455], [25.53271, 5.37431], [25.34558, 5.29101], [25.31256, 5.03668], [24.71816, 4.90509], [24.46719, 5.0915], [23.38847, 4.60013], [22.94817, 4.82392], [22.89094, 4.79321], [22.84691, 4.69887], [22.78526, 4.71423], [22.6928, 4.47285], [22.60915, 4.48821], [22.5431, 4.22041], [22.45504, 4.13039], [22.27682, 4.11347], [22.10721, 4.20723], [21.6405, 4.317], [21.55904, 4.25553], [21.25744, 4.33676], [21.21341, 4.29285], [21.11214, 4.33895], [21.08793, 4.39603], [20.90383, 4.44877], [20.60184, 4.42394], [18.62755, 3.47564], [18.63857, 3.19342], [18.10683, 2.26876], [18.08034, 1.58553], [17.85887, 1.04327], [17.86989, 0.58873], [17.95255, 0.48128], [17.93877, 0.32424], [17.81204, 0.23884], [17.66051, -0.26535], [17.72112, -0.52707], [17.32438, -0.99265], [16.97999, -1.12762], [16.70724, -1.45815], [16.50336, -1.8795], [16.16173, -2.16586], [16.22785, -2.59528], [16.1755, -3.25014], [16.21407, -3.2969], [15.89448, -3.9513], [15.53081, -4.042], [15.48121, -4.22062], [15.41785, -4.28381], [15.32693, -4.27282], [15.25411, -4.31121], [15.1978, -4.32388], [14.83101, -4.80838], [14.67948, -4.92093], [14.5059, -4.84956], [14.41499, -4.8825], [14.37366, -4.56125], [14.47284, -4.42941], [14.3957, -4.36623], [14.40672, -4.28381], [13.9108, -4.50906], [13.81162, -4.41842], [13.71794, -4.44864], [13.70417, -4.72601], [13.50305, -4.77818], [13.41764, -4.89897], [13.11182, -4.5942], [13.09648, -4.63739], [13.11195, -4.67745], [12.8733, -4.74346], [12.70868, -4.95505], [12.63465, -4.94632], [12.60251, -5.01715], [12.46297, -5.09408], [12.49815, -5.14058], [12.51589, -5.1332], [12.53586, -5.14658], [12.53599, -5.1618], [12.52301, -5.17481], [12.52318, -5.74353], [12.26557, -5.74031], [12.20376, -5.76338], [11.95767, -5.94705], [12.42245, -6.07585], [13.04371, -5.87078], [16.55507, -5.85631], [16.96282, -7.21787], [17.5828, -8.13784], [18.33635, -8.00126], [19.33698, -7.99743], [19.5469, -7.00195], [20.30218, -6.98955], [20.31846, -6.91953], [20.61689, -6.90876], [20.56263, -7.28566], [21.79824, -7.29628], [21.84856, -9.59871], [22.19039, -9.94628], [22.32604, -10.76291], [22.17954, -10.85884], [22.25951, -11.24911], [22.54205, -11.05784], [23.16602, -11.10577], [23.45631, -10.946], [23.86868, -11.02856], [24.00027, -10.89356], [24.34528, -11.06816], [24.42612, -11.44975], [25.34069, -11.19707], [25.33058, -11.65767], [26.01777, -11.91488], [26.88687, -12.01868], [27.04351, -11.61312], [27.22541, -11.60323], [27.21025, -11.76157], [27.59932, -12.22123], [28.33199, -12.41375], [29.01918, -13.41353], [29.60531, -13.21685], [29.65078, -13.41844], [29.81551, -13.44683], [29.8139, -12.14898], [29.48404, -12.23604], [29.4992, -12.43843], [29.18592, -12.37921], [28.48357, -11.87532], [28.37241, -11.57848], [28.65032, -10.65133], [28.62795, -9.92942], [28.68532, -9.78], [28.56208, -9.49122], [28.51627, -9.44726], [28.52636, -9.35379], [28.36562, -9.30091], [28.38526, -9.23393], [28.9711, -8.66935], [28.88917, -8.4831], [30.79243, -8.27382], [30.2567, -7.14121], [29.52552, -6.2731], [29.43673, -4.44845], [29.23708, -3.75856], [29.21463, -3.3514], [29.25633, -3.05471], [29.17258, -2.99385], [29.16037, -2.95457], [29.09797, -2.91935], [29.09119, -2.87871], [29.0505, -2.81774], [29.00404, -2.81978], [29.00167, -2.78523], [29.04081, -2.7416], [29.00357, -2.70596], [28.94346, -2.69124], [28.89793, -2.66111], [28.90226, -2.62385], [28.89288, -2.55848], [28.87943, -2.55165], [28.86193, -2.53185], [28.86209, -2.5231], [28.87497, -2.50887], [28.88846, -2.50493], [28.89342, -2.49017], [28.89132, -2.47557], [28.86846, -2.44866], [28.86826, -2.41888], [28.89601, -2.37321], [28.95642, -2.37321], [29.00051, -2.29001], [29.105, -2.27043], [29.17562, -2.12278], [29.11847, -1.90576], [29.24458, -1.69663], [29.24323, -1.66826], [29.36322, -1.50887], [29.45038, -1.5054], [29.53062, -1.40499], [29.59061, -1.39016], [29.58388, -0.89821], [29.63006, -0.8997], [29.62708, -0.71055], [29.67176, -0.55714], [29.67474, -0.47969], [29.65091, -0.46777], [29.72687, -0.08051], [29.7224, 0.07291], [29.77454, 0.16675], [29.81922, 0.16824], [29.87284, 0.39166], [29.97413, 0.52124], [29.95477, 0.64486], [29.98307, 0.84295], [30.1484, 0.89805], [30.22139, 0.99635], [30.24671, 1.14974], [30.48503, 1.21675], [31.30127, 2.11006], [31.28042, 2.17853], [31.20148, 2.2217], [31.1985, 2.29462], [31.12104, 2.27676], [31.07934, 2.30207], [31.06593, 2.35862], [30.96911, 2.41071], [30.91102, 2.33332], [30.83059, 2.42559], [30.74271, 2.43601], [30.75612, 2.5863], [30.8857, 2.83923], [30.8574, 2.9508], [30.77101, 3.04897], [30.84251, 3.26908], [30.93486, 3.40737], [30.94081, 3.50847], [30.85153, 3.48867], [30.85997, 3.5743], [30.80713, 3.60506], [30.78512, 3.67097], [30.56277, 3.62703], [30.57378, 3.74567], [30.55396, 3.84451], [30.47691, 3.83353], [30.27658, 3.95653], [30.22374, 3.93896], [30.1621, 4.10586], [30.06964, 4.13221], [29.79666, 4.37809], [29.82087, 4.56246], [29.49726, 4.7007], [29.43341, 4.50101], [29.22207, 4.34297], [29.03054, 4.48784], [28.8126, 4.48784], [28.6651, 4.42638], [28.20719, 4.35614], [27.79551, 4.59976], [27.76469, 4.79284], [27.65462, 4.89375], [27.56656, 4.89375], [27.44012, 5.07349]]]] } },
     { type: "Feature", properties: { iso1A2: "CF", iso1A3: "CAF", iso1N3: "140", wikidata: "Q929", nameEn: "Central African Republic", groups: ["017", "202", "002", "UN"], callingCodes: ["236"] }, geometry: { type: "MultiPolygon", coordinates: [[[[22.87758, 10.91915], [22.45889, 11.00246], [21.72139, 10.64136], [21.71479, 10.29932], [21.63553, 10.217], [21.52766, 10.2105], [21.34934, 9.95907], [21.26348, 9.97642], [20.82979, 9.44696], [20.36748, 9.11019], [19.06421, 9.00367], [18.86388, 8.87971], [19.11044, 8.68172], [18.79783, 8.25929], [18.67455, 8.22226], [18.62612, 8.14163], [18.64153, 8.08714], [18.6085, 8.05009], [18.02731, 8.01085], [17.93926, 7.95853], [17.67288, 7.98905], [16.8143, 7.53971], [16.6668, 7.67281], [16.658, 7.75353], [16.59415, 7.76444], [16.58315, 7.88657], [16.41583, 7.77971], [16.40703, 7.68809], [15.79942, 7.44149], [15.73118, 7.52006], [15.49743, 7.52179], [15.23397, 7.25135], [15.04717, 6.77085], [14.96311, 6.75693], [14.79966, 6.39043], [14.80122, 6.34866], [14.74206, 6.26356], [14.56149, 6.18928], [14.43073, 6.08867], [14.42917, 6.00508], [14.49455, 5.91683], [14.60974, 5.91838], [14.62375, 5.70466], [14.58951, 5.59777], [14.62531, 5.51411], [14.52724, 5.28319], [14.57083, 5.23979], [14.65489, 5.21343], [14.73383, 4.6135], [15.00825, 4.41458], [15.08609, 4.30282], [15.10644, 4.1362], [15.17482, 4.05131], [15.07686, 4.01805], [15.73522, 3.24348], [15.77725, 3.26835], [16.05449, 3.02306], [16.08252, 2.45708], [16.19357, 2.21537], [16.50126, 2.84739], [16.46701, 2.92512], [16.57598, 3.47999], [16.68283, 3.54257], [17.01746, 3.55136], [17.35649, 3.63045], [17.46876, 3.70515], [17.60966, 3.63705], [17.83421, 3.61068], [17.85842, 3.53378], [18.05656, 3.56893], [18.14902, 3.54476], [18.17323, 3.47665], [18.24148, 3.50302], [18.2723, 3.57992], [18.39558, 3.58212], [18.49245, 3.63924], [18.58711, 3.49423], [18.62755, 3.47564], [20.60184, 4.42394], [20.90383, 4.44877], [21.08793, 4.39603], [21.11214, 4.33895], [21.21341, 4.29285], [21.25744, 4.33676], [21.55904, 4.25553], [21.6405, 4.317], [22.10721, 4.20723], [22.27682, 4.11347], [22.45504, 4.13039], [22.5431, 4.22041], [22.60915, 4.48821], [22.6928, 4.47285], [22.78526, 4.71423], [22.84691, 4.69887], [22.89094, 4.79321], [22.94817, 4.82392], [23.38847, 4.60013], [24.46719, 5.0915], [24.71816, 4.90509], [25.31256, 5.03668], [25.34558, 5.29101], [25.53271, 5.37431], [25.86073, 5.19455], [26.13371, 5.25594], [26.48595, 5.04984], [26.74572, 5.10685], [26.85579, 5.03887], [26.93064, 5.13535], [27.09575, 5.22305], [27.44012, 5.07349], [27.26886, 5.25876], [27.23017, 5.37167], [27.28621, 5.56382], [27.22705, 5.62889], [27.22705, 5.71254], [26.51721, 6.09655], [26.58259, 6.1987], [26.32729, 6.36272], [26.38022, 6.63493], [25.90076, 7.09549], [25.37461, 7.33024], [25.35281, 7.42595], [25.20337, 7.50312], [25.20649, 7.61115], [25.29214, 7.66675], [25.25319, 7.8487], [24.98855, 7.96588], [24.85156, 8.16933], [24.35965, 8.26177], [24.13238, 8.36959], [24.25691, 8.69288], [23.51905, 8.71749], [23.59065, 8.99743], [23.44744, 8.99128], [23.4848, 9.16959], [23.56263, 9.19418], [23.64358, 9.28637], [23.64981, 9.44303], [23.62179, 9.53823], [23.69155, 9.67566], [23.67164, 9.86923], [23.3128, 10.45214], [23.02221, 10.69235], [22.87758, 10.91915]]]] } },
     { type: "Feature", properties: { iso1A2: "CG", iso1A3: "COG", iso1N3: "178", wikidata: "Q971", nameEn: "Republic of the Congo", groups: ["017", "202", "002", "UN"], callingCodes: ["242"] }, geometry: { type: "MultiPolygon", coordinates: [[[[18.62755, 3.47564], [18.58711, 3.49423], [18.49245, 3.63924], [18.39558, 3.58212], [18.2723, 3.57992], [18.24148, 3.50302], [18.17323, 3.47665], [18.14902, 3.54476], [18.05656, 3.56893], [17.85842, 3.53378], [17.83421, 3.61068], [17.60966, 3.63705], [17.46876, 3.70515], [17.35649, 3.63045], [17.01746, 3.55136], [16.68283, 3.54257], [16.57598, 3.47999], [16.46701, 2.92512], [16.50126, 2.84739], [16.19357, 2.21537], [16.15568, 2.18955], [16.08563, 2.19733], [16.05294, 1.9811], [16.14634, 1.70259], [16.02647, 1.65591], [16.02959, 1.76483], [15.48942, 1.98265], [15.34776, 1.91264], [15.22634, 2.03243], [15.00996, 1.98887], [14.61145, 2.17866], [13.29457, 2.16106], [13.13461, 1.57238], [13.25447, 1.32339], [13.15519, 1.23368], [13.89582, 1.4261], [14.25186, 1.39842], [14.48179, 0.9152], [14.26066, 0.57255], [14.10909, 0.58563], [13.88648, 0.26652], [13.90632, -0.2287], [14.06862, -0.20826], [14.2165, -0.38261], [14.41887, -0.44799], [14.52569, -0.57818], [14.41838, -1.89412], [14.25932, -1.97624], [14.23518, -2.15671], [14.16202, -2.23916], [14.23829, -2.33715], [14.10442, -2.49268], [13.85846, -2.46935], [13.92073, -2.35581], [13.75884, -2.09293], [13.47977, -2.43224], [13.02759, -2.33098], [12.82172, -1.91091], [12.61312, -1.8129], [12.44656, -1.92025], [12.47925, -2.32626], [12.04895, -2.41704], [11.96866, -2.33559], [11.74605, -2.39936], [11.57637, -2.33379], [11.64487, -2.61865], [11.5359, -2.85654], [11.64798, -2.81146], [11.80365, -3.00424], [11.70558, -3.0773], [11.70227, -3.17465], [11.96554, -3.30267], [11.8318, -3.5812], [11.92719, -3.62768], [11.87083, -3.71571], [11.68608, -3.68942], [11.57949, -3.52798], [11.48764, -3.51089], [11.22301, -3.69888], [11.12647, -3.94169], [10.75913, -4.39519], [11.50888, -5.33417], [12.00924, -5.02627], [12.16068, -4.90089], [12.20901, -4.75642], [12.25587, -4.79437], [12.32324, -4.78415], [12.40964, -4.60609], [12.64835, -4.55937], [12.76844, -4.38709], [12.87096, -4.40315], [12.91489, -4.47907], [13.09648, -4.63739], [13.11182, -4.5942], [13.41764, -4.89897], [13.50305, -4.77818], [13.70417, -4.72601], [13.71794, -4.44864], [13.81162, -4.41842], [13.9108, -4.50906], [14.40672, -4.28381], [14.3957, -4.36623], [14.47284, -4.42941], [14.37366, -4.56125], [14.41499, -4.8825], [14.5059, -4.84956], [14.67948, -4.92093], [14.83101, -4.80838], [15.1978, -4.32388], [15.25411, -4.31121], [15.32693, -4.27282], [15.41785, -4.28381], [15.48121, -4.22062], [15.53081, -4.042], [15.89448, -3.9513], [16.21407, -3.2969], [16.1755, -3.25014], [16.22785, -2.59528], [16.16173, -2.16586], [16.50336, -1.8795], [16.70724, -1.45815], [16.97999, -1.12762], [17.32438, -0.99265], [17.72112, -0.52707], [17.66051, -0.26535], [17.81204, 0.23884], [17.93877, 0.32424], [17.95255, 0.48128], [17.86989, 0.58873], [17.85887, 1.04327], [18.08034, 1.58553], [18.10683, 2.26876], [18.63857, 3.19342], [18.62755, 3.47564]]]] } },
-    { type: "Feature", properties: { iso1A2: "CH", iso1A3: "CHE", iso1N3: "756", wikidata: "Q39", nameEn: "Switzerland", groups: ["155", "150", "UN"], callingCodes: ["41"] }, geometry: { type: "MultiPolygon", coordinates: [[[[8.72809, 47.69282], [8.72617, 47.69651], [8.73671, 47.7169], [8.70543, 47.73121], [8.74251, 47.75168], [8.71778, 47.76571], [8.68985, 47.75686], [8.68022, 47.78599], [8.65292, 47.80066], [8.64425, 47.76398], [8.62408, 47.7626], [8.61657, 47.79998], [8.56415, 47.80633], [8.56814, 47.78001], [8.48868, 47.77215], [8.45771, 47.7493], [8.44807, 47.72426], [8.40569, 47.69855], [8.4211, 47.68407], [8.40473, 47.67499], [8.41346, 47.66676], [8.42264, 47.66667], [8.44711, 47.65379], [8.4667, 47.65747], [8.46605, 47.64103], [8.49656, 47.64709], [8.5322, 47.64687], [8.52801, 47.66059], [8.56141, 47.67088], [8.57683, 47.66158], [8.6052, 47.67258], [8.61113, 47.66332], [8.62884, 47.65098], [8.62049, 47.63757], [8.60412, 47.63735], [8.61471, 47.64514], [8.60701, 47.65271], [8.59545, 47.64298], [8.60348, 47.61204], [8.57586, 47.59537], [8.55756, 47.62394], [8.51686, 47.63476], [8.50747, 47.61897], [8.45578, 47.60121], [8.46637, 47.58389], [8.48949, 47.588], [8.49431, 47.58107], [8.43235, 47.56617], [8.39477, 47.57826], [8.38273, 47.56608], [8.32735, 47.57133], [8.30277, 47.58607], [8.29524, 47.5919], [8.29722, 47.60603], [8.2824, 47.61225], [8.26313, 47.6103], [8.25863, 47.61571], [8.23809, 47.61204], [8.22577, 47.60385], [8.22011, 47.6181], [8.20617, 47.62141], [8.19378, 47.61636], [8.1652, 47.5945], [8.14947, 47.59558], [8.13823, 47.59147], [8.13662, 47.58432], [8.11543, 47.5841], [8.10395, 47.57918], [8.10002, 47.56504], [8.08557, 47.55768], [8.06663, 47.56374], [8.04383, 47.55443], [8.02136, 47.55096], [8.00113, 47.55616], [7.97581, 47.55493], [7.95682, 47.55789], [7.94494, 47.54511], [7.91251, 47.55031], [7.90673, 47.57674], [7.88664, 47.58854], [7.84412, 47.5841], [7.81901, 47.58798], [7.79486, 47.55691], [7.75261, 47.54599], [7.71961, 47.54219], [7.69642, 47.53297], [7.68101, 47.53232], [7.6656, 47.53752], [7.66174, 47.54554], [7.65083, 47.54662], [7.63338, 47.56256], [7.67655, 47.56435], [7.68904, 47.57133], [7.67115, 47.5871], [7.68486, 47.59601], [7.69385, 47.60099], [7.68229, 47.59905], [7.67395, 47.59212], [7.64599, 47.59695], [7.64213, 47.5944], [7.64309, 47.59151], [7.61929, 47.57683], [7.60459, 47.57869], [7.60523, 47.58519], [7.58945, 47.59017], [7.58386, 47.57536], [7.56684, 47.57785], [7.56548, 47.57617], [7.55689, 47.57232], [7.55652, 47.56779], [7.53634, 47.55553], [7.52831, 47.55347], [7.51723, 47.54578], [7.50873, 47.54546], [7.49691, 47.53821], [7.50588, 47.52856], [7.51904, 47.53515], [7.53199, 47.5284], [7.5229, 47.51644], [7.49804, 47.51798], [7.51076, 47.49651], [7.47534, 47.47932], [7.43356, 47.49712], [7.42923, 47.48628], [7.4583, 47.47216], [7.4462, 47.46264], [7.43088, 47.45846], [7.40308, 47.43638], [7.35603, 47.43432], [7.33526, 47.44186], [7.24669, 47.4205], [7.17026, 47.44312], [7.19583, 47.49455], [7.16249, 47.49025], [7.12781, 47.50371], [7.07425, 47.48863], [7.0231, 47.50522], [6.98425, 47.49432], [7.0024, 47.45264], [6.93953, 47.43388], [6.93744, 47.40714], [6.88542, 47.37262], [6.87959, 47.35335], [7.03125, 47.36996], [7.0564, 47.35134], [7.05305, 47.33304], [6.94316, 47.28747], [6.95108, 47.26428], [6.9508, 47.24338], [6.8489, 47.15933], [6.76788, 47.1208], [6.68823, 47.06616], [6.71531, 47.0494], [6.43341, 46.92703], [6.46456, 46.88865], [6.43216, 46.80336], [6.45209, 46.77502], [6.38351, 46.73171], [6.27135, 46.68251], [6.11084, 46.57649], [6.1567, 46.54402], [6.07269, 46.46244], [6.08427, 46.44305], [6.06407, 46.41676], [6.09926, 46.40768], [6.15016, 46.3778], [6.15985, 46.37721], [6.16987, 46.36759], [6.15738, 46.3491], [6.13876, 46.33844], [6.1198, 46.31157], [6.11697, 46.29547], [6.1013, 46.28512], [6.11926, 46.2634], [6.12446, 46.25059], [6.10071, 46.23772], [6.08563, 46.24651], [6.07072, 46.24085], [6.0633, 46.24583], [6.05029, 46.23518], [6.04602, 46.23127], [6.03342, 46.2383], [6.02461, 46.23313], [5.97542, 46.21525], [5.96515, 46.19638], [5.99573, 46.18587], [5.98846, 46.17046], [5.98188, 46.17392], [5.97508, 46.15863], [5.9641, 46.14412], [5.95781, 46.12925], [5.97893, 46.13303], [5.9871, 46.14499], [6.01791, 46.14228], [6.03614, 46.13712], [6.04564, 46.14031], [6.05203, 46.15191], [6.07491, 46.14879], [6.09199, 46.15191], [6.09926, 46.14373], [6.13397, 46.1406], [6.15305, 46.15194], [6.18116, 46.16187], [6.18871, 46.16644], [6.18707, 46.17999], [6.19552, 46.18401], [6.19807, 46.18369], [6.20539, 46.19163], [6.21114, 46.1927], [6.21273, 46.19409], [6.21603, 46.19507], [6.21844, 46.19837], [6.22222, 46.19888], [6.22175, 46.20045], [6.23544, 46.20714], [6.23913, 46.20511], [6.24821, 46.20531], [6.26007, 46.21165], [6.27694, 46.21566], [6.29663, 46.22688], [6.31041, 46.24417], [6.29474, 46.26221], [6.26749, 46.24745], [6.24952, 46.26255], [6.23775, 46.27822], [6.25137, 46.29014], [6.24826, 46.30175], [6.21981, 46.31304], [6.25432, 46.3632], [6.53358, 46.45431], [6.82312, 46.42661], [6.8024, 46.39171], [6.77152, 46.34784], [6.86052, 46.28512], [6.78968, 46.14058], [6.89321, 46.12548], [6.87868, 46.03855], [6.93862, 46.06502], [7.00946, 45.9944], [7.04151, 45.92435], [7.10685, 45.85653], [7.56343, 45.97421], [7.85949, 45.91485], [7.9049, 45.99945], [7.98881, 45.99867], [8.02906, 46.10331], [8.11383, 46.11577], [8.16866, 46.17817], [8.08814, 46.26692], [8.31162, 46.38044], [8.30648, 46.41587], [8.42464, 46.46367], [8.46317, 46.43712], [8.45032, 46.26869], [8.62242, 46.12112], [8.75697, 46.10395], [8.80778, 46.10085], [8.85617, 46.0748], [8.79414, 46.00913], [8.78585, 45.98973], [8.79362, 45.99207], [8.8319, 45.9879], [8.85121, 45.97239], [8.86688, 45.96135], [8.88904, 45.95465], [8.93649, 45.86775], [8.94372, 45.86587], [8.93504, 45.86245], [8.91129, 45.8388], [8.94737, 45.84285], [8.9621, 45.83707], [8.99663, 45.83466], [9.00324, 45.82055], [9.0298, 45.82127], [9.03279, 45.82865], [9.03793, 45.83548], [9.03505, 45.83976], [9.04059, 45.8464], [9.04546, 45.84968], [9.06642, 45.8761], [9.09065, 45.89906], [8.99257, 45.9698], [9.01618, 46.04928], [9.24503, 46.23616], [9.29226, 46.32717], [9.25502, 46.43743], [9.28136, 46.49685], [9.36128, 46.5081], [9.40487, 46.46621], [9.45936, 46.50873], [9.46117, 46.37481], [9.57015, 46.2958], [9.71273, 46.29266], [9.73086, 46.35071], [9.95249, 46.38045], [10.07055, 46.21668], [10.14439, 46.22992], [10.17862, 46.25626], [10.10506, 46.3372], [10.165, 46.41051], [10.03715, 46.44479], [10.10307, 46.61003], [10.23674, 46.63484], [10.25309, 46.57432], [10.46136, 46.53164], [10.49375, 46.62049], [10.44686, 46.64162], [10.40475, 46.63671], [10.38659, 46.67847], [10.47197, 46.85698], [10.48376, 46.93891], [10.36933, 47.00212], [10.30031, 46.92093], [10.24128, 46.93147], [10.22675, 46.86942], [10.10715, 46.84296], [9.98058, 46.91434], [9.88266, 46.93343], [9.87935, 47.01337], [9.60717, 47.06091], [9.55721, 47.04762], [9.54041, 47.06495], [9.47548, 47.05257], [9.47139, 47.06402], [9.51362, 47.08505], [9.52089, 47.10019], [9.51044, 47.13727], [9.48774, 47.17402], [9.4891, 47.19346], [9.50318, 47.22153], [9.52406, 47.24959], [9.53116, 47.27029], [9.54773, 47.2809], [9.55857, 47.29919], [9.58513, 47.31334], [9.59978, 47.34671], [9.62476, 47.36639], [9.65427, 47.36824], [9.66243, 47.37136], [9.6711, 47.37824], [9.67445, 47.38429], [9.67334, 47.39191], [9.6629, 47.39591], [9.65136, 47.40504], [9.65043, 47.41937], [9.6446, 47.43233], [9.64483, 47.43842], [9.65863, 47.44847], [9.65728, 47.45383], [9.6423, 47.45599], [9.62475, 47.45685], [9.62158, 47.45858], [9.60841, 47.47178], [9.60484, 47.46358], [9.60205, 47.46165], [9.59482, 47.46305], [9.58208, 47.48344], [9.56312, 47.49495], [9.55125, 47.53629], [9.25619, 47.65939], [9.18203, 47.65598], [9.17593, 47.65399], [9.1755, 47.65584], [9.1705, 47.65513], [9.15181, 47.66904], [9.13845, 47.66389], [9.09891, 47.67801], [9.02093, 47.6868], [8.94093, 47.65596], [8.89946, 47.64769], [8.87625, 47.65441], [8.87383, 47.67045], [8.85065, 47.68209], [8.86989, 47.70504], [8.82002, 47.71458], [8.80663, 47.73821], [8.77309, 47.72059], [8.76965, 47.7075], [8.79966, 47.70222], [8.79511, 47.67462], [8.75856, 47.68969], [8.72809, 47.69282]], [[8.95861, 45.96485], [8.96668, 45.98436], [8.97741, 45.98317], [8.97604, 45.96151], [8.95861, 45.96485]], [[8.70847, 47.68904], [8.68985, 47.69552], [8.66837, 47.68437], [8.65769, 47.68928], [8.67508, 47.6979], [8.66416, 47.71367], [8.70237, 47.71453], [8.71773, 47.69088], [8.70847, 47.68904]]]] } },
+    { type: "Feature", geometry: { type: "MultiPolygon", coordinates: [[[[8.72809, 47.69282], [8.72617, 47.69651], [8.73671, 47.7169], [8.70543, 47.73121], [8.74251, 47.75168], [8.71778, 47.76571], [8.68985, 47.75686], [8.68022, 47.78599], [8.65292, 47.80066], [8.64425, 47.76398], [8.62408, 47.7626], [8.61657, 47.79998], [8.56415, 47.80633], [8.56814, 47.78001], [8.48868, 47.77215], [8.45771, 47.7493], [8.44807, 47.72426], [8.40569, 47.69855], [8.4211, 47.68407], [8.40473, 47.67499], [8.41346, 47.66676], [8.42264, 47.66667], [8.44711, 47.65379], [8.4667, 47.65747], [8.46605, 47.64103], [8.49656, 47.64709], [8.5322, 47.64687], [8.52801, 47.66059], [8.56141, 47.67088], [8.57683, 47.66158], [8.6052, 47.67258], [8.61113, 47.66332], [8.62884, 47.65098], [8.62049, 47.63757], [8.60412, 47.63735], [8.61471, 47.64514], [8.60701, 47.65271], [8.59545, 47.64298], [8.60348, 47.61204], [8.57586, 47.59537], [8.55756, 47.62394], [8.51686, 47.63476], [8.50747, 47.61897], [8.45578, 47.60121], [8.46637, 47.58389], [8.48949, 47.588], [8.49431, 47.58107], [8.43235, 47.56617], [8.39477, 47.57826], [8.38273, 47.56608], [8.35512, 47.57014], [8.32735, 47.57133], [8.30277, 47.58607], [8.29524, 47.5919], [8.29722, 47.60603], [8.2824, 47.61225], [8.26313, 47.6103], [8.25863, 47.61571], [8.23809, 47.61204], [8.22577, 47.60385], [8.22011, 47.6181], [8.20617, 47.62141], [8.19378, 47.61636], [8.1652, 47.5945], [8.14947, 47.59558], [8.13823, 47.59147], [8.13662, 47.58432], [8.11543, 47.5841], [8.10395, 47.57918], [8.10002, 47.56504], [8.08557, 47.55768], [8.06663, 47.56374], [8.04383, 47.55443], [8.02136, 47.55096], [8.00113, 47.55616], [7.97581, 47.55493], [7.95682, 47.55789], [7.94494, 47.54511], [7.91251, 47.55031], [7.90673, 47.57674], [7.88664, 47.58854], [7.84412, 47.5841], [7.81901, 47.58798], [7.79486, 47.55691], [7.75261, 47.54599], [7.71961, 47.54219], [7.69642, 47.53297], [7.68101, 47.53232], [7.6656, 47.53752], [7.66174, 47.54554], [7.65083, 47.54662], [7.63338, 47.56256], [7.67655, 47.56435], [7.68904, 47.57133], [7.67115, 47.5871], [7.68486, 47.59601], [7.69385, 47.60099], [7.68229, 47.59905], [7.67395, 47.59212], [7.64599, 47.59695], [7.64213, 47.5944], [7.64309, 47.59151], [7.61929, 47.57683], [7.60459, 47.57869], [7.60523, 47.58519], [7.58945, 47.59017], [7.58386, 47.57536], [7.56684, 47.57785], [7.56548, 47.57617], [7.55689, 47.57232], [7.55652, 47.56779], [7.53634, 47.55553], [7.52831, 47.55347], [7.51723, 47.54578], [7.50873, 47.54546], [7.49691, 47.53821], [7.50588, 47.52856], [7.51904, 47.53515], [7.53199, 47.5284], [7.5229, 47.51644], [7.49804, 47.51798], [7.51076, 47.49651], [7.47534, 47.47932], [7.43356, 47.49712], [7.42923, 47.48628], [7.4583, 47.47216], [7.4462, 47.46264], [7.43088, 47.45846], [7.40308, 47.43638], [7.35603, 47.43432], [7.33526, 47.44186], [7.24669, 47.4205], [7.17026, 47.44312], [7.19583, 47.49455], [7.16249, 47.49025], [7.12781, 47.50371], [7.07425, 47.48863], [7.0231, 47.50522], [6.98425, 47.49432], [7.0024, 47.45264], [6.93953, 47.43388], [6.93744, 47.40714], [6.88542, 47.37262], [6.87959, 47.35335], [7.03125, 47.36996], [7.0564, 47.35134], [7.05305, 47.33304], [6.94316, 47.28747], [6.95108, 47.26428], [6.9508, 47.24338], [6.8489, 47.15933], [6.76788, 47.1208], [6.68823, 47.06616], [6.71531, 47.0494], [6.43341, 46.92703], [6.46456, 46.88865], [6.43216, 46.80336], [6.45209, 46.77502], [6.38351, 46.73171], [6.27135, 46.68251], [6.11084, 46.57649], [6.1567, 46.54402], [6.07269, 46.46244], [6.08427, 46.44305], [6.06407, 46.41676], [6.09926, 46.40768], [6.15016, 46.3778], [6.15985, 46.37721], [6.16987, 46.36759], [6.15738, 46.3491], [6.13876, 46.33844], [6.1198, 46.31157], [6.11697, 46.29547], [6.1013, 46.28512], [6.11926, 46.2634], [6.12446, 46.25059], [6.10071, 46.23772], [6.08563, 46.24651], [6.07072, 46.24085], [6.0633, 46.24583], [6.05029, 46.23518], [6.04602, 46.23127], [6.03342, 46.2383], [6.02461, 46.23313], [5.97542, 46.21525], [5.96515, 46.19638], [5.99573, 46.18587], [5.98846, 46.17046], [5.98188, 46.17392], [5.97508, 46.15863], [5.9641, 46.14412], [5.95781, 46.12925], [5.97893, 46.13303], [5.9871, 46.14499], [6.01791, 46.14228], [6.03614, 46.13712], [6.04564, 46.14031], [6.05203, 46.15191], [6.07491, 46.14879], [6.09199, 46.15191], [6.09926, 46.14373], [6.13397, 46.1406], [6.15305, 46.15194], [6.18116, 46.16187], [6.18871, 46.16644], [6.18707, 46.17999], [6.19552, 46.18401], [6.19807, 46.18369], [6.20539, 46.19163], [6.21114, 46.1927], [6.21273, 46.19409], [6.21603, 46.19507], [6.21844, 46.19837], [6.22222, 46.19888], [6.22175, 46.20045], [6.23544, 46.20714], [6.23913, 46.20511], [6.24821, 46.20531], [6.26007, 46.21165], [6.27694, 46.21566], [6.29663, 46.22688], [6.31041, 46.24417], [6.29474, 46.26221], [6.26749, 46.24745], [6.24952, 46.26255], [6.23775, 46.27822], [6.25137, 46.29014], [6.24826, 46.30175], [6.21981, 46.31304], [6.25432, 46.3632], [6.53358, 46.45431], [6.82312, 46.42661], [6.8024, 46.39171], [6.77152, 46.34784], [6.86052, 46.28512], [6.78968, 46.14058], [6.89321, 46.12548], [6.87868, 46.03855], [6.93862, 46.06502], [7.00946, 45.9944], [7.04151, 45.92435], [7.10685, 45.85653], [7.56343, 45.97421], [7.85949, 45.91485], [7.9049, 45.99945], [7.98881, 45.99867], [8.02906, 46.10331], [8.11383, 46.11577], [8.16866, 46.17817], [8.08814, 46.26692], [8.31162, 46.38044], [8.30648, 46.41587], [8.42464, 46.46367], [8.46317, 46.43712], [8.45032, 46.26869], [8.62242, 46.12112], [8.75697, 46.10395], [8.80778, 46.10085], [8.85617, 46.0748], [8.79414, 46.00913], [8.78585, 45.98973], [8.79362, 45.99207], [8.8319, 45.9879], [8.85121, 45.97239], [8.86688, 45.96135], [8.88904, 45.95465], [8.93649, 45.86775], [8.94372, 45.86587], [8.93504, 45.86245], [8.91129, 45.8388], [8.94737, 45.84285], [8.9621, 45.83707], [8.99663, 45.83466], [9.00324, 45.82055], [9.0298, 45.82127], [9.03279, 45.82865], [9.03793, 45.83548], [9.03505, 45.83976], [9.04059, 45.8464], [9.04546, 45.84968], [9.06642, 45.8761], [9.09065, 45.89906], [8.99257, 45.9698], [9.01618, 46.04928], [9.24503, 46.23616], [9.29226, 46.32717], [9.25502, 46.43743], [9.28136, 46.49685], [9.36128, 46.5081], [9.40487, 46.46621], [9.45936, 46.50873], [9.46117, 46.37481], [9.57015, 46.2958], [9.71273, 46.29266], [9.73086, 46.35071], [9.95249, 46.38045], [10.07055, 46.21668], [10.14439, 46.22992], [10.17862, 46.25626], [10.10506, 46.3372], [10.165, 46.41051], [10.03715, 46.44479], [10.10307, 46.61003], [10.23674, 46.63484], [10.25309, 46.57432], [10.46136, 46.53164], [10.49375, 46.62049], [10.44686, 46.64162], [10.40475, 46.63671], [10.38659, 46.67847], [10.47197, 46.85698], [10.48376, 46.93891], [10.36933, 47.00212], [10.30031, 46.92093], [10.24128, 46.93147], [10.22675, 46.86942], [10.10715, 46.84296], [9.98058, 46.91434], [9.88266, 46.93343], [9.87935, 47.01337], [9.60717, 47.06091], [9.55721, 47.04762], [9.54041, 47.06495], [9.47548, 47.05257], [9.47139, 47.06402], [9.51362, 47.08505], [9.52089, 47.10019], [9.51044, 47.13727], [9.48774, 47.17402], [9.4891, 47.19346], [9.50318, 47.22153], [9.52406, 47.24959], [9.53116, 47.27029], [9.54773, 47.2809], [9.55857, 47.29919], [9.58513, 47.31334], [9.59978, 47.34671], [9.62476, 47.36639], [9.65427, 47.36824], [9.66243, 47.37136], [9.6711, 47.37824], [9.67445, 47.38429], [9.67334, 47.39191], [9.6629, 47.39591], [9.65136, 47.40504], [9.65043, 47.41937], [9.6446, 47.43233], [9.64483, 47.43842], [9.65863, 47.44847], [9.65728, 47.45383], [9.6423, 47.45599], [9.62475, 47.45685], [9.62158, 47.45858], [9.60841, 47.47178], [9.60484, 47.46358], [9.60205, 47.46165], [9.59482, 47.46305], [9.58208, 47.48344], [9.56312, 47.49495], [9.55125, 47.53629], [9.25619, 47.65939], [9.18203, 47.65598], [9.17593, 47.65399], [9.1755, 47.65584], [9.1705, 47.65513], [9.15181, 47.66904], [9.13845, 47.66389], [9.09891, 47.67801], [9.02093, 47.6868], [8.94093, 47.65596], [8.89946, 47.64769], [8.87625, 47.65441], [8.87383, 47.67045], [8.85065, 47.68209], [8.86989, 47.70504], [8.82002, 47.71458], [8.80663, 47.73821], [8.77309, 47.72059], [8.76965, 47.7075], [8.79966, 47.70222], [8.79511, 47.67462], [8.75856, 47.68969], [8.72809, 47.69282]], [[8.95861, 45.96485], [8.96668, 45.98436], [8.97741, 45.98317], [8.97604, 45.96151], [8.95861, 45.96485]], [[8.70847, 47.68904], [8.68985, 47.69552], [8.66837, 47.68437], [8.65769, 47.68928], [8.67508, 47.6979], [8.66416, 47.71367], [8.70237, 47.71453], [8.71773, 47.69088], [8.70847, 47.68904]]]] }, properties: { iso1A2: "CH", iso1A3: "CHE", iso1N3: "756", wikidata: "Q39", nameEn: "Switzerland", groups: ["155", "150", "UN"], callingCodes: ["41"] } },
     { type: "Feature", properties: { iso1A2: "CI", iso1A3: "CIV", iso1N3: "384", wikidata: "Q1008", nameEn: "C\xF4te d'Ivoire", groups: ["011", "202", "002", "UN"], callingCodes: ["225"] }, geometry: { type: "MultiPolygon", coordinates: [[[[-7.52774, 3.7105], [-3.34019, 4.17519], [-3.10675, 5.08515], [-3.11073, 5.12675], [-3.063, 5.13665], [-2.96554, 5.10397], [-2.95261, 5.12477], [-2.75502, 5.10657], [-2.73074, 5.1364], [-2.77625, 5.34621], [-2.72737, 5.34789], [-2.76614, 5.60963], [-2.85378, 5.65156], [-2.93132, 5.62137], [-2.96671, 5.6415], [-2.95323, 5.71865], [-3.01896, 5.71697], [-3.25999, 6.62521], [-3.21954, 6.74407], [-3.23327, 6.81744], [-2.95438, 7.23737], [-2.97822, 7.27165], [-2.92339, 7.60847], [-2.79467, 7.86002], [-2.78395, 7.94974], [-2.74819, 7.92613], [-2.67787, 8.02055], [-2.61232, 8.02645], [-2.62901, 8.11495], [-2.49037, 8.20872], [-2.58243, 8.7789], [-2.66357, 9.01771], [-2.77799, 9.04949], [-2.69814, 9.22717], [-2.68802, 9.49343], [-2.76494, 9.40778], [-2.93012, 9.57403], [-3.00765, 9.74019], [-3.16609, 9.85147], [-3.19306, 9.93781], [-3.27228, 9.84981], [-3.31779, 9.91125], [-3.69703, 9.94279], [-4.25999, 9.76012], [-4.31392, 9.60062], [-4.6426, 9.70696], [-4.96621, 9.89132], [-4.96453, 9.99923], [-5.12465, 10.29788], [-5.39602, 10.2929], [-5.51058, 10.43177], [-5.65135, 10.46767], [-5.78124, 10.43952], [-5.99478, 10.19694], [-6.18851, 10.24244], [-6.1731, 10.46983], [-6.24795, 10.74248], [-6.325, 10.68624], [-6.40646, 10.69922], [-6.42847, 10.5694], [-6.52974, 10.59104], [-6.63541, 10.66893], [-6.68164, 10.35074], [-6.93921, 10.35291], [-7.01186, 10.25111], [-6.97444, 10.21644], [-7.00966, 10.15794], [-7.0603, 10.14711], [-7.13331, 10.24877], [-7.3707, 10.24677], [-7.44555, 10.44602], [-7.52261, 10.4655], [-7.54462, 10.40921], [-7.63048, 10.46334], [-7.92107, 10.15577], [-7.97971, 10.17117], [-8.01225, 10.1021], [-8.11921, 10.04577], [-8.15652, 9.94288], [-8.09434, 9.86936], [-8.14657, 9.55062], [-8.03463, 9.39604], [-7.85056, 9.41812], [-7.90777, 9.20456], [-7.73862, 9.08422], [-7.92518, 8.99332], [-7.95503, 8.81146], [-7.69882, 8.66148], [-7.65653, 8.36873], [-7.92518, 8.50652], [-8.22991, 8.48438], [-8.2411, 8.24196], [-8.062, 8.16071], [-7.98675, 8.20134], [-7.99919, 8.11023], [-7.94695, 8.00925], [-8.06449, 8.04989], [-8.13414, 7.87991], [-8.09931, 7.78626], [-8.21374, 7.54466], [-8.4003, 7.6285], [-8.47114, 7.55676], [-8.41935, 7.51203], [-8.37458, 7.25794], [-8.29249, 7.1691], [-8.31736, 6.82837], [-8.59456, 6.50612], [-8.48652, 6.43797], [-8.45666, 6.49977], [-8.38453, 6.35887], [-8.3298, 6.36381], [-8.17557, 6.28222], [-8.00642, 6.31684], [-7.90692, 6.27728], [-7.83478, 6.20309], [-7.8497, 6.08932], [-7.79747, 6.07696], [-7.78254, 5.99037], [-7.70294, 5.90625], [-7.67309, 5.94337], [-7.48155, 5.80974], [-7.46165, 5.84934], [-7.43677, 5.84687], [-7.43926, 5.74787], [-7.37209, 5.61173], [-7.43428, 5.42355], [-7.36463, 5.32944], [-7.46165, 5.26256], [-7.48901, 5.14118], [-7.55369, 5.08667], [-7.53876, 4.94294], [-7.59349, 4.8909], [-7.53259, 4.35145], [-7.52774, 3.7105]]]] } },
     { type: "Feature", properties: { iso1A2: "CK", iso1A3: "COK", iso1N3: "184", wikidata: "Q26988", nameEn: "Cook Islands", country: "NZ", groups: ["061", "009", "UN"], driveSide: "left", callingCodes: ["682"] }, geometry: { type: "MultiPolygon", coordinates: [[[[-168.15106, -10.26955], [-156.45576, -31.75456], [-156.48634, -15.52824], [-156.50903, -7.4975], [-168.15106, -10.26955]]]] } },
     { type: "Feature", properties: { iso1A2: "CL", iso1A3: "CHL", iso1N3: "152", wikidata: "Q298", nameEn: "Chile", groups: ["005", "419", "019", "UN"], callingCodes: ["56"] }, geometry: { type: "MultiPolygon", coordinates: [[[[-68.60702, -52.65781], [-68.41683, -52.33516], [-69.97824, -52.00845], [-71.99889, -51.98018], [-72.33873, -51.59954], [-72.31343, -50.58411], [-73.15765, -50.78337], [-73.55259, -49.92488], [-73.45156, -49.79461], [-73.09655, -49.14342], [-72.56894, -48.81116], [-72.54042, -48.52392], [-72.27662, -48.28727], [-72.50478, -47.80586], [-71.94152, -47.13595], [-71.68577, -46.55385], [-71.75614, -45.61611], [-71.35687, -45.22075], [-72.06985, -44.81756], [-71.26418, -44.75684], [-71.16436, -44.46244], [-71.81318, -44.38097], [-71.64206, -43.64774], [-72.14828, -42.85321], [-72.15541, -42.15941], [-71.74901, -42.11711], [-71.92726, -40.72714], [-71.37826, -38.91474], [-70.89532, -38.6923], [-71.24279, -37.20264], [-70.95047, -36.4321], [-70.38008, -36.02375], [-70.49416, -35.24145], [-69.87386, -34.13344], [-69.88099, -33.34489], [-70.55832, -31.51559], [-70.14479, -30.36595], [-69.8596, -30.26131], [-69.99507, -29.28351], [-69.80969, -29.07185], [-69.66709, -28.44055], [-69.22504, -27.95042], [-68.77586, -27.16029], [-68.43363, -27.08414], [-68.27677, -26.90626], [-68.59048, -26.49861], [-68.56909, -26.28146], [-68.38372, -26.15353], [-68.57622, -25.32505], [-68.38372, -25.08636], [-68.56909, -24.69831], [-68.24825, -24.42596], [-67.33563, -24.04237], [-66.99632, -22.99839], [-67.18382, -22.81525], [-67.54284, -22.89771], [-67.85114, -22.87076], [-68.18816, -21.28614], [-68.40403, -20.94562], [-68.53957, -20.91542], [-68.55383, -20.7355], [-68.44023, -20.62701], [-68.7276, -20.46178], [-68.74273, -20.08817], [-68.57132, -20.03134], [-68.54611, -19.84651], [-68.66761, -19.72118], [-68.41218, -19.40499], [-68.61989, -19.27584], [-68.80602, -19.08355], [-68.87082, -19.06003], [-68.94987, -18.93302], [-69.07432, -18.28259], [-69.14807, -18.16893], [-69.07496, -18.03715], [-69.28671, -17.94844], [-69.34126, -17.72753], [-69.46623, -17.60518], [-69.46897, -17.4988], [-69.66483, -17.65083], [-69.79087, -17.65563], [-69.82868, -17.72048], [-69.75305, -17.94605], [-69.81607, -18.12582], [-69.96732, -18.25992], [-70.16394, -18.31737], [-70.31267, -18.31258], [-70.378, -18.3495], [-70.59118, -18.35072], [-113.52687, -26.52828], [-68.11646, -58.14883], [-66.07313, -55.19618], [-67.11046, -54.94199], [-67.46182, -54.92205], [-68.01394, -54.8753], [-68.60733, -54.9125], [-68.60702, -52.65781]]]] } },
     { type: "Feature", properties: { iso1A2: "HU", iso1A3: "HUN", iso1N3: "348", wikidata: "Q28", nameEn: "Hungary", groups: ["EU", "151", "150", "UN"], callingCodes: ["36"] }, geometry: { type: "MultiPolygon", coordinates: [[[[21.72525, 48.34628], [21.67134, 48.3989], [21.6068, 48.50365], [21.44063, 48.58456], [21.11516, 48.49546], [20.83248, 48.5824], [20.5215, 48.53336], [20.29943, 48.26104], [20.24312, 48.2784], [19.92452, 48.1283], [19.63338, 48.25006], [19.52489, 48.19791], [19.47957, 48.09437], [19.28182, 48.08336], [19.23924, 48.0595], [19.01952, 48.07052], [18.82176, 48.04206], [18.76134, 47.97499], [18.76821, 47.87469], [18.8506, 47.82308], [18.74074, 47.8157], [18.66521, 47.76772], [18.56496, 47.76588], [18.29305, 47.73541], [18.02938, 47.75665], [17.71215, 47.7548], [17.23699, 48.02094], [17.16001, 48.00636], [17.09786, 47.97336], [17.11022, 47.92461], [17.08275, 47.87719], [17.00997, 47.86245], [17.07039, 47.81129], [17.05048, 47.79377], [17.08893, 47.70928], [16.87538, 47.68895], [16.86509, 47.72268], [16.82938, 47.68432], [16.7511, 47.67878], [16.72089, 47.73469], [16.65679, 47.74197], [16.61183, 47.76171], [16.54779, 47.75074], [16.53514, 47.73837], [16.55129, 47.72268], [16.4222, 47.66537], [16.58699, 47.61772], [16.64193, 47.63114], [16.71059, 47.52692], [16.64821, 47.50155], [16.6718, 47.46139], [16.57152, 47.40868], [16.52414, 47.41007], [16.49908, 47.39416], [16.45104, 47.41181], [16.47782, 47.25918], [16.44142, 47.25079], [16.43663, 47.21127], [16.41739, 47.20649], [16.42801, 47.18422], [16.4523, 47.18812], [16.46442, 47.16845], [16.44932, 47.14418], [16.52863, 47.13974], [16.46134, 47.09395], [16.52176, 47.05747], [16.43936, 47.03548], [16.51369, 47.00084], [16.28202, 47.00159], [16.27594, 46.9643], [16.22403, 46.939], [16.19904, 46.94134], [16.10983, 46.867], [16.14365, 46.8547], [16.15711, 46.85434], [16.21892, 46.86961], [16.2365, 46.87775], [16.2941, 46.87137], [16.34547, 46.83836], [16.3408, 46.80641], [16.31303, 46.79838], [16.30966, 46.7787], [16.37816, 46.69975], [16.42641, 46.69228], [16.41863, 46.66238], [16.38594, 46.6549], [16.39217, 46.63673], [16.50139, 46.56684], [16.52885, 46.53303], [16.52604, 46.5051], [16.59527, 46.47524], [16.6639, 46.45203], [16.7154, 46.39523], [16.8541, 46.36255], [16.8903, 46.28122], [17.14592, 46.16697], [17.35672, 45.95209], [17.56821, 45.93728], [17.66545, 45.84207], [17.87377, 45.78522], [17.99805, 45.79671], [18.08869, 45.76511], [18.12439, 45.78905], [18.44368, 45.73972], [18.57483, 45.80772], [18.6792, 45.92057], [18.80211, 45.87995], [18.81394, 45.91329], [18.99712, 45.93537], [19.01284, 45.96529], [19.0791, 45.96458], [19.10388, 46.04015], [19.14543, 45.9998], [19.28826, 45.99694], [19.52473, 46.1171], [19.56113, 46.16824], [19.66007, 46.19005], [19.81491, 46.1313], [19.93508, 46.17553], [20.01816, 46.17696], [20.03533, 46.14509], [20.09713, 46.17315], [20.26068, 46.12332], [20.28324, 46.1438], [20.35573, 46.16629], [20.45377, 46.14405], [20.49718, 46.18721], [20.63863, 46.12728], [20.76085, 46.21002], [20.74574, 46.25467], [20.86797, 46.28884], [21.06572, 46.24897], [21.16872, 46.30118], [21.28061, 46.44941], [21.26929, 46.4993], [21.33214, 46.63035], [21.43926, 46.65109], [21.5151, 46.72147], [21.48935, 46.7577], [21.52028, 46.84118], [21.59307, 46.86935], [21.59581, 46.91628], [21.68645, 46.99595], [21.648, 47.03902], [21.78395, 47.11104], [21.94463, 47.38046], [22.01055, 47.37767], [22.03389, 47.42508], [22.00917, 47.50492], [22.31816, 47.76126], [22.41979, 47.7391], [22.46559, 47.76583], [22.67247, 47.7871], [22.76617, 47.8417], [22.77991, 47.87211], [22.89849, 47.95851], [22.84276, 47.98602], [22.87847, 48.04665], [22.81804, 48.11363], [22.73427, 48.12005], [22.66835, 48.09162], [22.58733, 48.10813], [22.59007, 48.15121], [22.49806, 48.25189], [22.38133, 48.23726], [22.2083, 48.42534], [22.14689, 48.4005], [21.83339, 48.36242], [21.8279, 48.33321], [21.72525, 48.34628]]]] } },
     { type: "Feature", properties: { iso1A2: "IC", wikidata: "Q5813", nameEn: "Canary Islands", country: "ES", groups: ["Q3320166", "Q105472", "EU", "039", "150", "UN"], isoStatus: "excRes", callingCodes: ["34"] }, geometry: { type: "MultiPolygon", coordinates: [[[[-12.00985, 30.24121], [-25.3475, 27.87574], [-14.43883, 27.02969], [-12.00985, 30.24121]]]] } },
     { type: "Feature", properties: { iso1A2: "ID", iso1A3: "IDN", iso1N3: "360", wikidata: "Q252", nameEn: "Indonesia", aliases: ["RI"] }, geometry: null },
-    { type: "Feature", properties: { iso1A2: "IE", iso1A3: "IRL", iso1N3: "372", wikidata: "Q27", nameEn: "Republic of Ireland", groups: ["EU", "Q22890", "154", "150", "UN"], driveSide: "left", callingCodes: ["353"] }, geometry: { type: "MultiPolygon", coordinates: [[[[-6.26218, 54.09785], [-6.29003, 54.11278], [-6.32694, 54.09337], [-6.36279, 54.11248], [-6.36605, 54.07234], [-6.47849, 54.06947], [-6.62842, 54.03503], [-6.66264, 54.0666], [-6.6382, 54.17071], [-6.70175, 54.20218], [-6.74575, 54.18788], [-6.81583, 54.22791], [-6.85179, 54.29176], [-6.87775, 54.34682], [-7.02034, 54.4212], [-7.19145, 54.31296], [-7.14908, 54.22732], [-7.25012, 54.20063], [-7.26316, 54.13863], [-7.29493, 54.12013], [-7.29687, 54.1354], [-7.28017, 54.16714], [-7.29157, 54.17191], [-7.34005, 54.14698], [-7.30553, 54.11869], [-7.32834, 54.11475], [-7.44567, 54.1539], [-7.4799, 54.12239], [-7.55812, 54.12239], [-7.69501, 54.20731], [-7.81397, 54.20159], [-7.8596, 54.21779], [-7.87101, 54.29299], [-8.04555, 54.36292], [-8.179, 54.46763], [-8.04538, 54.48941], [-7.99812, 54.54427], [-7.8596, 54.53671], [-7.70315, 54.62077], [-7.93293, 54.66603], [-7.83352, 54.73854], [-7.75041, 54.7103], [-7.64449, 54.75265], [-7.54671, 54.74606], [-7.54508, 54.79401], [-7.47626, 54.83084], [-7.4473, 54.87003], [-7.44404, 54.9403], [-7.40004, 54.94498], [-7.4033, 55.00391], [-7.34464, 55.04688], [-7.2471, 55.06933], [-6.34755, 55.49206], [-7.75229, 55.93854], [-22.01468, 48.19557], [-6.03913, 51.13217], [-5.37267, 53.63269], [-6.26218, 54.09785]]]] } },
+    { type: "Feature", geometry: { type: "MultiPolygon", coordinates: [[[[-6.26218, 54.09785], [-6.29003, 54.11278], [-6.32694, 54.09337], [-6.36279, 54.11248], [-6.36605, 54.07234], [-6.47849, 54.06947], [-6.62842, 54.03503], [-6.66264, 54.0666], [-6.6382, 54.17071], [-6.70175, 54.20218], [-6.74575, 54.18788], [-6.81583, 54.22791], [-6.85179, 54.29176], [-6.87775, 54.34682], [-7.02034, 54.4212], [-7.19145, 54.31296], [-7.14908, 54.22732], [-7.25012, 54.20063], [-7.26316, 54.13863], [-7.29493, 54.12013], [-7.29687, 54.1354], [-7.28017, 54.16714], [-7.29157, 54.17191], [-7.34005, 54.14698], [-7.30553, 54.11869], [-7.32834, 54.11475], [-7.44567, 54.1539], [-7.4799, 54.12239], [-7.55812, 54.12239], [-7.69501, 54.20731], [-7.81397, 54.20159], [-7.8596, 54.21779], [-7.87101, 54.29299], [-8.04555, 54.36292], [-8.179, 54.46763], [-8.04538, 54.48941], [-7.99812, 54.54427], [-7.8596, 54.53671], [-7.70315, 54.62077], [-7.93293, 54.66603], [-7.83352, 54.73854], [-7.75041, 54.7103], [-7.64449, 54.75265], [-7.54671, 54.74606], [-7.54508, 54.79401], [-7.47626, 54.83084], [-7.4473, 54.87003], [-7.44404, 54.9403], [-7.40004, 54.94498], [-7.4033, 55.00391], [-7.34464, 55.04688], [-7.2471, 55.06933], [-6.34755, 55.49206], [-7.75229, 55.93854], [-11.75, 54], [-11, 51], [-6.03913, 51.13217], [-5.37267, 53.63269], [-6.26218, 54.09785]]]] }, properties: { iso1A2: "IE", iso1A3: "IRL", iso1N3: "372", wikidata: "Q27", nameEn: "Republic of Ireland", groups: ["EU", "Q22890", "154", "150", "UN"], driveSide: "left", callingCodes: ["353"] } },
     { type: "Feature", properties: { iso1A2: "IL", iso1A3: "ISR", iso1N3: "376", wikidata: "Q801", nameEn: "Israel", groups: ["145", "142", "UN"], callingCodes: ["972"] }, geometry: { type: "MultiPolygon", coordinates: [[[[34.052, 31.46619], [34.29262, 31.70393], [34.48681, 31.59711], [34.56797, 31.54197], [34.48892, 31.48365], [34.40077, 31.40926], [34.36505, 31.36404], [34.37381, 31.30598], [34.36523, 31.28963], [34.29417, 31.24194], [34.26742, 31.21998], [34.92298, 29.45305], [34.97718, 29.54294], [34.98207, 29.58147], [35.02147, 29.66343], [35.14108, 30.07374], [35.19183, 30.34636], [35.16218, 30.43535], [35.19595, 30.50297], [35.21379, 30.60401], [35.29311, 30.71365], [35.33456, 30.81224], [35.33984, 30.8802], [35.41371, 30.95565], [35.43658, 31.12444], [35.40316, 31.25535], [35.47672, 31.49578], [35.39675, 31.49572], [35.22921, 31.37445], [35.13033, 31.3551], [35.02459, 31.35979], [34.92571, 31.34337], [34.88932, 31.37093], [34.87833, 31.39321], [34.89756, 31.43891], [34.93258, 31.47816], [34.94356, 31.50743], [34.9415, 31.55601], [34.95249, 31.59813], [35.00879, 31.65426], [35.08226, 31.69107], [35.10782, 31.71594], [35.11895, 31.71454], [35.12933, 31.7325], [35.13931, 31.73012], [35.15119, 31.73634], [35.15474, 31.73352], [35.16478, 31.73242], [35.18023, 31.72067], [35.20538, 31.72388], [35.21937, 31.71578], [35.22392, 31.71899], [35.23972, 31.70896], [35.24315, 31.71244], [35.2438, 31.7201], [35.24981, 31.72543], [35.25182, 31.73945], [35.26319, 31.74846], [35.25225, 31.7678], [35.26058, 31.79064], [35.25573, 31.81362], [35.26404, 31.82567], [35.251, 31.83085], [35.25753, 31.8387], [35.24816, 31.8458], [35.2304, 31.84222], [35.2249, 31.85433], [35.22817, 31.8638], [35.22567, 31.86745], [35.22294, 31.87889], [35.22014, 31.88264], [35.2136, 31.88241], [35.21276, 31.88153], [35.21016, 31.88237], [35.20945, 31.8815], [35.20791, 31.8821], [35.20673, 31.88151], [35.20381, 31.86716], [35.21128, 31.863], [35.216, 31.83894], [35.21469, 31.81835], [35.19461, 31.82687], [35.18169, 31.82542], [35.18603, 31.80901], [35.14174, 31.81325], [35.07677, 31.85627], [35.05617, 31.85685], [35.01978, 31.82944], [34.9724, 31.83352], [34.99712, 31.85569], [35.03489, 31.85919], [35.03978, 31.89276], [35.03489, 31.92448], [35.00124, 31.93264], [34.98682, 31.96935], [35.00261, 32.027], [34.9863, 32.09551], [34.99437, 32.10962], [34.98507, 32.12606], [34.99039, 32.14626], [34.96009, 32.17503], [34.95703, 32.19522], [34.98885, 32.20758], [35.01841, 32.23981], [35.02939, 32.2671], [35.01119, 32.28684], [35.01772, 32.33863], [35.04243, 32.35008], [35.05142, 32.3667], [35.0421, 32.38242], [35.05311, 32.4024], [35.05423, 32.41754], [35.07059, 32.4585], [35.08564, 32.46948], [35.09236, 32.47614], [35.10024, 32.47856], [35.10882, 32.4757], [35.15937, 32.50466], [35.2244, 32.55289], [35.25049, 32.52453], [35.29306, 32.50947], [35.30685, 32.51024], [35.35212, 32.52047], [35.40224, 32.50136], [35.42034, 32.46009], [35.41598, 32.45593], [35.41048, 32.43706], [35.42078, 32.41562], [35.55807, 32.38674], [35.55494, 32.42687], [35.57485, 32.48669], [35.56614, 32.64393], [35.59813, 32.65159], [35.61669, 32.67999], [35.66527, 32.681], [35.68467, 32.70715], [35.75983, 32.74803], [35.78745, 32.77938], [35.83758, 32.82817], [35.84021, 32.8725], [35.87012, 32.91976], [35.89298, 32.9456], [35.87188, 32.98028], [35.84802, 33.1031], [35.81911, 33.11077], [35.81911, 33.1336], [35.84285, 33.16673], [35.83846, 33.19397], [35.81647, 33.2028], [35.81295, 33.24841], [35.77513, 33.27342], [35.813, 33.3172], [35.77477, 33.33609], [35.62019, 33.27278], [35.62283, 33.24226], [35.58502, 33.26653], [35.58326, 33.28381], [35.56523, 33.28969], [35.55555, 33.25844], [35.54544, 33.25513], [35.54808, 33.236], [35.5362, 33.23196], [35.54228, 33.19865], [35.52573, 33.11921], [35.50335, 33.114], [35.50272, 33.09056], [35.448, 33.09264], [35.43059, 33.06659], [35.35223, 33.05617], [35.31429, 33.10515], [35.1924, 33.08743], [35.10645, 33.09318], [34.78515, 33.20368], [33.62659, 31.82938], [34.052, 31.46619]]]] } },
     { type: "Feature", properties: { iso1A2: "IM", iso1A3: "IMN", iso1N3: "833", wikidata: "Q9676", nameEn: "Isle of Man", country: "GB", groups: ["Q185086", "154", "150", "UN"], driveSide: "left", roadSpeedUnit: "mph", roadHeightUnit: "ft", callingCodes: ["44 01624", "44 07624", "44 07524", "44 07924"] }, geometry: { type: "MultiPolygon", coordinates: [[[[-3.98763, 54.07351], [-4.1819, 54.57861], [-5.6384, 53.81157], [-3.98763, 54.07351]]]] } },
     { type: "Feature", properties: { iso1A2: "IN", iso1A3: "IND", iso1N3: "356", wikidata: "Q668", nameEn: "India" }, geometry: null },
     { type: "Feature", properties: { iso1A2: "ZA", iso1A3: "ZAF", iso1N3: "710", wikidata: "Q258", nameEn: "South Africa", groups: ["018", "202", "002", "UN"], driveSide: "left", callingCodes: ["27"] }, geometry: { type: "MultiPolygon", coordinates: [[[[31.30611, -22.422], [31.16344, -22.32599], [31.08932, -22.34884], [30.86696, -22.28907], [30.6294, -22.32599], [30.48686, -22.31368], [30.38614, -22.34533], [30.28351, -22.35587], [30.2265, -22.2961], [30.13147, -22.30841], [29.92242, -22.19408], [29.76848, -22.14128], [29.64609, -22.12917], [29.37703, -22.19581], [29.21955, -22.17771], [29.18974, -22.18599], [29.15268, -22.21399], [29.10881, -22.21202], [29.0151, -22.22907], [28.91889, -22.44299], [28.63287, -22.55887], [28.34874, -22.5694], [28.04562, -22.8394], [28.04752, -22.90243], [27.93729, -22.96194], [27.93539, -23.04941], [27.74154, -23.2137], [27.6066, -23.21894], [27.52393, -23.37952], [27.33768, -23.40917], [26.99749, -23.65486], [26.84165, -24.24885], [26.51667, -24.47219], [26.46346, -24.60358], [26.39409, -24.63468], [25.8515, -24.75727], [25.84295, -24.78661], [25.88571, -24.87802], [25.72702, -25.25503], [25.69661, -25.29284], [25.6643, -25.4491], [25.58543, -25.6343], [25.33076, -25.76616], [25.12266, -25.75931], [25.01718, -25.72507], [24.8946, -25.80723], [24.67319, -25.81749], [24.44703, -25.73021], [24.36531, -25.773], [24.18287, -25.62916], [23.9244, -25.64286], [23.47588, -25.29971], [23.03497, -25.29971], [22.86012, -25.50572], [22.70808, -25.99186], [22.56365, -26.19668], [22.41921, -26.23078], [22.21206, -26.3773], [22.06192, -26.61882], [21.90703, -26.66808], [21.83291, -26.65959], [21.77114, -26.69015], [21.7854, -26.79199], [21.69322, -26.86152], [21.37869, -26.82083], [21.13353, -26.86661], [20.87031, -26.80047], [20.68596, -26.9039], [20.63275, -26.78181], [20.61754, -26.4692], [20.86081, -26.14892], [20.64795, -25.47827], [20.29826, -24.94869], [20.03678, -24.81004], [20.02809, -24.78725], [19.99817, -24.76768], [19.99882, -28.42622], [18.99885, -28.89165], [17.4579, -28.68718], [17.15405, -28.08573], [16.90446, -28.057], [16.59922, -28.53246], [16.46592, -28.57126], [16.45332, -28.63117], [12.51595, -32.27486], [38.88176, -48.03306], [34.51034, -26.91792], [32.35222, -26.86027], [32.29584, -26.852], [32.22302, -26.84136], [32.19409, -26.84032], [32.13315, -26.84345], [32.09664, -26.80721], [32.00893, -26.8096], [31.97463, -27.11057], [31.97592, -27.31675], [31.49834, -27.31549], [31.15027, -27.20151], [30.96088, -27.0245], [30.97757, -26.92706], [30.88826, -26.79622], [30.81101, -26.84722], [30.78927, -26.48271], [30.95819, -26.26303], [31.13073, -25.91558], [31.31237, -25.7431], [31.4175, -25.71886], [31.86881, -25.99973], [31.974, -25.95387], [31.92649, -25.84216], [32.00631, -25.65044], [31.97875, -25.46356], [32.01676, -25.38117], [32.03196, -25.10785], [31.9835, -24.29983], [31.90368, -24.18892], [31.87707, -23.95293], [31.77445, -23.90082], [31.70223, -23.72695], [31.67942, -23.60858], [31.56539, -23.47268], [31.55779, -23.176], [31.30611, -22.422]], [[29.33204, -29.45598], [29.28545, -29.58456], [29.12553, -29.76266], [29.16548, -29.91706], [28.9338, -30.05072], [28.80222, -30.10579], [28.68627, -30.12885], [28.399, -30.1592], [28.2319, -30.28476], [28.12073, -30.68072], [27.74814, -30.60635], [27.69467, -30.55862], [27.67819, -30.53437], [27.6521, -30.51707], [27.62137, -30.50509], [27.56781, -30.44562], [27.56901, -30.42504], [27.45452, -30.32239], [27.38108, -30.33456], [27.36649, -30.27246], [27.37293, -30.19401], [27.40778, -30.14577], [27.32555, -30.14785], [27.29603, -30.05473], [27.22719, -30.00718], [27.09489, -29.72796], [27.01016, -29.65439], [27.33464, -29.48161], [27.4358, -29.33465], [27.47254, -29.31968], [27.45125, -29.29708], [27.48679, -29.29349], [27.54258, -29.25575], [27.5158, -29.2261], [27.55974, -29.18954], [27.75458, -28.89839], [27.8907, -28.91612], [27.88933, -28.88156], [27.9392, -28.84864], [27.98675, -28.8787], [28.02503, -28.85991], [28.1317, -28.7293], [28.2348, -28.69471], [28.30518, -28.69531], [28.40612, -28.6215], [28.65091, -28.57025], [28.68043, -28.58744], [29.40524, -29.21246], [29.44883, -29.3772], [29.33204, -29.45598]]]] } },
     { type: "Feature", properties: { iso1A2: "ZM", iso1A3: "ZMB", iso1N3: "894", wikidata: "Q953", nameEn: "Zambia", groups: ["014", "202", "002", "UN"], driveSide: "left", callingCodes: ["260"] }, geometry: { type: "MultiPolygon", coordinates: [[[[32.95389, -9.40138], [32.76233, -9.31963], [32.75611, -9.28583], [32.53661, -9.24281], [32.49147, -9.14754], [32.43543, -9.11988], [32.25486, -9.13371], [32.16146, -9.05993], [32.08206, -9.04609], [31.98866, -9.07069], [31.94196, -9.02303], [31.94663, -8.93846], [31.81587, -8.88618], [31.71158, -8.91386], [31.57147, -8.81388], [31.57147, -8.70619], [31.37533, -8.60769], [31.00796, -8.58615], [30.79243, -8.27382], [28.88917, -8.4831], [28.9711, -8.66935], [28.38526, -9.23393], [28.36562, -9.30091], [28.52636, -9.35379], [28.51627, -9.44726], [28.56208, -9.49122], [28.68532, -9.78], [28.62795, -9.92942], [28.65032, -10.65133], [28.37241, -11.57848], [28.48357, -11.87532], [29.18592, -12.37921], [29.4992, -12.43843], [29.48404, -12.23604], [29.8139, -12.14898], [29.81551, -13.44683], [29.65078, -13.41844], [29.60531, -13.21685], [29.01918, -13.41353], [28.33199, -12.41375], [27.59932, -12.22123], [27.21025, -11.76157], [27.22541, -11.60323], [27.04351, -11.61312], [26.88687, -12.01868], [26.01777, -11.91488], [25.33058, -11.65767], [25.34069, -11.19707], [24.42612, -11.44975], [24.34528, -11.06816], [24.00027, -10.89356], [24.02603, -11.15368], [23.98804, -12.13149], [24.06672, -12.29058], [23.90937, -12.844], [24.03339, -12.99091], [21.97988, -13.00148], [22.00323, -16.18028], [22.17217, -16.50269], [23.20038, -17.47563], [23.47474, -17.62877], [24.23619, -17.47489], [24.32811, -17.49082], [24.38712, -17.46818], [24.5621, -17.52963], [24.70864, -17.49501], [25.00198, -17.58221], [25.26433, -17.79571], [25.51646, -17.86232], [25.6827, -17.81987], [25.85738, -17.91403], [25.85892, -17.97726], [26.08925, -17.98168], [26.0908, -17.93021], [26.21601, -17.88608], [26.55918, -17.99638], [26.68403, -18.07411], [26.74314, -18.0199], [26.89926, -17.98756], [27.14196, -17.81398], [27.30736, -17.60487], [27.61377, -17.34378], [27.62795, -17.24365], [27.83141, -16.96274], [28.73725, -16.5528], [28.76199, -16.51575], [28.81454, -16.48611], [28.8501, -16.04537], [28.9243, -15.93987], [29.01298, -15.93805], [29.21955, -15.76589], [29.4437, -15.68702], [29.8317, -15.6126], [30.35574, -15.6513], [30.41902, -15.62269], [30.22098, -14.99447], [33.24249, -14.00019], [33.16749, -13.93992], [33.07568, -13.98447], [33.02977, -14.05022], [32.99042, -13.95689], [32.88985, -13.82956], [32.79015, -13.80755], [32.76962, -13.77224], [32.84528, -13.71576], [32.7828, -13.64805], [32.68654, -13.64268], [32.66468, -13.60019], [32.68436, -13.55769], [32.73683, -13.57682], [32.84176, -13.52794], [32.86113, -13.47292], [33.0078, -13.19492], [32.98289, -13.12671], [33.02181, -12.88707], [32.96733, -12.88251], [32.94397, -12.76868], [33.05917, -12.59554], [33.18837, -12.61377], [33.28177, -12.54692], [33.37517, -12.54085], [33.54485, -12.35996], [33.47636, -12.32498], [33.3705, -12.34931], [33.25998, -12.14242], [33.33937, -11.91252], [33.32692, -11.59248], [33.24252, -11.59302], [33.23663, -11.40637], [33.29267, -11.43536], [33.29267, -11.3789], [33.39697, -11.15296], [33.25998, -10.88862], [33.28022, -10.84428], [33.47636, -10.78465], [33.70675, -10.56896], [33.54797, -10.36077], [33.53863, -10.20148], [33.31297, -10.05133], [33.37902, -9.9104], [33.36581, -9.81063], [33.31517, -9.82364], [33.2095, -9.61099], [33.12144, -9.58929], [33.10163, -9.66525], [33.05485, -9.61316], [33.00256, -9.63053], [33.00476, -9.5133], [32.95389, -9.40138]]]] } },
     { type: "Feature", properties: { iso1A2: "ZW", iso1A3: "ZWE", iso1N3: "716", wikidata: "Q954", nameEn: "Zimbabwe", groups: ["014", "202", "002", "UN"], driveSide: "left", callingCodes: ["263"] }, geometry: { type: "MultiPolygon", coordinates: [[[[30.41902, -15.62269], [30.35574, -15.6513], [29.8317, -15.6126], [29.4437, -15.68702], [29.21955, -15.76589], [29.01298, -15.93805], [28.9243, -15.93987], [28.8501, -16.04537], [28.81454, -16.48611], [28.76199, -16.51575], [28.73725, -16.5528], [27.83141, -16.96274], [27.62795, -17.24365], [27.61377, -17.34378], [27.30736, -17.60487], [27.14196, -17.81398], [26.89926, -17.98756], [26.74314, -18.0199], [26.68403, -18.07411], [26.55918, -17.99638], [26.21601, -17.88608], [26.0908, -17.93021], [26.08925, -17.98168], [25.85892, -17.97726], [25.85738, -17.91403], [25.6827, -17.81987], [25.51646, -17.86232], [25.26433, -17.79571], [25.23909, -17.90832], [25.31799, -18.07091], [25.39972, -18.12691], [25.53465, -18.39041], [25.68859, -18.56165], [25.79217, -18.6355], [25.82353, -18.82808], [25.94326, -18.90362], [25.99837, -19.02943], [25.96226, -19.08152], [26.17227, -19.53709], [26.72246, -19.92707], [27.21278, -20.08244], [27.29831, -20.28935], [27.28865, -20.49873], [27.69361, -20.48531], [27.72972, -20.51735], [27.69171, -21.08409], [27.91407, -21.31621], [28.01669, -21.57624], [28.29416, -21.59037], [28.49942, -21.66634], [28.58114, -21.63455], [29.07763, -21.81877], [29.04023, -21.85864], [29.02191, -21.90647], [29.02191, -21.95665], [29.04108, -22.00563], [29.08495, -22.04867], [29.14501, -22.07275], [29.1974, -22.07472], [29.24648, -22.05967], [29.3533, -22.18363], [29.37703, -22.19581], [29.64609, -22.12917], [29.76848, -22.14128], [29.92242, -22.19408], [30.13147, -22.30841], [30.2265, -22.2961], [30.28351, -22.35587], [30.38614, -22.34533], [30.48686, -22.31368], [30.6294, -22.32599], [30.86696, -22.28907], [31.08932, -22.34884], [31.16344, -22.32599], [31.30611, -22.422], [31.38336, -22.36919], [32.41234, -21.31246], [32.48236, -21.32873], [32.37115, -21.133], [32.51644, -20.91929], [32.48122, -20.63319], [32.55167, -20.56312], [32.66174, -20.56106], [32.85987, -20.27841], [32.85987, -20.16686], [32.93032, -20.03868], [33.01178, -20.02007], [33.06461, -19.77787], [32.95013, -19.67219], [32.84666, -19.68462], [32.84446, -19.48343], [32.78282, -19.47513], [32.77966, -19.36098], [32.85107, -19.29238], [32.87088, -19.09279], [32.84006, -19.0262], [32.72118, -19.02204], [32.69917, -18.94293], [32.73439, -18.92628], [32.70137, -18.84712], [32.82465, -18.77419], [32.9017, -18.7992], [32.95013, -18.69079], [32.88629, -18.58023], [32.88629, -18.51344], [33.02278, -18.4696], [33.03159, -18.35054], [32.94133, -17.99705], [33.0492, -17.60298], [32.98536, -17.55891], [32.96554, -17.48964], [33.0426, -17.3468], [33.00517, -17.30477], [32.96554, -17.11971], [32.84113, -16.92259], [32.91051, -16.89446], [32.97655, -16.70689], [32.78943, -16.70267], [32.69917, -16.66893], [32.71017, -16.59932], [32.42838, -16.4727], [32.28529, -16.43892], [32.02772, -16.43892], [31.91324, -16.41569], [31.90223, -16.34388], [31.67988, -16.19595], [31.42451, -16.15154], [31.30563, -16.01193], [31.13171, -15.98019], [30.97761, -16.05848], [30.91597, -15.99924], [30.42568, -15.9962], [30.41902, -15.62269]]]] } }
-  ];
-  var borders_default = { type, features };
+  ] };
   var borders = borders_default;
   var whichPolygonGetter = {};
   var featuresByCode = {};
           sharedGroups = sharedGroups.filter((groupID) => memberGroups.indexOf(groupID) !== -1);
         }
       });
-      props.groups = props.groups.concat(sharedGroups.filter((groupID) => props.groups.indexOf(groupID) === -1));
+      props.groups = props.groups.concat(
+        sharedGroups.filter((groupID) => props.groups.indexOf(groupID) === -1)
+      );
       sharedGroups.forEach((groupID) => {
         const groupFeature = featuresByCode[groupID];
         if (groupFeature.properties.members.indexOf(props.id) === -1) {
         if (!props.roadSpeedUnit)
           props.roadSpeedUnit = "km/h";
       } else if (props.members) {
-        const vals = Array.from(new Set(props.members.map((id2) => {
-          const member = featuresByCode[id2];
-          if (member.geometry)
-            return member.properties.roadSpeedUnit || "km/h";
-        }).filter(Boolean)));
+        const vals = Array.from(
+          new Set(
+            props.members.map((id2) => {
+              const member = featuresByCode[id2];
+              if (member.geometry)
+                return member.properties.roadSpeedUnit || "km/h";
+            }).filter(Boolean)
+          )
+        );
         if (vals.length === 1)
           props.roadSpeedUnit = vals[0];
       }
         if (!props.roadHeightUnit)
           props.roadHeightUnit = "m";
       } else if (props.members) {
-        const vals = Array.from(new Set(props.members.map((id2) => {
-          const member = featuresByCode[id2];
-          if (member.geometry)
-            return member.properties.roadHeightUnit || "m";
-        }).filter(Boolean)));
+        const vals = Array.from(
+          new Set(
+            props.members.map((id2) => {
+              const member = featuresByCode[id2];
+              if (member.geometry)
+                return member.properties.roadHeightUnit || "m";
+            }).filter(Boolean)
+          )
+        );
         if (vals.length === 1)
           props.roadHeightUnit = vals[0];
       }
         if (!props.driveSide)
           props.driveSide = "right";
       } else if (props.members) {
-        const vals = Array.from(new Set(props.members.map((id2) => {
-          const member = featuresByCode[id2];
-          if (member.geometry)
-            return member.properties.driveSide || "right";
-        }).filter(Boolean)));
+        const vals = Array.from(
+          new Set(
+            props.members.map((id2) => {
+              const member = featuresByCode[id2];
+              if (member.geometry)
+                return member.properties.driveSide || "right";
+            }).filter(Boolean)
+          )
+        );
         if (vals.length === 1)
           props.driveSide = vals[0];
       }
     function loadCallingCodes(feature22) {
       const props = feature22.properties;
       if (!feature22.geometry && props.members) {
-        props.callingCodes = Array.from(new Set(props.members.reduce((array2, id2) => {
-          const member = featuresByCode[id2];
-          if (member.geometry && member.properties.callingCodes) {
-            return array2.concat(member.properties.callingCodes);
-          }
-          return array2;
-        }, [])));
+        props.callingCodes = Array.from(
+          new Set(
+            props.members.reduce((array2, id2) => {
+              const member = featuresByCode[id2];
+              if (member.geometry && member.properties.callingCodes) {
+                return array2.concat(member.properties.callingCodes);
+              }
+              return array2;
+            }, [])
+          )
+        );
       }
     }
     function loadFlag(feature22) {
         }
       }
     }
-    const features2 = featuresContaining(loc);
-    const match = features2.find((feature22) => {
+    const features = featuresContaining(loc);
+    const match = features.find((feature22) => {
       let levelIndex = levels.indexOf(feature22.properties.level);
-      if (feature22.properties.level === targetLevel || levelIndex > targetLevelIndex && levelIndex <= maxLevelIndex) {
+      if (feature22.properties.level === targetLevel || // if no feature exists at the target level, return the first feature at the next level up
+      levelIndex > targetLevelIndex && levelIndex <= maxLevelIndex) {
         if (!withProp || feature22.properties[withProp]) {
           return feature22;
         }
     const feature22 = featureForID(id2);
     if (!feature22)
       return [];
-    let features2 = [];
+    let features = [];
     if (!strict) {
-      features2.push(feature22);
+      features.push(feature22);
     }
     const properties = feature22.properties;
     (properties.members || []).forEach((memberID) => {
-      features2.push(featuresByCode[memberID]);
+      features.push(featuresByCode[memberID]);
     });
-    return features2;
+    return features;
   }
   function aggregateFeature(id2) {
-    const features2 = featuresIn(id2, false);
-    if (features2.length === 0)
+    const features = featuresIn(id2, false);
+    if (features.length === 0)
       return null;
     let aggregateCoordinates = [];
-    features2.forEach((feature22) => {
+    features.forEach((feature22) => {
       if (feature22.geometry && feature22.geometry.type === "MultiPolygon" && feature22.geometry.coordinates) {
         aggregateCoordinates = aggregateCoordinates.concat(feature22.geometry.coordinates);
       }
     });
     return {
       type: "Feature",
-      properties: features2[0].properties,
+      properties: features[0].properties,
       geometry: {
         type: "MultiPolygon",
         coordinates: aggregateCoordinates
     return feature22 && feature22.properties.roadHeightUnit || null;
   }
 
-  // node_modules/@ideditor/location-conflation/index.mjs
+  // node_modules/@rapideditor/location-conflation/index.mjs
   var import_geojson_area = __toESM(require_geojson_area(), 1);
   var import_circle_to_polygon = __toESM(require_circle_to_polygon(), 1);
   var import_polygon_clipping = __toESM(require_polygon_clipping_umd(), 1);
   var import_geojson_precision = __toESM(require_geojson_precision(), 1);
   var import_json_stringify_pretty_compact = __toESM(require_json_stringify_pretty_compact(), 1);
   var location_conflation_default = class {
+    // constructor
+    //
+    // `fc`  Optional FeatureCollection of known features
+    //
+    // Optionally pass a GeoJSON FeatureCollection of known features which we can refer to later.
+    // Each feature must have a filename-like `id`, for example: `something.geojson`
+    //
+    // {
+    //   "type": "FeatureCollection"
+    //   "features": [
+    //     {
+    //       "type": "Feature",
+    //       "id": "philly_metro.geojson",
+    //       "properties": { … },
+    //       "geometry": { … }
+    //     }
+    //   ]
+    // }
     constructor(fc) {
       this._cache = {};
       this._strict = true;
       world.properties.area = import_geojson_area.default.geometry(world.geometry) / 1e6;
       this._cache.Q2 = world;
     }
+    // validateLocation
+    // `location`  The location to validate
+    //
+    // Pass a `location` value to validate
+    //
+    // Returns a result like:
+    //   {
+    //     type:     'point', 'geojson', or 'countrycoder'
+    //     location:  the queried location
+    //     id:        the stable identifier for the feature
+    //   }
+    // or `null` if the location is invalid
+    //
     validateLocation(location) {
       if (Array.isArray(location) && (location.length === 2 || location.length === 3)) {
         const lon = location[0];
         return null;
       }
     }
+    // resolveLocation
+    // `location`  The location to resolve
+    //
+    // Pass a `location` value to resolve
+    //
+    // Returns a result like:
+    //   {
+    //     type:      'point', 'geojson', or 'countrycoder'
+    //     location:  the queried location
+    //     id:        a stable identifier for the feature
+    //     feature:   the resolved GeoJSON feature
+    //   }
+    //  or `null` if the location is invalid
+    //
     resolveLocation(location) {
       const valid = this.validateLocation(location);
       if (!valid)
           id: id2,
           properties: { id: id2, area: Number(area.toFixed(2)) },
           geometry: (0, import_circle_to_polygon.default)([lon, lat], radius * 1e3, EDGES)
+          // km to m
         }, PRECISION);
         return Object.assign(valid, { feature: feature3 });
       } else if (valid.type === "geojson") {
         return null;
       }
     }
+    // validateLocationSet
+    // `locationSet`  the locationSet to validate
+    //
+    // Pass a locationSet Object to validate like:
+    //   {
+    //     include: [ Array of locations ],
+    //     exclude: [ Array of locations ]
+    //   }
+    //
+    // Returns a result like:
+    //   {
+    //     type:         'locationset'
+    //     locationSet:  the queried locationSet
+    //     id:           the stable identifier for the feature
+    //   }
+    // or `null` if the locationSet is invalid
+    //
     validateLocationSet(locationSet) {
       locationSet = locationSet || {};
       const validator = this.validateLocation.bind(this);
       }
       return { type: "locationset", locationSet, id: id2 };
     }
+    // resolveLocationSet
+    // `locationSet`  the locationSet to resolve
+    //
+    // Pass a locationSet Object to validate like:
+    //   {
+    //     include: [ Array of locations ],
+    //     exclude: [ Array of locations ]
+    //   }
+    //
+    // Returns a result like:
+    //   {
+    //     type:         'locationset'
+    //     locationSet:  the queried locationSet
+    //     id:           the stable identifier for the feature
+    //     feature:      the resolved GeoJSON feature
+    //   }
+    // or `null` if the locationSet is invalid
+    //
     resolveLocationSet(locationSet) {
       locationSet = locationSet || {};
       const valid = this.validateLocationSet(locationSet);
       this._cache[id2] = resultGeoJSON;
       return Object.assign(valid, { feature: resultGeoJSON });
     }
+    // strict
+    //
     strict(val) {
       if (val === void 0) {
         return this._strict;
         return this;
       }
     }
+    // cache
+    // convenience method to access the internal cache
     cache() {
       return this._cache;
     }
+    // stringify
+    // convenience method to prettyStringify the given object
     stringify(obj, options2) {
       return (0, import_json_stringify_pretty_compact.default)(obj, options2);
     }
   };
-  function _clip(features2, which) {
-    if (!Array.isArray(features2) || !features2.length)
+  function _clip(features, which) {
+    if (!Array.isArray(features) || !features.length)
       return null;
     const fn = { UNION: import_polygon_clipping.default.union, DIFFERENCE: import_polygon_clipping.default.difference }[which];
-    const args = features2.map((feature3) => feature3.geometry.coordinates);
+    const args = features.map((feature3) => feature3.geometry.coordinates);
     const coords = fn.apply(null, args);
     return {
       type: "Feature",
   var import_geojson_area2 = __toESM(require_geojson_area());
   var _loco = new location_conflation_default();
   var LocationManager = class {
+    /**
+     * @constructor
+     */
     constructor() {
       this._wp = null;
       this._resolved = /* @__PURE__ */ new Map();
       this._resolveLocationSet(world);
       this._rebuildIndex();
     }
+    /**
+     * _validateLocationSet
+     * Pass an Object with a `locationSet` property.
+     * Validates the `locationSet` and sets a `locationSetID` property on the object.
+     * To avoid so much computation we only resolve the include and exclude regions, but not the locationSet itself.
+     *
+     * Use `_resolveLocationSet()` instead if you need to resolve geojson of locationSet, for example to render it.
+     * Note: You need to call `_rebuildIndex()` after you're all finished validating the locationSets.
+     *
+     * @param  `obj`  Object to check, it should have `locationSet` property
+     */
     _validateLocationSet(obj) {
       if (obj.locationSetID)
         return;
         obj.locationSetID = "+[Q2]";
       }
     }
+    /**
+     * _resolveLocationSet
+     * Does everything that `_validateLocationSet()` does, but then "resolves" the locationSet into GeoJSON.
+     * This step is a bit more computationally expensive, so really only needed if you intend to render the shape.
+     *
+     * Note: You need to call `_rebuildIndex()` after you're all finished validating the locationSets.
+     *
+     * @param  `obj`  Object to check, it should have `locationSet` property
+     */
     _resolveLocationSet(obj) {
       this._validateLocationSet(obj);
       if (this._resolved.has(obj.locationSetID))
         obj.locationSetID = "+[Q2]";
       }
     }
+    /**
+     * _rebuildIndex
+     * Rebuilds the whichPolygon index with whatever features have been resolved into GeoJSON.
+     */
     _rebuildIndex() {
       this._wp = (0, import_which_polygon2.default)({ features: [...this._resolved.values()] });
     }
+    /**
+     * mergeCustomGeoJSON
+     * Accepts a FeatureCollection-like object containing custom locations
+     * Each feature must have a filename-like `id`, for example: `something.geojson`
+     * {
+     *   "type": "FeatureCollection"
+     *   "features": [
+     *     {
+     *       "type": "Feature",
+     *       "id": "philly_metro.geojson",
+     *       "properties": { … },
+     *       "geometry": { … }
+     *     }
+     *   ]
+     * }
+     *
+     * @param  `fc`  FeatureCollection-like Object containing custom locations
+     */
     mergeCustomGeoJSON(fc) {
       if (!fc || fc.type !== "FeatureCollection" || !Array.isArray(fc.features))
         return;
         _loco._cache[id2] = feature3;
       });
     }
+    /**
+     * mergeLocationSets
+     * Accepts an Array of Objects containing `locationSet` properties:
+     * [
+     *  { id: 'preset1', locationSet: {…} },
+     *  { id: 'preset2', locationSet: {…} },
+     *  …
+     * ]
+     * After validating, the Objects will be decorated with a `locationSetID` property:
+     * [
+     *  { id: 'preset1', locationSet: {…}, locationSetID: '+[Q2]' },
+     *  { id: 'preset2', locationSet: {…}, locationSetID: '+[Q30]' },
+     *  …
+     * ]
+     *
+     * @param  `objects`  Objects to check - they should have `locationSet` property
+     * @return  Promise resolved true (this function used to be slow/async, now it's faster and sync)
+     */
     mergeLocationSets(objects) {
       if (!Array.isArray(objects))
         return Promise.reject("nothing to do");
       this._rebuildIndex();
       return Promise.resolve(objects);
     }
+    /**
+     * locationSetID
+     * Returns a locationSetID for a given locationSet (fallback to `+[Q2]`, world)
+     * (The locationSet doesn't necessarily need to be resolved to compute its `id`)
+     *
+     * @param  `locationSet`  A locationSet Object, e.g. `{ include: ['us'] }`
+     * @return  String locationSetID, e.g. `+[Q30]`
+     */
     locationSetID(locationSet) {
       let locationSetID;
       try {
       }
       return locationSetID;
     }
+    /**
+     * feature
+     * Returns the resolved GeoJSON feature for a given locationSetID (fallback to 'world')
+     * A GeoJSON feature:
+     * {
+     *   type: 'Feature',
+     *   id: '+[Q30]',
+     *   properties: { id: '+[Q30]', area: 21817019.17, … },
+     *   geometry: { … }
+     * }
+     *
+     * @param  `locationSetID`  String identifier, e.g. `+[Q30]`
+     * @return  GeoJSON object (fallback to world)
+     */
     feature(locationSetID = "+[Q2]") {
       const feature3 = this._resolved.get(locationSetID);
       return feature3 || this._resolved.get("+[Q2]");
     }
+    /**
+     * locationSetsAt
+     * Find all the locationSets valid at the given location.
+     * Results include the area (in km²) to facilitate sorting.
+     *
+     * Object of locationSetIDs to areas (in km²)
+     * {
+     *   "+[Q2]": 511207893.3958111,
+     *   "+[Q30]": 21817019.17,
+     *   "+[new_jersey.geojson]": 22390.77,
+     *   …
+     * }
+     *
+     * @param  `loc`  `[lon,lat]` location to query, e.g. `[-74.4813, 40.7967]`
+     * @return  Object of locationSetIDs valid at given location
+     */
     locationSetsAt(loc) {
       let result = {};
       const hits = this._wp(loc, true) || [];
       });
       return result;
     }
+    // Direct access to the location-conflation resolver
     loco() {
       return _loco;
     }
 
   // node_modules/lodash-es/isObject.js
   function isObject(value) {
-    var type3 = typeof value;
-    return value != null && (type3 == "object" || type3 == "function");
+    var type2 = typeof value;
+    return value != null && (type2 == "object" || type2 == "function");
   }
   var isObject_default = isObject;
 
   }
   var toNumber_default = toNumber;
 
+  // node_modules/lodash-es/isFunction.js
+  var asyncTag = "[object AsyncFunction]";
+  var funcTag = "[object Function]";
+  var genTag = "[object GeneratorFunction]";
+  var proxyTag = "[object Proxy]";
+  function isFunction(value) {
+    if (!isObject_default(value)) {
+      return false;
+    }
+    var tag = baseGetTag_default(value);
+    return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
+  }
+  var isFunction_default = isFunction;
+
+  // node_modules/lodash-es/_coreJsData.js
+  var coreJsData = root_default["__core-js_shared__"];
+  var coreJsData_default = coreJsData;
+
+  // node_modules/lodash-es/_isMasked.js
+  var maskSrcKey = function() {
+    var uid = /[^.]+$/.exec(coreJsData_default && coreJsData_default.keys && coreJsData_default.keys.IE_PROTO || "");
+    return uid ? "Symbol(src)_1." + uid : "";
+  }();
+  function isMasked(func) {
+    return !!maskSrcKey && maskSrcKey in func;
+  }
+  var isMasked_default = isMasked;
+
+  // node_modules/lodash-es/_toSource.js
+  var funcProto = Function.prototype;
+  var funcToString = funcProto.toString;
+  function toSource(func) {
+    if (func != null) {
+      try {
+        return funcToString.call(func);
+      } catch (e) {
+      }
+      try {
+        return func + "";
+      } catch (e) {
+      }
+    }
+    return "";
+  }
+  var toSource_default = toSource;
+
+  // node_modules/lodash-es/_baseIsNative.js
+  var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
+  var reIsHostCtor = /^\[object .+?Constructor\]$/;
+  var funcProto2 = Function.prototype;
+  var objectProto3 = Object.prototype;
+  var funcToString2 = funcProto2.toString;
+  var hasOwnProperty2 = objectProto3.hasOwnProperty;
+  var reIsNative = RegExp(
+    "^" + funcToString2.call(hasOwnProperty2).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
+  );
+  function baseIsNative(value) {
+    if (!isObject_default(value) || isMasked_default(value)) {
+      return false;
+    }
+    var pattern = isFunction_default(value) ? reIsNative : reIsHostCtor;
+    return pattern.test(toSource_default(value));
+  }
+  var baseIsNative_default = baseIsNative;
+
+  // node_modules/lodash-es/_getValue.js
+  function getValue(object, key) {
+    return object == null ? void 0 : object[key];
+  }
+  var getValue_default = getValue;
+
+  // node_modules/lodash-es/_getNative.js
+  function getNative(object, key) {
+    var value = getValue_default(object, key);
+    return baseIsNative_default(value) ? value : void 0;
+  }
+  var getNative_default = getNative;
+
+  // node_modules/lodash-es/_WeakMap.js
+  var WeakMap = getNative_default(root_default, "WeakMap");
+  var WeakMap_default = WeakMap;
+
+  // node_modules/lodash-es/_isIndex.js
+  var MAX_SAFE_INTEGER = 9007199254740991;
+  var reIsUint = /^(?:0|[1-9]\d*)$/;
+  function isIndex(value, length) {
+    var type2 = typeof value;
+    length = length == null ? MAX_SAFE_INTEGER : length;
+    return !!length && (type2 == "number" || type2 != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
+  }
+  var isIndex_default = isIndex;
+
+  // node_modules/lodash-es/eq.js
+  function eq(value, other) {
+    return value === other || value !== value && other !== other;
+  }
+  var eq_default = eq;
+
+  // node_modules/lodash-es/isLength.js
+  var MAX_SAFE_INTEGER2 = 9007199254740991;
+  function isLength(value) {
+    return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER2;
+  }
+  var isLength_default = isLength;
+
+  // node_modules/lodash-es/isArrayLike.js
+  function isArrayLike(value) {
+    return value != null && isLength_default(value.length) && !isFunction_default(value);
+  }
+  var isArrayLike_default = isArrayLike;
+
+  // node_modules/lodash-es/_isPrototype.js
+  var objectProto4 = Object.prototype;
+  function isPrototype(value) {
+    var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto4;
+    return value === proto;
+  }
+  var isPrototype_default = isPrototype;
+
+  // node_modules/lodash-es/_baseTimes.js
+  function baseTimes(n2, iteratee) {
+    var index = -1, result = Array(n2);
+    while (++index < n2) {
+      result[index] = iteratee(index);
+    }
+    return result;
+  }
+  var baseTimes_default = baseTimes;
+
+  // node_modules/lodash-es/_baseIsArguments.js
+  var argsTag = "[object Arguments]";
+  function baseIsArguments(value) {
+    return isObjectLike_default(value) && baseGetTag_default(value) == argsTag;
+  }
+  var baseIsArguments_default = baseIsArguments;
+
+  // node_modules/lodash-es/isArguments.js
+  var objectProto5 = Object.prototype;
+  var hasOwnProperty3 = objectProto5.hasOwnProperty;
+  var propertyIsEnumerable = objectProto5.propertyIsEnumerable;
+  var isArguments = baseIsArguments_default(function() {
+    return arguments;
+  }()) ? baseIsArguments_default : function(value) {
+    return isObjectLike_default(value) && hasOwnProperty3.call(value, "callee") && !propertyIsEnumerable.call(value, "callee");
+  };
+  var isArguments_default = isArguments;
+
+  // node_modules/lodash-es/stubFalse.js
+  function stubFalse() {
+    return false;
+  }
+  var stubFalse_default = stubFalse;
+
+  // node_modules/lodash-es/isBuffer.js
+  var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports;
+  var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module;
+  var moduleExports = freeModule && freeModule.exports === freeExports;
+  var Buffer2 = moduleExports ? root_default.Buffer : void 0;
+  var nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : void 0;
+  var isBuffer = nativeIsBuffer || stubFalse_default;
+  var isBuffer_default = isBuffer;
+
+  // node_modules/lodash-es/_baseIsTypedArray.js
+  var argsTag2 = "[object Arguments]";
+  var arrayTag = "[object Array]";
+  var boolTag = "[object Boolean]";
+  var dateTag = "[object Date]";
+  var errorTag = "[object Error]";
+  var funcTag2 = "[object Function]";
+  var mapTag = "[object Map]";
+  var numberTag = "[object Number]";
+  var objectTag = "[object Object]";
+  var regexpTag = "[object RegExp]";
+  var setTag = "[object Set]";
+  var stringTag = "[object String]";
+  var weakMapTag = "[object WeakMap]";
+  var arrayBufferTag = "[object ArrayBuffer]";
+  var dataViewTag = "[object DataView]";
+  var float32Tag = "[object Float32Array]";
+  var float64Tag = "[object Float64Array]";
+  var int8Tag = "[object Int8Array]";
+  var int16Tag = "[object Int16Array]";
+  var int32Tag = "[object Int32Array]";
+  var uint8Tag = "[object Uint8Array]";
+  var uint8ClampedTag = "[object Uint8ClampedArray]";
+  var uint16Tag = "[object Uint16Array]";
+  var uint32Tag = "[object Uint32Array]";
+  var typedArrayTags = {};
+  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
+  typedArrayTags[argsTag2] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag2] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
+  function baseIsTypedArray(value) {
+    return isObjectLike_default(value) && isLength_default(value.length) && !!typedArrayTags[baseGetTag_default(value)];
+  }
+  var baseIsTypedArray_default = baseIsTypedArray;
+
+  // node_modules/lodash-es/_baseUnary.js
+  function baseUnary(func) {
+    return function(value) {
+      return func(value);
+    };
+  }
+  var baseUnary_default = baseUnary;
+
+  // node_modules/lodash-es/_nodeUtil.js
+  var freeExports2 = typeof exports == "object" && exports && !exports.nodeType && exports;
+  var freeModule2 = freeExports2 && typeof module == "object" && module && !module.nodeType && module;
+  var moduleExports2 = freeModule2 && freeModule2.exports === freeExports2;
+  var freeProcess = moduleExports2 && freeGlobal_default.process;
+  var nodeUtil = function() {
+    try {
+      var types = freeModule2 && freeModule2.require && freeModule2.require("util").types;
+      if (types) {
+        return types;
+      }
+      return freeProcess && freeProcess.binding && freeProcess.binding("util");
+    } catch (e) {
+    }
+  }();
+  var nodeUtil_default = nodeUtil;
+
+  // node_modules/lodash-es/isTypedArray.js
+  var nodeIsTypedArray = nodeUtil_default && nodeUtil_default.isTypedArray;
+  var isTypedArray = nodeIsTypedArray ? baseUnary_default(nodeIsTypedArray) : baseIsTypedArray_default;
+  var isTypedArray_default = isTypedArray;
+
+  // node_modules/lodash-es/_arrayLikeKeys.js
+  var objectProto6 = Object.prototype;
+  var hasOwnProperty4 = objectProto6.hasOwnProperty;
+  function arrayLikeKeys(value, inherited) {
+    var isArr = isArray_default(value), isArg = !isArr && isArguments_default(value), isBuff = !isArr && !isArg && isBuffer_default(value), isType = !isArr && !isArg && !isBuff && isTypedArray_default(value), skipIndexes = isArr || isArg || isBuff || isType, result = skipIndexes ? baseTimes_default(value.length, String) : [], length = result.length;
+    for (var key in value) {
+      if ((inherited || hasOwnProperty4.call(value, key)) && !(skipIndexes && // Safari 9 has enumerable `arguments.length` in strict mode.
+      (key == "length" || // Node.js 0.10 has enumerable non-index properties on buffers.
+      isBuff && (key == "offset" || key == "parent") || // PhantomJS 2 has enumerable non-index properties on typed arrays.
+      isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || // Skip index properties.
+      isIndex_default(key, length)))) {
+        result.push(key);
+      }
+    }
+    return result;
+  }
+  var arrayLikeKeys_default = arrayLikeKeys;
+
+  // node_modules/lodash-es/_overArg.js
+  function overArg(func, transform2) {
+    return function(arg) {
+      return func(transform2(arg));
+    };
+  }
+  var overArg_default = overArg;
+
+  // node_modules/lodash-es/_nativeKeys.js
+  var nativeKeys = overArg_default(Object.keys, Object);
+  var nativeKeys_default = nativeKeys;
+
+  // node_modules/lodash-es/_baseKeys.js
+  var objectProto7 = Object.prototype;
+  var hasOwnProperty5 = objectProto7.hasOwnProperty;
+  function baseKeys(object) {
+    if (!isPrototype_default(object)) {
+      return nativeKeys_default(object);
+    }
+    var result = [];
+    for (var key in Object(object)) {
+      if (hasOwnProperty5.call(object, key) && key != "constructor") {
+        result.push(key);
+      }
+    }
+    return result;
+  }
+  var baseKeys_default = baseKeys;
+
+  // node_modules/lodash-es/keys.js
+  function keys(object) {
+    return isArrayLike_default(object) ? arrayLikeKeys_default(object) : baseKeys_default(object);
+  }
+  var keys_default = keys;
+
+  // node_modules/lodash-es/_nativeCreate.js
+  var nativeCreate = getNative_default(Object, "create");
+  var nativeCreate_default = nativeCreate;
+
+  // node_modules/lodash-es/_hashClear.js
+  function hashClear() {
+    this.__data__ = nativeCreate_default ? nativeCreate_default(null) : {};
+    this.size = 0;
+  }
+  var hashClear_default = hashClear;
+
+  // node_modules/lodash-es/_hashDelete.js
+  function hashDelete(key) {
+    var result = this.has(key) && delete this.__data__[key];
+    this.size -= result ? 1 : 0;
+    return result;
+  }
+  var hashDelete_default = hashDelete;
+
+  // node_modules/lodash-es/_hashGet.js
+  var HASH_UNDEFINED = "__lodash_hash_undefined__";
+  var objectProto8 = Object.prototype;
+  var hasOwnProperty6 = objectProto8.hasOwnProperty;
+  function hashGet(key) {
+    var data = this.__data__;
+    if (nativeCreate_default) {
+      var result = data[key];
+      return result === HASH_UNDEFINED ? void 0 : result;
+    }
+    return hasOwnProperty6.call(data, key) ? data[key] : void 0;
+  }
+  var hashGet_default = hashGet;
+
+  // node_modules/lodash-es/_hashHas.js
+  var objectProto9 = Object.prototype;
+  var hasOwnProperty7 = objectProto9.hasOwnProperty;
+  function hashHas(key) {
+    var data = this.__data__;
+    return nativeCreate_default ? data[key] !== void 0 : hasOwnProperty7.call(data, key);
+  }
+  var hashHas_default = hashHas;
+
+  // node_modules/lodash-es/_hashSet.js
+  var HASH_UNDEFINED2 = "__lodash_hash_undefined__";
+  function hashSet(key, value) {
+    var data = this.__data__;
+    this.size += this.has(key) ? 0 : 1;
+    data[key] = nativeCreate_default && value === void 0 ? HASH_UNDEFINED2 : value;
+    return this;
+  }
+  var hashSet_default = hashSet;
+
+  // node_modules/lodash-es/_Hash.js
+  function Hash(entries) {
+    var index = -1, length = entries == null ? 0 : entries.length;
+    this.clear();
+    while (++index < length) {
+      var entry = entries[index];
+      this.set(entry[0], entry[1]);
+    }
+  }
+  Hash.prototype.clear = hashClear_default;
+  Hash.prototype["delete"] = hashDelete_default;
+  Hash.prototype.get = hashGet_default;
+  Hash.prototype.has = hashHas_default;
+  Hash.prototype.set = hashSet_default;
+  var Hash_default = Hash;
+
+  // node_modules/lodash-es/_listCacheClear.js
+  function listCacheClear() {
+    this.__data__ = [];
+    this.size = 0;
+  }
+  var listCacheClear_default = listCacheClear;
+
+  // node_modules/lodash-es/_assocIndexOf.js
+  function assocIndexOf(array2, key) {
+    var length = array2.length;
+    while (length--) {
+      if (eq_default(array2[length][0], key)) {
+        return length;
+      }
+    }
+    return -1;
+  }
+  var assocIndexOf_default = assocIndexOf;
+
+  // node_modules/lodash-es/_listCacheDelete.js
+  var arrayProto = Array.prototype;
+  var splice = arrayProto.splice;
+  function listCacheDelete(key) {
+    var data = this.__data__, index = assocIndexOf_default(data, key);
+    if (index < 0) {
+      return false;
+    }
+    var lastIndex = data.length - 1;
+    if (index == lastIndex) {
+      data.pop();
+    } else {
+      splice.call(data, index, 1);
+    }
+    --this.size;
+    return true;
+  }
+  var listCacheDelete_default = listCacheDelete;
+
+  // node_modules/lodash-es/_listCacheGet.js
+  function listCacheGet(key) {
+    var data = this.__data__, index = assocIndexOf_default(data, key);
+    return index < 0 ? void 0 : data[index][1];
+  }
+  var listCacheGet_default = listCacheGet;
+
+  // node_modules/lodash-es/_listCacheHas.js
+  function listCacheHas(key) {
+    return assocIndexOf_default(this.__data__, key) > -1;
+  }
+  var listCacheHas_default = listCacheHas;
+
+  // node_modules/lodash-es/_listCacheSet.js
+  function listCacheSet(key, value) {
+    var data = this.__data__, index = assocIndexOf_default(data, key);
+    if (index < 0) {
+      ++this.size;
+      data.push([key, value]);
+    } else {
+      data[index][1] = value;
+    }
+    return this;
+  }
+  var listCacheSet_default = listCacheSet;
+
+  // node_modules/lodash-es/_ListCache.js
+  function ListCache(entries) {
+    var index = -1, length = entries == null ? 0 : entries.length;
+    this.clear();
+    while (++index < length) {
+      var entry = entries[index];
+      this.set(entry[0], entry[1]);
+    }
+  }
+  ListCache.prototype.clear = listCacheClear_default;
+  ListCache.prototype["delete"] = listCacheDelete_default;
+  ListCache.prototype.get = listCacheGet_default;
+  ListCache.prototype.has = listCacheHas_default;
+  ListCache.prototype.set = listCacheSet_default;
+  var ListCache_default = ListCache;
+
+  // node_modules/lodash-es/_Map.js
+  var Map2 = getNative_default(root_default, "Map");
+  var Map_default = Map2;
+
+  // node_modules/lodash-es/_mapCacheClear.js
+  function mapCacheClear() {
+    this.size = 0;
+    this.__data__ = {
+      "hash": new Hash_default(),
+      "map": new (Map_default || ListCache_default)(),
+      "string": new Hash_default()
+    };
+  }
+  var mapCacheClear_default = mapCacheClear;
+
+  // node_modules/lodash-es/_isKeyable.js
+  function isKeyable(value) {
+    var type2 = typeof value;
+    return type2 == "string" || type2 == "number" || type2 == "symbol" || type2 == "boolean" ? value !== "__proto__" : value === null;
+  }
+  var isKeyable_default = isKeyable;
+
+  // node_modules/lodash-es/_getMapData.js
+  function getMapData(map2, key) {
+    var data = map2.__data__;
+    return isKeyable_default(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
+  }
+  var getMapData_default = getMapData;
+
+  // node_modules/lodash-es/_mapCacheDelete.js
+  function mapCacheDelete(key) {
+    var result = getMapData_default(this, key)["delete"](key);
+    this.size -= result ? 1 : 0;
+    return result;
+  }
+  var mapCacheDelete_default = mapCacheDelete;
+
+  // node_modules/lodash-es/_mapCacheGet.js
+  function mapCacheGet(key) {
+    return getMapData_default(this, key).get(key);
+  }
+  var mapCacheGet_default = mapCacheGet;
+
+  // node_modules/lodash-es/_mapCacheHas.js
+  function mapCacheHas(key) {
+    return getMapData_default(this, key).has(key);
+  }
+  var mapCacheHas_default = mapCacheHas;
+
+  // node_modules/lodash-es/_mapCacheSet.js
+  function mapCacheSet(key, value) {
+    var data = getMapData_default(this, key), size = data.size;
+    data.set(key, value);
+    this.size += data.size == size ? 0 : 1;
+    return this;
+  }
+  var mapCacheSet_default = mapCacheSet;
+
+  // node_modules/lodash-es/_MapCache.js
+  function MapCache(entries) {
+    var index = -1, length = entries == null ? 0 : entries.length;
+    this.clear();
+    while (++index < length) {
+      var entry = entries[index];
+      this.set(entry[0], entry[1]);
+    }
+  }
+  MapCache.prototype.clear = mapCacheClear_default;
+  MapCache.prototype["delete"] = mapCacheDelete_default;
+  MapCache.prototype.get = mapCacheGet_default;
+  MapCache.prototype.has = mapCacheHas_default;
+  MapCache.prototype.set = mapCacheSet_default;
+  var MapCache_default = MapCache;
+
   // node_modules/lodash-es/toString.js
   function toString(value) {
     return value == null ? "" : baseToString_default(value);
   }
   var toString_default = toString;
 
+  // node_modules/lodash-es/_arrayPush.js
+  function arrayPush(array2, values) {
+    var index = -1, length = values.length, offset = array2.length;
+    while (++index < length) {
+      array2[offset + index] = values[index];
+    }
+    return array2;
+  }
+  var arrayPush_default = arrayPush;
+
   // node_modules/lodash-es/_basePropertyOf.js
   function basePropertyOf(object) {
     return function(key) {
   }
   var basePropertyOf_default = basePropertyOf;
 
+  // node_modules/lodash-es/_stackClear.js
+  function stackClear() {
+    this.__data__ = new ListCache_default();
+    this.size = 0;
+  }
+  var stackClear_default = stackClear;
+
+  // node_modules/lodash-es/_stackDelete.js
+  function stackDelete(key) {
+    var data = this.__data__, result = data["delete"](key);
+    this.size = data.size;
+    return result;
+  }
+  var stackDelete_default = stackDelete;
+
+  // node_modules/lodash-es/_stackGet.js
+  function stackGet(key) {
+    return this.__data__.get(key);
+  }
+  var stackGet_default = stackGet;
+
+  // node_modules/lodash-es/_stackHas.js
+  function stackHas(key) {
+    return this.__data__.has(key);
+  }
+  var stackHas_default = stackHas;
+
+  // node_modules/lodash-es/_stackSet.js
+  var LARGE_ARRAY_SIZE = 200;
+  function stackSet(key, value) {
+    var data = this.__data__;
+    if (data instanceof ListCache_default) {
+      var pairs = data.__data__;
+      if (!Map_default || pairs.length < LARGE_ARRAY_SIZE - 1) {
+        pairs.push([key, value]);
+        this.size = ++data.size;
+        return this;
+      }
+      data = this.__data__ = new MapCache_default(pairs);
+    }
+    data.set(key, value);
+    this.size = data.size;
+    return this;
+  }
+  var stackSet_default = stackSet;
+
+  // node_modules/lodash-es/_Stack.js
+  function Stack(entries) {
+    var data = this.__data__ = new ListCache_default(entries);
+    this.size = data.size;
+  }
+  Stack.prototype.clear = stackClear_default;
+  Stack.prototype["delete"] = stackDelete_default;
+  Stack.prototype.get = stackGet_default;
+  Stack.prototype.has = stackHas_default;
+  Stack.prototype.set = stackSet_default;
+  var Stack_default = Stack;
+
+  // node_modules/lodash-es/_arrayFilter.js
+  function arrayFilter(array2, predicate) {
+    var index = -1, length = array2 == null ? 0 : array2.length, resIndex = 0, result = [];
+    while (++index < length) {
+      var value = array2[index];
+      if (predicate(value, index, array2)) {
+        result[resIndex++] = value;
+      }
+    }
+    return result;
+  }
+  var arrayFilter_default = arrayFilter;
+
+  // node_modules/lodash-es/stubArray.js
+  function stubArray() {
+    return [];
+  }
+  var stubArray_default = stubArray;
+
+  // node_modules/lodash-es/_getSymbols.js
+  var objectProto10 = Object.prototype;
+  var propertyIsEnumerable2 = objectProto10.propertyIsEnumerable;
+  var nativeGetSymbols = Object.getOwnPropertySymbols;
+  var getSymbols = !nativeGetSymbols ? stubArray_default : function(object) {
+    if (object == null) {
+      return [];
+    }
+    object = Object(object);
+    return arrayFilter_default(nativeGetSymbols(object), function(symbol) {
+      return propertyIsEnumerable2.call(object, symbol);
+    });
+  };
+  var getSymbols_default = getSymbols;
+
+  // node_modules/lodash-es/_baseGetAllKeys.js
+  function baseGetAllKeys(object, keysFunc, symbolsFunc) {
+    var result = keysFunc(object);
+    return isArray_default(object) ? result : arrayPush_default(result, symbolsFunc(object));
+  }
+  var baseGetAllKeys_default = baseGetAllKeys;
+
+  // node_modules/lodash-es/_getAllKeys.js
+  function getAllKeys(object) {
+    return baseGetAllKeys_default(object, keys_default, getSymbols_default);
+  }
+  var getAllKeys_default = getAllKeys;
+
+  // node_modules/lodash-es/_DataView.js
+  var DataView2 = getNative_default(root_default, "DataView");
+  var DataView_default = DataView2;
+
+  // node_modules/lodash-es/_Promise.js
+  var Promise2 = getNative_default(root_default, "Promise");
+  var Promise_default = Promise2;
+
+  // node_modules/lodash-es/_Set.js
+  var Set2 = getNative_default(root_default, "Set");
+  var Set_default = Set2;
+
+  // node_modules/lodash-es/_getTag.js
+  var mapTag2 = "[object Map]";
+  var objectTag2 = "[object Object]";
+  var promiseTag = "[object Promise]";
+  var setTag2 = "[object Set]";
+  var weakMapTag2 = "[object WeakMap]";
+  var dataViewTag2 = "[object DataView]";
+  var dataViewCtorString = toSource_default(DataView_default);
+  var mapCtorString = toSource_default(Map_default);
+  var promiseCtorString = toSource_default(Promise_default);
+  var setCtorString = toSource_default(Set_default);
+  var weakMapCtorString = toSource_default(WeakMap_default);
+  var getTag = baseGetTag_default;
+  if (DataView_default && getTag(new DataView_default(new ArrayBuffer(1))) != dataViewTag2 || Map_default && getTag(new Map_default()) != mapTag2 || Promise_default && getTag(Promise_default.resolve()) != promiseTag || Set_default && getTag(new Set_default()) != setTag2 || WeakMap_default && getTag(new WeakMap_default()) != weakMapTag2) {
+    getTag = function(value) {
+      var result = baseGetTag_default(value), Ctor = result == objectTag2 ? value.constructor : void 0, ctorString = Ctor ? toSource_default(Ctor) : "";
+      if (ctorString) {
+        switch (ctorString) {
+          case dataViewCtorString:
+            return dataViewTag2;
+          case mapCtorString:
+            return mapTag2;
+          case promiseCtorString:
+            return promiseTag;
+          case setCtorString:
+            return setTag2;
+          case weakMapCtorString:
+            return weakMapTag2;
+        }
+      }
+      return result;
+    };
+  }
+  var getTag_default = getTag;
+
+  // node_modules/lodash-es/_Uint8Array.js
+  var Uint8Array2 = root_default.Uint8Array;
+  var Uint8Array_default = Uint8Array2;
+
+  // node_modules/lodash-es/_setCacheAdd.js
+  var HASH_UNDEFINED3 = "__lodash_hash_undefined__";
+  function setCacheAdd(value) {
+    this.__data__.set(value, HASH_UNDEFINED3);
+    return this;
+  }
+  var setCacheAdd_default = setCacheAdd;
+
+  // node_modules/lodash-es/_setCacheHas.js
+  function setCacheHas(value) {
+    return this.__data__.has(value);
+  }
+  var setCacheHas_default = setCacheHas;
+
+  // node_modules/lodash-es/_SetCache.js
+  function SetCache(values) {
+    var index = -1, length = values == null ? 0 : values.length;
+    this.__data__ = new MapCache_default();
+    while (++index < length) {
+      this.add(values[index]);
+    }
+  }
+  SetCache.prototype.add = SetCache.prototype.push = setCacheAdd_default;
+  SetCache.prototype.has = setCacheHas_default;
+  var SetCache_default = SetCache;
+
+  // node_modules/lodash-es/_arraySome.js
+  function arraySome(array2, predicate) {
+    var index = -1, length = array2 == null ? 0 : array2.length;
+    while (++index < length) {
+      if (predicate(array2[index], index, array2)) {
+        return true;
+      }
+    }
+    return false;
+  }
+  var arraySome_default = arraySome;
+
+  // node_modules/lodash-es/_cacheHas.js
+  function cacheHas(cache, key) {
+    return cache.has(key);
+  }
+  var cacheHas_default = cacheHas;
+
+  // node_modules/lodash-es/_equalArrays.js
+  var COMPARE_PARTIAL_FLAG = 1;
+  var COMPARE_UNORDERED_FLAG = 2;
+  function equalArrays(array2, other, bitmask, customizer, equalFunc, stack) {
+    var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array2.length, othLength = other.length;
+    if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
+      return false;
+    }
+    var arrStacked = stack.get(array2);
+    var othStacked = stack.get(other);
+    if (arrStacked && othStacked) {
+      return arrStacked == other && othStacked == array2;
+    }
+    var index = -1, result = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache_default() : void 0;
+    stack.set(array2, other);
+    stack.set(other, array2);
+    while (++index < arrLength) {
+      var arrValue = array2[index], othValue = other[index];
+      if (customizer) {
+        var compared = isPartial ? customizer(othValue, arrValue, index, other, array2, stack) : customizer(arrValue, othValue, index, array2, other, stack);
+      }
+      if (compared !== void 0) {
+        if (compared) {
+          continue;
+        }
+        result = false;
+        break;
+      }
+      if (seen) {
+        if (!arraySome_default(other, function(othValue2, othIndex) {
+          if (!cacheHas_default(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) {
+            return seen.push(othIndex);
+          }
+        })) {
+          result = false;
+          break;
+        }
+      } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
+        result = false;
+        break;
+      }
+    }
+    stack["delete"](array2);
+    stack["delete"](other);
+    return result;
+  }
+  var equalArrays_default = equalArrays;
+
+  // node_modules/lodash-es/_mapToArray.js
+  function mapToArray(map2) {
+    var index = -1, result = Array(map2.size);
+    map2.forEach(function(value, key) {
+      result[++index] = [key, value];
+    });
+    return result;
+  }
+  var mapToArray_default = mapToArray;
+
+  // node_modules/lodash-es/_setToArray.js
+  function setToArray(set3) {
+    var index = -1, result = Array(set3.size);
+    set3.forEach(function(value) {
+      result[++index] = value;
+    });
+    return result;
+  }
+  var setToArray_default = setToArray;
+
+  // node_modules/lodash-es/_equalByTag.js
+  var COMPARE_PARTIAL_FLAG2 = 1;
+  var COMPARE_UNORDERED_FLAG2 = 2;
+  var boolTag2 = "[object Boolean]";
+  var dateTag2 = "[object Date]";
+  var errorTag2 = "[object Error]";
+  var mapTag3 = "[object Map]";
+  var numberTag2 = "[object Number]";
+  var regexpTag2 = "[object RegExp]";
+  var setTag3 = "[object Set]";
+  var stringTag2 = "[object String]";
+  var symbolTag2 = "[object Symbol]";
+  var arrayBufferTag2 = "[object ArrayBuffer]";
+  var dataViewTag3 = "[object DataView]";
+  var symbolProto2 = Symbol_default ? Symbol_default.prototype : void 0;
+  var symbolValueOf = symbolProto2 ? symbolProto2.valueOf : void 0;
+  function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
+    switch (tag) {
+      case dataViewTag3:
+        if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
+          return false;
+        }
+        object = object.buffer;
+        other = other.buffer;
+      case arrayBufferTag2:
+        if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array_default(object), new Uint8Array_default(other))) {
+          return false;
+        }
+        return true;
+      case boolTag2:
+      case dateTag2:
+      case numberTag2:
+        return eq_default(+object, +other);
+      case errorTag2:
+        return object.name == other.name && object.message == other.message;
+      case regexpTag2:
+      case stringTag2:
+        return object == other + "";
+      case mapTag3:
+        var convert = mapToArray_default;
+      case setTag3:
+        var isPartial = bitmask & COMPARE_PARTIAL_FLAG2;
+        convert || (convert = setToArray_default);
+        if (object.size != other.size && !isPartial) {
+          return false;
+        }
+        var stacked = stack.get(object);
+        if (stacked) {
+          return stacked == other;
+        }
+        bitmask |= COMPARE_UNORDERED_FLAG2;
+        stack.set(object, other);
+        var result = equalArrays_default(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
+        stack["delete"](object);
+        return result;
+      case symbolTag2:
+        if (symbolValueOf) {
+          return symbolValueOf.call(object) == symbolValueOf.call(other);
+        }
+    }
+    return false;
+  }
+  var equalByTag_default = equalByTag;
+
+  // node_modules/lodash-es/_equalObjects.js
+  var COMPARE_PARTIAL_FLAG3 = 1;
+  var objectProto11 = Object.prototype;
+  var hasOwnProperty8 = objectProto11.hasOwnProperty;
+  function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
+    var isPartial = bitmask & COMPARE_PARTIAL_FLAG3, objProps = getAllKeys_default(object), objLength = objProps.length, othProps = getAllKeys_default(other), othLength = othProps.length;
+    if (objLength != othLength && !isPartial) {
+      return false;
+    }
+    var index = objLength;
+    while (index--) {
+      var key = objProps[index];
+      if (!(isPartial ? key in other : hasOwnProperty8.call(other, key))) {
+        return false;
+      }
+    }
+    var objStacked = stack.get(object);
+    var othStacked = stack.get(other);
+    if (objStacked && othStacked) {
+      return objStacked == other && othStacked == object;
+    }
+    var result = true;
+    stack.set(object, other);
+    stack.set(other, object);
+    var skipCtor = isPartial;
+    while (++index < objLength) {
+      key = objProps[index];
+      var objValue = object[key], othValue = other[key];
+      if (customizer) {
+        var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
+      }
+      if (!(compared === void 0 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
+        result = false;
+        break;
+      }
+      skipCtor || (skipCtor = key == "constructor");
+    }
+    if (result && !skipCtor) {
+      var objCtor = object.constructor, othCtor = other.constructor;
+      if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) {
+        result = false;
+      }
+    }
+    stack["delete"](object);
+    stack["delete"](other);
+    return result;
+  }
+  var equalObjects_default = equalObjects;
+
+  // node_modules/lodash-es/_baseIsEqualDeep.js
+  var COMPARE_PARTIAL_FLAG4 = 1;
+  var argsTag3 = "[object Arguments]";
+  var arrayTag2 = "[object Array]";
+  var objectTag3 = "[object Object]";
+  var objectProto12 = Object.prototype;
+  var hasOwnProperty9 = objectProto12.hasOwnProperty;
+  function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
+    var objIsArr = isArray_default(object), othIsArr = isArray_default(other), objTag = objIsArr ? arrayTag2 : getTag_default(object), othTag = othIsArr ? arrayTag2 : getTag_default(other);
+    objTag = objTag == argsTag3 ? objectTag3 : objTag;
+    othTag = othTag == argsTag3 ? objectTag3 : othTag;
+    var objIsObj = objTag == objectTag3, othIsObj = othTag == objectTag3, isSameTag = objTag == othTag;
+    if (isSameTag && isBuffer_default(object)) {
+      if (!isBuffer_default(other)) {
+        return false;
+      }
+      objIsArr = true;
+      objIsObj = false;
+    }
+    if (isSameTag && !objIsObj) {
+      stack || (stack = new Stack_default());
+      return objIsArr || isTypedArray_default(object) ? equalArrays_default(object, other, bitmask, customizer, equalFunc, stack) : equalByTag_default(object, other, objTag, bitmask, customizer, equalFunc, stack);
+    }
+    if (!(bitmask & COMPARE_PARTIAL_FLAG4)) {
+      var objIsWrapped = objIsObj && hasOwnProperty9.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty9.call(other, "__wrapped__");
+      if (objIsWrapped || othIsWrapped) {
+        var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other;
+        stack || (stack = new Stack_default());
+        return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
+      }
+    }
+    if (!isSameTag) {
+      return false;
+    }
+    stack || (stack = new Stack_default());
+    return equalObjects_default(object, other, bitmask, customizer, equalFunc, stack);
+  }
+  var baseIsEqualDeep_default = baseIsEqualDeep;
+
+  // node_modules/lodash-es/_baseIsEqual.js
+  function baseIsEqual(value, other, bitmask, customizer, stack) {
+    if (value === other) {
+      return true;
+    }
+    if (value == null || other == null || !isObjectLike_default(value) && !isObjectLike_default(other)) {
+      return value !== value && other !== other;
+    }
+    return baseIsEqualDeep_default(value, other, bitmask, customizer, baseIsEqual, stack);
+  }
+  var baseIsEqual_default = baseIsEqual;
+
   // node_modules/lodash-es/now.js
   var now2 = function() {
     return root_default.Date.now();
   }
   var escape_default = escape2;
 
+  // node_modules/lodash-es/isEqual.js
+  function isEqual(value, other) {
+    return baseIsEqual_default(value, other);
+  }
+  var isEqual_default = isEqual;
+
   // node_modules/lodash-es/throttle.js
   var FUNC_ERROR_TEXT2 = "Expected a function";
   function throttle(func, wait, options2) {
       _detected.version = navigator.appVersion;
     }
     _detected.version = _detected.version.split(/\W/).slice(0, 2).join(".");
-    _detected.opera = _detected.browser.toLowerCase() === "opera" && parseFloat(_detected.version) < 15;
+    _detected.opera = _detected.browser.toLowerCase() === "opera" && Number(_detected.version) < 15;
     if (_detected.browser.toLowerCase() === "msie") {
       _detected.ie = true;
       _detected.browser = "Internet Explorer";
       _detected.os = "win";
       _detected.platform = "Unknown";
     }
-    _detected.isMobileWebKit = (/\b(iPad|iPhone|iPod)\b/.test(ua) || navigator.platform === "MacIntel" && "maxTouchPoints" in navigator && navigator.maxTouchPoints > 1) && /WebKit/.test(ua) && !/Edge/.test(ua) && !window.MSStream;
+    _detected.isMobileWebKit = (/\b(iPad|iPhone|iPod)\b/.test(ua) || // HACK: iPadOS 13+ requests desktop sites by default by using a Mac user agent,
+    // so assume any "mac" with multitouch is actually iOS
+    navigator.platform === "MacIntel" && "maxTouchPoints" in navigator && navigator.maxTouchPoints > 1) && /WebKit/.test(ua) && !/Edge/.test(ua) && !window.MSStream;
     _detected.browserLocales = Array.from(new Set(
+      // remove duplicates
       [navigator.language].concat(navigator.languages || []).concat([
+        // old property for backwards compatibility
         navigator.userLanguage
       ]).filter(Boolean)
     ));
   }
 
   // modules/util/get_set_value.js
-  function utilGetSetValue(selection2, value) {
-    function d3_selection_value(value2) {
+  function utilGetSetValue(selection2, value, shouldUpdate) {
+    function setValue(value2, shouldUpdate2) {
       function valueNull() {
         delete this.value;
       }
       function valueConstant() {
-        if (this.value !== value2) {
+        if (shouldUpdate2(this.value, value2)) {
           this.value = value2;
         }
       }
         var x = value2.apply(this, arguments);
         if (x === null || x === void 0) {
           delete this.value;
-        } else if (this.value !== x) {
+        } else if (shouldUpdate2(this.value, x)) {
           this.value = x;
         }
       }
       return value2 === null || value2 === void 0 ? valueNull : typeof value2 === "function" ? valueFunction : valueConstant;
     }
+    function stickyCursor(func) {
+      return function() {
+        const cursor = { start: this.selectionStart, end: this.selectionEnd };
+        func.apply(this, arguments);
+        this.setSelectionRange(cursor.start, cursor.end);
+      };
+    }
     if (arguments.length === 1) {
       return selection2.property("value");
     }
-    return selection2.each(d3_selection_value(value));
+    if (shouldUpdate === void 0) {
+      shouldUpdate = (a, b) => a !== b;
+    }
+    const supportedTypes = ["text", "search", "url", "tel", "password"];
+    if (!supportedTypes.includes(this.type)) {
+      return selection2.each(setValue(value, shouldUpdate));
+    }
+    return selection2.each(stickyCursor(setValue(value, shouldUpdate)));
   }
 
   // modules/util/keybinding.js
           callback,
           event: {
             key: void 0,
+            // preferred
             keyCode: 0,
+            // fallback
             modifiers: {
               shiftKey: false,
               ctrlKey: false,
     return keybinding;
   }
   utilKeybinding.modifierCodes = {
+    // Shift key, ⇧
     "\u21E7": 16,
     shift: 16,
+    // CTRL key, on Mac: ⌃
     "\u2303": 17,
     ctrl: 17,
+    // ALT key, on Mac: ⌥ (Alt)
     "\u2325": 18,
     alt: 18,
     option: 18,
+    // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
     "\u2318": 91,
     meta: 91,
     cmd: 91,
   utilKeybinding.plusKeys = ["plus", "ffplus", "=", "ffequals", "\u2260", "\xB1"];
   utilKeybinding.minusKeys = ["_", "-", "ffminus", "dash", "\u2013", "\u2014"];
   utilKeybinding.keys = {
+    // Backspace key, on Mac: ⌫ (Backspace)
     "\u232B": "Backspace",
     backspace: "Backspace",
+    // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
     "\u21E5": "Tab",
     "\u21C6": "Tab",
     tab: "Tab",
+    // Return key, ↩
     "\u21A9": "Enter",
     "\u21B5": "Enter",
     "\u23CE": "Enter",
     "return": "Enter",
     enter: "Enter",
     "\u2305": "Enter",
+    // Pause/Break key
     "pause": "Pause",
     "pause-break": "Pause",
+    // Caps Lock key, ⇪
     "\u21EA": "CapsLock",
     caps: "CapsLock",
     "caps-lock": "CapsLock",
+    // Escape key, on Mac: ⎋, on Windows: Esc
     "\u238B": ["Escape", "Esc"],
     escape: ["Escape", "Esc"],
     esc: ["Escape", "Esc"],
+    // Space key
     space: [" ", "Spacebar"],
+    // Page-Up key, or pgup, on Mac: ↖
     "\u2196": "PageUp",
     pgup: "PageUp",
     "page-up": "PageUp",
+    // Page-Down key, or pgdown, on Mac: ↘
     "\u2198": "PageDown",
     pgdown: "PageDown",
     "page-down": "PageDown",
+    // END key, on Mac: ⇟
     "\u21DF": "End",
     end: "End",
+    // HOME key, on Mac: ⇞
     "\u21DE": "Home",
     home: "Home",
+    // Insert key, or ins
     ins: "Insert",
     insert: "Insert",
+    // Delete key, on Mac: ⌦ (Delete)
     "\u2326": ["Delete", "Del"],
     del: ["Delete", "Del"],
     "delete": ["Delete", "Del"],
+    // Left Arrow Key, or ←
     "\u2190": ["ArrowLeft", "Left"],
     left: ["ArrowLeft", "Left"],
     "arrow-left": ["ArrowLeft", "Left"],
+    // Up Arrow Key, or ↑
     "\u2191": ["ArrowUp", "Up"],
     up: ["ArrowUp", "Up"],
     "arrow-up": ["ArrowUp", "Up"],
+    // Right Arrow Key, or →
     "\u2192": ["ArrowRight", "Right"],
     right: ["ArrowRight", "Right"],
     "arrow-right": ["ArrowRight", "Right"],
+    // Up Arrow Key, or ↓
     "\u2193": ["ArrowDown", "Down"],
     down: ["ArrowDown", "Down"],
     "arrow-down": ["ArrowDown", "Down"],
+    // odities, stuff for backward compatibility (browsers and code):
+    // Num-Multiply, or *
     "*": ["*", "Multiply"],
     star: ["*", "Multiply"],
     asterisk: ["*", "Multiply"],
     multiply: ["*", "Multiply"],
+    // Num-Plus or +
     "+": ["+", "Add"],
     "plus": ["+", "Add"],
+    // Num-Subtract, or -
     "-": ["-", "Subtract"],
     subtract: ["-", "Subtract"],
     "dash": ["-", "Subtract"],
+    // Semicolon
     semicolon: ";",
+    // = or equals
     equals: "=",
+    // Comma, or ,
     comma: ",",
+    // Period, or ., or full-stop
     period: ".",
     "full-stop": ".",
+    // Slash, or /, or forward-slash
     slash: "/",
     "forward-slash": "/",
+    // Tick, or `, or back-quote
     tick: "`",
     "back-quote": "`",
+    // Open bracket, or [
     "open-bracket": "[",
+    // Back slash, or \
     "back-slash": "\\",
+    // Close backet, or ]
     "close-bracket": "]",
+    // Apostrophe, or Quote, or '
     quote: "'",
     apostrophe: "'",
+    // NUMPAD 0-9
     "num-0": "0",
     "num-1": "1",
     "num-2": "2",
     "num-7": "7",
     "num-8": "8",
     "num-9": "9",
+    // F1-F25
     f1: "F1",
     f2: "F2",
     f3: "F3",
     f25: "F25"
   };
   utilKeybinding.keyCodes = {
+    // Backspace key, on Mac: ⌫ (Backspace)
     "\u232B": 8,
     backspace: 8,
+    // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
     "\u21E5": 9,
     "\u21C6": 9,
     tab: 9,
+    // Return key, ↩
     "\u21A9": 13,
     "\u21B5": 13,
     "\u23CE": 13,
     "return": 13,
     enter: 13,
     "\u2305": 13,
+    // Pause/Break key
     "pause": 19,
     "pause-break": 19,
+    // Caps Lock key, ⇪
     "\u21EA": 20,
     caps: 20,
     "caps-lock": 20,
+    // Escape key, on Mac: ⎋, on Windows: Esc
     "\u238B": 27,
     escape: 27,
     esc: 27,
+    // Space key
     space: 32,
+    // Page-Up key, or pgup, on Mac: ↖
     "\u2196": 33,
     pgup: 33,
     "page-up": 33,
+    // Page-Down key, or pgdown, on Mac: ↘
     "\u2198": 34,
     pgdown: 34,
     "page-down": 34,
+    // END key, on Mac: ⇟
     "\u21DF": 35,
     end: 35,
+    // HOME key, on Mac: ⇞
     "\u21DE": 36,
     home: 36,
+    // Insert key, or ins
     ins: 45,
     insert: 45,
+    // Delete key, on Mac: ⌦ (Delete)
     "\u2326": 46,
     del: 46,
     "delete": 46,
+    // Left Arrow Key, or ←
     "\u2190": 37,
     left: 37,
     "arrow-left": 37,
+    // Up Arrow Key, or ↑
     "\u2191": 38,
     up: 38,
     "arrow-up": 38,
+    // Right Arrow Key, or →
     "\u2192": 39,
     right: 39,
     "arrow-right": 39,
+    // Up Arrow Key, or ↓
     "\u2193": 40,
     down: 40,
     "arrow-down": 40,
+    // odities, printing characters that come out wrong:
+    // Firefox Equals
     "ffequals": 61,
+    // Num-Multiply, or *
     "*": 106,
     star: 106,
     asterisk: 106,
     multiply: 106,
+    // Num-Plus or +
     "+": 107,
     "plus": 107,
+    // Num-Subtract, or -
     "-": 109,
     subtract: 109,
+    // Vertical Bar / Pipe
     "|": 124,
+    // Firefox Plus
     "ffplus": 171,
+    // Firefox Minus
     "ffminus": 173,
+    // Semicolon
     ";": 186,
     semicolon: 186,
+    // = or equals
     "=": 187,
     "equals": 187,
+    // Comma, or ,
     ",": 188,
     comma: 188,
+    // Dash / Underscore key
     "dash": 189,
+    // Period, or ., or full-stop
     ".": 190,
     period: 190,
     "full-stop": 190,
+    // Slash, or /, or forward-slash
     "/": 191,
     slash: 191,
     "forward-slash": 191,
+    // Tick, or `, or back-quote
     "`": 192,
     tick: 192,
     "back-quote": 192,
+    // Open bracket, or [
     "[": 219,
     "open-bracket": 219,
+    // Back slash, or \
     "\\": 220,
     "back-slash": 220,
+    // Close backet, or ]
     "]": 221,
     "close-bracket": 221,
+    // Apostrophe, or Quote, or '
     "'": 222,
     quote: 222,
     apostrophe: 222
     var mutex = {};
     var intervalID;
     function renew() {
-      var expires = new Date();
+      var expires = /* @__PURE__ */ new Date();
       expires.setSeconds(expires.getSeconds() + 5);
       document.cookie = name + "=1; expires=" + expires.toUTCString() + "; sameSite=strict";
     }
       }).filter(Boolean);
     };
     tiler8.getGeoJSON = function(projection2) {
-      var features2 = tiler8.getTiles(projection2).map(function(tile) {
+      var features = tiler8.getTiles(projection2).map(function(tile) {
         return {
           type: "Feature",
           properties: {
       });
       return {
         type: "FeatureCollection",
-        features: features2
+        features
       };
     };
     tiler8.tileSize = function(val) {
   }
 
   // modules/util/trigger_event.js
-  function utilTriggerEvent(target, type3) {
+  function utilTriggerEvent(target, type2) {
     target.each(function() {
       var evt = document.createEvent("HTMLEvents");
-      evt.initEvent(type3, true, true);
+      evt.initEvent(type2, true, true);
       this.dispatchEvent(evt);
     });
   }
         return _loadPromise;
       let filesToFetch = [
         "languages",
+        // load the list of languages
         "locales"
+        // load the list of supported locales
       ];
       const localeDirs = {
         general: "locales",
       let locale2 = _localeCode;
       if (locale2.toLowerCase() === "en-us")
         locale2 = "en";
-      _languageNames = _localeStrings.general[locale2].languageNames;
-      _scriptNames = _localeStrings.general[locale2].scriptNames;
+      _languageNames = _localeStrings.general[locale2].languageNames || _localeStrings.general[_languageCode].languageNames;
+      _scriptNames = _localeStrings.general[locale2].scriptNames || _localeStrings.general[_languageCode].scriptNames;
       _usesMetric = _localeCode.slice(-3).toLowerCase() !== "-us";
     }
     localizer.loadLocale = (locale2, scopeId, directory) => {
       return ret;
     };
     localizer.languageName = (code, options2) => {
-      if (_languageNames[code]) {
+      if (_languageNames && _languageNames[code]) {
         return _languageNames[code];
       }
       if (options2 && options2.localOnly)
           return localizer.t("translate.language_and_code", { language: langInfo.nativeName, code });
         } else if (langInfo.base && langInfo.script) {
           const base = langInfo.base;
-          if (_languageNames[base]) {
+          if (_languageNames && _languageNames[base]) {
             const scriptCode = langInfo.script;
-            const script = _scriptNames[scriptCode] || scriptCode;
+            const script = _scriptNames && _scriptNames[scriptCode] || scriptCode;
             return localizer.t("translate.language_and_code", { language: _languageNames[base], code: script });
           } else if (_dataLanguages[base] && _dataLanguages[base].nativeName) {
             return localizer.t("translate.language_and_code", { language: _dataLanguages[base].nativeName, code });
       }
       return code;
     };
+    localizer.floatFormatter = (locale2) => {
+      if (!("Intl" in window && "NumberFormat" in Intl && "formatToParts" in Intl.NumberFormat.prototype)) {
+        return (number3, fractionDigits) => {
+          return fractionDigits === void 0 ? number3.toString() : number3.toFixed(fractionDigits);
+        };
+      } else {
+        return (number3, fractionDigits) => number3.toLocaleString(locale2, {
+          minimumFractionDigits: fractionDigits,
+          maximumFractionDigits: fractionDigits === void 0 ? 20 : fractionDigits
+        });
+      }
+    };
+    localizer.floatParser = (locale2) => {
+      const polyfill = (string) => +string.trim();
+      if (!("Intl" in window && "NumberFormat" in Intl))
+        return polyfill;
+      const format2 = new Intl.NumberFormat(locale2, { maximumFractionDigits: 20 });
+      if (!("formatToParts" in format2))
+        return polyfill;
+      const parts = format2.formatToParts(-12345.6);
+      const numerals = Array.from({ length: 10 }).map((_, i2) => format2.format(i2));
+      const index = new Map(numerals.map((d, i2) => [d, i2]));
+      const literalPart = parts.find((d) => d.type === "literal");
+      const literal = literalPart && new RegExp(`[${literalPart.value}]`, "g");
+      const groupPart = parts.find((d) => d.type === "group");
+      const group = groupPart && new RegExp(`[${groupPart.value}]`, "g");
+      const decimalPart = parts.find((d) => d.type === "decimal");
+      const decimal = decimalPart && new RegExp(`[${decimalPart.value}]`);
+      const numeral = new RegExp(`[${numerals.join("")}]`, "g");
+      const getIndex = (d) => index.get(d);
+      return (string) => {
+        string = string.trim();
+        if (literal)
+          string = string.replace(literal, "");
+        if (group)
+          string = string.replace(group, "");
+        if (decimal)
+          string = string.replace(decimal, ".");
+        string = string.replace(numeral, getIndex);
+        return string ? +string : NaN;
+      };
+    };
+    localizer.decimalPlaceCounter = (locale2) => {
+      var literal, group, decimal;
+      if ("Intl" in window && "NumberFormat" in Intl) {
+        const format2 = new Intl.NumberFormat(locale2, { maximumFractionDigits: 20 });
+        if ("formatToParts" in format2) {
+          const parts = format2.formatToParts(-12345.6);
+          const literalPart = parts.find((d) => d.type === "literal");
+          literal = literalPart && new RegExp(`[${literalPart.value}]`, "g");
+          const groupPart = parts.find((d) => d.type === "group");
+          group = groupPart && new RegExp(`[${groupPart.value}]`, "g");
+          const decimalPart = parts.find((d) => d.type === "decimal");
+          decimal = decimalPart && new RegExp(`[${decimalPart.value}]`);
+        }
+      }
+      return (string) => {
+        string = string.trim();
+        if (literal)
+          string = string.replace(literal, "");
+        if (group)
+          string = string.replace(group, "");
+        const parts = string.split(decimal || ".");
+        return parts && parts[1] && parts[1].length || 0;
+      };
+    };
     return localizer;
   }
 
   }
 
   // modules/presets/preset.js
+  var import_lodash = __toESM(require_lodash());
   function presetPreset(presetID, preset, addable, allFields, allPresets) {
     allFields = allFields || {};
     allPresets = allPresets || {};
     let _this = Object.assign({}, preset);
     let _addable = addable || false;
-    let _resolvedFields;
-    let _resolvedMoreFields;
     let _searchName;
     let _searchNameStripped;
     let _searchAliases;
     _this.originalReference = _this.reference || {};
     _this.originalFields = _this.fields || [];
     _this.originalMoreFields = _this.moreFields || [];
-    _this.fields = () => _resolvedFields || (_resolvedFields = resolveFields("fields"));
-    _this.moreFields = () => _resolvedMoreFields || (_resolvedMoreFields = resolveFields("moreFields"));
-    _this.resetFields = () => _resolvedFields = _resolvedMoreFields = null;
+    _this.fields = (loc) => resolveFields("fields", loc);
+    _this.moreFields = (loc) => resolveFields("moreFields", loc);
     _this.tags = _this.tags || {};
     _this.addTags = _this.addTags || _this.tags;
     _this.removeTags = _this.removeTags || _this.addTags;
         return { key, value };
       }
     };
-    _this.unsetTags = (tags, geometry, ignoringKeys, skipFieldDefaults) => {
+    _this.unsetTags = (tags, geometry, ignoringKeys, skipFieldDefaults, loc) => {
       let removeTags = ignoringKeys ? utilObjectOmit(_this.removeTags, ignoringKeys) : _this.removeTags;
       tags = utilObjectOmit(tags, Object.keys(removeTags));
       if (geometry && !skipFieldDefaults) {
-        _this.fields().forEach((field) => {
+        _this.fields(loc).forEach((field) => {
           if (field.matchGeometry(geometry) && field.key && field.default === tags[field.key] && (!ignoringKeys || ignoringKeys.indexOf(field.key) === -1)) {
             delete tags[field.key];
           }
       delete tags.area;
       return tags;
     };
-    _this.setTags = (tags, geometry, skipFieldDefaults) => {
+    _this.setTags = (tags, geometry, skipFieldDefaults, loc) => {
       const addTags = _this.addTags;
       tags = Object.assign({}, tags);
       for (let k in addTags) {
         }
       }
       if (geometry && !skipFieldDefaults) {
-        _this.fields().forEach((field) => {
+        _this.fields(loc).forEach((field) => {
           if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
             tags[field.key] = field.default;
           }
       }
       return tags;
     };
-    function resolveFields(which) {
+    function resolveFields(which, loc) {
       const fieldIDs = which === "fields" ? _this.originalFields : _this.originalMoreFields;
       let resolved = [];
       fieldIDs.forEach((fieldID) => {
         const match = fieldID.match(referenceRegex);
         if (match !== null) {
-          resolved = resolved.concat(inheritFields(match[1], which));
+          resolved = resolved.concat(inheritFields(allPresets[match[1]], which));
         } else if (allFields[fieldID]) {
           resolved.push(allFields[fieldID]);
         } else {
         const endIndex = _this.id.lastIndexOf("/");
         const parentID = endIndex && _this.id.substring(0, endIndex);
         if (parentID) {
-          resolved = inheritFields(parentID, which);
+          let parent = allPresets[parentID];
+          if (loc) {
+            const validHere = _sharedLocationManager.locationSetsAt(loc);
+            if (parent?.locationSetID && !validHere[parent.locationSetID]) {
+              const candidateIDs = Object.keys(allPresets).filter((k) => k.startsWith(parentID));
+              parent = allPresets[candidateIDs.find((candidateID) => {
+                const candidate = allPresets[candidateID];
+                return validHere[candidate.locationSetID] && (0, import_lodash.isEqual)(candidate.tags, parent.tags);
+              })];
+            }
+          }
+          resolved = inheritFields(parent, which);
         }
       }
       return utilArrayUniq(resolved);
-      function inheritFields(presetID2, which2) {
-        const parent = allPresets[presetID2];
+      function inheritFields(parent, which2) {
         if (!parent)
           return [];
         if (which2 === "fields") {
         }
       }
       function shouldInherit(f2) {
-        if (f2.key && _this.tags[f2.key] !== void 0 && f2.type !== "multiCombo" && f2.type !== "semiCombo" && f2.type !== "manyCombo" && f2.type !== "check")
+        if (f2.key && _this.tags[f2.key] !== void 0 && // inherit anyway if multiple values are allowed or just a checkbox
+        f2.type !== "multiCombo" && f2.type !== "semiCombo" && f2.type !== "manyCombo" && f2.type !== "check")
           return false;
         return true;
       }
         });
       }
       _universal = Object.values(_fields).filter((field) => field.universal);
-      Object.values(_presets).forEach((preset) => preset.resetFields());
       _geometryIndex = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
       _this.collection.forEach((preset) => {
         (preset.geometry || []).forEach((geometry) => {
         footway: true,
         railway: true,
         junction: true,
+        traffic_calming: true,
         type: true
       };
       let areaKeys = {};
       const presets = _this.collection.filter((p) => !p.suggestion && !p.replacement);
       presets.forEach((p) => {
-        const keys = p.tags && Object.keys(p.tags);
-        const key = keys && keys.length && keys[0];
+        const keys2 = p.tags && Object.keys(p.tags);
+        const key = keys2 && keys2.length && keys2[0];
         if (!key)
           return;
         if (ignore[key])
         let key;
         for (key in p.addTags) {
           const value = p.addTags[key];
-          if (key in areaKeys && p.geometry.indexOf("line") !== -1 && value !== "*") {
+          if (key in areaKeys && // probably an area...
+          p.geometry.indexOf("line") !== -1 && // but sometimes a line
+          value !== "*") {
             areaKeys[key][value] = true;
           }
         }
       return _this.collection.filter((lineTags, d) => {
         if (d.suggestion || d.replacement || d.searchable === false)
           return lineTags;
-        const keys = d.tags && Object.keys(d.tags);
-        const key = keys && keys.length && keys[0];
+        const keys2 = d.tags && Object.keys(d.tags);
+        const key = keys2 && keys2.length && keys2[0];
         if (!key)
           return lineTags;
         if (d.geometry.indexOf("line") !== -1) {
       return _this.collection.reduce((pointTags, d) => {
         if (d.suggestion || d.replacement || d.searchable === false)
           return pointTags;
-        const keys = d.tags && Object.keys(d.tags);
-        const key = keys && keys.length && keys[0];
+        const keys2 = d.tags && Object.keys(d.tags);
+        const key = keys2 && keys2.length && keys2[0];
         if (!key)
           return pointTags;
         if (d.geometry.indexOf("point") !== -1) {
       return _this.collection.reduce((vertexTags, d) => {
         if (d.suggestion || d.replacement || d.searchable === false)
           return vertexTags;
-        const keys = d.tags && Object.keys(d.tags);
-        const key = keys && keys.length && keys[0];
+        const keys2 = d.tags && Object.keys(d.tags);
+        const key = keys2 && keys2.length && keys2[0];
         if (!key)
           return vertexTags;
         if (d.geometry.indexOf("vertex") !== -1) {
   }
   function utilTagDiff(oldTags, newTags) {
     var tagDiff = [];
-    var keys = utilArrayUnion(Object.keys(oldTags), Object.keys(newTags)).sort();
-    keys.forEach(function(k) {
+    var keys2 = utilArrayUnion(Object.keys(oldTags), Object.keys(newTags)).sort();
+    keys2.forEach(function(k) {
       var oldVal = oldTags[k];
       var newVal = newTags[k];
       if ((oldVal || oldVal === "") && (newVal === void 0 || newVal !== oldVal)) {
       return graph.hasEntity(entityID);
     }).filter(Boolean);
     entities.forEach(function(entity) {
-      var keys = Object.keys(entity.tags).filter(Boolean);
-      keys.forEach(function(key2) {
+      var keys2 = Object.keys(entity.tags).filter(Boolean);
+      keys2.forEach(function(key2) {
         allKeys.add(key2);
       });
     });
         } else {
           matrix[i2][j2] = Math.min(
             matrix[i2 - 1][j2 - 1] + 1,
+            // substitution
             Math.min(
               matrix[i2][j2 - 1] + 1,
+              // insertion
               matrix[i2 - 1][j2] + 1
             )
           );
     return str2.toLowerCase().replace(/[^a-z0-9]+/g, "_");
   }
   function utilUniqueDomId(val) {
-    return "ideditor-" + utilSafeClassName(val.toString()) + "-" + new Date().getTime().toString();
+    return "ideditor-" + utilSafeClassName(val.toString()) + "-" + (/* @__PURE__ */ new Date()).getTime().toString();
   }
   function utilUnicodeCharsCount(str2) {
     return Array.from(str2).length;
     }
     return ids[oldestIDIndex];
   }
+  function utilCleanOsmString(val, maxChars) {
+    if (val === void 0 || val === null) {
+      val = "";
+    } else {
+      val = val.toString();
+    }
+    val = val.trim();
+    if (val.normalize)
+      val = val.normalize("NFC");
+    return utilUnicodeCharsTruncated(val, maxChars);
+  }
 
   // modules/osm/entity.js
   function osmEntity(attrs) {
     }
     return new osmEntity().initialize(arguments);
   }
-  osmEntity.id = function(type3) {
-    return osmEntity.id.fromOSM(type3, osmEntity.id.next[type3]--);
+  osmEntity.id = function(type2) {
+    return osmEntity.id.fromOSM(type2, osmEntity.id.next[type2]--);
   };
   osmEntity.id.next = {
     changeset: -1,
     way: -1,
     relation: -1
   };
-  osmEntity.id.fromOSM = function(type3, id2) {
-    return type3[0] + id2;
+  osmEntity.id.fromOSM = function(type2, id2) {
+    return type2[0] + id2;
   };
   osmEntity.id.toOSM = function(id2) {
     var match = id2.match(/^[cnwr](-?\d+)$/);
           merged[k] = utilUnicodeCharsTruncated(
             utilArrayUnion(t1.split(/;\s*/), t2.split(/;\s*/)).join(";"),
             255
+            // avoid exceeding character limit; see also context.maxCharsForTagValue()
           );
         }
       }
         return -10;
       return 0;
     },
+    // the approximate width of the line based on its tags except its `width` tag
     impliedLineWidthMeters: function() {
       var averageWidths = {
         highway: {
+          // width is for single lane
           motorway: 5,
           motorway_link: 5,
           trunk: 4.5,
           footway: 1.5
         },
         railway: {
+          // width includes ties and rail bed, not just track gauge
           rail: 2.5,
           light_rail: 2.5,
           tram: 2.5,
       }
       return false;
     },
+    // Some identifier for tag that implies that this way is "sided",
+    // i.e. the right side is the 'inside' (e.g. the right side of a
+    // natural=cliff is lower).
     sidednessIdentifier: function() {
-      for (var key in this.tags) {
-        var value = this.tags[key];
+      for (const realKey in this.tags) {
+        const value = this.tags[realKey];
+        const key = osmRemoveLifecyclePrefix(realKey);
         if (key in osmRightSideIsInsideTags && value in osmRightSideIsInsideTags[key]) {
           if (osmRightSideIsInsideTags[key][value] === true) {
             return key;
       }
       return true;
     },
+    // returns an object with the tag that implies this is an area, if any
     tagSuggestingArea: function() {
       return osmTagSuggestingArea(this.tags);
     },
         return this.isArea() ? "area" : "line";
       });
     },
+    // returns an array of objects representing the segments between the nodes in this way
     segments: function(graph) {
       function segmentExtent(graph2) {
         var n1 = graph2.hasEntity(this.nodes[0]);
         return segments;
       });
     },
+    // If this way is not closed, append the beginning node to the end of the nodelist to close it.
     close: function() {
       if (this.isClosed() || !this.nodes.length)
         return this;
       nodes.push(nodes[0]);
       return this.update({ nodes });
     },
+    // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
     unclose: function() {
       if (!this.isClosed())
         return this;
       nodes = nodes.filter(noRepeatNodes);
       return this.update({ nodes });
     },
+    // Adds a node (id) in front of the node which is currently at position index.
+    // If index is undefined, the node will be added to the end of the way for linear ways,
+    //   or just before the final connecting node for circular ways.
+    // Consecutive duplicates are eliminated including existing ones.
+    // Circularity is always preserved when adding a node.
     addNode: function(id2, index) {
       var nodes = this.nodes.slice();
       var isClosed = this.isClosed();
       }
       return this.update({ nodes });
     },
+    // Replaces the node which is currently at position index with the given node (id).
+    // Consecutive duplicates are eliminated including existing ones.
+    // Circularity is preserved when updating a node.
     updateNode: function(id2, index) {
       var nodes = this.nodes.slice();
       var isClosed = this.isClosed();
       }
       return this.update({ nodes });
     },
+    // Replaces each occurrence of node id needle with replacement.
+    // Consecutive duplicates are eliminated including existing ones.
+    // Circularity is preserved.
     replaceNode: function(needleID, replacementID) {
       var nodes = this.nodes.slice();
       var isClosed = this.isClosed();
       }
       return this.update({ nodes });
     },
+    // Removes each occurrence of node id.
+    // Consecutive duplicates are eliminated including existing ones.
+    // Circularity is preserved.
     removeNode: function(id2) {
       var nodes = this.nodes.slice();
       var isClosed = this.isClosed();
       var entity = graph.entity(entityID);
       var geometry = entity.geometry(graph);
       var tags = entity.tags;
+      const loc = entity.extent(graph).center();
       var preserveKeys;
       if (newPreset) {
         preserveKeys = [];
         if (newPreset.addTags) {
           preserveKeys = preserveKeys.concat(Object.keys(newPreset.addTags));
         }
-        newPreset.fields().concat(newPreset.moreFields()).filter((f2) => f2.matchGeometry(geometry)).map((f2) => f2.key).filter(Boolean).forEach((key) => preserveKeys.push(key));
+        if (oldPreset && !oldPreset.id.startsWith(newPreset.id)) {
+          newPreset.fields(loc).concat(newPreset.moreFields(loc)).filter((f2) => f2.matchGeometry(geometry)).map((f2) => f2.key).filter(Boolean).forEach((key) => preserveKeys.push(key));
+        }
       }
       if (oldPreset)
-        tags = oldPreset.unsetTags(tags, geometry, preserveKeys);
+        tags = oldPreset.unsetTags(tags, geometry, preserveKeys, false, loc);
       if (newPreset)
-        tags = newPreset.setTags(tags, geometry, skipFieldDefaults);
+        tags = newPreset.setTags(tags, geometry, skipFieldDefaults, loc);
       return graph.replace(entity.update({ tags }));
     };
   }
     isDegenerate: function() {
       return !(Array.isArray(this.loc) && this.loc.length === 2 && this.loc[0] >= -180 && this.loc[0] <= 180 && this.loc[1] >= -90 && this.loc[1] <= 90);
     },
+    // Inspect tags and geometry to determine which direction(s) this node/vertex points
     directions: function(resolver, projection2) {
       var val;
       var i2;
       } else {
         val = (this.tags.direction || "").toLowerCase();
         var re2 = /:direction$/i;
-        var keys = Object.keys(this.tags);
-        for (i2 = 0; i2 < keys.length; i2++) {
-          if (re2.test(keys[i2])) {
-            val = this.tags[keys[i2]].toLowerCase();
+        var keys2 = Object.keys(this.tags);
+        for (i2 = 0; i2 < keys2.length; i2++) {
+          if (re2.test(keys2[i2])) {
+            val = this.tags[keys2[i2]].toLowerCase();
             break;
           }
         }
       difference.created().forEach(checkTags);
       return graph;
       function checkTags(entity) {
-        const keys = Object.keys(entity.tags);
+        const keys2 = Object.keys(entity.tags);
         let didDiscard = false;
         let tags = {};
-        for (let i2 = 0; i2 < keys.length; i2++) {
-          const k = keys[i2];
+        for (let i2 = 0; i2 < keys2.length; i2++) {
+          const k = keys2[i2];
           if (discardTags[k] || !entity.tags[k]) {
             didDiscard = true;
           } else {
           return;
         var multipolygon = multipolygons[0];
         for (var key in survivor.tags) {
-          if (multipolygon.tags[key] && multipolygon.tags[key] !== survivor.tags[key])
+          if (multipolygon.tags[key] && // don't collapse if tags cannot be cleanly merged
+          multipolygon.tags[key] !== survivor.tags[key])
             return;
         }
         survivor = survivor.mergeTags(multipolygon.tags);
         graph = graph.replace(survivor);
-        graph = actionDeleteRelation(multipolygon.id, true)(graph);
+        graph = actionDeleteRelation(
+          multipolygon.id,
+          true
+          /* allow untagged members */
+        )(graph);
         var tags = Object.assign({}, survivor.tags);
         if (survivor.geometry(graph) !== "area") {
           tags.area = "yes";
         }
       };
     },
+    // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
+    // XML. Returns a string.
     osmChangeJXON: function(changes) {
       var changeset_id = this.id;
       function nest(x, order) {
     isDegenerate: function() {
       return this.members.length === 0;
     },
+    // Return an array of members, each extended with an 'index' property whose value
+    // is the member index.
     indexedMembers: function() {
       var result = new Array(this.members.length);
       for (var i2 = 0; i2 < this.members.length; i2++) {
       }
       return result;
     },
+    // Return the first member with the given role. A copy of the member object
+    // is returned, extended with an 'index' property whose value is the member index.
     memberByRole: function(role) {
       for (var i2 = 0; i2 < this.members.length; i2++) {
         if (this.members[i2].role === role) {
         }
       }
     },
+    // Same as memberByRole, but returns all members with the given role
     membersByRole: function(role) {
       var result = [];
       for (var i2 = 0; i2 < this.members.length; i2++) {
       }
       return result;
     },
+    // Return the first member with the given id. A copy of the member object
+    // is returned, extended with an 'index' property whose value is the member index.
     memberById: function(id2) {
       for (var i2 = 0; i2 < this.members.length; i2++) {
         if (this.members[i2].id === id2) {
         }
       }
     },
+    // Return the first member with the given id and role. A copy of the member object
+    // is returned, extended with an 'index' property whose value is the member index.
     memberByIdAndRole: function(id2, role) {
       for (var i2 = 0; i2 < this.members.length; i2++) {
         if (this.members[i2].id === id2 && this.members[i2].role === role) {
       members.splice(toIndex, 0, members.splice(fromIndex, 1)[0]);
       return this.update({ members });
     },
+    // Wherever a member appears with id `needle.id`, replace it with a member
+    // with id `replacement.id`, type `replacement.type`, and the original role,
+    // By default, adding a duplicate member (by id and role) is prevented.
+    // Return an updated relation.
     replaceMember: function(needle, replacement, keepDuplicates) {
       if (!this.memberById(needle.id))
         return this;
     isConnectivity: function() {
       return !!(this.tags.type && this.tags.type.match(/^connectivity:?/));
     },
+    // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
+    // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
+    //
+    // This corresponds to the structure needed for rendering a multipolygon path using a
+    // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
+    //
+    // In the case of invalid geometries, this function will still return a result which
+    // includes the nodes of all way members, but some Nds may be unclosed and some inner
+    // rings not matched with the intended outer ring.
+    //
     multipolygon: function(resolver) {
       var outers = this.members.filter(function(m) {
         return "outer" === (m.role || "outer");
   });
 
   // modules/osm/qa_item.js
-  var QAItem = class {
+  var QAItem = class _QAItem {
     constructor(loc, service, itemType, id2, props) {
       this.loc = loc;
       this.service = service.title;
       this.itemType = itemType;
-      this.id = id2 ? id2 : `${QAItem.id()}`;
+      this.id = id2 ? id2 : `${_QAItem.id()}`;
       this.update(props);
       if (service && typeof service.getIcon === "function") {
         this.icon = service.getIcon(itemType);
       this.id = id2;
       return this;
     }
+    // Generic handling for newly created QAItems
     static id() {
       return this.nextId--;
     }
         wayB = wayB.update({ nodes: nodesB });
       }
       if (wayA.tags.step_count) {
-        var stepCount = parseFloat(wayA.tags.step_count);
-        if (stepCount && isFinite(stepCount) && stepCount > 0 && Math.round(stepCount) === stepCount) {
+        var stepCount = Number(wayA.tags.step_count);
+        if (stepCount && // ensure a number
+        isFinite(stepCount) && // ensure positive
+        stepCount > 0 && // ensure integer
+        Math.round(stepCount) === stepCount) {
           var tagsA = Object.assign({}, wayA.tags);
           var tagsB = Object.assign({}, wayB.tags);
           var ratioA = lengthA / (lengthA + lengthB);
         "parentRels": Object.getPrototypeOf(this._parentRels)
       };
     },
+    // Unlike other graph methods, rebase mutates in place. This is because it
+    // is used only during the history operation that merges newly downloaded
+    // data into each state. To external consumers, it should appear as if the
+    // graph always contained the newly downloaded data.
     rebase: function(entities, stack, force) {
       var base = this.base();
       var i2, j2, k, id2;
       }, this);
       this.transients = {};
     },
+    // Updates calculated properties (parentWays, parentRels) for the specified change
     _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
       parentWays = parentWays || this._parentWays;
       parentRels = parentRels || this._parentRels;
-      var type3 = entity && entity.type || oldentity && oldentity.type;
+      var type2 = entity && entity.type || oldentity && oldentity.type;
       var removed, added, i2;
-      if (type3 === "way") {
+      if (type2 === "way") {
         if (oldentity && entity) {
           removed = utilArrayDifference(oldentity.nodes, entity.nodes);
           added = utilArrayDifference(entity.nodes, oldentity.nodes);
           parentWays[added[i2]] = new Set(parentWays[added[i2]]);
           parentWays[added[i2]].add(entity.id);
         }
-      } else if (type3 === "relation") {
+      } else if (type2 === "relation") {
         var oldentityMemberIDs = oldentity ? oldentity.members.map(function(m) {
           return m.id;
         }) : [];
         graph.frozen = true;
       return graph;
     },
+    // Obliterates any existing entities
     load: function(entities) {
       var base = this.base();
       this.entities = Object.create(base.entities);
           if (!entity.__via)
             return;
         }
-        if (!entity.__oneWay && keyVertexIds.indexOf(n1.id) !== -1 && currPath.indexOf(n1.id) === -1) {
+        if (!entity.__oneWay && // bidirectional..
+        keyVertexIds.indexOf(n1.id) !== -1 && // key vertex..
+        currPath.indexOf(n1.id) === -1) {
           nextNodes.push(n1);
         }
-        if (keyVertexIds.indexOf(n2.id) !== -1 && currPath.indexOf(n2.id) === -1) {
+        if (keyVertexIds.indexOf(n2.id) !== -1 && // key vertex..
+        currPath.indexOf(n2.id) === -1) {
           nextNodes.push(n2);
         }
         nextNodes.forEach(function(nextNode) {
         ab,
         oStart: h.buffer1[0],
         oLength: h.buffer1[1],
+        // length of o to remove
         abStart: h.buffer2[0],
         abLength: h.buffer2[1]
+        // length of a/b to insert
+        // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1])
       });
     }
     diffIndices(o, a).forEach((item) => addHunk(item, "a"));
   }
 
   // modules/actions/merge_remote_changes.js
-  var import_lodash = __toESM(require_lodash());
+  var import_lodash2 = __toESM(require_lodash());
   function actionMergeRemoteChanges(id2, localGraph, remoteGraph, discardTags, formatUser) {
     discardTags = discardTags || {};
     var _option = "safe";
     var _conflicts = [];
     function user(d) {
-      return typeof formatUser === "function" ? formatUser(d) : (0, import_lodash.escape)(d);
+      return typeof formatUser === "function" ? formatUser(d) : (0, import_lodash2.escape)(d);
     }
     function mergeLocation(remote, target) {
       function pointEqual(a, b) {
       var o = base.tags || {};
       var a = target.tags || {};
       var b = remote.tags || {};
-      var keys = utilArrayUnion(utilArrayUnion(Object.keys(o), Object.keys(a)), Object.keys(b)).filter(function(k2) {
+      var keys2 = utilArrayUnion(utilArrayUnion(Object.keys(o), Object.keys(a)), Object.keys(b)).filter(function(k2) {
         return !discardTags[k2];
       });
       var tags = Object.assign({}, a);
       var changed = false;
-      for (var i2 = 0; i2 < keys.length; i2++) {
-        var k = keys[i2];
+      for (var i2 = 0; i2 < keys2.length; i2++) {
+        var k = keys2[i2];
         if (o[k] !== b[k] && a[k] !== b[k]) {
           if (o[k] !== a[k]) {
             _conflicts.push(_t.html(
       var keepingAllNodes = nodes.every(function(node, i3) {
         return i3 === 0 || i3 === nodes.length - 1 || shouldKeepNode(node, graph);
       });
-      if (maxDistance < 1e-4 && keepingAllNodes) {
+      if (maxDistance < 1e-4 && // Allow straightening even if already straight in order to remove extraneous nodes
+      keepingAllNodes) {
         return "straight_enough";
       }
     };
       _downPointer = {
         id: d3_event.pointerId || "mouse",
         pointerLocGetter,
-        downTime: +new Date(),
+        downTime: +/* @__PURE__ */ new Date(),
         downLoc: pointerLocGetter(d3_event)
       };
       dispatch10.call("down", this, d3_event, datum2(d3_event));
       _lastPointerUpEvent = d3_event;
       if (downPointer.isCancelled)
         return;
-      var t2 = +new Date();
+      var t2 = +/* @__PURE__ */ new Date();
       var p2 = downPointer.pointerLocGetter(d3_event);
       var dist = geoVecLength(downPointer.downLoc, p2);
       if (dist < _closeTolerance || dist < _tolerance && t2 - downPointer.downTime < 500) {
         _disableSpace = false;
         select_default2(window).on("keyup.space-block", null);
       });
-      var loc = context.map().mouse() || context.projection(context.map().center());
+      var loc = context.map().mouse() || // or the map center if the mouse has never entered the map
+      context.projection(context.map().center());
       click(d3_event, loc);
     }
     function backspace(d3_event) {
     var group = locale2.grouping === void 0 || locale2.thousands === void 0 ? identity_default3 : formatGroup_default(map.call(locale2.grouping, Number), locale2.thousands + ""), currencyPrefix = locale2.currency === void 0 ? "" : locale2.currency[0] + "", currencySuffix = locale2.currency === void 0 ? "" : locale2.currency[1] + "", decimal = locale2.decimal === void 0 ? "." : locale2.decimal + "", numerals = locale2.numerals === void 0 ? identity_default3 : formatNumerals_default(map.call(locale2.numerals, String)), percent = locale2.percent === void 0 ? "%" : locale2.percent + "", minus = locale2.minus === void 0 ? "\u2212" : locale2.minus + "", nan = locale2.nan === void 0 ? "NaN" : locale2.nan + "";
     function newFormat(specifier) {
       specifier = formatSpecifier(specifier);
-      var fill = specifier.fill, align = specifier.align, sign2 = specifier.sign, symbol = specifier.symbol, zero3 = specifier.zero, width = specifier.width, comma = specifier.comma, precision2 = specifier.precision, trim = specifier.trim, type3 = specifier.type;
-      if (type3 === "n")
-        comma = true, type3 = "g";
-      else if (!formatTypes_default[type3])
-        precision2 === void 0 && (precision2 = 12), trim = true, type3 = "g";
+      var fill = specifier.fill, align = specifier.align, sign2 = specifier.sign, symbol = specifier.symbol, zero3 = specifier.zero, width = specifier.width, comma = specifier.comma, precision2 = specifier.precision, trim = specifier.trim, type2 = specifier.type;
+      if (type2 === "n")
+        comma = true, type2 = "g";
+      else if (!formatTypes_default[type2])
+        precision2 === void 0 && (precision2 = 12), trim = true, type2 = "g";
       if (zero3 || fill === "0" && align === "=")
         zero3 = true, fill = "0", align = "=";
-      var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type3) ? "0" + type3.toLowerCase() : "", suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type3) ? percent : "";
-      var formatType = formatTypes_default[type3], maybeSuffix = /[defgprs%]/.test(type3);
-      precision2 = precision2 === void 0 ? 6 : /[gprs]/.test(type3) ? Math.max(1, Math.min(21, precision2)) : Math.max(0, Math.min(20, precision2));
+      var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type2) ? "0" + type2.toLowerCase() : "", suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type2) ? percent : "";
+      var formatType = formatTypes_default[type2], maybeSuffix = /[defgprs%]/.test(type2);
+      precision2 = precision2 === void 0 ? 6 : /[gprs]/.test(type2) ? Math.max(1, Math.min(21, precision2)) : Math.max(0, Math.min(20, precision2));
       function format2(value) {
         var valuePrefix = prefix, valueSuffix = suffix, i2, n2, c;
-        if (type3 === "c") {
+        if (type2 === "c") {
           valueSuffix = formatType(value) + valueSuffix;
           value = "";
         } else {
           if (valueNegative && +value === 0 && sign2 !== "+")
             valueNegative = false;
           valuePrefix = (valueNegative ? sign2 === "(" ? sign2 : minus : sign2 === "-" || sign2 === "(" ? "" : sign2) + valuePrefix;
-          valueSuffix = (type3 === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign2 === "(" ? ")" : "");
+          valueSuffix = (type2 === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign2 === "(" ? ")" : "");
           if (maybeSuffix) {
             i2 = -1, n2 = value.length;
             while (++i2 < n2) {
     var _done = false;
     var _timer;
     function ratchetyInterpolator(a, b, steps2, units) {
-      a = parseFloat(a);
-      b = parseFloat(b);
+      a = Number(a);
+      b = Number(b);
       var sample = quantize().domain([0, 1]).range(quantize_default(number_default(a, b), steps2));
       return function(t) {
         return String(sample(t)) + (units || "");
         var opacity;
         var width;
         if (tag === "circle") {
-          opacity = parseFloat(s.style("fill-opacity") || 0.5);
-          width = parseFloat(s.style("r") || 15.5);
+          opacity = Number(s.style("fill-opacity") || 0.5);
+          width = Number(s.style("r") || 15.5);
         } else {
-          opacity = parseFloat(s.style("stroke-opacity") || 0.7);
-          width = parseFloat(s.style("stroke-width") || 10);
+          opacity = Number(s.style("stroke-opacity") || 0.7);
+          width = Number(s.style("stroke-width") || 10);
         }
         p.tag = tag;
         p.from.opacity = opacity * 0.6;
         var parents = context.graph().parentRelations(entity);
         for (var i2 = 0; i2 < parents.length; i2++) {
           var parent = parents[i2];
-          var type3 = parent.tags.type;
+          var type2 = parent.tags.type;
           var role = parent.memberById(id2).role || "outer";
-          if (type3 === "route" || type3 === "boundary" || type3 === "multipolygon" && role === "outer") {
+          if (type2 === "route" || type2 === "boundary" || type2 === "multipolygon" && role === "outer") {
             return true;
           }
         }
   }
 
   // node_modules/d3-fetch/src/xml.js
-  function parser(type3) {
-    return (input, init2) => text_default3(input, init2).then((text2) => new DOMParser().parseFromString(text2, type3));
+  function parser(type2) {
+    return (input, init2) => text_default3(input, init2).then((text2) => new DOMParser().parseFromString(text2, type2));
   }
   var xml_default = parser("application/xml");
   var html = parser("text/html");
   var _krData = { errorTypes: {}, localizeStrings: {} };
   var _cache;
   var _krRuleset = [
+    // no 20 - multiple node on same spot - these are mostly boundaries overlapping roads
     30,
     40,
     50,
         rtree: new import_rbush.default()
       };
     },
+    // KeepRight API:  http://osm.mueschelsoft.de/keepright/interfacing.php
     loadIssues(projection2) {
       const options2 = {
         format: "geojson",
           callback(null, d);
       });
     },
+    // Get all cached QAItems covering the viewport
     getItems(projection2) {
       const viewport = projection2.clipExtent();
       const min3 = [viewport[0][0], viewport[1][1]];
       const bbox2 = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
       return _cache.rtree.search(bbox2).map((d) => d.data);
     },
+    // Get a QAItem from cache
+    // NOTE: Don't change method name until UI v3 is merged
     getError(id2) {
       return _cache.data[id2];
     },
+    // Replace a single QAItem in the cache
     replaceItem(item) {
       if (!(item instanceof QAItem) || !item.id)
         return;
       updateRtree(encodeIssueRtree(item), true);
       return item;
     },
+    // Remove a single QAItem from the cache
     removeItem(item) {
       if (!(item instanceof QAItem) || !item.id)
         return;
     issueURL(item) {
       return `${_krUrlRoot}/report_map.php?schema=${item.schema}&error=${item.id}`;
     },
+    // Get an array of issues closed during this session.
+    // Used to populate `closed:keepright` changeset tag
     getClosedIDs() {
       return Object.keys(_cache.closed).sort();
     }
         client: "iD",
         status: "OPEN",
         zoom: "19"
+        // Use a high zoom so that clusters aren't returned
       };
       const tiles = tiler2.zoomExtent([_tileZoom2, _tileZoom2]).getTiles(projection2);
       abortUnwantedRequests2(_cache2, tiles);
                 loc = preventCoincident(loc, false);
                 let d = new QAItem(loc, this, k, itemId, {
                   issueKey: k,
+                  // used as a category
                   identifier: {
+                    // used to post changes
                     wayId,
                     fromNodeId,
                     toNodeId
             }
             if (data.tiles) {
               data.tiles.forEach((feature3) => {
-                const { type: type3, x, y, numberOfTrips } = feature3;
-                const geoType = type3.toLowerCase();
+                const { type: type2, x, y, numberOfTrips } = feature3;
+                const geoType = type2.toLowerCase();
                 const itemId = `${geoType}${x}${y}${numberOfTrips}`;
                 let loc = pointAverage(feature3.points);
                 loc = preventCoincident(loc, false);
         json_default(url, options2).then(() => {
           delete _cache2.inflightPost[d.id];
           if (!d.newStatus) {
-            const now3 = new Date();
+            const now3 = /* @__PURE__ */ new Date();
             let comments = d.comments ? d.comments : [];
             comments.push({
               username: payload.username,
         });
       }
     },
+    // Get all cached QAItems covering the viewport
     getItems(projection2) {
       const viewport = projection2.clipExtent();
       const min3 = [viewport[0][0], viewport[1][1]];
       const bbox2 = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
       return _cache2.rtree.search(bbox2).map((d) => d.data);
     },
+    // Get a QAItem from cache
+    // NOTE: Don't change method name until UI v3 is merged
     getError(id2) {
       return _cache2.data[id2];
     },
+    // get the name of the icon to display for this item
     getIcon(itemType) {
       return _impOsmData.icons[itemType];
     },
+    // Replace a single QAItem in the cache
     replaceItem(issue) {
       if (!(issue instanceof QAItem) || !issue.id)
         return;
       updateRtree2(encodeIssueRtree2(issue), true);
       return issue;
     },
+    // Remove a single QAItem from the cache
     removeItem(issue) {
       if (!(issue instanceof QAItem) || !issue.id)
         return;
       delete _cache2.data[issue.id];
       updateRtree2(encodeIssueRtree2(issue), false);
     },
+    // Used to populate `closed:improveosm:*` changeset tags
     getClosedCounts() {
       return _cache2.closed;
     }
       headerIds: true,
       headerPrefix: "",
       highlight: null,
+      hooks: null,
       langPrefix: "language-",
       mangle: true,
       pedantic: false,
     defaults = newDefaults;
   }
   var escapeTest = /[&<>"']/;
-  var escapeReplace = /[&<>"']/g;
-  var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
-  var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
+  var escapeReplace = new RegExp(escapeTest.source, "g");
+  var escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;
+  var escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, "g");
   var escapeReplacements = {
     "&": "&amp;",
     "<": "&lt;",
   }
   var noopTest = { exec: function noopTest2() {
   } };
-  function merge2(obj) {
-    let i2 = 1, target, key;
-    for (; i2 < arguments.length; i2++) {
-      target = arguments[i2];
-      for (key in target) {
-        if (Object.prototype.hasOwnProperty.call(target, key)) {
-          obj[key] = target[key];
-        }
-      }
-    }
-    return obj;
-  }
   function splitCells(tableRow, count) {
     const row = tableRow.replace(/\|/g, (match, offset, str2) => {
       let escaped = false, curr = offset;
     }
     return -1;
   }
-  function checkSanitizeDeprecation(opt) {
-    if (opt && opt.sanitize && !opt.silent) {
+  function checkDeprecations(opt, callback) {
+    if (!opt || opt.silent) {
+      return;
+    }
+    if (callback) {
+      console.warn("marked(): callback is deprecated since version 5.0.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/using_pro#async");
+    }
+    if (opt.sanitize || opt.sanitizer) {
       console.warn("marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options");
     }
-  }
-  function repeatString(pattern, count) {
-    if (count < 1) {
-      return "";
+    if (opt.highlight || opt.langPrefix !== "language-") {
+      console.warn("marked(): highlight and langPrefix parameters are deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-highlight.");
     }
-    let result = "";
-    while (count > 1) {
-      if (count & 1) {
-        result += pattern;
-      }
-      count >>= 1;
-      pattern += pattern;
+    if (opt.mangle) {
+      console.warn("marked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.");
+    }
+    if (opt.baseUrl) {
+      console.warn("marked(): baseUrl parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-base-url.");
+    }
+    if (opt.smartypants) {
+      console.warn("marked(): smartypants parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-smartypants.");
+    }
+    if (opt.xhtml) {
+      console.warn("marked(): xhtml parameter is deprecated since version 5.0.0, should not be used and will be removed in the future. Instead use https://www.npmjs.com/package/marked-xhtml.");
+    }
+    if (opt.headerIds || opt.headerPrefix) {
+      console.warn("marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install  https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.");
     }
-    return result + pattern;
   }
   function outputLink(cap, link2, raw, lexer2) {
     const href = link2.href;
       const cap = this.rules.block.blockquote.exec(src);
       if (cap) {
         const text2 = cap[0].replace(/^ *>[ \t]?/gm, "");
+        const top = this.lexer.state.top;
+        this.lexer.state.top = true;
+        const tokens = this.lexer.blockTokens(text2);
+        this.lexer.state.top = top;
         return {
           type: "blockquote",
           raw: cap[0],
-          tokens: this.lexer.blockTokens(text2, []),
+          tokens,
           text: text2
         };
       }
           }
           raw = cap[0];
           src = src.substring(raw.length);
-          line = cap[2].split("\n", 1)[0];
+          line = cap[2].split("\n", 1)[0].replace(/^\t+/, (t) => " ".repeat(3 * t.length));
           nextLine = src.split("\n", 1)[0];
           if (this.options.pedantic) {
             indent2 = 2;
             endEarly = true;
           }
           if (!endEarly) {
-            const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent2 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?: [^\\n]*)?(?:\\n|$))`);
+            const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent2 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[   ][^\\n]*)?(?:\\n|$))`);
             const hrRegex = new RegExp(`^ {0,${Math.min(3, indent2 - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);
             const fencesBeginRegex = new RegExp(`^ {0,${Math.min(3, indent2 - 1)}}(?:\`\`\`|~~~)`);
             const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent2 - 1)}}#`);
             while (src) {
               rawLine = src.split("\n", 1)[0];
-              line = rawLine;
+              nextLine = rawLine;
               if (this.options.pedantic) {
-                line = line.replace(/^ {1,4}(?=( {4})*[^ ])/g, "  ");
+                nextLine = nextLine.replace(/^ {1,4}(?=( {4})*[^ ])/g, "  ");
               }
-              if (fencesBeginRegex.test(line)) {
+              if (fencesBeginRegex.test(nextLine)) {
                 break;
               }
-              if (headingBeginRegex.test(line)) {
+              if (headingBeginRegex.test(nextLine)) {
                 break;
               }
-              if (nextBulletRegex.test(line)) {
+              if (nextBulletRegex.test(nextLine)) {
                 break;
               }
               if (hrRegex.test(src)) {
                 break;
               }
-              if (line.search(/[^ ]/) >= indent2 || !line.trim()) {
-                itemContents += "\n" + line.slice(indent2);
-              } else if (!blankLine) {
-                itemContents += "\n" + line;
+              if (nextLine.search(/[^ ]/) >= indent2 || !nextLine.trim()) {
+                itemContents += "\n" + nextLine.slice(indent2);
               } else {
-                break;
+                if (blankLine) {
+                  break;
+                }
+                if (line.search(/[^ ]/) >= 4) {
+                  break;
+                }
+                if (fencesBeginRegex.test(line)) {
+                  break;
+                }
+                if (headingBeginRegex.test(line)) {
+                  break;
+                }
+                if (hrRegex.test(line)) {
+                  break;
+                }
+                itemContents += "\n" + nextLine;
               }
-              if (!blankLine && !line.trim()) {
+              if (!blankLine && !nextLine.trim()) {
                 blankLine = true;
               }
               raw += rawLine + "\n";
               src = src.substring(rawLine.length + 1);
+              line = nextLine.slice(indent2);
             }
           }
           if (!list.loose) {
         for (i2 = 0; i2 < l; i2++) {
           this.lexer.state.top = false;
           list.items[i2].tokens = this.lexer.blockTokens(list.items[i2].text, []);
-          const spacers = list.items[i2].tokens.filter((t) => t.type === "space");
-          const hasMultipleLineBreaks = spacers.every((t) => {
-            const chars = t.raw.split("");
-            let lineBreaks = 0;
-            for (const char of chars) {
-              if (char === "\n") {
-                lineBreaks += 1;
-              }
-              if (lineBreaks > 1) {
-                return true;
-              }
-            }
-            return false;
-          });
-          if (!list.loose && spacers.length && hasMultipleLineBreaks) {
-            list.loose = true;
+          if (!list.loose) {
+            const spacers = list.items[i2].tokens.filter((t) => t.type === "space");
+            const hasMultipleLineBreaks = spacers.length > 0 && spacers.some((t) => /\n.*\n/.test(t.raw));
+            list.loose = hasMultipleLineBreaks;
+          }
+        }
+        if (list.loose) {
+          for (i2 = 0; i2 < l; i2++) {
             list.items[i2].loose = true;
           }
         }
       if (cap) {
         const token = {
           type: "html",
+          block: true,
           raw: cap[0],
           pre: !this.options.sanitizer && (cap[1] === "pre" || cap[1] === "script" || cap[1] === "style"),
           text: cap[0]
     def(src) {
       const cap = this.rules.block.def.exec(src);
       if (cap) {
-        if (cap[3])
-          cap[3] = cap[3].substring(1, cap[3].length - 1);
         const tag = cap[1].toLowerCase().replace(/\s+/g, " ");
+        const href = cap[2] ? cap[2].replace(/^<(.*)>$/, "$1").replace(this.rules.inline._escapes, "$1") : "";
+        const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline._escapes, "$1") : cap[3];
         return {
           type: "def",
           tag,
           raw: cap[0],
-          href: cap[2] ? cap[2].replace(this.rules.inline._escapes, "$1") : cap[2],
-          title: cap[3] ? cap[3].replace(this.rules.inline._escapes, "$1") : cap[3]
+          href,
+          title
         };
       }
     }
           raw: cap[0],
           inLink: this.lexer.state.inLink,
           inRawBlock: this.lexer.state.inRawBlock,
+          block: false,
           text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape4(cap[0]) : cap[0]
         };
       }
       if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
         let link2 = (cap[2] || cap[1]).replace(/\s+/g, " ");
         link2 = links[link2.toLowerCase()];
-        if (!link2 || !link2.href) {
+        if (!link2) {
           const text2 = cap[0].charAt(0);
           return {
             type: "text",
       if (match[3] && prevChar.match(/[\p{L}\p{N}]/u))
         return;
       const nextChar = match[1] || match[2] || "";
-      if (!nextChar || nextChar && (prevChar === "" || this.rules.inline.punctuation.exec(prevChar))) {
+      if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {
         const lLength = match[0].length - 1;
         let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
         const endReg = match[0][0] === "*" ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
           if (delimTotal > 0)
             continue;
           rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
-          const raw = src.slice(0, lLength + match.index + (match[0].length - rDelim.length) + rLength);
+          const raw = src.slice(0, lLength + match.index + rLength + 1);
           if (Math.min(lLength, rLength) % 2) {
             const text3 = raw.slice(1, -1);
             return {
           } while (prevCapZero !== cap[0]);
           text2 = escape4(cap[0]);
           if (cap[1] === "www.") {
-            href = "http://" + text2;
+            href = "http://" + cap[0];
           } else {
-            href = text2;
+            href = cap[0];
           }
         }
         return {
   var block = {
     newline: /^(?: *(?:\n|$))+/,
     code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
-    fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
+    fences: /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
     hr: /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,
     heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
     blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
     list: /^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,
     html: "^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))",
-    def: /^ {0,3}\[(label)\]: *(?:\n *)?<?([^\s>]+)>?(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,
+    def: /^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,
     table: noopTest,
-    lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
+    lheading: /^((?:(?!^bull ).|\n(?!\n|bull ))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
+    // regex template, placeholders will be replaced according to different paragraph
+    // interruption rules of commonmark and the original markdown spec:
     _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
     text: /^[^\n]+/
   };
   block._tag = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
   block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
   block.html = edit(block.html, "i").replace("comment", block._comment).replace("tag", block._tag).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
+  block.lheading = edit(block.lheading).replace(/bull/g, block.bullet).getRegex();
   block.paragraph = edit(block._paragraph).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
   block.blockquote = edit(block.blockquote).replace("paragraph", block.paragraph).getRegex();
-  block.normal = merge2({}, block);
-  block.gfm = merge2({}, block.normal, {
+  block.normal = { ...block };
+  block.gfm = {
+    ...block.normal,
     table: "^ *([^\\n ].*\\|.*)\\n {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"
-  });
+    // Cells
+  };
   block.gfm.table = edit(block.gfm.table).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("blockquote", " {0,3}>").replace("code", " {4}[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
   block.gfm.paragraph = edit(block._paragraph).replace("hr", block.hr).replace("heading", " {0,3}#{1,6} ").replace("|lheading", "").replace("table", block.gfm.table).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", block._tag).getRegex();
-  block.pedantic = merge2({}, block.normal, {
+  block.pedantic = {
+    ...block.normal,
     html: edit(
       `^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`
     ).replace("comment", block._comment).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),
     def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
     heading: /^(#{1,6})(.*)(?:\n+|$)/,
     fences: noopTest,
+    // fences not supported
+    lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
     paragraph: edit(block.normal._paragraph).replace("hr", block.hr).replace("heading", " *#{1,6} *[^\n]").replace("lheading", block.lheading).replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").getRegex()
-  });
+  };
   var inline = {
     escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
     autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
     url: noopTest,
     tag: "^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>",
+    // CDATA section
     link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
     reflink: /^!?\[(label)\]\[(ref)\]/,
     nolink: /^!?\[(ref)\](?:\[\])?/,
     reflinkSearch: "reflink|nolink(?!\\()",
     emStrong: {
-      lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
-      rDelimAst: /^(?:[^_*\\]|\\.)*?\_\_(?:[^_*\\]|\\.)*?\*(?:[^_*\\]|\\.)*?(?=\_\_)|(?:[^*\\]|\\.)+(?=[^*])|[punct_](\*+)(?=[\s]|$)|(?:[^punct*_\s\\]|\\.)(\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|(?:[^punct*_\s\\]|\\.)(\*+)(?=[^punct*_\s])/,
-      rDelimUnd: /^(?:[^_*\\]|\\.)*?\*\*(?:[^_*\\]|\\.)*?\_(?:[^_*\\]|\\.)*?(?=\*\*)|(?:[^_\\]|\\.)+(?=[^_])|[punct*](\_+)(?=[\s]|$)|(?:[^punct*_\s\\]|\\.)(\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/
+      lDelim: /^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,
+      //         (1) and (2) can only be a Right Delimiter. (3) and (4) can only be Left.  (5) and (6) can be either Left or Right.
+      //         | Skip orphan inside strong      | Consume to delim | (1) #***              | (2) a***#, a***                    | (3) #***a, ***a                  | (4) ***#                 | (5) #***#                         | (6) a***a
+      rDelimAst: /^[^_*]*?__[^_*]*?\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\*)[punct](\*+)(?=[\s]|$)|[^punct\s](\*+)(?!\*)(?=[punct\s]|$)|(?!\*)[punct\s](\*+)(?=[^punct\s])|[\s](\*+)(?!\*)(?=[punct])|(?!\*)[punct](\*+)(?!\*)(?=[punct])|[^punct\s](\*+)(?=[^punct\s])/,
+      rDelimUnd: /^[^_*]*?\*\*[^_*]*?_[^_*]*?(?=\*\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\s]|$)|[^punct\s](_+)(?!_)(?=[punct\s]|$)|(?!_)[punct\s](_+)(?=[^punct\s])|[\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])/
+      // ^- Not allowed for _
     },
     code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
     br: /^( {2,}|\\)\n(?!\s*$)/,
     del: noopTest,
     text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
-    punctuation: /^([\spunctuation])/
+    punctuation: /^((?![*_])[\spunctuation])/
   };
-  inline._punctuation = "!\"#$%&'()+\\-.,/:;<=>?@\\[\\]`^{|}~";
-  inline.punctuation = edit(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
-  inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
-  inline.escapedEmSt = /(?:^|[^\\])(?:\\\\)*\\[*_]/g;
+  inline._punctuation = "\\p{P}$+<=>`^|~";
+  inline.punctuation = edit(inline.punctuation, "u").replace(/punctuation/g, inline._punctuation).getRegex();
+  inline.blockSkip = /\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g;
+  inline.anyPunctuation = /\\[punct]/g;
+  inline._escapes = /\\([punct])/g;
   inline._comment = edit(block._comment).replace("(?:-->|$)", "-->").getRegex();
-  inline.emStrong.lDelim = edit(inline.emStrong.lDelim).replace(/punct/g, inline._punctuation).getRegex();
-  inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, "g").replace(/punct/g, inline._punctuation).getRegex();
-  inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, "g").replace(/punct/g, inline._punctuation).getRegex();
-  inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
+  inline.emStrong.lDelim = edit(inline.emStrong.lDelim, "u").replace(/punct/g, inline._punctuation).getRegex();
+  inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, "gu").replace(/punct/g, inline._punctuation).getRegex();
+  inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, "gu").replace(/punct/g, inline._punctuation).getRegex();
+  inline.anyPunctuation = edit(inline.anyPunctuation, "gu").replace(/punct/g, inline._punctuation).getRegex();
+  inline._escapes = edit(inline._escapes, "gu").replace(/punct/g, inline._punctuation).getRegex();
   inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
   inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
   inline.autolink = edit(inline.autolink).replace("scheme", inline._scheme).replace("email", inline._email).getRegex();
   inline.reflink = edit(inline.reflink).replace("label", inline._label).replace("ref", block._label).getRegex();
   inline.nolink = edit(inline.nolink).replace("ref", block._label).getRegex();
   inline.reflinkSearch = edit(inline.reflinkSearch, "g").replace("reflink", inline.reflink).replace("nolink", inline.nolink).getRegex();
-  inline.normal = merge2({}, inline);
-  inline.pedantic = merge2({}, inline.normal, {
+  inline.normal = { ...inline };
+  inline.pedantic = {
+    ...inline.normal,
     strong: {
       start: /^__|\*\*/,
       middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
     },
     link: edit(/^!?\[(label)\]\((.*?)\)/).replace("label", inline._label).getRegex(),
     reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", inline._label).getRegex()
-  });
-  inline.gfm = merge2({}, inline.normal, {
+  };
+  inline.gfm = {
+    ...inline.normal,
     escape: edit(inline.escape).replace("])", "~|])").getRegex(),
     _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
     url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
-    _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
+    _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,
     del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
     text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
-  });
+  };
   inline.gfm.url = edit(inline.gfm.url, "i").replace("email", inline.gfm._extended_email).getRegex();
-  inline.breaks = merge2({}, inline.gfm, {
+  inline.breaks = {
+    ...inline.gfm,
     br: edit(inline.br).replace("{2,}", "*").getRegex(),
     text: edit(inline.gfm.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex()
-  });
+  };
   function smartypants(text2) {
     return text2.replace(/---/g, "\u2014").replace(/--/g, "\u2013").replace(/(^|[-\u2014/(\[{"\s])'/g, "$1\u2018").replace(/'/g, "\u2019").replace(/(^|[-\u2014/(\[{\u2018\s])"/g, "$1\u201C").replace(/"/g, "\u201D").replace(/\.{3}/g, "\u2026");
   }
     }
     return out;
   }
-  var Lexer = class {
+  var Lexer = class _Lexer {
     constructor(options2) {
       this.tokens = [];
       this.tokens.links = /* @__PURE__ */ Object.create(null);
       }
       this.tokenizer.rules = rules;
     }
+    /**
+     * Expose Rules
+     */
     static get rules() {
       return {
         block,
         inline
       };
     }
+    /**
+     * Static Lex Method
+     */
     static lex(src, options2) {
-      const lexer2 = new Lexer(options2);
+      const lexer2 = new _Lexer(options2);
       return lexer2.lex(src);
     }
+    /**
+     * Static Lex Inline Method
+     */
     static lexInline(src, options2) {
-      const lexer2 = new Lexer(options2);
+      const lexer2 = new _Lexer(options2);
       return lexer2.inlineTokens(src);
     }
+    /**
+     * Preprocessing
+     */
     lex(src) {
       src = src.replace(/\r\n|\r/g, "\n");
       this.blockTokens(src, this.tokens);
       }
       return this.tokens;
     }
+    /**
+     * Lexing
+     */
     blockTokens(src, tokens = []) {
       if (this.options.pedantic) {
         src = src.replace(/\t/g, "    ").replace(/^ +$/gm, "");
       this.inlineQueue.push({ src, tokens });
       return tokens;
     }
+    /**
+     * Lexing/Compiling
+     */
     inlineTokens(src, tokens = []) {
       let token, lastToken, cutSrc;
       let maskedSrc = src;
         if (links.length > 0) {
           while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
             if (links.includes(match[0].slice(match[0].lastIndexOf("[") + 1, -1))) {
-              maskedSrc = maskedSrc.slice(0, match.index) + "[" + repeatString("a", match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
+              maskedSrc = maskedSrc.slice(0, match.index) + "[" + "a".repeat(match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
             }
           }
         }
       }
       while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
-        maskedSrc = maskedSrc.slice(0, match.index) + "[" + repeatString("a", match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
+        maskedSrc = maskedSrc.slice(0, match.index) + "[" + "a".repeat(match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
       }
-      while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
-        maskedSrc = maskedSrc.slice(0, match.index + match[0].length - 2) + "++" + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
-        this.tokenizer.rules.inline.escapedEmSt.lastIndex--;
+      while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
+        maskedSrc = maskedSrc.slice(0, match.index) + "++" + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
       }
       while (src) {
         if (!keepPrevChar) {
       if (!lang) {
         return "<pre><code>" + (escaped ? code : escape4(code, true)) + "</code></pre>\n";
       }
-      return '<pre><code class="' + this.options.langPrefix + escape4(lang, true) + '">' + (escaped ? code : escape4(code, true)) + "</code></pre>\n";
+      return '<pre><code class="' + this.options.langPrefix + escape4(lang) + '">' + (escaped ? code : escape4(code, true)) + "</code></pre>\n";
     }
+    /**
+     * @param {string} quote
+     */
     blockquote(quote2) {
       return `<blockquote>
 ${quote2}</blockquote>
 `;
     }
-    html(html2) {
+    html(html2, block2) {
       return html2;
     }
+    /**
+     * @param {string} text
+     * @param {string} level
+     * @param {string} raw
+     * @param {any} slugger
+     */
     heading(text2, level, raw, slugger) {
       if (this.options.headerIds) {
         const id2 = this.options.headerPrefix + slugger.slug(raw);
@@ -36399,9 +38261,12 @@ ${quote2}</blockquote>
       return this.options.xhtml ? "<hr/>\n" : "<hr>\n";
     }
     list(body, ordered, start2) {
-      const type3 = ordered ? "ol" : "ul", startatt = ordered && start2 !== 1 ? ' start="' + start2 + '"' : "";
-      return "<" + type3 + startatt + ">\n" + body + "</" + type3 + ">\n";
+      const type2 = ordered ? "ol" : "ul", startatt = ordered && start2 !== 1 ? ' start="' + start2 + '"' : "";
+      return "<" + type2 + startatt + ">\n" + body + "</" + type2 + ">\n";
     }
+    /**
+     * @param {string} text
+     */
     listitem(text2) {
       return `<li>${text2}</li>
 `;
@@ -36409,53 +38274,86 @@ ${quote2}</blockquote>
     checkbox(checked) {
       return "<input " + (checked ? 'checked="" ' : "") + 'disabled="" type="checkbox"' + (this.options.xhtml ? " /" : "") + "> ";
     }
+    /**
+     * @param {string} text
+     */
     paragraph(text2) {
       return `<p>${text2}</p>
 `;
     }
+    /**
+     * @param {string} header
+     * @param {string} body
+     */
     table(header, body) {
       if (body)
         body = `<tbody>${body}</tbody>`;
       return "<table>\n<thead>\n" + header + "</thead>\n" + body + "</table>\n";
     }
+    /**
+     * @param {string} content
+     */
     tablerow(content) {
       return `<tr>
 ${content}</tr>
 `;
     }
     tablecell(content, flags) {
-      const type3 = flags.header ? "th" : "td";
-      const tag = flags.align ? `<${type3} align="${flags.align}">` : `<${type3}>`;
-      return tag + content + `</${type3}>
+      const type2 = flags.header ? "th" : "td";
+      const tag = flags.align ? `<${type2} align="${flags.align}">` : `<${type2}>`;
+      return tag + content + `</${type2}>
 `;
     }
+    /**
+     * span level renderer
+     * @param {string} text
+     */
     strong(text2) {
       return `<strong>${text2}</strong>`;
     }
+    /**
+     * @param {string} text
+     */
     em(text2) {
       return `<em>${text2}</em>`;
     }
+    /**
+     * @param {string} text
+     */
     codespan(text2) {
       return `<code>${text2}</code>`;
     }
     br() {
       return this.options.xhtml ? "<br/>" : "<br>";
     }
+    /**
+     * @param {string} text
+     */
     del(text2) {
       return `<del>${text2}</del>`;
     }
+    /**
+     * @param {string} href
+     * @param {string} title
+     * @param {string} text
+     */
     link(href, title, text2) {
       href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
       if (href === null) {
         return text2;
       }
-      let out = '<a href="' + escape4(href) + '"';
+      let out = '<a href="' + href + '"';
       if (title) {
         out += ' title="' + title + '"';
       }
       out += ">" + text2 + "</a>";
       return out;
     }
+    /**
+     * @param {string} href
+     * @param {string} title
+     * @param {string} text
+     */
     image(href, title, text2) {
       href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
       if (href === null) {
@@ -36473,6 +38371,7 @@ ${content}</tr>
     }
   };
   var TextRenderer = class {
+    // no need for block level renderers
     strong(text2) {
       return text2;
     }
@@ -36505,9 +38404,17 @@ ${content}</tr>
     constructor() {
       this.seen = {};
     }
+    /**
+     * @param {string} value
+     */
     serialize(value) {
       return value.toLowerCase().trim().replace(/<[!\/a-z].*?>/ig, "").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, "").replace(/\s/g, "-");
     }
+    /**
+     * Finds the next safe (unique) slug to use
+     * @param {string} originalSlug
+     * @param {boolean} isDryRun
+     */
     getNextSafeSlug(originalSlug, isDryRun) {
       let slug = originalSlug;
       let occurenceAccumulator = 0;
@@ -36524,12 +38431,18 @@ ${content}</tr>
       }
       return slug;
     }
+    /**
+     * Convert string to unique id
+     * @param {object} [options]
+     * @param {boolean} [options.dryrun] Generates the next unique slug without
+     * updating the internal accumulator.
+     */
     slug(value, options2 = {}) {
       const slug = this.serialize(value);
       return this.getNextSafeSlug(slug, options2.dryrun);
     }
   };
-  var Parser = class {
+  var Parser = class _Parser {
     constructor(options2) {
       this.options = options2 || defaults;
       this.options.renderer = this.options.renderer || new Renderer();
@@ -36538,14 +38451,23 @@ ${content}</tr>
       this.textRenderer = new TextRenderer();
       this.slugger = new Slugger();
     }
+    /**
+     * Static Parse Method
+     */
     static parse(tokens, options2) {
-      const parser3 = new Parser(options2);
+      const parser3 = new _Parser(options2);
       return parser3.parse(tokens);
     }
+    /**
+     * Static Parse Inline Method
+     */
     static parseInline(tokens, options2) {
-      const parser3 = new Parser(options2);
+      const parser3 = new _Parser(options2);
       return parser3.parseInline(tokens);
     }
+    /**
+     * Parse Loop
+     */
     parse(tokens, top = true) {
       let out = "", i2, j2, k, l2, l3, row, cell, header, body, token, ordered, start2, loose, itemBody, item, checked, task, checkbox, ret;
       const l = tokens.length;
@@ -36652,7 +38574,7 @@ ${content}</tr>
             continue;
           }
           case "html": {
-            out += this.renderer.html(token.text);
+            out += this.renderer.html(token.text, token.block);
             continue;
           }
           case "paragraph": {
@@ -36681,6 +38603,9 @@ ${content}</tr>
       }
       return out;
     }
+    /**
+     * Parse Inline Tokens
+     */
     parseInline(tokens, renderer) {
       renderer = renderer || this.renderer;
       let out = "", i2, token, ret;
@@ -36749,259 +38674,353 @@ ${content}</tr>
       return out;
     }
   };
-  function marked(src, opt, callback) {
-    if (typeof src === "undefined" || src === null) {
-      throw new Error("marked(): input parameter is undefined or null");
-    }
-    if (typeof src !== "string") {
-      throw new Error("marked(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected");
+  var Hooks = class {
+    constructor(options2) {
+      this.options = options2 || defaults;
     }
-    if (typeof opt === "function") {
-      callback = opt;
-      opt = null;
+    static passThroughHooks = /* @__PURE__ */ new Set([
+      "preprocess",
+      "postprocess"
+    ]);
+    /**
+     * Process markdown before marked
+     */
+    preprocess(markdown) {
+      return markdown;
+    }
+    /**
+     * Process HTML after marked is finished
+     */
+    postprocess(html2) {
+      return html2;
     }
-    opt = merge2({}, marked.defaults, opt || {});
-    checkSanitizeDeprecation(opt);
-    if (callback) {
-      const highlight = opt.highlight;
-      let tokens;
-      try {
-        tokens = Lexer.lex(src, opt);
-      } catch (e) {
-        return callback(e);
-      }
-      const done = function(err) {
-        let out;
-        if (!err) {
-          try {
-            if (opt.walkTokens) {
-              marked.walkTokens(tokens, opt.walkTokens);
+  };
+  var Marked = class {
+    defaults = getDefaults();
+    options = this.setOptions;
+    parse = this.#parseMarkdown(Lexer.lex, Parser.parse);
+    parseInline = this.#parseMarkdown(Lexer.lexInline, Parser.parseInline);
+    Parser = Parser;
+    parser = Parser.parse;
+    Renderer = Renderer;
+    TextRenderer = TextRenderer;
+    Lexer = Lexer;
+    lexer = Lexer.lex;
+    Tokenizer = Tokenizer;
+    Slugger = Slugger;
+    Hooks = Hooks;
+    constructor(...args) {
+      this.use(...args);
+    }
+    walkTokens(tokens, callback) {
+      let values = [];
+      for (const token of tokens) {
+        values = values.concat(callback.call(this, token));
+        switch (token.type) {
+          case "table": {
+            for (const cell of token.header) {
+              values = values.concat(this.walkTokens(cell.tokens, callback));
+            }
+            for (const row of token.rows) {
+              for (const cell of row) {
+                values = values.concat(this.walkTokens(cell.tokens, callback));
+              }
+            }
+            break;
+          }
+          case "list": {
+            values = values.concat(this.walkTokens(token.items, callback));
+            break;
+          }
+          default: {
+            if (this.defaults.extensions && this.defaults.extensions.childTokens && this.defaults.extensions.childTokens[token.type]) {
+              this.defaults.extensions.childTokens[token.type].forEach((childTokens) => {
+                values = values.concat(this.walkTokens(token[childTokens], callback));
+              });
+            } else if (token.tokens) {
+              values = values.concat(this.walkTokens(token.tokens, callback));
             }
-            out = Parser.parse(tokens, opt);
-          } catch (e) {
-            err = e;
           }
         }
-        opt.highlight = highlight;
-        return err ? callback(err) : callback(null, out);
-      };
-      if (!highlight || highlight.length < 3) {
-        return done();
-      }
-      delete opt.highlight;
-      if (!tokens.length)
-        return done();
-      let pending = 0;
-      marked.walkTokens(tokens, function(token) {
-        if (token.type === "code") {
-          pending++;
-          setTimeout(() => {
-            highlight(token.text, token.lang, function(err, code) {
-              if (err) {
-                return done(err);
+      }
+      return values;
+    }
+    use(...args) {
+      const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} };
+      args.forEach((pack) => {
+        const opts = { ...pack };
+        opts.async = this.defaults.async || opts.async || false;
+        if (pack.extensions) {
+          pack.extensions.forEach((ext) => {
+            if (!ext.name) {
+              throw new Error("extension name required");
+            }
+            if (ext.renderer) {
+              const prevRenderer = extensions.renderers[ext.name];
+              if (prevRenderer) {
+                extensions.renderers[ext.name] = function(...args2) {
+                  let ret = ext.renderer.apply(this, args2);
+                  if (ret === false) {
+                    ret = prevRenderer.apply(this, args2);
+                  }
+                  return ret;
+                };
+              } else {
+                extensions.renderers[ext.name] = ext.renderer;
               }
-              if (code != null && code !== token.text) {
-                token.text = code;
-                token.escaped = true;
+            }
+            if (ext.tokenizer) {
+              if (!ext.level || ext.level !== "block" && ext.level !== "inline") {
+                throw new Error("extension level must be 'block' or 'inline'");
               }
-              pending--;
-              if (pending === 0) {
-                done();
+              if (extensions[ext.level]) {
+                extensions[ext.level].unshift(ext.tokenizer);
+              } else {
+                extensions[ext.level] = [ext.tokenizer];
               }
-            });
-          }, 0);
-        }
-      });
-      if (pending === 0) {
-        done();
-      }
-      return;
-    }
-    function onError(e) {
-      e.message += "\nPlease report this to https://github.com/markedjs/marked.";
-      if (opt.silent) {
-        return "<p>An error occurred:</p><pre>" + escape4(e.message + "", true) + "</pre>";
-      }
-      throw e;
-    }
-    try {
-      const tokens = Lexer.lex(src, opt);
-      if (opt.walkTokens) {
-        if (opt.async) {
-          return Promise.all(marked.walkTokens(tokens, opt.walkTokens)).then(() => {
-            return Parser.parse(tokens, opt);
-          }).catch(onError);
+              if (ext.start) {
+                if (ext.level === "block") {
+                  if (extensions.startBlock) {
+                    extensions.startBlock.push(ext.start);
+                  } else {
+                    extensions.startBlock = [ext.start];
+                  }
+                } else if (ext.level === "inline") {
+                  if (extensions.startInline) {
+                    extensions.startInline.push(ext.start);
+                  } else {
+                    extensions.startInline = [ext.start];
+                  }
+                }
+              }
+            }
+            if (ext.childTokens) {
+              extensions.childTokens[ext.name] = ext.childTokens;
+            }
+          });
+          opts.extensions = extensions;
+        }
+        if (pack.renderer) {
+          const renderer = this.defaults.renderer || new Renderer(this.defaults);
+          for (const prop in pack.renderer) {
+            const prevRenderer = renderer[prop];
+            renderer[prop] = (...args2) => {
+              let ret = pack.renderer[prop].apply(renderer, args2);
+              if (ret === false) {
+                ret = prevRenderer.apply(renderer, args2);
+              }
+              return ret;
+            };
+          }
+          opts.renderer = renderer;
         }
-        marked.walkTokens(tokens, opt.walkTokens);
-      }
-      return Parser.parse(tokens, opt);
-    } catch (e) {
-      onError(e);
-    }
-  }
-  marked.options = marked.setOptions = function(opt) {
-    merge2(marked.defaults, opt);
-    changeDefaults(marked.defaults);
-    return marked;
-  };
-  marked.getDefaults = getDefaults;
-  marked.defaults = defaults;
-  marked.use = function(...args) {
-    const opts = merge2({}, ...args);
-    const extensions = marked.defaults.extensions || { renderers: {}, childTokens: {} };
-    let hasExtensions;
-    args.forEach((pack) => {
-      if (pack.extensions) {
-        hasExtensions = true;
-        pack.extensions.forEach((ext) => {
-          if (!ext.name) {
-            throw new Error("extension name required");
-          }
-          if (ext.renderer) {
-            const prevRenderer = extensions.renderers ? extensions.renderers[ext.name] : null;
-            if (prevRenderer) {
-              extensions.renderers[ext.name] = function(...args2) {
-                let ret = ext.renderer.apply(this, args2);
+        if (pack.tokenizer) {
+          const tokenizer = this.defaults.tokenizer || new Tokenizer(this.defaults);
+          for (const prop in pack.tokenizer) {
+            const prevTokenizer = tokenizer[prop];
+            tokenizer[prop] = (...args2) => {
+              let ret = pack.tokenizer[prop].apply(tokenizer, args2);
+              if (ret === false) {
+                ret = prevTokenizer.apply(tokenizer, args2);
+              }
+              return ret;
+            };
+          }
+          opts.tokenizer = tokenizer;
+        }
+        if (pack.hooks) {
+          const hooks = this.defaults.hooks || new Hooks();
+          for (const prop in pack.hooks) {
+            const prevHook = hooks[prop];
+            if (Hooks.passThroughHooks.has(prop)) {
+              hooks[prop] = (arg) => {
+                if (this.defaults.async) {
+                  return Promise.resolve(pack.hooks[prop].call(hooks, arg)).then((ret2) => {
+                    return prevHook.call(hooks, ret2);
+                  });
+                }
+                const ret = pack.hooks[prop].call(hooks, arg);
+                return prevHook.call(hooks, ret);
+              };
+            } else {
+              hooks[prop] = (...args2) => {
+                let ret = pack.hooks[prop].apply(hooks, args2);
                 if (ret === false) {
-                  ret = prevRenderer.apply(this, args2);
+                  ret = prevHook.apply(hooks, args2);
                 }
                 return ret;
               };
-            } else {
-              extensions.renderers[ext.name] = ext.renderer;
             }
           }
-          if (ext.tokenizer) {
-            if (!ext.level || ext.level !== "block" && ext.level !== "inline") {
-              throw new Error("extension level must be 'block' or 'inline'");
+          opts.hooks = hooks;
+        }
+        if (pack.walkTokens) {
+          const walkTokens2 = this.defaults.walkTokens;
+          opts.walkTokens = function(token) {
+            let values = [];
+            values.push(pack.walkTokens.call(this, token));
+            if (walkTokens2) {
+              values = values.concat(walkTokens2.call(this, token));
             }
-            if (extensions[ext.level]) {
-              extensions[ext.level].unshift(ext.tokenizer);
-            } else {
-              extensions[ext.level] = [ext.tokenizer];
+            return values;
+          };
+        }
+        this.defaults = { ...this.defaults, ...opts };
+      });
+      return this;
+    }
+    setOptions(opt) {
+      this.defaults = { ...this.defaults, ...opt };
+      return this;
+    }
+    #parseMarkdown(lexer2, parser3) {
+      return (src, opt, callback) => {
+        if (typeof opt === "function") {
+          callback = opt;
+          opt = null;
+        }
+        const origOpt = { ...opt };
+        opt = { ...this.defaults, ...origOpt };
+        const throwError = this.#onError(opt.silent, opt.async, callback);
+        if (typeof src === "undefined" || src === null) {
+          return throwError(new Error("marked(): input parameter is undefined or null"));
+        }
+        if (typeof src !== "string") {
+          return throwError(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected"));
+        }
+        checkDeprecations(opt, callback);
+        if (opt.hooks) {
+          opt.hooks.options = opt;
+        }
+        if (callback) {
+          const highlight = opt.highlight;
+          let tokens;
+          try {
+            if (opt.hooks) {
+              src = opt.hooks.preprocess(src);
             }
-            if (ext.start) {
-              if (ext.level === "block") {
-                if (extensions.startBlock) {
-                  extensions.startBlock.push(ext.start);
-                } else {
-                  extensions.startBlock = [ext.start];
+            tokens = lexer2(src, opt);
+          } catch (e) {
+            return throwError(e);
+          }
+          const done = (err) => {
+            let out;
+            if (!err) {
+              try {
+                if (opt.walkTokens) {
+                  this.walkTokens(tokens, opt.walkTokens);
                 }
-              } else if (ext.level === "inline") {
-                if (extensions.startInline) {
-                  extensions.startInline.push(ext.start);
-                } else {
-                  extensions.startInline = [ext.start];
+                out = parser3(tokens, opt);
+                if (opt.hooks) {
+                  out = opt.hooks.postprocess(out);
                 }
+              } catch (e) {
+                err = e;
               }
             }
-          }
-          if (ext.childTokens) {
-            extensions.childTokens[ext.name] = ext.childTokens;
-          }
-        });
-      }
-      if (pack.renderer) {
-        const renderer = marked.defaults.renderer || new Renderer();
-        for (const prop in pack.renderer) {
-          const prevRenderer = renderer[prop];
-          renderer[prop] = (...args2) => {
-            let ret = pack.renderer[prop].apply(renderer, args2);
-            if (ret === false) {
-              ret = prevRenderer.apply(renderer, args2);
-            }
-            return ret;
+            opt.highlight = highlight;
+            return err ? throwError(err) : callback(null, out);
           };
-        }
-        opts.renderer = renderer;
-      }
-      if (pack.tokenizer) {
-        const tokenizer = marked.defaults.tokenizer || new Tokenizer();
-        for (const prop in pack.tokenizer) {
-          const prevTokenizer = tokenizer[prop];
-          tokenizer[prop] = (...args2) => {
-            let ret = pack.tokenizer[prop].apply(tokenizer, args2);
-            if (ret === false) {
-              ret = prevTokenizer.apply(tokenizer, args2);
+          if (!highlight || highlight.length < 3) {
+            return done();
+          }
+          delete opt.highlight;
+          if (!tokens.length)
+            return done();
+          let pending = 0;
+          this.walkTokens(tokens, (token) => {
+            if (token.type === "code") {
+              pending++;
+              setTimeout(() => {
+                highlight(token.text, token.lang, (err, code) => {
+                  if (err) {
+                    return done(err);
+                  }
+                  if (code != null && code !== token.text) {
+                    token.text = code;
+                    token.escaped = true;
+                  }
+                  pending--;
+                  if (pending === 0) {
+                    done();
+                  }
+                });
+              }, 0);
             }
-            return ret;
-          };
+          });
+          if (pending === 0) {
+            done();
+          }
+          return;
         }
-        opts.tokenizer = tokenizer;
-      }
-      if (pack.walkTokens) {
-        const walkTokens2 = marked.defaults.walkTokens;
-        opts.walkTokens = function(token) {
-          let values = [];
-          values.push(pack.walkTokens.call(this, token));
-          if (walkTokens2) {
-            values = values.concat(walkTokens2.call(this, token));
+        if (opt.async) {
+          return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src).then((src2) => lexer2(src2, opt)).then((tokens) => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens).then((tokens) => parser3(tokens, opt)).then((html2) => opt.hooks ? opt.hooks.postprocess(html2) : html2).catch(throwError);
+        }
+        try {
+          if (opt.hooks) {
+            src = opt.hooks.preprocess(src);
           }
-          return values;
-        };
-      }
-      if (hasExtensions) {
-        opts.extensions = extensions;
-      }
-      marked.setOptions(opts);
-    });
-  };
-  marked.walkTokens = function(tokens, callback) {
-    let values = [];
-    for (const token of tokens) {
-      values = values.concat(callback.call(marked, token));
-      switch (token.type) {
-        case "table": {
-          for (const cell of token.header) {
-            values = values.concat(marked.walkTokens(cell.tokens, callback));
+          const tokens = lexer2(src, opt);
+          if (opt.walkTokens) {
+            this.walkTokens(tokens, opt.walkTokens);
           }
-          for (const row of token.rows) {
-            for (const cell of row) {
-              values = values.concat(marked.walkTokens(cell.tokens, callback));
-            }
+          let html2 = parser3(tokens, opt);
+          if (opt.hooks) {
+            html2 = opt.hooks.postprocess(html2);
           }
-          break;
-        }
-        case "list": {
-          values = values.concat(marked.walkTokens(token.items, callback));
-          break;
+          return html2;
+        } catch (e) {
+          return throwError(e);
         }
-        default: {
-          if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) {
-            marked.defaults.extensions.childTokens[token.type].forEach(function(childTokens) {
-              values = values.concat(marked.walkTokens(token[childTokens], callback));
-            });
-          } else if (token.tokens) {
-            values = values.concat(marked.walkTokens(token.tokens, callback));
+      };
+    }
+    #onError(silent, async, callback) {
+      return (e) => {
+        e.message += "\nPlease report this to https://github.com/markedjs/marked.";
+        if (silent) {
+          const msg = "<p>An error occurred:</p><pre>" + escape4(e.message + "", true) + "</pre>";
+          if (async) {
+            return Promise.resolve(msg);
+          }
+          if (callback) {
+            callback(null, msg);
+            return;
           }
+          return msg;
         }
-      }
+        if (async) {
+          return Promise.reject(e);
+        }
+        if (callback) {
+          callback(e);
+          return;
+        }
+        throw e;
+      };
     }
-    return values;
   };
-  marked.parseInline = function(src, opt) {
-    if (typeof src === "undefined" || src === null) {
-      throw new Error("marked.parseInline(): input parameter is undefined or null");
-    }
-    if (typeof src !== "string") {
-      throw new Error("marked.parseInline(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected");
-    }
-    opt = merge2({}, marked.defaults, opt || {});
-    checkSanitizeDeprecation(opt);
-    try {
-      const tokens = Lexer.lexInline(src, opt);
-      if (opt.walkTokens) {
-        marked.walkTokens(tokens, opt.walkTokens);
-      }
-      return Parser.parseInline(tokens, opt);
-    } catch (e) {
-      e.message += "\nPlease report this to https://github.com/markedjs/marked.";
-      if (opt.silent) {
-        return "<p>An error occurred:</p><pre>" + escape4(e.message + "", true) + "</pre>";
-      }
-      throw e;
-    }
+  var markedInstance = new Marked(defaults);
+  function marked(src, opt, callback) {
+    return markedInstance.parse(src, opt, callback);
+  }
+  marked.options = marked.setOptions = function(opt) {
+    markedInstance.setOptions(opt);
+    marked.defaults = markedInstance.defaults;
+    changeDefaults(marked.defaults);
+    return marked;
+  };
+  marked.getDefaults = getDefaults;
+  marked.defaults = defaults;
+  marked.use = function(...args) {
+    markedInstance.use(...args);
+    marked.defaults = markedInstance.defaults;
+    changeDefaults(marked.defaults);
+    return marked;
+  };
+  marked.walkTokens = function(tokens, callback) {
+    return markedInstance.walkTokens(tokens, callback);
   };
+  marked.parseInline = markedInstance.parseInline;
   marked.Parser = Parser;
   marked.parser = Parser.parse;
   marked.Renderer = Renderer;
@@ -37010,6 +39029,7 @@ ${content}</tr>
   marked.lexer = Lexer.lex;
   marked.Tokenizer = Tokenizer;
   marked.Slugger = Slugger;
+  marked.Hooks = Hooks;
   marked.parse = marked;
   var options = marked.options;
   var setOptions = marked.setOptions;
@@ -37092,6 +39112,8 @@ ${content}</tr>
     },
     loadIssues(projection2) {
       let params = {
+        // Tiles return a maximum # of issues
+        // So we want to filter our request for only types iD supports
         item: _osmoseData.items
       };
       let tiles = tiler3.zoomExtent([_tileZoom3, _tileZoom3]).getTiles(projection2);
@@ -37213,6 +39235,7 @@ ${content}</tr>
           callback(err.message);
       });
     },
+    // Get all cached QAItems covering the viewport
     getItems(projection2) {
       const viewport = projection2.clipExtent();
       const min3 = [viewport[0][0], viewport[1][1]];
@@ -37220,12 +39243,16 @@ ${content}</tr>
       const bbox2 = geoExtent(projection2.invert(min3), projection2.invert(max3)).bbox();
       return _cache3.rtree.search(bbox2).map((d) => d.data);
     },
+    // Get a QAItem from cache
+    // NOTE: Don't change method name until UI v3 is merged
     getError(id2) {
       return _cache3.data[id2];
     },
+    // get the name of the icon to display for this item
     getIcon(itemType) {
       return _osmoseData.icons[itemType];
     },
+    // Replace a single QAItem in the cache
     replaceItem(item) {
       if (!(item instanceof QAItem) || !item.id)
         return;
@@ -37233,12 +39260,14 @@ ${content}</tr>
       updateRtree3(encodeIssueRtree3(item), true);
       return item;
     },
+    // Remove a single QAItem from the cache
     removeItem(item) {
       if (!(item instanceof QAItem) || !item.id)
         return;
       delete _cache3.data[item.id];
       updateRtree3(encodeIssueRtree3(item), false);
     },
+    // Used to populate `closed:osmose:*` changeset tags
     getClosedCounts() {
       return _cache3.closed;
     },
@@ -37311,9 +39340,9 @@ ${content}</tr>
   }
   function loadTileDataToCache(data, tile, which) {
     const vectorTile = new import_vector_tile.VectorTile(new import_pbf.default(data));
-    let features2, cache, layer, i2, feature3, loc, d;
+    let features, cache, layer, i2, feature3, loc, d;
     if (vectorTile.layers.hasOwnProperty("image")) {
-      features2 = [];
+      features = [];
       cache = _mlyCache.images;
       layer = vectorTile.layers.image;
       for (i2 = 0; i2 < layer.length; i2++) {
@@ -37328,7 +39357,7 @@ ${content}</tr>
           sequence_id: feature3.properties.sequence_id
         };
         cache.forImageId[d.id] = d;
-        features2.push({
+        features.push({
           minX: loc[0],
           minY: loc[1],
           maxX: loc[0],
@@ -37337,11 +39366,11 @@ ${content}</tr>
         });
       }
       if (cache.rtree) {
-        cache.rtree.load(features2);
+        cache.rtree.load(features);
       }
     }
     if (vectorTile.layers.hasOwnProperty("sequence")) {
-      features2 = [];
+      features = [];
       cache = _mlyCache.sequences;
       layer = vectorTile.layers.sequence;
       for (i2 = 0; i2 < layer.length; i2++) {
@@ -37354,7 +39383,7 @@ ${content}</tr>
       }
     }
     if (vectorTile.layers.hasOwnProperty("point")) {
-      features2 = [];
+      features = [];
       cache = _mlyCache[which];
       layer = vectorTile.layers.point;
       for (i2 = 0; i2 < layer.length; i2++) {
@@ -37367,7 +39396,7 @@ ${content}</tr>
           last_seen_at: feature3.properties.last_seen_at,
           value: feature3.properties.value
         };
-        features2.push({
+        features.push({
           minX: loc[0],
           minY: loc[1],
           maxX: loc[0],
@@ -37376,11 +39405,11 @@ ${content}</tr>
         });
       }
       if (cache.rtree) {
-        cache.rtree.load(features2);
+        cache.rtree.load(features);
       }
     }
     if (vectorTile.layers.hasOwnProperty("traffic_sign")) {
-      features2 = [];
+      features = [];
       cache = _mlyCache[which];
       layer = vectorTile.layers.traffic_sign;
       for (i2 = 0; i2 < layer.length; i2++) {
@@ -37393,7 +39422,7 @@ ${content}</tr>
           last_seen_at: feature3.properties.last_seen_at,
           value: feature3.properties.value
         };
-        features2.push({
+        features.push({
           minX: loc[0],
           minY: loc[1],
           maxX: loc[0],
@@ -37402,7 +39431,7 @@ ${content}</tr>
         });
       }
       if (cache.rtree) {
-        cache.rtree.load(features2);
+        cache.rtree.load(features);
       }
     }
   }
@@ -37437,12 +39466,14 @@ ${content}</tr>
     }, []);
   }
   var mapillary_default = {
+    // Initialize Mapillary
     init: function() {
       if (!_mlyCache) {
         this.reset();
       }
       this.event = utilRebind(this, dispatch5, "on");
     },
+    // Reset cache and state
     reset: function() {
       if (_mlyCache) {
         Object.values(_mlyCache.requests.inflight).forEach(function(request3) {
@@ -37459,21 +39490,26 @@ ${content}</tr>
       };
       _mlyActiveImage = null;
     },
+    // Get visible images
     images: function(projection2) {
       const limit = 5;
       return searchLimited(limit, projection2, _mlyCache.images.rtree);
     },
+    // Get visible traffic signs
     signs: function(projection2) {
       const limit = 5;
       return searchLimited(limit, projection2, _mlyCache.signs.rtree);
     },
+    // Get visible map (point) features
     mapFeatures: function(projection2) {
       const limit = 5;
       return searchLimited(limit, projection2, _mlyCache.points.rtree);
     },
+    // Get cached image by id
     cachedImage: function(imageId) {
       return _mlyCache.images.forImageId[imageId];
     },
+    // Get visible sequences
     sequences: function(projection2) {
       const viewport = projection2.clipExtent();
       const min3 = [viewport[0][0], viewport[1][1]];
@@ -37493,15 +39529,19 @@ ${content}</tr>
       });
       return lineStrings;
     },
+    // Load images in the visible area
     loadImages: function(projection2) {
       loadTiles("images", tileUrl, 14, projection2);
     },
+    // Load traffic signs in the visible area
     loadSigns: function(projection2) {
       loadTiles("signs", trafficSignTileUrl, 14, projection2);
     },
+    // Load map (point) features in the visible area
     loadMapFeatures: function(projection2) {
       loadTiles("points", mapFeatureTileUrl, 14, projection2);
     },
+    // Return a promise that resolves when the image viewer (Mapillary JS) library has finished loading
     ensureViewerLoaded: function(context) {
       if (_loadViewerPromise)
         return _loadViewerPromise;
@@ -37529,31 +39569,45 @@ ${content}</tr>
       });
       return _loadViewerPromise;
     },
+    // Load traffic sign image sprites
     loadSignResources: function(context) {
-      context.ui().svgDefs.addSprites(["mapillary-sprite"], false);
+      context.ui().svgDefs.addSprites(
+        ["mapillary-sprite"],
+        false
+        /* don't override colors */
+      );
       return this;
     },
+    // Load map (point) feature image sprites
     loadObjectResources: function(context) {
-      context.ui().svgDefs.addSprites(["mapillary-object-sprite"], false);
+      context.ui().svgDefs.addSprites(
+        ["mapillary-object-sprite"],
+        false
+        /* don't override colors */
+      );
       return this;
     },
+    // Remove previous detections in image viewer
     resetTags: function() {
       if (_mlyViewer && !_mlyFallback) {
         _mlyViewer.getComponent("tag").removeAll();
       }
     },
+    // Show map feature detections in image viewer
     showFeatureDetections: function(value) {
       _mlyShowFeatureDetections = value;
       if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
         this.resetTags();
       }
     },
+    // Show traffic sign detections in image viewer
     showSignDetections: function(value) {
       _mlyShowSignDetections = value;
       if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
         this.resetTags();
       }
     },
+    // Apply filter to image viewer
     filterViewer: function(context) {
       const showsPano = context.photos().showsPanoramic();
       const showsFlat = context.photos().showsFlat();
@@ -37576,6 +39630,7 @@ ${content}</tr>
       _mlyViewerFilter = filter2;
       return filter2;
     },
+    // Make the image viewer visible
     showViewer: function(context) {
       const wrap2 = context.container().select(".photoviewer").classed("hide", false);
       const isHidden = wrap2.selectAll(".photo-wrapper.mly-wrapper.hide").size();
@@ -37586,6 +39641,7 @@ ${content}</tr>
       }
       return this;
     },
+    // Hide the image viewer and resets map markers
     hideViewer: function(context) {
       _mlyActiveImage = null;
       if (!_mlyFallback && _mlyViewer) {
@@ -37601,6 +39657,7 @@ ${content}</tr>
       dispatch5.call("loadedSigns");
       return this.setStyles(context, null);
     },
+    // Update the URL with current image id
     updateUrlImage: function(imageId) {
       if (!window.mocha) {
         const hash = utilStringQs(window.location.hash);
@@ -37612,12 +39669,14 @@ ${content}</tr>
         window.location.replace("#" + utilQsString(hash, true));
       }
     },
+    // Highlight the detection in the viewer that is related to the clicked map feature
     highlightDetection: function(detection) {
       if (detection) {
         _mlyHighlightedDetection = detection.id;
       }
       return this;
     },
+    // Initialize image viewer (Mapillar JS)
     initViewer: function(context) {
       const that = this;
       if (!window.mapillary)
@@ -37642,7 +39701,9 @@ ${content}</tr>
           sequence: false,
           tag: false,
           image: true,
+          // fallback
           navigation: true
+          // fallback
         };
       }
       _mlyViewer = new mapillary.Viewer(opts);
@@ -37672,6 +39733,7 @@ ${content}</tr>
         dispatch5.call("bearingChanged", void 0, e);
       }
     },
+    // Move to an image
     selectImage: function(context, imageId) {
       if (_mlyViewer && imageId) {
         _mlyViewer.moveTo(imageId).catch(function(e) {
@@ -37680,12 +39742,15 @@ ${content}</tr>
       }
       return this;
     },
+    // Return the currently displayed image
     getActiveImage: function() {
       return _mlyActiveImage;
     },
+    // Return a list of detection objects for the given id
     getDetections: function(id2) {
       return loadData(`${apiUrl}/${id2}/detections?access_token=${accessToken}&fields=id,value,image`);
     },
+    // Set the currently visible image
     setActiveImage: function(image) {
       if (image) {
         _mlyActiveImage = {
@@ -37699,6 +39764,7 @@ ${content}</tr>
         _mlyActiveImage = null;
       }
     },
+    // Update the currently highlighted sequence and selected bubble.
     setStyles: function(context, hovered) {
       const hoveredImageId = hovered && hovered.id;
       const hoveredSequenceId = hovered && hovered.sequence_id;
@@ -37715,6 +39781,7 @@ ${content}</tr>
       });
       return this;
     },
+    // Get detections for the current image and shows them in the image viewer
     updateDetections: function(imageId, url) {
       if (!_mlyViewer || _mlyFallback)
         return;
@@ -37789,6 +39856,7 @@ ${content}</tr>
         return tag;
       }
     },
+    // Return the current cache
     cache: function() {
       return _mlyCache;
     }
@@ -37964,6 +40032,7 @@ ${content}</tr>
       this._areaKeys = osmAreaKeys;
       this._lineKeys = buildLineKeys();
     },
+    // list of rules only relevant to tag checks...
     filterRuleChecks: function(selector) {
       var _ruleChecks = this._ruleChecks;
       return Object.keys(selector).reduce(function(rules, key) {
@@ -37973,6 +40042,7 @@ ${content}</tr>
         return rules;
       }, []);
     },
+    // builds tagMap from mapcss-parse selector object...
     buildTagMap: function(selector) {
       var getRegexValues = function(regexes) {
         return regexes.map(function(regex) {
@@ -37982,10 +40052,10 @@ ${content}</tr>
       var tagMap = Object.keys(selector).reduce(function(expectedTags, key) {
         var values;
         var isRegex = /regex/gi.test(key);
-        var isEqual = /equals/gi.test(key);
-        if (isRegex || isEqual) {
+        var isEqual4 = /equals/gi.test(key);
+        if (isRegex || isEqual4) {
           Object.keys(selector[key]).forEach(function(selectorKey) {
-            values = isEqual ? [selector[key][selectorKey]] : getRegexValues(selector[key][selectorKey]);
+            values = isEqual4 ? [selector[key][selectorKey]] : getRegexValues(selector[key][selectorKey]);
             if (expectedTags.hasOwnProperty(selectorKey)) {
               values = values.concat(expectedTags[selectorKey]);
             }
@@ -38003,6 +40073,7 @@ ${content}</tr>
       }, {});
       return tagMap;
     },
+    // inspired by osmWay#isArea()
     inferGeometry: function(tagMap) {
       var _lineKeys = this._lineKeys;
       var _areaKeys = this._areaKeys;
@@ -38030,14 +40101,18 @@ ${content}</tr>
       }
       return "line";
     },
+    // adds from mapcss-parse selector check...
     addRule: function(selector) {
       var rule = {
+        // checks relevant to mapcss-selector
         checks: this.filterRuleChecks(selector),
+        // true if all conditions for a tag error are true..
         matches: function(entity) {
           return this.checks.every(function(check) {
             return check(entity.tags);
           });
         },
+        // borrowed from Way#isArea()
         inferredGeometry: this.inferGeometry(this.buildTagMap(selector), this._areaKeys),
         geometryMatches: function(entity, graph) {
           if (entity.type === "node" || entity.type === "relation") {
@@ -38046,6 +40121,7 @@ ${content}</tr>
             return this.inferredGeometry === entity.geometry(graph);
           }
         },
+        // when geometries match and tag matches are present, return a warning...
         findIssues: function(entity, graph, issues) {
           if (this.geometryMatches(entity, graph) && this.matches(entity)) {
             var severity = Object.keys(selector).indexOf("error") > -1 ? "error" : "warning";
@@ -38066,971 +40142,245 @@ ${content}</tr>
     clearRules: function() {
       this._validationRules = [];
     },
+    // returns validationRules...
     validationRules: function() {
       return this._validationRules;
     },
+    // returns ruleChecks
     ruleChecks: function() {
       return this._ruleChecks;
     }
   };
 
   // modules/services/nominatim.js
-  var import_rbush5 = __toESM(require_rbush_min());
-  var apibase = nominatimApiUrl;
-  var _inflight = {};
-  var _nominatimCache;
-  var nominatim_default = {
-    init: function() {
-      _inflight = {};
-      _nominatimCache = new import_rbush5.default();
-    },
-    reset: function() {
-      Object.values(_inflight).forEach(function(controller) {
-        controller.abort();
-      });
-      _inflight = {};
-      _nominatimCache = new import_rbush5.default();
-    },
-    countryCode: function(location, callback) {
-      this.reverse(location, function(err, result) {
-        if (err) {
-          return callback(err);
-        } else if (result.address) {
-          return callback(null, result.address.country_code);
-        } else {
-          return callback("Unable to geocode", null);
-        }
-      });
-    },
-    reverse: function(loc, callback) {
-      var cached = _nominatimCache.search(
-        { minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1] }
-      );
-      if (cached.length > 0) {
-        if (callback)
-          callback(null, cached[0].data);
+  var import_rbush7 = __toESM(require_rbush_min());
+
+  // modules/core/difference.js
+  var import_fast_deep_equal3 = __toESM(require_fast_deep_equal());
+  function coreDifference(base, head) {
+    var _changes = {};
+    var _didChange = {};
+    var _diff = {};
+    function checkEntityID(id2) {
+      var h = head.entities[id2];
+      var b = base.entities[id2];
+      if (h === b)
+        return;
+      if (_changes[id2])
+        return;
+      if (!h && b) {
+        _changes[id2] = { base: b, head: h };
+        _didChange.deletion = true;
         return;
       }
-      var params = { zoom: 13, format: "json", addressdetails: 1, lat: loc[1], lon: loc[0] };
-      var url = apibase + "reverse?" + utilQsString(params);
-      if (_inflight[url])
+      if (h && !b) {
+        _changes[id2] = { base: b, head: h };
+        _didChange.addition = true;
         return;
-      var controller = new AbortController();
-      _inflight[url] = controller;
-      json_default(url, { signal: controller.signal }).then(function(result) {
-        delete _inflight[url];
-        if (result && result.error) {
-          throw new Error(result.error);
-        }
-        var extent = geoExtent(loc).padByMeters(200);
-        _nominatimCache.insert(Object.assign(extent.bbox(), { data: result }));
-        if (callback)
-          callback(null, result);
-      }).catch(function(err) {
-        delete _inflight[url];
-        if (err.name === "AbortError")
+      }
+      if (h && b) {
+        if (h.members && b.members && !(0, import_fast_deep_equal3.default)(h.members, b.members)) {
+          _changes[id2] = { base: b, head: h };
+          _didChange.geometry = true;
+          _didChange.properties = true;
           return;
-        if (callback)
-          callback(err.message);
+        }
+        if (h.loc && b.loc && !geoVecEqual(h.loc, b.loc)) {
+          _changes[id2] = { base: b, head: h };
+          _didChange.geometry = true;
+        }
+        if (h.nodes && b.nodes && !(0, import_fast_deep_equal3.default)(h.nodes, b.nodes)) {
+          _changes[id2] = { base: b, head: h };
+          _didChange.geometry = true;
+        }
+        if (h.tags && b.tags && !(0, import_fast_deep_equal3.default)(h.tags, b.tags)) {
+          _changes[id2] = { base: b, head: h };
+          _didChange.properties = true;
+        }
+      }
+    }
+    function load() {
+      var ids = utilArrayUniq(Object.keys(head.entities).concat(Object.keys(base.entities)));
+      for (var i2 = 0; i2 < ids.length; i2++) {
+        checkEntityID(ids[i2]);
+      }
+    }
+    load();
+    _diff.length = function length() {
+      return Object.keys(_changes).length;
+    };
+    _diff.changes = function changes() {
+      return _changes;
+    };
+    _diff.didChange = _didChange;
+    _diff.extantIDs = function extantIDs(includeRelMembers) {
+      var result = /* @__PURE__ */ new Set();
+      Object.keys(_changes).forEach(function(id2) {
+        if (_changes[id2].head) {
+          result.add(id2);
+        }
+        var h = _changes[id2].head;
+        var b = _changes[id2].base;
+        var entity = h || b;
+        if (includeRelMembers && entity.type === "relation") {
+          var mh = h ? h.members.map(function(m) {
+            return m.id;
+          }) : [];
+          var mb = b ? b.members.map(function(m) {
+            return m.id;
+          }) : [];
+          utilArrayUnion(mh, mb).forEach(function(memberID) {
+            if (head.hasEntity(memberID)) {
+              result.add(memberID);
+            }
+          });
+        }
       });
-    },
-    search: function(val, callback) {
-      var searchVal = encodeURIComponent(val);
-      var url = apibase + "search/" + searchVal + "?limit=10&format=json";
-      if (_inflight[url])
-        return;
-      var controller = new AbortController();
-      _inflight[url] = controller;
-      json_default(url, { signal: controller.signal }).then(function(result) {
-        delete _inflight[url];
-        if (result && result.error) {
-          throw new Error(result.error);
+      return Array.from(result);
+    };
+    _diff.modified = function modified() {
+      var result = [];
+      Object.values(_changes).forEach(function(change) {
+        if (change.base && change.head) {
+          result.push(change.head);
         }
-        if (callback)
-          callback(null, result);
-      }).catch(function(err) {
-        delete _inflight[url];
-        if (err.name === "AbortError")
-          return;
-        if (callback)
-          callback(err.message);
       });
-    }
-  };
-
-  // node_modules/name-suggestion-index/lib/matcher.js
-  var import_which_polygon3 = __toESM(require_which_polygon(), 1);
-
-  // node_modules/name-suggestion-index/lib/simplify.js
-  var import_diacritics2 = __toESM(require_diacritics(), 1);
-  function simplify(str2) {
-    if (typeof str2 !== "string")
-      return "";
-    return import_diacritics2.default.remove(
-      str2.replace(/&/g, "and").replace(/İ/ig, "i").replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u2000-\u206f\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00-\u2e7f\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, "").toLowerCase()
-    );
-  }
-
-  // node_modules/name-suggestion-index/config/matchGroups.json
-  var matchGroups_default = {
-    matchGroups: {
-      adult_gaming_centre: [
-        "amenity/casino",
-        "amenity/gambling",
-        "leisure/adult_gaming_centre"
-      ],
-      beauty: [
-        "shop/beauty",
-        "shop/hairdresser_supply"
-      ],
-      bed: [
-        "shop/bed",
-        "shop/furniture"
-      ],
-      beverages: [
-        "shop/alcohol",
-        "shop/beer",
-        "shop/beverages",
-        "shop/kiosk",
-        "shop/wine"
-      ],
-      camping: [
-        "tourism/camp_site",
-        "tourism/caravan_site"
-      ],
-      car_parts: [
-        "shop/car_parts",
-        "shop/car_repair",
-        "shop/tires",
-        "shop/tyres"
-      ],
-      clinic: [
-        "amenity/clinic",
-        "amenity/doctors",
-        "healthcare/clinic",
-        "healthcare/laboratory",
-        "healthcare/physiotherapist",
-        "healthcare/sample_collection",
-        "healthcare/dialysis"
-      ],
-      convenience: [
-        "shop/beauty",
-        "shop/chemist",
-        "shop/convenience",
-        "shop/cosmetics",
-        "shop/grocery",
-        "shop/kiosk",
-        "shop/newsagent",
-        "shop/perfumery"
-      ],
-      coworking: [
-        "amenity/coworking_space",
-        "office/coworking",
-        "office/coworking_space"
-      ],
-      dentist: [
-        "amenity/dentist",
-        "amenity/doctors",
-        "healthcare/dentist"
-      ],
-      electronics: [
-        "office/telecommunication",
-        "shop/computer",
-        "shop/electronics",
-        "shop/hifi",
-        "shop/kiosk",
-        "shop/mobile",
-        "shop/mobile_phone",
-        "shop/telecommunication"
-      ],
-      fabric: [
-        "shop/fabric",
-        "shop/haberdashery",
-        "shop/sewing"
-      ],
-      fashion: [
-        "shop/accessories",
-        "shop/bag",
-        "shop/boutique",
-        "shop/clothes",
-        "shop/department_store",
-        "shop/fashion",
-        "shop/fashion_accessories",
-        "shop/sports",
-        "shop/shoes"
-      ],
-      financial: [
-        "amenity/bank",
-        "office/accountant",
-        "office/financial",
-        "office/financial_advisor",
-        "office/tax_advisor",
-        "shop/tax"
-      ],
-      fitness: [
-        "leisure/fitness_centre",
-        "leisure/fitness_center",
-        "leisure/sports_centre",
-        "leisure/sports_center"
-      ],
-      food: [
-        "amenity/bar",
-        "amenity/cafe",
-        "amenity/fast_food",
-        "amenity/ice_cream",
-        "amenity/pub",
-        "amenity/restaurant",
-        "shop/bakery",
-        "shop/candy",
-        "shop/chocolate",
-        "shop/coffee",
-        "shop/confectionary",
-        "shop/confectionery",
-        "shop/food",
-        "shop/kiosk",
-        "shop/ice_cream",
-        "shop/pastry",
-        "shop/tea"
-      ],
-      fuel: [
-        "amenity/fuel",
-        "shop/gas",
-        "shop/convenience;gas",
-        "shop/gas;convenience"
-      ],
-      gift: [
-        "shop/gift",
-        "shop/card",
-        "shop/cards",
-        "shop/kiosk",
-        "shop/stationery"
-      ],
-      hardware: [
-        "shop/bathroom_furnishing",
-        "shop/carpet",
-        "shop/diy",
-        "shop/doityourself",
-        "shop/doors",
-        "shop/electrical",
-        "shop/flooring",
-        "shop/hardware",
-        "shop/hardware_store",
-        "shop/power_tools",
-        "shop/tool_hire",
-        "shop/tools",
-        "shop/trade"
-      ],
-      health_food: [
-        "shop/health",
-        "shop/health_food",
-        "shop/herbalist",
-        "shop/nutrition_supplements"
-      ],
-      hobby: [
-        "shop/electronics",
-        "shop/hobby",
-        "shop/books",
-        "shop/games",
-        "shop/collector",
-        "shop/toys",
-        "shop/model",
-        "shop/video_games",
-        "shop/anime"
-      ],
-      hospital: [
-        "amenity/doctors",
-        "amenity/hospital",
-        "healthcare/hospital"
-      ],
-      houseware: [
-        "shop/houseware",
-        "shop/interior_decoration"
-      ],
-      lifeboat_station: [
-        "amenity/lifeboat_station",
-        "emergency/lifeboat_station",
-        "emergency/marine_rescue"
-      ],
-      lodging: [
-        "tourism/hotel",
-        "tourism/motel"
-      ],
-      money_transfer: [
-        "amenity/money_transfer",
-        "shop/money_transfer"
-      ],
-      office_supplies: [
-        "shop/office_supplies",
-        "shop/stationary",
-        "shop/stationery"
-      ],
-      outdoor: [
-        "shop/clothes",
-        "shop/outdoor",
-        "shop/sports"
-      ],
-      parcel_locker: [
-        "amenity/parcel_locker",
-        "amenity/vending_machine"
-      ],
-      pharmacy: [
-        "amenity/doctors",
-        "amenity/pharmacy",
-        "healthcare/pharmacy"
-      ],
-      playground: [
-        "amenity/theme_park",
-        "leisure/amusement_arcade",
-        "leisure/playground"
-      ],
-      rental: [
-        "amenity/bicycle_rental",
-        "amenity/boat_rental",
-        "amenity/car_rental",
-        "amenity/truck_rental",
-        "amenity/vehicle_rental",
-        "shop/kiosk",
-        "shop/rental"
-      ],
-      school: [
-        "amenity/childcare",
-        "amenity/college",
-        "amenity/kindergarten",
-        "amenity/language_school",
-        "amenity/prep_school",
-        "amenity/school",
-        "amenity/university"
-      ],
-      storage: [
-        "shop/storage_units",
-        "shop/storage_rental"
-      ],
-      substation: [
-        "power/station",
-        "power/substation",
-        "power/sub_station"
-      ],
-      supermarket: [
-        "shop/food",
-        "shop/frozen_food",
-        "shop/greengrocer",
-        "shop/grocery",
-        "shop/supermarket",
-        "shop/wholesale"
-      ],
-      variety_store: [
-        "shop/variety_store",
-        "shop/discount",
-        "shop/convenience"
-      ],
-      vending: [
-        "amenity/vending_machine",
-        "shop/kiosk",
-        "shop/vending_machine"
-      ],
-      weight_loss: [
-        "amenity/clinic",
-        "amenity/doctors",
-        "amenity/weight_clinic",
-        "healthcare/counselling",
-        "leisure/fitness_centre",
-        "office/therapist",
-        "shop/beauty",
-        "shop/diet",
-        "shop/food",
-        "shop/health_food",
-        "shop/herbalist",
-        "shop/nutrition",
-        "shop/nutrition_supplements",
-        "shop/weight_loss"
-      ],
-      wholesale: [
-        "shop/wholesale",
-        "shop/supermarket",
-        "shop/department_store"
-      ]
-    }
-  };
-
-  // node_modules/name-suggestion-index/config/genericWords.json
-  var genericWords_default = {
-    genericWords: [
-      "^(barn|bazaa?r|bench|bou?tique|building|casa|church)$",
-      "^(baseball|basketball|football|soccer|softball|tennis(halle)?)\\s?(field|court)?$",
-      "^(club|green|out|ware)\\s?house$",
-      "^(driveway|el \xE1rbol|fountain|generic|golf|government|graveyard)$",
-      "^(fixme|n\\s?\\/?\\s?a|name|no\\s?name|none|null|temporary|test|unknown)$",
-      "^(hofladen|librairie|magazine?|maison)$",
-      "^(mobile home|skate)?\\s?park$",
-      "^(obuwie|pond|pool|sale|shops?|sklep|stores?)$",
-      "^\\?+$",
-      "^private$",
-      "^tattoo( studio)?$",
-      "^windmill$",
-      "^\u0446\u0435\u0440\u043A\u043E\u0432\u043D\u0430\u044F( \u043B\u0430\u0432\u043A\u0430)?$"
-    ]
-  };
-
-  // node_modules/name-suggestion-index/config/trees.json
-  var trees_default = {
-    trees: {
-      brands: {
-        emoji: "\u{1F354}",
-        mainTag: "brand:wikidata",
-        sourceTags: ["brand", "name"],
-        nameTags: {
-          primary: "^(name|name:\\w+)$",
-          alternate: "^(brand|brand:\\w+|operator|operator:\\w+|\\w+_name|\\w+_name:\\w+)$"
+      return result;
+    };
+    _diff.created = function created() {
+      var result = [];
+      Object.values(_changes).forEach(function(change) {
+        if (!change.base && change.head) {
+          result.push(change.head);
         }
-      },
-      flags: {
-        emoji: "\u{1F6A9}",
-        mainTag: "flag:wikidata",
-        nameTags: {
-          primary: "^(flag:name|flag:name:\\w+)$",
-          alternate: "^(country|country:\\w+|flag|flag:\\w+|subject|subject:\\w+)$"
+      });
+      return result;
+    };
+    _diff.deleted = function deleted() {
+      var result = [];
+      Object.values(_changes).forEach(function(change) {
+        if (change.base && !change.head) {
+          result.push(change.base);
         }
-      },
-      operators: {
-        emoji: "\u{1F4BC}",
-        mainTag: "operator:wikidata",
-        sourceTags: ["operator"],
-        nameTags: {
-          primary: "^(name|name:\\w+|operator|operator:\\w+)$",
-          alternate: "^(brand|brand:\\w+|\\w+_name|\\w+_name:\\w+)$"
+      });
+      return result;
+    };
+    _diff.summary = function summary() {
+      var relevant = {};
+      var keys2 = Object.keys(_changes);
+      for (var i2 = 0; i2 < keys2.length; i2++) {
+        var change = _changes[keys2[i2]];
+        if (change.head && change.head.geometry(head) !== "vertex") {
+          addEntity(change.head, head, change.base ? "modified" : "created");
+        } else if (change.base && change.base.geometry(base) !== "vertex") {
+          addEntity(change.base, base, "deleted");
+        } else if (change.base && change.head) {
+          var moved = !(0, import_fast_deep_equal3.default)(change.base.loc, change.head.loc);
+          var retagged = !(0, import_fast_deep_equal3.default)(change.base.tags, change.head.tags);
+          if (moved) {
+            addParents(change.head);
+          }
+          if (retagged || moved && change.head.hasInterestingTags()) {
+            addEntity(change.head, head, "modified");
+          }
+        } else if (change.head && change.head.hasInterestingTags()) {
+          addEntity(change.head, head, "created");
+        } else if (change.base && change.base.hasInterestingTags()) {
+          addEntity(change.base, base, "deleted");
         }
-      },
-      transit: {
-        emoji: "\u{1F687}",
-        mainTag: "network:wikidata",
-        sourceTags: ["network"],
-        nameTags: {
-          primary: "^network$",
-          alternate: "^(operator|operator:\\w+|network:\\w+|\\w+_name|\\w+_name:\\w+)$"
+      }
+      return Object.values(relevant);
+      function addEntity(entity, graph, changeType) {
+        relevant[entity.id] = {
+          entity,
+          graph,
+          changeType
+        };
+      }
+      function addParents(entity) {
+        var parents = head.parentWays(entity);
+        for (var j2 = parents.length - 1; j2 >= 0; j2--) {
+          var parent = parents[j2];
+          if (!(parent.id in relevant)) {
+            addEntity(parent, head, "modified");
+          }
         }
       }
-    }
-  };
-
-  // node_modules/name-suggestion-index/lib/matcher.js
-  var matchGroups = matchGroups_default.matchGroups;
-  var trees = trees_default.trees;
-  var Matcher = class {
-    constructor() {
-      this.matchIndex = void 0;
-      this.genericWords = /* @__PURE__ */ new Map();
-      (genericWords_default.genericWords || []).forEach((s) => this.genericWords.set(s, new RegExp(s, "i")));
-      this.itemLocation = void 0;
-      this.locationSets = void 0;
-      this.locationIndex = void 0;
-      this.warnings = [];
-    }
-    buildMatchIndex(data) {
-      const that = this;
-      if (that.matchIndex)
-        return;
-      that.matchIndex = /* @__PURE__ */ new Map();
-      const seenTree = /* @__PURE__ */ new Map();
-      Object.keys(data).forEach((tkv) => {
-        const category = data[tkv];
-        const parts = tkv.split("/", 3);
-        const t = parts[0];
-        const k = parts[1];
-        const v = parts[2];
-        const thiskv = `${k}/${v}`;
-        const tree = trees[t];
-        let branch = that.matchIndex.get(thiskv);
-        if (!branch) {
-          branch = {
-            primary: /* @__PURE__ */ new Map(),
-            alternate: /* @__PURE__ */ new Map(),
-            excludeGeneric: /* @__PURE__ */ new Map(),
-            excludeNamed: /* @__PURE__ */ new Map()
-          };
-          that.matchIndex.set(thiskv, branch);
+    };
+    _diff.complete = function complete(extent) {
+      var result = {};
+      var id2, change;
+      for (id2 in _changes) {
+        change = _changes[id2];
+        var h = change.head;
+        var b = change.base;
+        var entity = h || b;
+        var i2;
+        if (extent && (!h || !h.intersects(extent, head)) && (!b || !b.intersects(extent, base))) {
+          continue;
         }
-        const properties = category.properties || {};
-        const exclude = properties.exclude || {};
-        (exclude.generic || []).forEach((s) => branch.excludeGeneric.set(s, new RegExp(s, "i")));
-        (exclude.named || []).forEach((s) => branch.excludeNamed.set(s, new RegExp(s, "i")));
-        const excludeRegexes = [...branch.excludeGeneric.values(), ...branch.excludeNamed.values()];
-        let items = category.items;
-        if (!Array.isArray(items) || !items.length)
-          return;
-        const primaryName = new RegExp(tree.nameTags.primary, "i");
-        const alternateName = new RegExp(tree.nameTags.alternate, "i");
-        const notName = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i;
-        const skipGenericKV = skipGenericKVMatches(t, k, v);
-        const genericKV = /* @__PURE__ */ new Set([`${k}/yes`, `building/yes`]);
-        const matchGroupKV = /* @__PURE__ */ new Set();
-        Object.values(matchGroups).forEach((matchGroup) => {
-          const inGroup = matchGroup.some((otherkv) => otherkv === thiskv);
-          if (!inGroup)
-            return;
-          matchGroup.forEach((otherkv) => {
-            if (otherkv === thiskv)
-              return;
-            matchGroupKV.add(otherkv);
-            const otherk = otherkv.split("/", 2)[0];
-            genericKV.add(`${otherk}/yes`);
-          });
-        });
-        items.forEach((item) => {
-          if (!item.id)
-            return;
-          if (Array.isArray(item.matchTags) && item.matchTags.length) {
-            item.matchTags = item.matchTags.filter((matchTag) => !matchGroupKV.has(matchTag) && !genericKV.has(matchTag));
-            if (!item.matchTags.length)
-              delete item.matchTags;
-          }
-          let kvTags = [`${thiskv}`].concat(item.matchTags || []);
-          if (!skipGenericKV) {
-            kvTags = kvTags.concat(Array.from(genericKV));
+        result[id2] = h;
+        if (entity.type === "way") {
+          var nh = h ? h.nodes : [];
+          var nb = b ? b.nodes : [];
+          var diff;
+          diff = utilArrayDifference(nh, nb);
+          for (i2 = 0; i2 < diff.length; i2++) {
+            result[diff[i2]] = head.hasEntity(diff[i2]);
           }
-          Object.keys(item.tags).forEach((osmkey) => {
-            if (notName.test(osmkey))
-              return;
-            const osmvalue = item.tags[osmkey];
-            if (!osmvalue || excludeRegexes.some((regex) => regex.test(osmvalue)))
-              return;
-            if (primaryName.test(osmkey)) {
-              kvTags.forEach((kv) => insertName("primary", t, kv, simplify(osmvalue), item.id));
-            } else if (alternateName.test(osmkey)) {
-              kvTags.forEach((kv) => insertName("alternate", t, kv, simplify(osmvalue), item.id));
-            }
-          });
-          let keepMatchNames = /* @__PURE__ */ new Set();
-          (item.matchNames || []).forEach((matchName) => {
-            const nsimple = simplify(matchName);
-            kvTags.forEach((kv) => {
-              const branch2 = that.matchIndex.get(kv);
-              const primaryLeaf = branch2 && branch2.primary.get(nsimple);
-              const alternateLeaf = branch2 && branch2.alternate.get(nsimple);
-              const inPrimary = primaryLeaf && primaryLeaf.has(item.id);
-              const inAlternate = alternateLeaf && alternateLeaf.has(item.id);
-              if (!inPrimary && !inAlternate) {
-                insertName("alternate", t, kv, nsimple, item.id);
-                keepMatchNames.add(matchName);
-              }
-            });
-          });
-          if (keepMatchNames.size) {
-            item.matchNames = Array.from(keepMatchNames);
-          } else {
-            delete item.matchNames;
+          diff = utilArrayDifference(nb, nh);
+          for (i2 = 0; i2 < diff.length; i2++) {
+            result[diff[i2]] = head.hasEntity(diff[i2]);
           }
-        });
-      });
-      function insertName(which, t, kv, nsimple, itemID) {
-        if (!nsimple) {
-          that.warnings.push(`Warning: skipping empty ${which} name for item ${t}/${kv}: ${itemID}`);
-          return;
-        }
-        let branch = that.matchIndex.get(kv);
-        if (!branch) {
-          branch = {
-            primary: /* @__PURE__ */ new Map(),
-            alternate: /* @__PURE__ */ new Map(),
-            excludeGeneric: /* @__PURE__ */ new Map(),
-            excludeNamed: /* @__PURE__ */ new Map()
-          };
-          that.matchIndex.set(kv, branch);
-        }
-        let leaf = branch[which].get(nsimple);
-        if (!leaf) {
-          leaf = /* @__PURE__ */ new Set();
-          branch[which].set(nsimple, leaf);
         }
-        leaf.add(itemID);
-        if (!/yes$/.test(kv)) {
-          const kvnsimple = `${kv}/${nsimple}`;
-          const existing = seenTree.get(kvnsimple);
-          if (existing && existing !== t) {
-            const items = Array.from(leaf);
-            that.warnings.push(`Duplicate cache key "${kvnsimple}" in trees "${t}" and "${existing}", check items: ${items}`);
-            return;
+        if (entity.type === "relation" && entity.isMultipolygon()) {
+          var mh = h ? h.members.map(function(m) {
+            return m.id;
+          }) : [];
+          var mb = b ? b.members.map(function(m) {
+            return m.id;
+          }) : [];
+          var ids = utilArrayUnion(mh, mb);
+          for (i2 = 0; i2 < ids.length; i2++) {
+            var member = head.hasEntity(ids[i2]);
+            if (!member)
+              continue;
+            if (extent && !member.intersects(extent, head))
+              continue;
+            result[ids[i2]] = member;
           }
-          seenTree.set(kvnsimple, t);
         }
+        addParents(head.parentWays(entity), result);
+        addParents(head.parentRelations(entity), result);
       }
-      function skipGenericKVMatches(t, k, v) {
-        return t === "flags" || t === "transit" || k === "landuse" || v === "atm" || v === "bicycle_parking" || v === "car_sharing" || v === "caravan_site" || v === "charging_station" || v === "dog_park" || v === "parking" || v === "phone" || v === "playground" || v === "post_box" || v === "public_bookcase" || v === "recycling" || v === "vending_machine";
+      return result;
+      function addParents(parents, result2) {
+        for (var i3 = 0; i3 < parents.length; i3++) {
+          var parent = parents[i3];
+          if (parent.id in result2)
+            continue;
+          result2[parent.id] = parent;
+          addParents(head.parentRelations(parent), result2);
+        }
       }
-    }
-    buildLocationIndex(data, loco) {
-      const that = this;
-      if (that.locationIndex)
-        return;
-      that.itemLocation = /* @__PURE__ */ new Map();
-      that.locationSets = /* @__PURE__ */ new Map();
-      Object.keys(data).forEach((tkv) => {
-        const items = data[tkv].items;
-        if (!Array.isArray(items) || !items.length)
-          return;
-        items.forEach((item) => {
-          if (that.itemLocation.has(item.id))
-            return;
-          let resolved;
-          try {
-            resolved = loco.resolveLocationSet(item.locationSet);
-          } catch (err) {
-            console.warn(`buildLocationIndex: ${err.message}`);
-          }
-          if (!resolved || !resolved.id)
-            return;
-          that.itemLocation.set(item.id, resolved.id);
-          if (that.locationSets.has(resolved.id))
-            return;
-          let feature3 = _cloneDeep2(resolved.feature);
-          feature3.id = resolved.id;
-          feature3.properties.id = resolved.id;
-          if (!feature3.geometry.coordinates.length || !feature3.properties.area) {
-            console.warn(`buildLocationIndex: locationSet ${resolved.id} for ${item.id} resolves to an empty feature:`);
-            console.warn(JSON.stringify(feature3));
-            return;
-          }
-          that.locationSets.set(resolved.id, feature3);
-        });
-      });
-      that.locationIndex = (0, import_which_polygon3.default)({ type: "FeatureCollection", features: [...that.locationSets.values()] });
-      function _cloneDeep2(obj) {
-        return JSON.parse(JSON.stringify(obj));
-      }
-    }
-    match(k, v, n2, loc) {
-      const that = this;
-      if (!that.matchIndex) {
-        throw new Error("match:  matchIndex not built.");
-      }
-      let matchLocations;
-      if (Array.isArray(loc) && that.locationIndex) {
-        matchLocations = that.locationIndex([loc[0], loc[1], loc[0], loc[1]], true);
-      }
-      const nsimple = simplify(n2);
-      let seen = /* @__PURE__ */ new Set();
-      let results = [];
-      gatherResults("primary");
-      gatherResults("alternate");
-      if (results.length)
-        return results;
-      gatherResults("exclude");
-      return results.length ? results : null;
-      function gatherResults(which) {
-        const kv = `${k}/${v}`;
-        let didMatch = tryMatch(which, kv);
-        if (didMatch)
-          return;
-        for (let mg in matchGroups) {
-          const matchGroup = matchGroups[mg];
-          const inGroup = matchGroup.some((otherkv) => otherkv === kv);
-          if (!inGroup)
-            continue;
-          for (let i2 = 0; i2 < matchGroup.length; i2++) {
-            const otherkv = matchGroup[i2];
-            if (otherkv === kv)
-              continue;
-            didMatch = tryMatch(which, otherkv);
-            if (didMatch)
-              return;
-          }
-        }
-        if (which === "exclude") {
-          const regex = [...that.genericWords.values()].find((regex2) => regex2.test(n2));
-          if (regex) {
-            results.push({ match: "excludeGeneric", pattern: String(regex) });
-            return;
-          }
-        }
-      }
-      function tryMatch(which, kv) {
-        const branch = that.matchIndex.get(kv);
-        if (!branch)
-          return;
-        if (which === "exclude") {
-          let regex = [...branch.excludeNamed.values()].find((regex2) => regex2.test(n2));
-          if (regex) {
-            results.push({ match: "excludeNamed", pattern: String(regex), kv });
-            return;
-          }
-          regex = [...branch.excludeGeneric.values()].find((regex2) => regex2.test(n2));
-          if (regex) {
-            results.push({ match: "excludeGeneric", pattern: String(regex), kv });
-            return;
-          }
-          return;
-        }
-        const leaf = branch[which].get(nsimple);
-        if (!leaf || !leaf.size)
-          return;
-        let hits = Array.from(leaf).map((itemID) => {
-          let area = Infinity;
-          if (that.itemLocation && that.locationSets) {
-            const location = that.locationSets.get(that.itemLocation.get(itemID));
-            area = location && location.properties.area || Infinity;
-          }
-          return { match: which, itemID, area, kv, nsimple };
-        });
-        let sortFn = byAreaDescending;
-        if (matchLocations) {
-          hits = hits.filter(isValidLocation);
-          sortFn = byAreaAscending;
-        }
-        if (!hits.length)
-          return;
-        hits.sort(sortFn).forEach((hit) => {
-          if (seen.has(hit.itemID))
-            return;
-          seen.add(hit.itemID);
-          results.push(hit);
-        });
-        return true;
-        function isValidLocation(hit) {
-          if (!that.itemLocation)
-            return true;
-          return matchLocations.find((props) => props.id === that.itemLocation.get(hit.itemID));
-        }
-        function byAreaAscending(hitA, hitB) {
-          return hitA.area - hitB.area;
-        }
-        function byAreaDescending(hitA, hitB) {
-          return hitB.area - hitA.area;
-        }
-      }
-    }
-    getWarnings() {
-      return this.warnings;
-    }
-  };
-
-  // modules/services/nsi.js
-  var import_vparse2 = __toESM(require_vparse());
-
-  // modules/core/difference.js
-  var import_fast_deep_equal3 = __toESM(require_fast_deep_equal());
-  function coreDifference(base, head) {
-    var _changes = {};
-    var _didChange = {};
-    var _diff = {};
-    function checkEntityID(id2) {
-      var h = head.entities[id2];
-      var b = base.entities[id2];
-      if (h === b)
-        return;
-      if (_changes[id2])
-        return;
-      if (!h && b) {
-        _changes[id2] = { base: b, head: h };
-        _didChange.deletion = true;
-        return;
-      }
-      if (h && !b) {
-        _changes[id2] = { base: b, head: h };
-        _didChange.addition = true;
-        return;
-      }
-      if (h && b) {
-        if (h.members && b.members && !(0, import_fast_deep_equal3.default)(h.members, b.members)) {
-          _changes[id2] = { base: b, head: h };
-          _didChange.geometry = true;
-          _didChange.properties = true;
-          return;
-        }
-        if (h.loc && b.loc && !geoVecEqual(h.loc, b.loc)) {
-          _changes[id2] = { base: b, head: h };
-          _didChange.geometry = true;
-        }
-        if (h.nodes && b.nodes && !(0, import_fast_deep_equal3.default)(h.nodes, b.nodes)) {
-          _changes[id2] = { base: b, head: h };
-          _didChange.geometry = true;
-        }
-        if (h.tags && b.tags && !(0, import_fast_deep_equal3.default)(h.tags, b.tags)) {
-          _changes[id2] = { base: b, head: h };
-          _didChange.properties = true;
-        }
-      }
-    }
-    function load() {
-      var ids = utilArrayUniq(Object.keys(head.entities).concat(Object.keys(base.entities)));
-      for (var i2 = 0; i2 < ids.length; i2++) {
-        checkEntityID(ids[i2]);
-      }
-    }
-    load();
-    _diff.length = function length() {
-      return Object.keys(_changes).length;
-    };
-    _diff.changes = function changes() {
-      return _changes;
-    };
-    _diff.didChange = _didChange;
-    _diff.extantIDs = function extantIDs(includeRelMembers) {
-      var result = /* @__PURE__ */ new Set();
-      Object.keys(_changes).forEach(function(id2) {
-        if (_changes[id2].head) {
-          result.add(id2);
-        }
-        var h = _changes[id2].head;
-        var b = _changes[id2].base;
-        var entity = h || b;
-        if (includeRelMembers && entity.type === "relation") {
-          var mh = h ? h.members.map(function(m) {
-            return m.id;
-          }) : [];
-          var mb = b ? b.members.map(function(m) {
-            return m.id;
-          }) : [];
-          utilArrayUnion(mh, mb).forEach(function(memberID) {
-            if (head.hasEntity(memberID)) {
-              result.add(memberID);
-            }
-          });
-        }
-      });
-      return Array.from(result);
-    };
-    _diff.modified = function modified() {
-      var result = [];
-      Object.values(_changes).forEach(function(change) {
-        if (change.base && change.head) {
-          result.push(change.head);
-        }
-      });
-      return result;
-    };
-    _diff.created = function created() {
-      var result = [];
-      Object.values(_changes).forEach(function(change) {
-        if (!change.base && change.head) {
-          result.push(change.head);
-        }
-      });
-      return result;
-    };
-    _diff.deleted = function deleted() {
-      var result = [];
-      Object.values(_changes).forEach(function(change) {
-        if (change.base && !change.head) {
-          result.push(change.base);
-        }
-      });
-      return result;
-    };
-    _diff.summary = function summary() {
-      var relevant = {};
-      var keys = Object.keys(_changes);
-      for (var i2 = 0; i2 < keys.length; i2++) {
-        var change = _changes[keys[i2]];
-        if (change.head && change.head.geometry(head) !== "vertex") {
-          addEntity(change.head, head, change.base ? "modified" : "created");
-        } else if (change.base && change.base.geometry(base) !== "vertex") {
-          addEntity(change.base, base, "deleted");
-        } else if (change.base && change.head) {
-          var moved = !(0, import_fast_deep_equal3.default)(change.base.loc, change.head.loc);
-          var retagged = !(0, import_fast_deep_equal3.default)(change.base.tags, change.head.tags);
-          if (moved) {
-            addParents(change.head);
-          }
-          if (retagged || moved && change.head.hasInterestingTags()) {
-            addEntity(change.head, head, "modified");
-          }
-        } else if (change.head && change.head.hasInterestingTags()) {
-          addEntity(change.head, head, "created");
-        } else if (change.base && change.base.hasInterestingTags()) {
-          addEntity(change.base, base, "deleted");
-        }
-      }
-      return Object.values(relevant);
-      function addEntity(entity, graph, changeType) {
-        relevant[entity.id] = {
-          entity,
-          graph,
-          changeType
-        };
-      }
-      function addParents(entity) {
-        var parents = head.parentWays(entity);
-        for (var j2 = parents.length - 1; j2 >= 0; j2--) {
-          var parent = parents[j2];
-          if (!(parent.id in relevant)) {
-            addEntity(parent, head, "modified");
-          }
-        }
-      }
-    };
-    _diff.complete = function complete(extent) {
-      var result = {};
-      var id2, change;
-      for (id2 in _changes) {
-        change = _changes[id2];
-        var h = change.head;
-        var b = change.base;
-        var entity = h || b;
-        var i2;
-        if (extent && (!h || !h.intersects(extent, head)) && (!b || !b.intersects(extent, base))) {
-          continue;
-        }
-        result[id2] = h;
-        if (entity.type === "way") {
-          var nh = h ? h.nodes : [];
-          var nb = b ? b.nodes : [];
-          var diff;
-          diff = utilArrayDifference(nh, nb);
-          for (i2 = 0; i2 < diff.length; i2++) {
-            result[diff[i2]] = head.hasEntity(diff[i2]);
-          }
-          diff = utilArrayDifference(nb, nh);
-          for (i2 = 0; i2 < diff.length; i2++) {
-            result[diff[i2]] = head.hasEntity(diff[i2]);
-          }
-        }
-        if (entity.type === "relation" && entity.isMultipolygon()) {
-          var mh = h ? h.members.map(function(m) {
-            return m.id;
-          }) : [];
-          var mb = b ? b.members.map(function(m) {
-            return m.id;
-          }) : [];
-          var ids = utilArrayUnion(mh, mb);
-          for (i2 = 0; i2 < ids.length; i2++) {
-            var member = head.hasEntity(ids[i2]);
-            if (!member)
-              continue;
-            if (extent && !member.intersects(extent, head))
-              continue;
-            result[ids[i2]] = member;
-          }
-        }
-        addParents(head.parentWays(entity), result);
-        addParents(head.parentRelations(entity), result);
-      }
-      return result;
-      function addParents(parents, result2) {
-        for (var i3 = 0; i3 < parents.length; i3++) {
-          var parent = parents[i3];
-          if (parent.id in result2)
-            continue;
-          result2[parent.id] = parent;
-          addParents(head.parentRelations(parent), result2);
-        }
-      }
-    };
-    return _diff;
-  }
-
-  // modules/core/tree.js
-  var import_rbush6 = __toESM(require_rbush_min());
-  function coreTree(head) {
-    var _rtree = new import_rbush6.default();
-    var _bboxes = {};
-    var _segmentsRTree = new import_rbush6.default();
-    var _segmentsBBoxes = {};
-    var _segmentsByWayId = {};
-    var tree = {};
-    function entityBBox(entity) {
-      var bbox2 = entity.extent(head).bbox();
-      bbox2.id = entity.id;
-      _bboxes[entity.id] = bbox2;
-      return bbox2;
+    };
+    return _diff;
+  }
+
+  // modules/core/tree.js
+  var import_rbush5 = __toESM(require_rbush_min());
+  function coreTree(head) {
+    var _rtree = new import_rbush5.default();
+    var _bboxes = {};
+    var _segmentsRTree = new import_rbush5.default();
+    var _segmentsBBoxes = {};
+    var _segmentsByWayId = {};
+    var tree = {};
+    function entityBBox(entity) {
+      var bbox2 = entity.extent(head).bbox();
+      bbox2.id = entity.id;
+      _bboxes[entity.id] = bbox2;
+      return bbox2;
     }
     function segmentBBox(segment) {
       var extent = segment.extent(head);
@@ -39350,6 +40700,7 @@ ${content}</tr>
         select_default2(document).interrupt("history.perform");
         return _replace(arguments, 1);
       },
+      // Same as calling pop and then perform
       overwrite: function() {
         select_default2(document).interrupt("history.perform");
         return _overwrite(arguments, 1);
@@ -39366,6 +40717,7 @@ ${content}</tr>
         }
         return change(previous);
       },
+      // Back to the previous annotated state or _index = 0.
       undo: function() {
         select_default2(document).interrupt("history.perform");
         var previousStack = _stack[_index];
@@ -39378,6 +40730,7 @@ ${content}</tr>
         dispatch10.call("undone", this, _stack[_index], previousStack);
         return change(previous);
       },
+      // Forward to the next annotated state.
       redo: function() {
         select_default2(document).interrupt("history.perform");
         var previousStack = _stack[_index];
@@ -39421,6 +40774,8 @@ ${content}</tr>
           i2++;
         }
       },
+      // Returns the entities from the active graph with bounding boxes
+      // overlapping the given `extent`.
       intersects: function(extent) {
         return _tree.intersects(extent, _stack[_index].graph);
       },
@@ -39477,6 +40832,7 @@ ${content}</tr>
           return Array.from(s);
         }
       },
+      // save the current history state
       checkpoint: function(key) {
         _checkpoints[key] = {
           stack: _stack,
@@ -39484,6 +40840,7 @@ ${content}</tr>
         };
         return history;
       },
+      // restore history state to a given checkpoint or reset completely
       reset: function(key) {
         if (key !== void 0 && _checkpoints.hasOwnProperty(key)) {
           _stack = _checkpoints[key].stack;
@@ -39498,6 +40855,16 @@ ${content}</tr>
         dispatch10.call("change");
         return history;
       },
+      // `toIntroGraph()` is used to export the intro graph used by the walkthrough.
+      //
+      // To use it:
+      //  1. Start the walkthrough.
+      //  2. Get to a "free editing" tutorial step
+      //  3. Make your edits to the walkthrough map
+      //  4. In your browser dev console run:
+      //        `id.history().toIntroGraph()`
+      //  5. This outputs stringified JSON to the browser console
+      //  6. Copy it to `data/intro_graph.json` and prettify it in your code editor
       toIntroGraph: function() {
         var nextID = { n: 0, r: 0, w: 0 };
         var permIDs = {};
@@ -39612,7 +40979,8 @@ ${content}</tr>
           stack: s,
           nextIDs: osmEntity.id.next,
           index: _index,
-          timestamp: new Date().getTime()
+          // note the time the changes were saved
+          timestamp: (/* @__PURE__ */ new Date()).getTime()
         });
       },
       fromJSON: function(json, loadChildNodes) {
@@ -39731,13 +41099,15 @@ ${content}</tr>
         lock.unlock();
       },
       save: function() {
-        if (lock.locked() && !_hasUnresolvedRestorableChanges) {
+        if (lock.locked() && // don't overwrite existing, unresolved changes
+        !_hasUnresolvedRestorableChanges) {
           const success = corePreferences(getKey("saved_history"), history.toJSON() || null);
           if (!success)
             dispatch10.call("storage_error");
         }
         return history;
       },
+      // delete the history version saved in localStorage
       clearSaved: function() {
         context.debouncedSave.cancel();
         if (lock.locked()) {
@@ -39755,6 +41125,7 @@ ${content}</tr>
       hasRestorableChanges: function() {
         return _hasUnresolvedRestorableChanges;
       },
+      // load history from a version stored in localStorage
       restore: function() {
         if (lock.locked()) {
           _hasUnresolvedRestorableChanges = false;
@@ -39792,7 +41163,7 @@ ${content}</tr>
 
   // modules/validations/almost_junction.js
   function validationAlmostJunction(context) {
-    const type3 = "almost_junction";
+    const type2 = "almost_junction";
     const EXTEND_TH_METERS = 5;
     const WELD_TH_METERS = 0.75;
     const CLOSE_NODE_TH = EXTEND_TH_METERS - WELD_TH_METERS;
@@ -39813,7 +41184,7 @@ ${content}</tr>
       let issues = [];
       extendableNodeInfos.forEach((extendableNodeInfo) => {
         issues.push(new validationIssue({
-          type: type3,
+          type: type2,
           subtype: "highway-highway",
           severity: "warning",
           message: function(context2) {
@@ -40031,13 +41402,13 @@ ${content}</tr>
         return null;
       }
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/close_nodes.js
   function validationCloseNodes(context) {
-    var type3 = "close_nodes";
+    var type2 = "close_nodes";
     var pointThresholdMeters = 0.2;
     var validation = function(entity, graph) {
       if (entity.type === "node") {
@@ -40175,7 +41546,7 @@ ${content}</tr>
             if (zAxisDifferentiates)
               continue;
             issues.push(new validationIssue({
-              type: type3,
+              type: type2,
               subtype: "detached",
               severity: "warning",
               message: function(context2) {
@@ -40227,7 +41598,7 @@ ${content}</tr>
             return null;
         }
         return new validationIssue({
-          type: type3,
+          type: type2,
           subtype: "vertices",
           severity: "warning",
           message: function(context2) {
@@ -40261,13 +41632,14 @@ ${content}</tr>
         }
       }
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/crossing_ways.js
+  var import_lodash3 = __toESM(require_lodash());
   function validationCrossingWays(context) {
-    var type3 = "crossing_ways";
+    var type2 = "crossing_ways";
     function getFeatureWithFeatureTypeTagsForWay(way, graph) {
       if (getFeatureType(way, graph) === null) {
         var parentRels = graph.parentRelations(way);
@@ -40365,8 +41737,7 @@ ${content}</tr>
       secondary: true,
       secondary_link: true
     };
-    var nonCrossingHighways = { track: true };
-    function tagsForConnectionNodeIfAllowed(entity1, entity2, graph) {
+    function tagsForConnectionNodeIfAllowed(entity1, entity2, graph, lessLikelyTags) {
       var featureType1 = getFeatureType(entity1, graph);
       var featureType2 = getFeatureType(entity2, graph);
       var geometry1 = entity1.geometry(graph);
@@ -40378,11 +41749,14 @@ ${content}</tr>
           var entity2IsPath = osmPathHighwayTagValues[entity2.tags.highway];
           if ((entity1IsPath || entity2IsPath) && entity1IsPath !== entity2IsPath) {
             var roadFeature = entity1IsPath ? entity2 : entity1;
-            if (nonCrossingHighways[roadFeature.tags.highway]) {
+            var pathFeature = entity1IsPath ? entity1 : entity2;
+            if (roadFeature.tags.highway === "track") {
               return {};
             }
-            var pathFeature = entity1IsPath ? entity1 : entity2;
-            if (["marked", "unmarked", "traffic_signals"].indexOf(pathFeature.tags.crossing) !== -1) {
+            if (!lessLikelyTags && roadFeature.tags.highway === "service" && pathFeature.tags.highway === "footway" && pathFeature.tags.footway === "sidewalk") {
+              return {};
+            }
+            if (["marked", "unmarked", "traffic_signals", "uncontrolled"].indexOf(pathFeature.tags.crossing) !== -1) {
               return bothLines ? { highway: "crossing", crossing: pathFeature.tags.crossing } : {};
             }
             return bothLines ? { highway: "crossing" } : {};
@@ -40518,7 +41892,8 @@ ${content}</tr>
         return [entity];
       } else if (entity.type === "relation") {
         return entity.members.reduce(function(array2, member) {
-          if (member.type === "way" && (!member.role || member.role === "outer" || member.role === "inner")) {
+          if (member.type === "way" && // only look at geometry ways
+          (!member.role || member.role === "outer" || member.role === "inner")) {
             var entity2 = graph.hasEntity(member.id);
             if (entity2 && array2.indexOf(entity2) === -1) {
               array2.push(entity2);
@@ -40580,7 +41955,7 @@ ${content}</tr>
       }
       var uniqueID = crossing.crossPoint[0].toFixed(4) + "," + crossing.crossPoint[1].toFixed(4);
       return new validationIssue({
-        type: type3,
+        type: type2,
         subtype,
         severity: "warning",
         message: function(context2) {
@@ -40612,6 +41987,10 @@ ${content}</tr>
           var fixes = [];
           if (connectionTags) {
             fixes.push(makeConnectWaysFix(this.data.connectionTags));
+            let lessLikelyConnectionTags = tagsForConnectionNodeIfAllowed(entities[0], entities[1], graph, true);
+            if (lessLikelyConnectionTags && !(0, import_lodash3.isEqual)(connectionTags, lessLikelyConnectionTags)) {
+              fixes.push(makeConnectWaysFix(lessLikelyConnectionTags));
+            }
           }
           if (isCrossingIndoors) {
             fixes.push(new validationIssueFix({
@@ -40671,7 +42050,7 @@ ${content}</tr>
           var action = function actionAddStructure(graph) {
             var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
             var crossedWay = graph.hasEntity(crossedWayID);
-            var structLengthMeters = crossedWay && crossedWay.tags.width && parseFloat(crossedWay.tags.width);
+            var structLengthMeters = crossedWay && isFinite(crossedWay.tags.width) && Number(crossedWay.tags.width);
             if (!structLengthMeters) {
               structLengthMeters = crossedWay && crossedWay.impliedLineWidthMeters();
             }
@@ -40790,19 +42169,24 @@ ${content}</tr>
     }
     function makeConnectWaysFix(connectionTags) {
       var fixTitleID = "connect_features";
+      var fixIcon = "iD-icon-crossing";
+      if (connectionTags.highway === "crossing") {
+        fixTitleID = "connect_using_crossing";
+        fixIcon = "temaki-pedestrian";
+      }
       if (connectionTags.ford) {
         fixTitleID = "connect_using_ford";
+        fixIcon = "roentgen-ford";
       }
-      return new validationIssueFix({
-        icon: "iD-icon-crossing",
+      const fix = new validationIssueFix({
+        icon: fixIcon,
         title: _t.append("issues.fix." + fixTitleID + ".title"),
         onClick: function(context2) {
           var loc = this.issue.loc;
-          var connectionTags2 = this.issue.data.connectionTags;
           var edges = this.issue.data.edges;
           context2.perform(
             function actionConnectCrossingWays(graph) {
-              var node = osmNode({ loc, tags: connectionTags2 });
+              var node = osmNode({ loc, tags: connectionTags });
               graph = graph.replace(node);
               var nodesToMerge = [node.id];
               var mergeThresholdInMeters = 0.75;
@@ -40824,6 +42208,8 @@ ${content}</tr>
           );
         }
       });
+      fix._connectionTags = connectionTags;
+      return fix;
     }
     function makeChangeLayerFix(higherOrLower) {
       return new validationIssueFix({
@@ -40867,7 +42253,7 @@ ${content}</tr>
         }
       });
     }
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
@@ -40942,7 +42328,10 @@ ${content}</tr>
       }
       context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
       _drawNode = context.entity(_drawNode.id);
-      checkGeometry(true);
+      checkGeometry(
+        true
+        /* includeDrawNode */
+      );
     }
     function checkGeometry(includeDrawNode) {
       var nopeDisabled = context.surface().classed("nope-disabled");
@@ -41055,7 +42444,10 @@ ${content}</tr>
       } else {
         createDrawNode(loc);
       }
-      checkGeometry(true);
+      checkGeometry(
+        true
+        /* includeDrawNode */
+      );
       if (d && d.properties && d.properties.nope || context.surface().classed("nope")) {
         if (!_pointerHasMoved) {
           removeDrawNode();
@@ -41082,7 +42474,8 @@ ${content}</tr>
       });
     };
     drawWay.addNode = function(node, d) {
-      if (node.id === _headNodeID || _origWay.isClosed() && node.id === _origWay.first()) {
+      if (node.id === _headNodeID || // or the first node when drawing an area
+      _origWay.isClosed() && node.id === _origWay.first()) {
         drawWay.finish();
         return;
       }
@@ -41145,7 +42538,10 @@ ${content}</tr>
     keybinding.on(_t("operations.follow.key"), followMode);
     select_default2(document).call(keybinding);
     drawWay.finish = function() {
-      checkGeometry(false);
+      checkGeometry(
+        false
+        /* includeDrawNode */
+      );
       if (context.surface().classed("nope")) {
         dispatch10.call("rejectedSelfIntersection", this);
         return;
@@ -41218,7 +42614,7 @@ ${content}</tr>
 
   // modules/validations/disconnected_way.js
   function validationDisconnectedWay() {
-    var type3 = "disconnected_way";
+    var type2 = "disconnected_way";
     function isTaggedAsHighway(entity) {
       return osmRoutableHighwayTagValues[entity.tags.highway];
     }
@@ -41227,7 +42623,7 @@ ${content}</tr>
       if (!routingIslandWays)
         return [];
       return [new validationIssue({
-        type: type3,
+        type: type2,
         subtype: "highway",
         severity: "warning",
         message: function(context) {
@@ -41286,7 +42682,8 @@ ${content}</tr>
         var waysToCheck = [];
         function queueParentWays(node) {
           graph.parentWays(node).forEach(function(parentWay) {
-            if (!routingIsland.has(parentWay) && isRoutableWay(parentWay, false)) {
+            if (!routingIsland.has(parentWay) && // only check each feature once
+            isRoutableWay(parentWay, false)) {
               routingIsland.add(parentWay);
               waysToCheck.push(parentWay);
             }
@@ -41370,13 +42767,13 @@ ${content}</tr>
         });
       }
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/invalid_format.js
   function validationFormatting() {
-    var type3 = "invalid_format";
+    var type2 = "invalid_format";
     var validation = function(entity) {
       var issues = [];
       function isValidEmail(email) {
@@ -41394,7 +42791,7 @@ ${content}</tr>
         });
         if (emails.length) {
           issues.push(new validationIssue({
-            type: type3,
+            type: type2,
             subtype: "email",
             severity: "warning",
             message: function(context) {
@@ -41413,13 +42810,13 @@ ${content}</tr>
       }
       return issues;
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/help_request.js
   function validationHelpRequest(context) {
-    var type3 = "help_request";
+    var type2 = "help_request";
     var validation = function checkFixmeTag(entity) {
       if (!entity.tags.fixme)
         return [];
@@ -41431,13 +42828,18 @@ ${content}</tr>
           return [];
       }
       return [new validationIssue({
-        type: type3,
+        type: type2,
         subtype: "fixme_tag",
         severity: "warning",
         message: function(context2) {
           var entity2 = context2.hasEntity(this.entityIds[0]);
           return entity2 ? _t.append("issues.fixme_tag.message", {
-            feature: utilDisplayLabel(entity2, context2.graph(), true)
+            feature: utilDisplayLabel(
+              entity2,
+              context2.graph(),
+              true
+              /* verbose */
+            )
           }) : "";
         },
         dynamicFixes: function() {
@@ -41454,13 +42856,13 @@ ${content}</tr>
         selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.fixme_tag.reference"));
       }
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/impossible_oneway.js
   function validationImpossibleOneway() {
-    var type3 = "impossible_oneway";
+    var type2 = "impossible_oneway";
     var validation = function checkImpossibleOneway(entity, graph) {
       if (entity.type !== "way" || entity.geometry(graph) !== "line")
         return [];
@@ -41586,7 +42988,7 @@ ${content}</tr>
           referenceID += placement;
         }
         return [new validationIssue({
-          type: type3,
+          type: type2,
           subtype: wayType,
           severity: "warning",
           message: function(context) {
@@ -41645,13 +43047,13 @@ ${content}</tr>
         modeDrawLine(context, way.id, context.graph(), "line", way.affix(vertex.id), true)
       );
     }
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/incompatible_source.js
   function validationIncompatibleSource() {
-    const type3 = "incompatible_source";
+    const type2 = "incompatible_source";
     const incompatibleRules = [
       {
         id: "amap",
@@ -41683,12 +43085,17 @@ ${content}</tr>
         if (!matchRule)
           return null;
         return new validationIssue({
-          type: type3,
+          type: type2,
           severity: "warning",
           message: (context) => {
             const entity2 = context.hasEntity(entityID);
             return entity2 ? _t.append("issues.incompatible_source.feature.message", {
-              feature: utilDisplayLabel(entity2, context.graph(), true),
+              feature: utilDisplayLabel(
+                entity2,
+                context.graph(),
+                true
+                /* verbose */
+              ),
               value: source
             }) : "";
           },
@@ -41708,13 +43115,13 @@ ${content}</tr>
         };
       }
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/maprules.js
   function validationMaprules() {
-    var type3 = "maprules";
+    var type2 = "maprules";
     var validation = function checkMaprules(entity, graph) {
       if (!services.maprules)
         return [];
@@ -41726,14 +43133,14 @@ ${content}</tr>
       }
       return issues;
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/mismatched_geometry.js
   var import_fast_deep_equal4 = __toESM(require_fast_deep_equal());
   function validationMismatchedGeometry() {
-    var type3 = "mismatched_geometry";
+    var type2 = "mismatched_geometry";
     function tagSuggestingLineIsArea(entity) {
       if (entity.type !== "way" || entity.isClosed())
         return null;
@@ -41799,13 +43206,18 @@ ${content}</tr>
         }
       }
       return new validationIssue({
-        type: type3,
+        type: type2,
         subtype: "area_as_line",
         severity: "warning",
         message: function(context) {
           var entity2 = context.hasEntity(this.entityIds[0]);
           return entity2 ? _t.append("issues.tag_suggests_area.message", {
-            feature: utilDisplayLabel(entity2, "area", true),
+            feature: utilDisplayLabel(
+              entity2,
+              "area",
+              true
+              /* verbose */
+            ),
             tag: utilTagText({ tags: tagSuggestingArea })
           }) : "";
         },
@@ -41856,13 +43268,18 @@ ${content}</tr>
       var allowedGeometries = osmNodeGeometriesForTags(entity.tags);
       if (geometry === "point" && !allowedGeometries.point && allowedGeometries.vertex) {
         return new validationIssue({
-          type: type3,
+          type: type2,
           subtype: "vertex_as_point",
           severity: "warning",
           message: function(context) {
             var entity2 = context.hasEntity(this.entityIds[0]);
             return entity2 ? _t.append("issues.vertex_as_point.message", {
-              feature: utilDisplayLabel(entity2, "vertex", true)
+              feature: utilDisplayLabel(
+                entity2,
+                "vertex",
+                true
+                /* verbose */
+              )
             }) : "";
           },
           reference: function showReference(selection2) {
@@ -41872,13 +43289,18 @@ ${content}</tr>
         });
       } else if (geometry === "vertex" && !allowedGeometries.vertex && allowedGeometries.point) {
         return new validationIssue({
-          type: type3,
+          type: type2,
           subtype: "point_as_vertex",
           severity: "warning",
           message: function(context) {
             var entity2 = context.hasEntity(this.entityIds[0]);
             return entity2 ? _t.append("issues.point_as_vertex.message", {
-              feature: utilDisplayLabel(entity2, "point", true)
+              feature: utilDisplayLabel(
+                entity2,
+                "point",
+                true
+                /* verbose */
+              )
             }) : "";
           },
           reference: function showReference(selection2) {
@@ -41904,7 +43326,8 @@ ${content}</tr>
       var asSource = _mainPresetIndex.match(entity, graph);
       var targetGeom = targetGeoms.find((nodeGeom) => {
         var asTarget = _mainPresetIndex.matchTags(entity.tags, nodeGeom);
-        if (!asSource || !asTarget || asSource === asTarget || (0, import_fast_deep_equal4.default)(asSource.tags, asTarget.tags))
+        if (!asSource || !asTarget || asSource === asTarget || // sometimes there are two presets with the same tags for different geometries
+        (0, import_fast_deep_equal4.default)(asSource.tags, asTarget.tags))
           return false;
         if (asTarget.isFallback())
           return false;
@@ -41930,13 +43353,18 @@ ${content}</tr>
         dynamicFixes = lineToAreaDynamicFixes;
       }
       return new validationIssue({
-        type: type3,
+        type: type2,
         subtype,
         severity: "warning",
         message: function(context) {
           var entity2 = context.hasEntity(this.entityIds[0]);
           return entity2 ? _t.append("issues." + referenceId + ".message", {
-            feature: utilDisplayLabel(entity2, targetGeom, true)
+            feature: utilDisplayLabel(
+              entity2,
+              targetGeom,
+              true
+              /* verbose */
+            )
           }) : "";
         },
         reference: function showReference(selection2) {
@@ -41997,7 +43425,8 @@ ${content}</tr>
       ];
     }
     function unclosedMultipolygonPartIssues(entity, graph) {
-      if (entity.type !== "relation" || !entity.isMultipolygon() || entity.isDegenerate() || !entity.isComplete(graph))
+      if (entity.type !== "relation" || !entity.isMultipolygon() || entity.isDegenerate() || // cannot determine issues for incompletely-downloaded relations
+      !entity.isComplete(graph))
         return [];
       var sequences = osmJoinWays(entity.members, graph);
       var issues = [];
@@ -42010,13 +43439,18 @@ ${content}</tr>
         if (firstNode === lastNode)
           continue;
         var issue = new validationIssue({
-          type: type3,
+          type: type2,
           subtype: "unclosed_multipolygon_part",
           severity: "warning",
           message: function(context) {
             var entity2 = context.hasEntity(this.entityIds[0]);
             return entity2 ? _t.append("issues.unclosed_multipolygon_part.message", {
-              feature: utilDisplayLabel(entity2, context.graph(), true)
+              feature: utilDisplayLabel(
+                entity2,
+                context.graph(),
+                true
+                /* verbose */
+              )
             }) : "";
           },
           reference: showReference,
@@ -42045,13 +43479,13 @@ ${content}</tr>
         return [mismatch];
       return unclosedMultipolygonPartIssues(entity, graph);
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/missing_role.js
   function validationMissingRole() {
-    var type3 = "missing_role";
+    var type2 = "missing_role";
     var validation = function checkMissingRole(entity, graph) {
       var issues = [];
       if (entity.type === "way") {
@@ -42078,7 +43512,7 @@ ${content}</tr>
     }
     function makeIssue(way, relation, member) {
       return new validationIssue({
-        type: type3,
+        type: type2,
         severity: "warning",
         message: function(context) {
           var member2 = context.hasEntity(this.entityIds[1]), relation2 = context.hasEntity(this.entityIds[0]);
@@ -42131,13 +43565,13 @@ ${content}</tr>
         }
       });
     }
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/missing_tag.js
   function validationMissingTag(context) {
-    var type3 = "missing_tag";
+    var type2 = "missing_tag";
     function hasDescriptiveTags(entity, graph) {
       var onlyAttributeKeys = ["description", "name", "note", "start_date"];
       var entityDescriptiveKeys = Object.keys(entity.tags).filter(function(k) {
@@ -42162,7 +43596,9 @@ ${content}</tr>
       var subtype;
       var osm = context.connection();
       var isUnloadedNode = entity.type === "node" && osm && !osm.isDataLoaded(entity.loc);
-      if (!isUnloadedNode && entity.geometry(graph) !== "vertex" && !entity.hasParentRelations(graph)) {
+      if (!isUnloadedNode && // allow untagged nodes that are part of ways
+      entity.geometry(graph) !== "vertex" && // allow untagged entities that are part of relations
+      !entity.hasParentRelations(graph)) {
         if (Object.keys(entity.tags).length === 0) {
           subtype = "any";
         } else if (!hasDescriptiveTags(entity, graph)) {
@@ -42181,7 +43617,7 @@ ${content}</tr>
       var canDelete = entity.version === void 0 || entity.v !== void 0;
       var severity = canDelete && subtype !== "highway_classification" ? "error" : "warning";
       return [new validationIssue({
-        type: type3,
+        type: type2,
         subtype,
         severity,
         message: function(context2) {
@@ -42230,28 +43666,34 @@ ${content}</tr>
         selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues." + referenceID + ".reference"));
       }
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/outdated_tags.js
   function validationOutdatedTags() {
-    const type3 = "outdated_tags";
+    const type2 = "outdated_tags";
     let _waitingForDeprecated = true;
     let _dataDeprecated;
     _mainFileFetcher.get("deprecated").then((d) => _dataDeprecated = d).catch(() => {
     }).finally(() => _waitingForDeprecated = false);
     function oldTagIssues(entity, graph) {
-      const oldTags = Object.assign({}, entity.tags);
+      if (!entity.hasInterestingTags())
+        return [];
       let preset = _mainPresetIndex.match(entity, graph);
-      let subtype = "deprecated_tags";
       if (!preset)
         return [];
-      if (!entity.hasInterestingTags())
-        return [];
+      const oldTags = Object.assign({}, entity.tags);
+      let subtype = "deprecated_tags";
       if (preset.replacement) {
         const newPreset = _mainPresetIndex.item(preset.replacement);
-        graph = actionChangePreset(entity.id, preset, newPreset, true)(graph);
+        graph = actionChangePreset(
+          entity.id,
+          preset,
+          newPreset,
+          true
+          /* skip field defaults */
+        )(graph);
         entity = graph.entity(entity.id);
         preset = newPreset;
       }
@@ -42305,7 +43747,7 @@ ${content}</tr>
       }
       let autoArgs = subtype !== "noncanonical_brand" ? [doUpgrade, _t("issues.fix.upgrade_tags.annotation")] : null;
       issues.push(new validationIssue({
-        type: type3,
+        type: type2,
         subtype,
         severity: "warning",
         message: showMessage,
@@ -42379,7 +43821,12 @@ ${content}</tr>
           messageID += "_incomplete";
         }
         return _t.append(messageID, {
-          feature: utilDisplayLabel(currEntity, context.graph(), true)
+          feature: utilDisplayLabel(
+            currEntity,
+            context.graph(),
+            true
+            /* verbose */
+          )
         });
       }
       function showReference(selection2) {
@@ -42406,7 +43853,7 @@ ${content}</tr>
       if (!multipolygon || !outerWay)
         return [];
       return [new validationIssue({
-        type: type3,
+        type: type2,
         subtype: "old_multipolygon",
         severity: "warning",
         message: showMessage,
@@ -42439,7 +43886,12 @@ ${content}</tr>
           return "";
         return _t.append(
           "issues.old_multipolygon.message",
-          { multipolygon: utilDisplayLabel(currMultipolygon, context.graph(), true) }
+          { multipolygon: utilDisplayLabel(
+            currMultipolygon,
+            context.graph(),
+            true
+            /* verbose */
+          ) }
         );
       }
       function showReference(selection2) {
@@ -42452,13 +43904,13 @@ ${content}</tr>
         issues = oldTagIssues(entity, graph);
       return issues;
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/private_data.js
   function validationPrivateData() {
-    var type3 = "private_data";
+    var type2 = "private_data";
     var privateBuildingValues = {
       detached: true,
       farm: true,
@@ -42502,7 +43954,7 @@ ${content}</tr>
         return [];
       var fixID = tagDiff.length === 1 ? "remove_tag" : "remove_tags";
       return [new validationIssue({
-        type: type3,
+        type: type2,
         severity: "warning",
         message: showMessage,
         reference: showReference,
@@ -42554,13 +44006,13 @@ ${content}</tr>
         });
       }
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/suspicious_name.js
   function validationSuspiciousName() {
-    const type3 = "suspicious_name";
+    const type2 = "suspicious_name";
     const keysToTestForGenericValues = [
       "aerialway",
       "aeroway",
@@ -42606,7 +44058,7 @@ ${content}</tr>
     }
     function makeGenericNameIssue(entityId, nameKey, genericName, langCode) {
       return new validationIssue({
-        type: type3,
+        type: type2,
         subtype: "generic_name",
         severity: "warning",
         message: function(context) {
@@ -42648,7 +44100,7 @@ ${content}</tr>
     }
     function makeIncorrectNameIssue(entityId, nameKey, incorrectName, langCode) {
       return new validationIssue({
-        type: type3,
+        type: type2,
         subtype: "not_name",
         severity: "warning",
         message: function(context) {
@@ -42717,13 +44169,13 @@ ${content}</tr>
       }
       return issues;
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
   // modules/validations/unsquare_way.js
   function validationUnsquareWay(context) {
-    var type3 = "unsquare_way";
+    var type2 = "unsquare_way";
     var DEFAULT_DEG_THRESHOLD = 5;
     var epsilon3 = 0.05;
     var nodeThreshold = 10;
@@ -42762,7 +44214,7 @@ ${content}</tr>
       if (hasConnectedSquarableWays)
         return [];
       var storedDegreeThreshold = corePreferences("validate-square-degrees");
-      var degreeThreshold = isNaN(storedDegreeThreshold) ? DEFAULT_DEG_THRESHOLD : parseFloat(storedDegreeThreshold);
+      var degreeThreshold = isFinite(storedDegreeThreshold) ? Number(storedDegreeThreshold) : DEFAULT_DEG_THRESHOLD;
       var points = nodes.map(function(node) {
         return context.projection(node.loc);
       });
@@ -42775,7 +44227,7 @@ ${content}</tr>
         autoArgs = [autoAction, _t("operations.orthogonalize.annotation.feature", { n: 1 })];
       }
       return [new validationIssue({
-        type: type3,
+        type: type2,
         subtype: "building",
         severity: "warning",
         message: function(context2) {
@@ -42804,6 +44256,21 @@ ${content}</tr>
                 }, 175);
               }
             })
+            /*
+            new validationIssueFix({
+                title: t.append('issues.fix.tag_as_unsquare.title'),
+                onClick: function(context) {
+                    var entityId = this.issue.entityIds[0];
+                    var entity = context.entity(entityId);
+                    var tags = Object.assign({}, entity.tags);  // shallow copy
+                    tags.nonsquare = 'yes';
+                    context.perform(
+                        actionChangeTags(entityId, tags),
+                        t('issues.fix.tag_as_unsquare.annotation')
+                    );
+                }
+            })
+            */
           ];
         }
       })];
@@ -42811,7 +44278,7 @@ ${content}</tr>
         selection2.selectAll(".issue-reference").data([0]).enter().append("div").attr("class", "issue-reference").call(_t.append("issues.unsquare_way.buildings.reference"));
       }
     };
-    validation.type = type3;
+    validation.type = type2;
     return validation;
   }
 
@@ -42840,11 +44307,11 @@ ${content}</tr>
       rules.forEach((rule) => {
         rule = rule.trim();
         const parts = rule.split("/", 2);
-        const type3 = parts[0];
+        const type2 = parts[0];
         const subtype = parts[1] || "*";
-        if (!type3 || !subtype)
+        if (!type2 || !subtype)
           return;
-        result.push({ type: makeRegExp(type3), subtype: makeRegExp(subtype) });
+        result.push({ type: makeRegExp(type2), subtype: makeRegExp(subtype) });
       });
       return result;
       function makeRegExp(str2) {
@@ -43004,14 +44471,19 @@ ${content}</tr>
     };
     validator.getSharedEntityIssues = (entityIDs, options2) => {
       const orderedIssueTypes = [
+        // Show some issue types in a particular order:
         "missing_tag",
         "missing_role",
+        // - missing data first
         "outdated_tags",
         "mismatched_geometry",
+        // - identity issues
         "crossing_ways",
         "almost_junction",
+        // - geometry issues where fixing them might solve connectivity issues
         "disconnected_way",
         "impossible_oneway"
+        // - finally connectivity issues
       ];
       const allIssues = validator.getIssues(options2);
       const forEntityIDs = new Set(entityIDs);
@@ -43048,9 +44520,9 @@ ${content}</tr>
       corePreferences("validate-disabledRules", Object.keys(_disabledRules).join(","));
       validator.validate();
     };
-    validator.disableRules = (keys) => {
+    validator.disableRules = (keys2) => {
       _disabledRules = {};
-      keys.forEach((k) => _disabledRules[k] = true);
+      keys2.forEach((k) => _disabledRules[k] = true);
       corePreferences("validate-disabledRules", Object.keys(_disabledRules).join(","));
       validator.validate();
     };
@@ -43126,23 +44598,23 @@ ${content}</tr>
         detected = detected.filter(applySeverityOverrides);
         result.issues = result.issues.concat(detected);
         function applySeverityOverrides(issue) {
-          const type3 = issue.type;
+          const type2 = issue.type;
           const subtype = issue.subtype || "";
           let i2;
           for (i2 = 0; i2 < _errorOverrides.length; i2++) {
-            if (_errorOverrides[i2].type.test(type3) && _errorOverrides[i2].subtype.test(subtype)) {
+            if (_errorOverrides[i2].type.test(type2) && _errorOverrides[i2].subtype.test(subtype)) {
               issue.severity = "error";
               return true;
             }
           }
           for (i2 = 0; i2 < _warningOverrides.length; i2++) {
-            if (_warningOverrides[i2].type.test(type3) && _warningOverrides[i2].subtype.test(subtype)) {
+            if (_warningOverrides[i2].type.test(type2) && _warningOverrides[i2].subtype.test(subtype)) {
               issue.severity = "warning";
               return true;
             }
           }
           for (i2 = 0; i2 < _disableOverrides.length; i2++) {
-            if (_disableOverrides[i2].type.test(type3) && _disableOverrides[i2].subtype.test(subtype)) {
+            if (_disableOverrides[i2].type.test(type2) && _disableOverrides[i2].subtype.test(subtype)) {
               return false;
             }
           }
@@ -43232,7 +44704,9 @@ ${content}</tr>
       queuedEntityIDs: /* @__PURE__ */ new Set(),
       provisionalEntityIDs: /* @__PURE__ */ new Set(),
       issuesByIssueID: {},
+      // issue.id -> issue
       issuesByEntityID: {}
+      // entity.id -> Set(issue.id)
     };
     cache.cacheIssue = (issue) => {
       (issue.entityIds || []).forEach((entityID) => {
@@ -43257,8 +44731,8 @@ ${content}</tr>
     cache.uncacheIssues = (issues) => {
       issues.forEach(cache.uncacheIssue);
     };
-    cache.uncacheIssuesOfType = (type3) => {
-      const issuesOfType = Object.values(cache.issuesByIssueID).filter((issue) => issue.type === type3);
+    cache.uncacheIssuesOfType = (type2) => {
+      const issuesOfType = Object.values(cache.issuesByIssueID).filter((issue) => issue.type === type2);
       cache.uncacheIssues(issuesOfType);
     };
     cache.uncacheEntityID = (entityID) => {
@@ -43300,14 +44774,23 @@ ${content}</tr>
   // modules/core/uploader.js
   function coreUploader(context) {
     var dispatch10 = dispatch_default(
+      // Start and end events are dispatched exactly once each per legitimate outside call to `save`
       "saveStarted",
+      // dispatched as soon as a call to `save` has been deemed legitimate
       "saveEnded",
+      // dispatched after the result event has been dispatched
       "willAttemptUpload",
+      // dispatched before the actual upload call occurs, if it will
       "progressChanged",
+      // Each save results in one of these outcomes:
       "resultNoChanges",
+      // upload wasn't attempted since there were no edits
       "resultErrors",
+      // upload failed due to errors
       "resultConflicts",
+      // upload failed due to data conflicts
       "resultSuccess"
+      // upload completed without errors
     );
     var _isSaving = false;
     var _conflicts = [];
@@ -43483,9 +44966,9 @@ ${content}</tr>
           var remote = remoteGraph.entity(id2);
           if (sameVersions(local, remote))
             return;
-          var merge3 = actionMergeRemoteChanges(id2, localGraph, remoteGraph, _discardTags, formatUser);
-          history.replace(merge3);
-          var mergeConflicts = merge3.conflicts();
+          var merge2 = actionMergeRemoteChanges(id2, localGraph, remoteGraph, _discardTags, formatUser);
+          history.replace(merge2);
+          var mergeConflicts = merge2.conflicts();
           if (!mergeConflicts.length)
             return;
           var forceLocal = actionMergeRemoteChanges(id2, localGraph, remoteGraph, _discardTags).withOption("force_local");
@@ -43594,10 +45077,16 @@ ${content}</tr>
   }
 
   // modules/renderer/background_source.js
-  var import_lodash2 = __toESM(require_lodash());
+  var import_lodash4 = __toESM(require_lodash());
 
   // modules/util/IntervalTasksQueue.js
   var IntervalTasksQueue = class {
+    /**
+     * Interval in milliseconds inside which only 1 task can execute.
+     * e.g. if interval is 200ms, and 5 async tasks are unqueued,
+     * they will complete in ~1s if not cleared
+     * @param {number} intervalInMs
+     */
     constructor(intervalInMs) {
       this.intervalInMs = intervalInMs;
       this.pendingHandles = [];
@@ -43671,20 +45160,20 @@ ${content}</tr>
     };
     source.name = function() {
       var id_safe = source.id.replace(/\./g, "<TX_DOT>");
-      return _t("imagery." + id_safe + ".name", { default: (0, import_lodash2.escape)(_name) });
+      return _t("imagery." + id_safe + ".name", { default: (0, import_lodash4.escape)(_name) });
     };
     source.label = function() {
       var id_safe = source.id.replace(/\./g, "<TX_DOT>");
-      return _t.append("imagery." + id_safe + ".name", { default: (0, import_lodash2.escape)(_name) });
+      return _t.append("imagery." + id_safe + ".name", { default: (0, import_lodash4.escape)(_name) });
     };
     source.hasDescription = function() {
       var id_safe = source.id.replace(/\./g, "<TX_DOT>");
-      var descriptionText = _mainLocalizer.tInfo("imagery." + id_safe + ".description", { default: (0, import_lodash2.escape)(_description) }).text;
+      var descriptionText = _mainLocalizer.tInfo("imagery." + id_safe + ".description", { default: (0, import_lodash4.escape)(_description) }).text;
       return descriptionText !== "";
     };
     source.description = function() {
       var id_safe = source.id.replace(/\./g, "<TX_DOT>");
-      return _t.append("imagery." + id_safe + ".description", { default: (0, import_lodash2.escape)(_description) });
+      return _t.append("imagery." + id_safe + ".description", { default: (0, import_lodash4.escape)(_description) });
     };
     source.best = function() {
       return _best;
@@ -43753,7 +45242,8 @@ ${content}</tr>
             case "wkid":
               return projection2.replace(/^EPSG:/, "");
             case "bbox":
-              if (projection2 === "EPSG:4326" && /VERSION=1.3|CRS={proj}/.test(source.template().toUpperCase())) {
+              if (projection2 === "EPSG:4326" && // The CRS parameter implies version 1.3 (prior versions use SRS)
+              /VERSION=1.3|CRS={proj}/.test(source.template().toUpperCase())) {
                 return maxXminY.y + "," + minXmaxY.x + "," + minXmaxY.y + "," + maxXminY.x;
               } else {
                 return minXmaxY.x + "," + maxXminY.y + "," + maxXminY.x + "," + minXmaxY.y;
@@ -43978,8 +45468,8 @@ ${content}</tr>
           vintage,
           source: clean2(result.NICE_NAME),
           description: clean2(result.NICE_DESC),
-          resolution: clean2(+parseFloat(result.SRC_RES).toFixed(4)),
-          accuracy: clean2(+parseFloat(result.SRC_ACC).toFixed(4))
+          resolution: clean2(+Number(result.SRC_RES).toFixed(4)),
+          accuracy: clean2(+Number(result.SRC_ACC).toFixed(4))
         };
         if (isFinite(metadata.resolution)) {
           metadata.resolution += " m";
@@ -44241,14 +45731,14 @@ ${content}</tr>
   // node_modules/@turf/bbox-clip/dist/es/index.js
   function bboxClip(feature3, bbox2) {
     var geom = getGeom(feature3);
-    var type3 = geom.type;
+    var type2 = geom.type;
     var properties = feature3.type === "Feature" ? feature3.properties : {};
     var coords = geom.coordinates;
-    switch (type3) {
+    switch (type2) {
       case "LineString":
       case "MultiLineString": {
         var lines_1 = [];
-        if (type3 === "LineString") {
+        if (type2 === "LineString") {
           coords = [coords];
         }
         coords.forEach(function(line) {
@@ -44266,7 +45756,7 @@ ${content}</tr>
           return clipPolygon(poly, bbox2);
         }), properties);
       default:
-        throw new Error("geometry " + type3 + " not supported");
+        throw new Error("geometry " + type2 + " not supported");
     }
   }
   function clipPolygon(rings, bbox2) {
@@ -44290,7 +45780,7 @@ ${content}</tr>
   function coordEach(geojson, callback, excludeWrapCoord) {
     if (geojson === null)
       return;
-    var j2, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type3 = geojson.type, isFeatureCollection = type3 === "FeatureCollection", isFeature = type3 === "Feature", stop = isFeatureCollection ? geojson.features.length : 1;
+    var j2, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type2 = geojson.type, isFeatureCollection = type2 === "FeatureCollection", isFeature = type2 === "Feature", stop = isFeatureCollection ? geojson.features.length : 1;
     for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
       geometryMaybeCollection = isFeatureCollection ? geojson.features[featureIndex].geometry : isFeature ? geojson.geometry : geojson;
       isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false;
@@ -44414,7 +45904,7 @@ ${content}</tr>
   var es_default = bbox;
 
   // modules/renderer/background.js
-  var import_which_polygon4 = __toESM(require_which_polygon());
+  var import_which_polygon3 = __toESM(require_which_polygon());
 
   // modules/renderer/tile_layer.js
   function rendererTileLayer(context) {
@@ -44579,6 +46069,7 @@ ${content}</tr>
             if (result && result.vintage && result.vintage.range) {
               span.text(result.vintage.range);
             } else {
+              span.text("");
               span.call(_t.append("info_panels.background.vintage"));
               span.append("span").text(": ");
               span.call(_t.append("info_panels.background.unknown"));
@@ -44631,7 +46122,7 @@ ${content}</tr>
           imagery: sources,
           features: {}
         };
-        const features2 = sources.map((source) => {
+        const features = sources.map((source) => {
           if (!source.polygon)
             return null;
           const rings = source.polygon.map((ring) => [ring]);
@@ -44643,7 +46134,7 @@ ${content}</tr>
           _imageryIndex.features[source.id] = feature3;
           return feature3;
         }).filter(Boolean);
-        _imageryIndex.query = (0, import_which_polygon4.default)({ type: "FeatureCollection", features: features2 });
+        _imageryIndex.query = (0, import_which_polygon3.default)({ type: "FeatureCollection", features });
         _imageryIndex.backgrounds = sources.map((source) => {
           if (source.type === "bing") {
             return rendererBackgroundSource.Bing(source, dispatch10);
@@ -44991,7 +46482,7 @@ ${content}</tr>
   // modules/renderer/features.js
   function rendererFeatures(context) {
     var dispatch10 = dispatch_default("change", "redraw");
-    var features2 = utilRebind({}, dispatch10, "on");
+    var features = utilRebind({}, dispatch10, "on");
     var _deferred2 = /* @__PURE__ */ new Set();
     var traffic_roads = {
       "motorway": true,
@@ -45006,7 +46497,8 @@ ${content}</tr>
       "tertiary_link": true,
       "residential": true,
       "unclassified": true,
-      "living_street": true
+      "living_street": true,
+      "busway": true
     };
     var service_roads = {
       "service": true,
@@ -45031,7 +46523,7 @@ ${content}</tr>
     function update() {
       if (!window.mocha) {
         var hash = utilStringQs(window.location.hash);
-        var disabled = features2.disabled();
+        var disabled = features.disabled();
         if (disabled.length) {
           hash.disable_features = disabled.join(",");
         } else {
@@ -45040,7 +46532,7 @@ ${content}</tr>
         window.location.replace("#" + utilQsString(hash, true));
         corePreferences("disabled-features", disabled.join(","));
       }
-      _hidden = features2.hidden();
+      _hidden = features.hidden();
       dispatch10.call("change");
       dispatch10.call("redraw");
     }
@@ -45050,6 +46542,7 @@ ${content}</tr>
       _rules[k] = {
         filter: filter2,
         enabled: isEnabled,
+        // whether the user wants it enabled..
         count: 0,
         currentMax: max3 || Infinity,
         defaultMax: max3 || Infinity,
@@ -45126,13 +46619,13 @@ ${content}</tr>
     defineRule("others", function isOther(tags, geometry) {
       return geometry === "line" || geometry === "area";
     });
-    features2.features = function() {
+    features.features = function() {
       return _rules;
     };
-    features2.keys = function() {
+    features.keys = function() {
       return _keys;
     };
-    features2.enabled = function(k) {
+    features.enabled = function(k) {
       if (!arguments.length) {
         return _keys.filter(function(k2) {
           return _rules[k2].enabled;
@@ -45140,7 +46633,7 @@ ${content}</tr>
       }
       return _rules[k] && _rules[k].enabled;
     };
-    features2.disabled = function(k) {
+    features.disabled = function(k) {
       if (!arguments.length) {
         return _keys.filter(function(k2) {
           return !_rules[k2].enabled;
@@ -45148,7 +46641,7 @@ ${content}</tr>
       }
       return _rules[k] && !_rules[k].enabled;
     };
-    features2.hidden = function(k) {
+    features.hidden = function(k) {
       if (!arguments.length) {
         return _keys.filter(function(k2) {
           return _rules[k2].hidden();
@@ -45156,7 +46649,7 @@ ${content}</tr>
       }
       return _rules[k] && _rules[k].hidden();
     };
-    features2.autoHidden = function(k) {
+    features.autoHidden = function(k) {
       if (!arguments.length) {
         return _keys.filter(function(k2) {
           return _rules[k2].autoHidden();
@@ -45164,13 +46657,13 @@ ${content}</tr>
       }
       return _rules[k] && _rules[k].autoHidden();
     };
-    features2.enable = function(k) {
+    features.enable = function(k) {
       if (_rules[k] && !_rules[k].enabled) {
         _rules[k].enable();
         update();
       }
     };
-    features2.enableAll = function() {
+    features.enableAll = function() {
       var didEnable = false;
       for (var k in _rules) {
         if (!_rules[k].enabled) {
@@ -45181,13 +46674,13 @@ ${content}</tr>
       if (didEnable)
         update();
     };
-    features2.disable = function(k) {
+    features.disable = function(k) {
       if (_rules[k] && _rules[k].enabled) {
         _rules[k].disable();
         update();
       }
     };
-    features2.disableAll = function() {
+    features.disableAll = function() {
       var didDisable = false;
       for (var k in _rules) {
         if (_rules[k].enabled) {
@@ -45198,7 +46691,7 @@ ${content}</tr>
       if (didDisable)
         update();
     };
-    features2.toggle = function(k) {
+    features.toggle = function(k) {
       if (_rules[k]) {
         (function(f2) {
           return f2.enabled ? f2.disable() : f2.enable();
@@ -45206,13 +46699,13 @@ ${content}</tr>
         update();
       }
     };
-    features2.resetStats = function() {
+    features.resetStats = function() {
       for (var i2 = 0; i2 < _keys.length; i2++) {
         _rules[_keys[i2]].count = 0;
       }
       dispatch10.call("change");
     };
-    features2.gatherStats = function(d, resolver, dimensions) {
+    features.gatherStats = function(d, resolver, dimensions) {
       var needsRedraw = false;
       var types = utilArrayGroupBy(d, "type");
       var entities = [].concat(types.relation || [], types.way || [], types.node || []);
@@ -45223,12 +46716,12 @@ ${content}</tr>
       _cullFactor = dimensions[0] * dimensions[1] / 1e6;
       for (i2 = 0; i2 < entities.length; i2++) {
         geometry = entities[i2].geometry(resolver);
-        matches = Object.keys(features2.getMatches(entities[i2], resolver, geometry));
+        matches = Object.keys(features.getMatches(entities[i2], resolver, geometry));
         for (j2 = 0; j2 < matches.length; j2++) {
           _rules[matches[j2]].count++;
         }
       }
-      currHidden = features2.hidden();
+      currHidden = features.hidden();
       if (currHidden !== _hidden) {
         _hidden = currHidden;
         needsRedraw = true;
@@ -45236,21 +46729,21 @@ ${content}</tr>
       }
       return needsRedraw;
     };
-    features2.stats = function() {
+    features.stats = function() {
       for (var i2 = 0; i2 < _keys.length; i2++) {
         _stats[_keys[i2]] = _rules[_keys[i2]].count;
       }
       return _stats;
     };
-    features2.clear = function(d) {
+    features.clear = function(d) {
       for (var i2 = 0; i2 < d.length; i2++) {
-        features2.clearEntity(d[i2]);
+        features.clearEntity(d[i2]);
       }
     };
-    features2.clearEntity = function(entity) {
+    features.clearEntity = function(entity) {
       delete _cache4[osmEntity.key(entity)];
     };
-    features2.reset = function() {
+    features.reset = function() {
       Array.from(_deferred2).forEach(function(handle) {
         window.cancelIdleCallback(handle);
         _deferred2.delete(handle);
@@ -45260,7 +46753,7 @@ ${content}</tr>
     function relationShouldBeChecked(relation) {
       return relation.tags.type === "boundary";
     }
-    features2.getMatches = function(entity, resolver, geometry) {
+    features.getMatches = function(entity, resolver, geometry) {
       if (geometry === "vertex" || geometry === "relation" && !relationShouldBeChecked(entity))
         return {};
       var ent = osmEntity.key(entity);
@@ -45275,8 +46768,9 @@ ${content}</tr>
             if (hasMatch)
               continue;
             if (entity.type === "way") {
-              var parents = features2.getParents(entity, resolver, geometry);
-              if (parents.length === 1 && parents[0].isMultipolygon() || parents.length > 0 && parents.every(function(parent) {
+              var parents = features.getParents(entity, resolver, geometry);
+              if (parents.length === 1 && parents[0].isMultipolygon() || // 2b. or belongs only to boundary relations
+              parents.length > 0 && parents.every(function(parent) {
                 return parent.tags.type === "boundary";
               })) {
                 var pkey = osmEntity.key(parents[0]);
@@ -45295,7 +46789,7 @@ ${content}</tr>
       }
       return _cache4[ent].matches;
     };
-    features2.getParents = function(entity, resolver, geometry) {
+    features.getParents = function(entity, resolver, geometry) {
       if (geometry === "point")
         return [];
       var ent = osmEntity.key(entity);
@@ -45313,7 +46807,7 @@ ${content}</tr>
       }
       return _cache4[ent].parents;
     };
-    features2.isHiddenPreset = function(preset, geometry) {
+    features.isHiddenPreset = function(preset, geometry) {
       if (!_hidden.length)
         return false;
       if (!preset.tags)
@@ -45329,36 +46823,36 @@ ${content}</tr>
       }
       return false;
     };
-    features2.isHiddenFeature = function(entity, resolver, geometry) {
+    features.isHiddenFeature = function(entity, resolver, geometry) {
       if (!_hidden.length)
         return false;
       if (!entity.version)
         return false;
       if (_forceVisible[entity.id])
         return false;
-      var matches = Object.keys(features2.getMatches(entity, resolver, geometry));
+      var matches = Object.keys(features.getMatches(entity, resolver, geometry));
       return matches.length && matches.every(function(k) {
-        return features2.hidden(k);
+        return features.hidden(k);
       });
     };
-    features2.isHiddenChild = function(entity, resolver, geometry) {
+    features.isHiddenChild = function(entity, resolver, geometry) {
       if (!_hidden.length)
         return false;
       if (!entity.version || geometry === "point")
         return false;
       if (_forceVisible[entity.id])
         return false;
-      var parents = features2.getParents(entity, resolver, geometry);
+      var parents = features.getParents(entity, resolver, geometry);
       if (!parents.length)
         return false;
       for (var i2 = 0; i2 < parents.length; i2++) {
-        if (!features2.isHidden(parents[i2], resolver, parents[i2].geometry(resolver))) {
+        if (!features.isHidden(parents[i2], resolver, parents[i2].geometry(resolver))) {
           return false;
         }
       }
       return true;
     };
-    features2.hasHiddenConnections = function(entity, resolver) {
+    features.hasHiddenConnections = function(entity, resolver) {
       if (!_hidden.length)
         return false;
       var childNodes, connections;
@@ -45367,36 +46861,36 @@ ${content}</tr>
         connections = [];
       } else {
         childNodes = entity.nodes ? resolver.childNodes(entity) : [];
-        connections = features2.getParents(entity, resolver, entity.geometry(resolver));
+        connections = features.getParents(entity, resolver, entity.geometry(resolver));
       }
       connections = childNodes.reduce(function(result, e) {
         return resolver.isShared(e) ? utilArrayUnion(result, resolver.parentWays(e)) : result;
       }, connections);
       return connections.some(function(e) {
-        return features2.isHidden(e, resolver, e.geometry(resolver));
+        return features.isHidden(e, resolver, e.geometry(resolver));
       });
     };
-    features2.isHidden = function(entity, resolver, geometry) {
+    features.isHidden = function(entity, resolver, geometry) {
       if (!_hidden.length)
         return false;
       if (!entity.version)
         return false;
-      var fn = geometry === "vertex" ? features2.isHiddenChild : features2.isHiddenFeature;
+      var fn = geometry === "vertex" ? features.isHiddenChild : features.isHiddenFeature;
       return fn(entity, resolver, geometry);
     };
-    features2.filter = function(d, resolver) {
+    features.filter = function(d, resolver) {
       if (!_hidden.length)
         return d;
       var result = [];
       for (var i2 = 0; i2 < d.length; i2++) {
         var entity = d[i2];
-        if (!features2.isHidden(entity, resolver, entity.geometry(resolver))) {
+        if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
           result.push(entity);
         }
       }
       return result;
     };
-    features2.forceVisible = function(entityIDs) {
+    features.forceVisible = function(entityIDs) {
       if (!arguments.length)
         return Object.keys(_forceVisible);
       _forceVisible = {};
@@ -45409,18 +46903,18 @@ ${content}</tr>
           }
         }
       }
-      return features2;
+      return features;
     };
-    features2.init = function() {
+    features.init = function() {
       var storage = corePreferences("disabled-features");
       if (storage) {
         var storageDisabled = storage.replace(/;/g, ",").split(",");
-        storageDisabled.forEach(features2.disable);
+        storageDisabled.forEach(features.disable);
       }
       var hash = utilStringQs(window.location.hash);
       if (hash.disable_features) {
         var hashDisabled = hash.disable_features.replace(/;/g, ",").split(",");
-        hashDisabled.forEach(features2.disable);
+        hashDisabled.forEach(features.disable);
       }
     };
     context.history().on("merge.features", function(newEntities) {
@@ -45432,12 +46926,12 @@ ${content}</tr>
         var entities = [].concat(types.relation || [], types.way || [], types.node || []);
         for (var i2 = 0; i2 < entities.length; i2++) {
           var geometry = entities[i2].geometry(graph);
-          features2.getMatches(entities[i2], graph, geometry);
+          features.getMatches(entities[i2], graph, geometry);
         }
       });
       _deferred2.add(handle);
     });
-    return features2;
+    return features;
   }
 
   // modules/svg/areas.js
@@ -45596,8 +47090,8 @@ ${content}</tr>
       var tags = entity.tags;
       var shouldCopyMultipolygonTags = !entity.hasInterestingTags();
       graph.parentRelations(entity).forEach(function(relation) {
-        var type3 = relation.tags.type;
-        if (type3 === "multipolygon" && shouldCopyMultipolygonTags || type3 === "boundary") {
+        var type2 = relation.tags.type;
+        if (type2 === "multipolygon" && shouldCopyMultipolygonTags || type2 === "boundary") {
           tags = Object.assign({}, relation.tags, tags);
         }
       });
@@ -45612,14 +47106,14 @@ ${content}</tr>
     }
     function getWaySegments() {
       var isActiveWay = way.nodes.indexOf(activeID) !== -1;
-      var features2 = { passive: [], active: [] };
+      var features = { passive: [], active: [] };
       var start2 = {};
       var end = {};
-      var node, type3;
+      var node, type2;
       for (var i2 = 0; i2 < way.nodes.length; i2++) {
         node = graph.entity(way.nodes[i2]);
-        type3 = svgPassiveVertex(node, graph, activeID);
-        end = { node, type: type3 };
+        type2 = svgPassiveVertex(node, graph, activeID);
+        end = { node, type: type2 };
         if (start2.type !== void 0) {
           if (start2.node.id === activeID || end.node.id === activeID) {
           } else if (isActiveWay && (start2.type === 2 || end.type === 2)) {
@@ -45632,9 +47126,9 @@ ${content}</tr>
         }
         start2 = end;
       }
-      return features2;
+      return features;
       function pushActive(start3, end2, index) {
-        features2.active.push({
+        features.active.push({
           type: "Feature",
           id: way.id + "-" + index + "-nope",
           properties: {
@@ -45651,7 +47145,7 @@ ${content}</tr>
         });
       }
       function pushPassive(start3, end2, index) {
-        features2.passive.push({
+        features.passive.push({
           type: "Feature",
           id: way.id + "-" + index,
           properties: {
@@ -45828,7 +47322,7 @@ ${content}</tr>
       if (qid) {
         classes.push("tag-wikidata");
       }
-      return classes.join(" ").trim();
+      return classes.filter((klass) => /^[-_a-z0-9]+$/.test(klass)).join(" ").trim();
     };
     tagClasses.tags = function(val) {
       if (!arguments.length)
@@ -45841,6 +47335,12 @@ ${content}</tr>
 
   // modules/svg/tag_pattern.js
   var patterns = {
+    // tag - pattern name
+    // -or-
+    // tag - value - pattern name
+    // -or-
+    // tag - value - rules (optional tag-values, pattern name)
+    // (matches earlier rules first, so fallback should be last entry)
     amenity: {
       grave_yard: "cemetery",
       fountain: "water_standing"
@@ -45861,6 +47361,7 @@ ${content}</tr>
         { leaf_type: "needleleaved", pattern: "forest_needleleaved" },
         { leaf_type: "leafless", pattern: "forest_leafless" },
         { pattern: "forest" }
+        // same as 'leaf_type:mixed'
       ],
       grave_yard: "cemetery",
       grass: "grass",
@@ -45896,6 +47397,7 @@ ${content}</tr>
         { leaf_type: "needleleaved", pattern: "forest_needleleaved" },
         { leaf_type: "leafless", pattern: "forest_leafless" },
         { pattern: "forest" }
+        // same as 'leaf_type:mixed'
       ]
     },
     golf: {
@@ -45967,9 +47469,9 @@ ${content}</tr>
       var base = context.history().base();
       var data = { targets: [], nopes: [] };
       entities.forEach(function(way) {
-        var features2 = svgSegmentWay(way, graph, activeID);
-        data.targets.push.apply(data.targets, features2.passive);
-        data.nopes.push.apply(data.nopes, features2.active);
+        var features = svgSegmentWay(way, graph, activeID);
+        data.targets.push.apply(data.targets, features.passive);
+        data.nopes.push.apply(data.nopes, features.active);
       });
       var targetData = data.targets.filter(getPath);
       var targets = selection2.selectAll(".area.target-allowed").filter(function(d) {
@@ -46139,7 +47641,7 @@ ${content}</tr>
     const val = parseFloat(nodeVal(get1(node, tagName)));
     if (isNaN(val))
       return void 0;
-    if (val && callback)
+    if (callback)
       callback(val);
     return val;
   }
@@ -46385,6 +47887,14 @@ ${content}</tr>
   function getColor(node, output) {
     return get3(node, "color", (elem) => fixColor(nodeVal(elem), output));
   }
+  function extractIconHref(node) {
+    return get3(node, "Icon", (icon2, properties) => {
+      val1(icon2, "href", (href) => {
+        properties.icon = href;
+      });
+      return properties;
+    });
+  }
   function extractIcon(node) {
     return get3(node, "IconStyle", (iconStyle) => {
       return Object.assign(getColor(iconStyle, "icon"), numericProperty(iconStyle, "scale", "icon-scale"), numericProperty(iconStyle, "heading", "icon-heading"), get3(iconStyle, "hotSpot", (hotspot) => {
@@ -46398,12 +47908,7 @@ ${content}</tr>
             "icon-offset-units": [xunits, yunits]
           };
         return {};
-      }), get3(iconStyle, "Icon", (icon2, properties) => {
-        val1(icon2, "href", (href) => {
-          properties.icon = href;
-        });
-        return properties;
-      }));
+      }), extractIconHref(iconStyle));
     });
   }
   function extractLabel(node) {
@@ -46430,6 +47935,68 @@ ${content}</tr>
   function extractStyle(node) {
     return Object.assign({}, extractPoly(node), extractLine(node), extractLabel(node), extractIcon(node));
   }
+  var toNumber2 = (x) => Number(x);
+  var typeConverters = {
+    string: (x) => x,
+    int: toNumber2,
+    uint: toNumber2,
+    short: toNumber2,
+    ushort: toNumber2,
+    float: toNumber2,
+    double: toNumber2,
+    bool: (x) => Boolean(x)
+  };
+  function extractExtendedData(node, schema) {
+    return get3(node, "ExtendedData", (extendedData, properties) => {
+      for (const data of $(extendedData, "Data")) {
+        properties[data.getAttribute("name") || ""] = nodeVal(get1(data, "value"));
+      }
+      for (const simpleData of $(extendedData, "SimpleData")) {
+        const name = simpleData.getAttribute("name") || "";
+        const typeConverter = schema[name] || typeConverters.string;
+        properties[name] = typeConverter(nodeVal(simpleData));
+      }
+      return properties;
+    });
+  }
+  function getMaybeHTMLDescription(node) {
+    const descriptionNode = get1(node, "description");
+    for (const c of Array.from(descriptionNode?.childNodes || [])) {
+      if (c.nodeType === 4) {
+        return {
+          description: {
+            "@type": "html",
+            value: nodeVal(c)
+          }
+        };
+      }
+    }
+    return {};
+  }
+  function extractTimeSpan(node) {
+    return get3(node, "TimeSpan", (timeSpan) => {
+      return {
+        timespan: {
+          begin: nodeVal(get1(timeSpan, "begin")),
+          end: nodeVal(get1(timeSpan, "end"))
+        }
+      };
+    });
+  }
+  function extractTimeStamp(node) {
+    return get3(node, "TimeStamp", (timeStamp) => {
+      return { timestamp: nodeVal(get1(timeStamp, "when")) };
+    });
+  }
+  function extractCascadedStyle(node, styleMap) {
+    return val1(node, "styleUrl", (styleUrl) => {
+      styleUrl = normalizeId(styleUrl);
+      if (styleMap[styleUrl]) {
+        return Object.assign({ styleUrl }, styleMap[styleUrl]);
+      }
+      return { styleUrl };
+    });
+  }
   var removeSpace = /\s*/g;
   var trimSpace = /^\s*|\s*$/g;
   var splitSpace = /\s+/;
@@ -46480,30 +48047,26 @@ ${content}</tr>
     }
     return ring;
   }
-  var GEO_TYPES = [
-    "Polygon",
-    "LineString",
-    "Point",
-    "Track",
-    "gx:Track"
-  ];
   function getCoordinates(node) {
     return nodeVal(get1(node, "coordinates"));
   }
   function getGeometry(node) {
-    const geometries = [];
-    const coordTimes = [];
-    for (const t of ["MultiGeometry", "MultiTrack", "gx:MultiTrack"]) {
-      const elem = get1(node, t);
-      if (elem) {
-        return getGeometry(elem);
-      }
-    }
-    for (const geoType of GEO_TYPES) {
-      for (const geomNode of $(node, geoType)) {
-        switch (geoType) {
+    let geometries = [];
+    let coordTimes = [];
+    for (let i2 = 0; i2 < node.childNodes.length; i2++) {
+      const child = node.childNodes.item(i2);
+      if (isElement(child)) {
+        switch (child.tagName) {
+          case "MultiGeometry":
+          case "MultiTrack":
+          case "gx:MultiTrack": {
+            const childGeometries = getGeometry(child);
+            geometries = geometries.concat(childGeometries.geometries);
+            coordTimes = coordTimes.concat(childGeometries.coordTimes);
+            break;
+          }
           case "Point": {
-            const coordinates = coord1(getCoordinates(geomNode));
+            const coordinates = coord1(getCoordinates(child));
             if (coordinates.length >= 2) {
               geometries.push({
                 type: "Point",
@@ -46512,8 +48075,9 @@ ${content}</tr>
             }
             break;
           }
+          case "LinearRing":
           case "LineString": {
-            const coordinates = coord(getCoordinates(geomNode));
+            const coordinates = coord(getCoordinates(child));
             if (coordinates.length >= 2) {
               geometries.push({
                 type: "LineString",
@@ -46524,7 +48088,7 @@ ${content}</tr>
           }
           case "Polygon": {
             const coords = [];
-            for (const linearRing of $(geomNode, "LinearRing")) {
+            for (const linearRing of $(child, "LinearRing")) {
               const ring = fixRing(coord(getCoordinates(linearRing)));
               if (ring.length >= 4) {
                 coords.push(ring);
@@ -46540,7 +48104,7 @@ ${content}</tr>
           }
           case "Track":
           case "gx:Track": {
-            const gx = gxCoords(geomNode);
+            const gx = gxCoords(child);
             if (!gx)
               break;
             const { times, geometry } = gx;
@@ -46557,62 +48121,13 @@ ${content}</tr>
       coordTimes
     };
   }
-  function extractExtendedData(node) {
-    return get3(node, "ExtendedData", (extendedData, properties) => {
-      for (const data of $(extendedData, "Data")) {
-        properties[data.getAttribute("name") || ""] = nodeVal(get1(data, "value"));
-      }
-      for (const simpleData of $(extendedData, "SimpleData")) {
-        properties[simpleData.getAttribute("name") || ""] = nodeVal(simpleData);
-      }
-      return properties;
-    });
-  }
   function geometryListToGeometry(geometries) {
     return geometries.length === 0 ? null : geometries.length === 1 ? geometries[0] : {
       type: "GeometryCollection",
       geometries
     };
   }
-  function extractTimeSpan(node) {
-    return get3(node, "TimeSpan", (timeSpan) => {
-      return {
-        timespan: {
-          begin: nodeVal(get1(timeSpan, "begin")),
-          end: nodeVal(get1(timeSpan, "end"))
-        }
-      };
-    });
-  }
-  function extractTimeStamp(node) {
-    return get3(node, "TimeStamp", (timeStamp) => {
-      return { timestamp: nodeVal(get1(timeStamp, "when")) };
-    });
-  }
-  function extractCascadedStyle(node, styleMap) {
-    return val1(node, "styleUrl", (styleUrl) => {
-      styleUrl = normalizeId(styleUrl);
-      if (styleMap[styleUrl]) {
-        return Object.assign({ styleUrl }, styleMap[styleUrl]);
-      }
-      return { styleUrl };
-    });
-  }
-  function getMaybeHTMLDescription(node) {
-    const descriptionNode = get1(node, "description");
-    for (const c of Array.from(descriptionNode?.childNodes || [])) {
-      if (c.nodeType === 4) {
-        return {
-          description: {
-            "@type": "html",
-            value: nodeVal(c)
-          }
-        };
-      }
-    }
-    return {};
-  }
-  function getPlacemark(node, styleMap) {
+  function getPlacemark(node, styleMap, schema) {
     const { coordTimes, geometries } = getGeometry(node);
     const feature3 = {
       type: "Feature",
@@ -46624,7 +48139,7 @@ ${content}</tr>
         "open",
         "phoneNumber",
         "description"
-      ]), getMaybeHTMLDescription(node), extractCascadedStyle(node, styleMap), extractStyle(node), extractExtendedData(node), extractTimeSpan(node), extractTimeStamp(node), coordTimes.length ? {
+      ]), getMaybeHTMLDescription(node), extractCascadedStyle(node, styleMap), extractStyle(node), extractExtendedData(node, schema), extractTimeSpan(node), extractTimeStamp(node), coordTimes.length ? {
         coordinateProperties: {
           times: coordTimes.length === 1 ? coordTimes[0] : coordTimes
         }
@@ -46638,6 +48153,100 @@ ${content}</tr>
       feature3.id = id2;
     return feature3;
   }
+  function getGroundOverlayBox(node) {
+    const latLonQuad = get1(node, "gx:LatLonQuad");
+    if (latLonQuad) {
+      const ring = fixRing(coord(getCoordinates(node)));
+      return {
+        type: "Polygon",
+        coordinates: [ring]
+      };
+    }
+    return getLatLonBox(node);
+  }
+  var DEGREES_TO_RADIANS = Math.PI / 180;
+  function rotateBox(bbox2, coordinates, rotation) {
+    const center = [(bbox2[0] + bbox2[2]) / 2, (bbox2[1] + bbox2[3]) / 2];
+    return [
+      coordinates[0].map((coordinate) => {
+        const dy = coordinate[1] - center[1];
+        const dx = coordinate[0] - center[0];
+        const distance = Math.sqrt(Math.pow(dy, 2) + Math.pow(dx, 2));
+        const angle2 = Math.atan2(dy, dx) - rotation * DEGREES_TO_RADIANS;
+        return [
+          center[0] + Math.cos(angle2) * distance,
+          center[1] + Math.sin(angle2) * distance
+        ];
+      })
+    ];
+  }
+  function getLatLonBox(node) {
+    const latLonBox = get1(node, "LatLonBox");
+    if (latLonBox) {
+      const north = num1(latLonBox, "north");
+      const west = num1(latLonBox, "west");
+      const east = num1(latLonBox, "east");
+      const south = num1(latLonBox, "south");
+      const rotation = num1(latLonBox, "rotation");
+      if (typeof north === "number" && typeof south === "number" && typeof west === "number" && typeof east === "number") {
+        const bbox2 = [west, south, east, north];
+        let coordinates = [
+          [
+            [west, north],
+            [east, north],
+            [east, south],
+            [west, south],
+            [west, north]
+            // top left (again)
+          ]
+        ];
+        if (typeof rotation === "number") {
+          coordinates = rotateBox(bbox2, coordinates, rotation);
+        }
+        return {
+          type: "Polygon",
+          coordinates
+        };
+      }
+    }
+    return null;
+  }
+  function getGroundOverlay(node, styleMap, schema) {
+    const geometry = getGroundOverlayBox(node);
+    const feature3 = {
+      type: "Feature",
+      geometry,
+      properties: Object.assign(
+        /**
+         * Related to
+         * https://gist.github.com/tmcw/037a1cb6660d74a392e9da7446540f46
+         */
+        { "@geometry-type": "groundoverlay" },
+        getMulti(node, [
+          "name",
+          "address",
+          "visibility",
+          "open",
+          "phoneNumber",
+          "description"
+        ]),
+        getMaybeHTMLDescription(node),
+        extractCascadedStyle(node, styleMap),
+        extractStyle(node),
+        extractIconHref(node),
+        extractExtendedData(node, schema),
+        extractTimeSpan(node),
+        extractTimeStamp(node)
+      )
+    };
+    if (feature3.properties?.visibility !== void 0) {
+      feature3.properties.visibility = feature3.properties.visibility !== "0";
+    }
+    const id2 = node.getAttribute("id");
+    if (id2 !== null && id2 !== "")
+      feature3.id = id2;
+    return feature3;
+  }
   function getStyleId(style) {
     let id2 = style.getAttribute("id");
     const parentNode = style.parentNode;
@@ -46662,10 +48271,23 @@ ${content}</tr>
     }
     return styleMap;
   }
+  function buildSchema(node) {
+    const schema = {};
+    for (const field of $(node, "SimpleField")) {
+      schema[field.getAttribute("name") || ""] = typeConverters[field.getAttribute("type") || ""] || typeConverters["string"];
+    }
+    return schema;
+  }
   function* kmlGen(node) {
     const styleMap = buildStyleMap(node);
+    const schema = buildSchema(node);
     for (const placemark of $(node, "Placemark")) {
-      const feature3 = getPlacemark(placemark, styleMap);
+      const feature3 = getPlacemark(placemark, styleMap, schema);
+      if (feature3)
+        yield feature3;
+    }
+    for (const groundOverlay of $(node, "GroundOverlay")) {
+      const feature3 = getGroundOverlay(groundOverlay, styleMap, schema);
       if (feature3)
         yield feature3;
     }
@@ -47013,12 +48635,12 @@ ${content}</tr>
       return _src || "";
     };
     drawData.fitZoom = function() {
-      var features2 = getFeatures(_geojson);
-      if (!features2.length)
+      var features = getFeatures(_geojson);
+      if (!features.length)
         return;
       var map2 = context.map();
       var viewport = map2.trimmedExtent().polygon();
-      var coords = features2.reduce(function(coords2, feature3) {
+      var coords = features.reduce(function(coords2, feature3) {
         var geom = feature3.geometry;
         if (!geom)
           return coords2;
@@ -47084,8 +48706,8 @@ ${content}</tr>
       const extent = context.map().extent();
       _mainFileFetcher.get("imagery").then((d) => {
         const hits = showImagery && d.query.bbox(extent.rectangle(), true) || [];
-        const features2 = hits.map((d2) => d2.features[d2.id]);
-        let imagery = layer.selectAll("path.debug-imagery").data(features2);
+        const features = hits.map((d2) => d2.features[d2.id]);
+        let imagery = layer.selectAll("path.debug-imagery").data(features);
         imagery.exit().remove();
         imagery.enter().append("path").attr("class", "debug-imagery debug orange");
       }).catch(() => {
@@ -47134,6 +48756,7 @@ ${content}</tr>
       "maki-sprite",
       "temaki-sprite",
       "fa-sprite",
+      "roentgen-sprite",
       "community-sprite"
     ];
     function drawDefs(selection2) {
@@ -47150,6 +48773,7 @@ ${content}</tr>
       _defsSelection.append("marker").attr("id", "ideditor-viewfield-marker").attr("viewBox", "0 0 16 16").attr("refX", 8).attr("refY", 16).attr("markerWidth", 4).attr("markerHeight", 4).attr("markerUnits", "strokeWidth").attr("orient", "auto").append("path").attr("class", "viewfield-marker-path").attr("d", "M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z").attr("fill", "#333").attr("fill-opacity", "0.75").attr("stroke", "#fff").attr("stroke-width", "0.5px").attr("stroke-opacity", "0.75");
       _defsSelection.append("marker").attr("id", "ideditor-viewfield-marker-wireframe").attr("viewBox", "0 0 16 16").attr("refX", 8).attr("refY", 16).attr("markerWidth", 4).attr("markerHeight", 4).attr("markerUnits", "strokeWidth").attr("orient", "auto").append("path").attr("class", "viewfield-marker-path").attr("d", "M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z").attr("fill", "none").attr("stroke", "#fff").attr("stroke-width", "0.5px").attr("stroke-opacity", "0.75");
       var patterns2 = _defsSelection.selectAll("pattern").data([
+        // pattern name, pattern image name
         ["beach", "dots"],
         ["construction", "construction"],
         ["cemetery", "cemetery"],
@@ -47401,13 +49025,13 @@ ${content}</tr>
   }
 
   // modules/svg/labels.js
-  var import_rbush7 = __toESM(require_rbush_min());
+  var import_rbush6 = __toESM(require_rbush_min());
   function svgLabels(projection2, context) {
     var path = path_default(projection2);
     var detected = utilDetect();
     var baselineHack = detected.ie || detected.browser.toLowerCase() === "edge" || detected.browser.toLowerCase() === "firefox" && detected.version >= 70;
-    var _rdrawn = new import_rbush7.default();
-    var _rskipped = new import_rbush7.default();
+    var _rdrawn = new import_rbush6.default();
+    var _rskipped = new import_rbush6.default();
     var _textWidthCache = {};
     var _entitybboxes = {};
     var labelStack = [
@@ -49483,9 +51107,9 @@ ${content}</tr>
       var base = context.history().base();
       var data = { targets: [], nopes: [] };
       entities.forEach(function(way) {
-        var features2 = svgSegmentWay(way, graph, activeID);
-        data.targets.push.apply(data.targets, features2.passive);
-        data.nopes.push.apply(data.nopes, features2.active);
+        var features = svgSegmentWay(way, graph, activeID);
+        data.targets.push.apply(data.targets, features.passive);
+        data.nopes.push.apply(data.nopes, features.active);
       });
       var targetData = data.targets.filter(getPath);
       var targets = selection2.selectAll(".line.target-allowed").filter(function(d) {
@@ -49544,7 +51168,8 @@ ${content}</tr>
             var parentMultipolygons = parentRelations.filter(function(relation) {
               return relation.isMultipolygon();
             });
-            if (parentMultipolygons.length > 0 && parentRelations.length === parentMultipolygons.length) {
+            if (parentMultipolygons.length > 0 && // and only multipolygon relations
+            parentRelations.length === parentMultipolygons.length) {
               prefix = "relation area";
             }
           }
@@ -49957,6 +51582,7 @@ ${content}</tr>
   var import_fast_deep_equal8 = __toESM(require_fast_deep_equal());
   function svgVertices(projection2, context) {
     var radiuses = {
+      //       z16-, z17,   z18+,  w/icon
       shadow: [6, 7.5, 7.5, 12],
       stroke: [2.5, 3.5, 3.5, 8],
       fill: [1, 1.5, 1.5, 1.5]
@@ -50201,8 +51827,11 @@ ${content}</tr>
       }
       var sets2 = {
         persistent: _currPersistent,
+        // persistent = important vertices (render always)
         selected: _currSelected,
+        // selected + siblings of selected (render always)
         hovered: _currHover
+        // hovered + siblings of hovered (render only in draw modes)
       };
       var all = Object.assign({}, isMoving ? _currHover : {}, _currSelected, _currPersistent);
       var filterRendered = function(d) {
@@ -50265,8 +51894,8 @@ ${content}</tr>
   }
 
   // modules/util/bind_once.js
-  function utilBindOnce(target, type3, listener, capture) {
-    var typeOnce = type3 + ".once";
+  function utilBindOnce(target, type2, listener, capture) {
+    var typeOnce = type2 + ".once";
     function one2() {
       target.on(typeOnce, null);
       listener.apply(this, arguments);
@@ -50552,7 +52181,8 @@ ${content}</tr>
     var _maxDistance = 20;
     var _pointer;
     function pointerIsValidFor(loc) {
-      return new Date().getTime() - _pointer.startTime <= _maxTimespan && geoVecLength(_pointer.startLoc, loc) <= _maxDistance;
+      return (/* @__PURE__ */ new Date()).getTime() - _pointer.startTime <= _maxTimespan && // all pointer events must occur within a small distance of the first pointerdown
+      geoVecLength(_pointer.startLoc, loc) <= _maxDistance;
     }
     function pointerdown(d3_event) {
       if (d3_event.ctrlKey || d3_event.button === 2)
@@ -50564,7 +52194,7 @@ ${content}</tr>
       if (!_pointer) {
         _pointer = {
           startLoc: loc,
-          startTime: new Date().getTime(),
+          startTime: (/* @__PURE__ */ new Date()).getTime(),
           upCount: 0,
           pointerId: d3_event.pointerId
         };
@@ -50717,7 +52347,9 @@ ${content}</tr>
         }
       });
       var detected = utilDetect();
-      if ("GestureEvent" in window && !detected.isMobileWebKit) {
+      if ("GestureEvent" in window && // Listening for gesture events on iOS 13.4+ breaks double-tapping,
+      // but we only need to do this on desktop Safari anyway. – #7694
+      !detected.isMobileWebKit) {
         surface.on("gesturestart.surface", function(d3_event) {
           d3_event.preventDefault();
           _gestureTransformStart = projection2.transform();
@@ -50727,7 +52359,8 @@ ${content}</tr>
       _doubleUpHandler.on("doubleUp.map", function(d3_event, p02) {
         if (!_dblClickZoomEnabled)
           return;
-        if (typeof d3_event.target.__data__ === "object" && !select_default2(d3_event.target).classed("fill"))
+        if (typeof d3_event.target.__data__ === "object" && // or area fills
+        !select_default2(d3_event.target).classed("fill"))
           return;
         var zoomOut2 = d3_event.shiftKey;
         var t = projection2.transform();
@@ -50738,7 +52371,10 @@ ${content}</tr>
         map2.transformEase(t);
       });
       context.on("enter.map", function() {
-        if (!map2.editableDataEnabled(true))
+        if (!map2.editableDataEnabled(
+          true
+          /* skip zoom check */
+        ))
           return;
         if (_isTransformed)
           return;
@@ -50797,7 +52433,7 @@ ${content}</tr>
     function drawEditable(difference, extent) {
       var mode = context.mode();
       var graph = context.graph();
-      var features2 = context.features();
+      var features = context.features();
       var all = context.history().intersects(map2.extent());
       var fullRedraw = false;
       var data;
@@ -50821,9 +52457,9 @@ ${content}</tr>
         filter2 = function(d) {
           return set3.has(d.id);
         };
-        features2.clear(data);
+        features.clear(data);
       } else {
-        if (features2.gatherStats(all, graph, _dimensions)) {
+        if (features.gatherStats(all, graph, _dimensions)) {
           extent = void 0;
         }
         if (extent) {
@@ -50841,7 +52477,7 @@ ${content}</tr>
         }
       }
       if (applyFeatureLayerFilters) {
-        data = features2.filter(data, graph);
+        data = features.filter(data, graph);
       } else {
         context.features().resetStats();
       }
@@ -50882,7 +52518,9 @@ ${content}</tr>
       e.preventDefault();
       var props = {
         deltaMode: 0,
+        // dummy values to ignore in zoomPan
         deltaY: 1,
+        // dummy values to ignore in zoomPan
         clientX: e.clientX,
         clientY: e.clientY,
         screenX: e.screenX,
@@ -50917,7 +52555,9 @@ ${content}</tr>
           dY = sign2 * clamp(
             Math.exp((lines - 1) * 0.75) * 4.000244140625,
             4.000244140625,
+            // min
             350.000244140625
+            // max
           );
           if (detected.os !== "mac") {
             dY *= 5;
@@ -51244,7 +52884,12 @@ ${content}</tr>
     };
     map2.transformEase = function(t2, duration) {
       duration = duration || 250;
-      setTransform(t2, duration, false);
+      setTransform(
+        t2,
+        duration,
+        false
+        /* don't force */
+      );
       return map2;
     };
     map2.zoomToEase = function(obj, duration) {
@@ -51424,20 +53069,20 @@ ${content}</tr>
     photos.dateFilterValue = function(val) {
       return val === _dateFilters[0] ? _fromDate : _toDate;
     };
-    photos.setDateFilter = function(type3, val, updateUrl) {
+    photos.setDateFilter = function(type2, val, updateUrl) {
       var date = val && new Date(val);
       if (date && !isNaN(date)) {
         val = date.toISOString().slice(0, 10);
       } else {
         val = null;
       }
-      if (type3 === _dateFilters[0]) {
+      if (type2 === _dateFilters[0]) {
         _fromDate = val;
         if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
           _toDate = _fromDate;
         }
       }
-      if (type3 === _dateFilters[1]) {
+      if (type2 === _dateFilters[1]) {
         _toDate = val;
         if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
           _fromDate = _toDate;
@@ -52038,7 +53683,7 @@ ${content}</tr>
     tooltip.content(function() {
       var heading = _heading.apply(this, arguments);
       var text2 = _title.apply(this, arguments);
-      var keys = _keys.apply(this, arguments);
+      var keys2 = _keys.apply(this, arguments);
       var headingCallback = typeof heading === "function" ? heading : (s) => s.text(heading);
       var textCallback = typeof text2 === "function" ? text2 : (s) => s.text(text2);
       return function(selection2) {
@@ -52048,12 +53693,12 @@ ${content}</tr>
         var textSelect = selection2.selectAll(".tooltip-text").data(text2 ? [text2] : []);
         textSelect.exit().remove();
         textSelect.enter().append("div").attr("class", "tooltip-text").merge(textSelect).text("").call(textCallback);
-        var keyhintWrap = selection2.selectAll(".keyhint-wrap").data(keys && keys.length ? [0] : []);
+        var keyhintWrap = selection2.selectAll(".keyhint-wrap").data(keys2 && keys2.length ? [0] : []);
         keyhintWrap.exit().remove();
         var keyhintWrapEnter = keyhintWrap.enter().append("div").attr("class", "keyhint-wrap");
         keyhintWrapEnter.append("span").call(_t.append("tooltip_keyhint"));
         keyhintWrap = keyhintWrapEnter.merge(keyhintWrap);
-        keyhintWrap.selectAll("kbd.shortcut").data(keys && keys.length ? keys : []).enter().append("kbd").attr("class", "shortcut").text(function(d) {
+        keyhintWrap.selectAll("kbd.shortcut").data(keys2 && keys2.length ? keys2 : []).enter().append("kbd").attr("class", "shortcut").text(function(d) {
           return d;
         });
       };
@@ -52119,8 +53764,8 @@ ${content}</tr>
         select_default2(this).call(tooltip).append("div").attr("class", "icon-wrap").call(svgIcon(d.icon && d.icon() || "#iD-operation-" + d.id, "operation"));
       });
       if (showLabels) {
-        buttonsEnter.append("span").attr("class", "label").html(function(d) {
-          return d.title;
+        buttonsEnter.append("span").attr("class", "label").each(function(d) {
+          select_default2(this).call(d.title);
         });
       }
       buttonsEnter.merge(buttons).classed("disabled", function(d) {
@@ -52255,10 +53900,10 @@ ${content}</tr>
   // modules/ui/feature_info.js
   function uiFeatureInfo(context) {
     function update(selection2) {
-      var features2 = context.features();
-      var stats = features2.stats();
+      var features = context.features();
+      var stats = features.stats();
       var count = 0;
-      var hiddenList = features2.hidden().map(function(k) {
+      var hiddenList = features.hidden().map(function(k) {
         if (stats[k]) {
           count += stats[k];
           return _t.append("inspector.title_count", {
@@ -52397,16 +54042,19 @@ ${content}</tr>
       if (!isSupported())
         return;
       var detected = utilDetect();
-      var keys = detected.os === "mac" ? [uiCmd("\u2303\u2318F"), "f11"] : ["f11"];
-      context.keybinding().on(keys, fullScreen);
+      var keys2 = detected.os === "mac" ? [uiCmd("\u2303\u2318F"), "f11"] : ["f11"];
+      context.keybinding().on(keys2, fullScreen);
     };
   }
 
   // modules/ui/geolocate.js
   function uiGeolocate(context) {
     var _geolocationOptions = {
+      // prioritize speed and power usage over precision
       enableHighAccuracy: false,
+      // don't hang indefinitely getting the location
       timeout: 6e3
+      // 6sec
     };
     var _locating = uiLoading(context).message(_t.html("geolocate.locating")).blocking(true);
     var _layer = context.layers().layer("geolocate");
@@ -52418,7 +54066,11 @@ ${content}</tr>
       if (context.inIntro())
         return;
       if (!_layer.enabled() && !_locating.isShown()) {
-        _timeoutID = setTimeout(error, 1e4);
+        _timeoutID = setTimeout(
+          error,
+          1e4
+          /* 10sec */
+        );
         context.container().call(_locating);
         navigator.geolocation.getCurrentPosition(success, error, _geolocationOptions);
       } else {
@@ -53147,6 +54799,7 @@ ${content}</tr>
   function helpHtml(id2, replacements) {
     if (!helpStringReplacements) {
       helpStringReplacements = {
+        // insert icons corresponding to various UI elements
         point_icon: icon("#iD-icon-point", "inline"),
         line_icon: icon("#iD-icon-line", "inline"),
         area_icon: icon("#iD-icon-area", "inline"),
@@ -53160,6 +54813,7 @@ ${content}</tr>
         undo_icon: icon(_mainLocalizer.textDirection() === "rtl" ? "#iD-icon-redo" : "#iD-icon-undo", "inline"),
         redo_icon: icon(_mainLocalizer.textDirection() === "rtl" ? "#iD-icon-undo" : "#iD-icon-redo", "inline"),
         save_icon: icon("#iD-icon-save", "inline"),
+        // operation icons
         circularize_icon: icon("#iD-operation-circularize", "inline operation"),
         continue_icon: icon("#iD-operation-continue", "inline operation"),
         copy_icon: icon("#iD-operation-copy", "inline operation"),
@@ -53177,6 +54831,7 @@ ${content}</tr>
         rotate_icon: icon("#iD-operation-rotate", "inline operation"),
         split_icon: icon("#iD-operation-split", "inline operation"),
         straighten_icon: icon("#iD-operation-straighten", "inline operation"),
+        // interaction icons
         leftclick: icon("#iD-walkthrough-mouse-left", "inline operation"),
         rightclick: icon("#iD-walkthrough-mouse-right", "inline operation"),
         mousewheel_icon: icon("#iD-walkthrough-mousewheel", "inline operation"),
@@ -53185,6 +54840,7 @@ ${content}</tr>
         longpress_icon: icon("#iD-walkthrough-longpress", "inline operation"),
         touchdrag_icon: icon("#iD-walkthrough-touchdrag", "inline operation"),
         pinch_icon: icon("#iD-walkthrough-pinch-apart", "inline operation"),
+        // insert keys; may be localized and platform-dependent
         shift: uiCmd.display("\u21E7"),
         alt: uiCmd.display("\u2325"),
         return: uiCmd.display("\u21B5"),
@@ -53193,6 +54849,7 @@ ${content}</tr>
         add_note_key: _t.html("modes.add_note.key"),
         help_key: _t.html("help.key"),
         shortcuts_key: _t.html("shortcuts.toggle.key"),
+        // reference localized UI labels directly so that they'll always match
         save: _t.html("save.title"),
         undo: _t.html("undo.title"),
         redo: _t.html("redo.title"),
@@ -53623,7 +55280,7 @@ ${content}</tr>
         if (context.map().zoom() !== zoomStart) {
           context.map().on("move.intro", null);
           timeout2(function() {
-            continueTo(features2);
+            continueTo(features);
           }, 3e3);
         }
       });
@@ -53632,7 +55289,7 @@ ${content}</tr>
         nextStep();
       }
     }
-    function features2() {
+    function features() {
       var onClick = function() {
         continueTo(pointsLinesAreas);
       };
@@ -57225,7 +58882,7 @@ ${content}</tr>
           return;
         if (input.classed("disabled"))
           return;
-        _tDown = +new Date();
+        _tDown = +/* @__PURE__ */ new Date();
         var start2 = input.property("selectionStart");
         var end = input.property("selectionEnd");
         if (start2 !== end) {
@@ -57421,7 +59078,7 @@ ${content}</tr>
         var val = _caseSensitive ? value() : value().toLowerCase();
         if (!val)
           return;
-        if (!isNaN(parseFloat(val)) && isFinite(val))
+        if (isFinite(val))
           return;
         const suggestionValues = [];
         _suggestions.forEach((s) => {
@@ -58127,23 +59784,42 @@ ${content}</tr>
     return utilRebind(check, dispatch10, "on");
   }
 
+  // modules/ui/length_indicator.js
+  function uiLengthIndicator(maxChars) {
+    var _wrap = select_default2(null);
+    var _tooltip = uiPopover("tooltip max-length-warning").placement("bottom").hasArrow(true).content(() => (selection2) => {
+      selection2.text("");
+      selection2.call(svgIcon("#iD-icon-alert", "inline"));
+      selection2.call(_t.append("inspector.max_length_reached", { maxChars }));
+    });
+    var _silent = false;
+    var lengthIndicator = function(selection2) {
+      _wrap = selection2.selectAll("span.length-indicator-wrap").data([0]);
+      _wrap = _wrap.enter().append("span").merge(_wrap).classed("length-indicator-wrap", true);
+      selection2.call(_tooltip);
+    };
+    lengthIndicator.update = function(val) {
+      const strLen = utilUnicodeCharsCount(utilCleanOsmString(val, Number.POSITIVE_INFINITY));
+      let indicator = _wrap.selectAll("span.length-indicator").data([strLen]);
+      indicator.enter().append("span").merge(indicator).classed("length-indicator", true).classed("limit-reached", (d) => d > maxChars).style("border-right-width", (d) => `${Math.abs(maxChars - d) * 2}px`).style("margin-right", (d) => d > maxChars ? `${(maxChars - d) * 2}px` : 0).style("opacity", (d) => d > maxChars * 0.8 ? Math.min(1, (d / maxChars - 0.8) / (1 - 0.8)) : 0).style("pointer-events", (d) => d > maxChars * 0.8 ? null : "none");
+      if (_silent)
+        return;
+      if (strLen > maxChars) {
+        _tooltip.show();
+      } else {
+        _tooltip.hide();
+      }
+    };
+    lengthIndicator.silent = function(val) {
+      if (!arguments.length)
+        return _silent;
+      _silent = val;
+      return lengthIndicator;
+    };
+    return lengthIndicator;
+  }
+
   // modules/ui/fields/combo.js
-  var valueIcons = {
-    "crossing:markings": [
-      "dashes",
-      "dots",
-      "ladder:paired",
-      "ladder:skewed",
-      "ladder",
-      "lines:paired",
-      "lines",
-      "surface",
-      "zebra:bicolour",
-      "zebra:double",
-      "zebra:paired",
-      "zebra"
-    ]
-  };
   function uiFieldCombo(field, context) {
     var dispatch10 = dispatch_default("change");
     var _isMulti = field.type === "multiCombo" || field.type === "manyCombo";
@@ -58156,6 +59832,7 @@ ${content}</tr>
     var _container = select_default2(null);
     var _inputWrap = select_default2(null);
     var _input = select_default2(null);
+    var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue());
     var _comboData = [];
     var _multiData = [];
     var _entityIDs = [];
@@ -58180,7 +59857,7 @@ ${content}</tr>
     }
     function tagValue(dval) {
       dval = clean2(dval || "");
-      var found = getOptions().find(function(o) {
+      var found = getOptions(true).find(function(o) {
         return o.key && clean2(o.value) === dval;
       });
       if (found)
@@ -58188,19 +59865,26 @@ ${content}</tr>
       if (field.type === "typeCombo" && !dval) {
         return "yes";
       }
+      return restrictTagValueSpelling(dval) || void 0;
+    }
+    function restrictTagValueSpelling(dval) {
       if (_snake_case) {
         dval = snake(dval);
       }
       if (!field.caseSensitive) {
         dval = dval.toLowerCase();
       }
-      return dval || void 0;
+      return dval;
+    }
+    function getLabelId(field2, v) {
+      return field2.hasTextForStringId(`options.${v}.title`) ? `options.${v}.title` : `options.${v}`;
     }
     function displayValue(tval) {
       tval = tval || "";
       var stringsField = field.resolveReference("stringsCrossReference");
-      if (stringsField.hasTextForStringId("options." + tval)) {
-        return stringsField.t("options." + tval, { default: tval });
+      const labelId = getLabelId(stringsField, tval);
+      if (stringsField.hasTextForStringId(labelId)) {
+        return stringsField.t(labelId, { default: tval });
       }
       if (field.type === "typeCombo" && tval.toLowerCase() === "yes") {
         return "";
@@ -58210,8 +59894,9 @@ ${content}</tr>
     function renderValue(tval) {
       tval = tval || "";
       var stringsField = field.resolveReference("stringsCrossReference");
-      if (stringsField.hasTextForStringId("options." + tval)) {
-        return stringsField.t.append("options." + tval, { default: tval });
+      const labelId = getLabelId(stringsField, tval);
+      if (stringsField.hasTextForStringId(labelId)) {
+        return stringsField.t.append(labelId, { default: tval });
       }
       if (field.type === "typeCombo" && tval.toLowerCase() === "yes") {
         tval = "";
@@ -58221,7 +59906,7 @@ ${content}</tr>
     function objectDifference(a, b) {
       return a.filter(function(d1) {
         return !b.some(function(d2) {
-          return !d2.isMixed && d1.value === d2.value;
+          return d1.value === d2.value;
         });
       });
     }
@@ -58234,20 +59919,27 @@ ${content}</tr>
         setTaginfoValues("", setPlaceholder);
       } else {
         selection2.call(_combobox, attachTo);
-        setStaticValues(setPlaceholder);
+        setTimeout(() => setStaticValues(setPlaceholder), 0);
       }
     }
-    function getOptions() {
+    function getOptions(allOptions) {
       var stringsField = field.resolveReference("stringsCrossReference");
       if (!(field.options || stringsField.options))
         return [];
-      return (field.options || stringsField.options).map(function(v) {
+      let options2;
+      if (allOptions !== true) {
+        options2 = field.options || stringsField.options;
+      } else {
+        options2 = [].concat(field.options, stringsField.options).filter(Boolean);
+      }
+      return options2.map(function(v) {
+        const labelId = getLabelId(stringsField, v);
         return {
           key: v,
-          value: stringsField.t("options." + v, { default: v }),
-          title: v,
-          display: addComboboxIcons(stringsField.t.append("options." + v, { default: v }), v),
-          klass: stringsField.hasTextForStringId("options." + v) ? "" : "raw-option"
+          value: stringsField.t(labelId, { default: v }),
+          title: stringsField.t(`options.${v}.description`, { default: v }),
+          display: addComboboxIcons(stringsField.t.append(labelId, { default: v }), v),
+          klass: stringsField.hasTextForStringId(labelId) ? "" : "raw-option"
         };
       });
     }
@@ -58282,33 +59974,35 @@ ${content}</tr>
       services.taginfo[fn](params, function(err, data) {
         if (err)
           return;
-        data = data.filter(function(d) {
-          return field.type !== "typeCombo" || d.value !== "yes";
+        data = data.filter((d) => field.type !== "typeCombo" || d.value !== "yes");
+        data = data.filter((d) => {
+          var value = d.value;
+          if (_isMulti) {
+            value = value.slice(field.key.length);
+          }
+          return value === restrictTagValueSpelling(value);
         });
         var deprecatedValues = osmEntity.deprecatedTagValuesByKey(_dataDeprecated)[field.key];
         if (deprecatedValues) {
-          data = data.filter(function(d) {
-            return deprecatedValues.indexOf(d.value) === -1;
-          });
+          data = data.filter((d) => !deprecatedValues.includes(d.value));
         }
         if (hasCountryPrefix) {
-          data = data.filter(function(d) {
-            return d.value.toLowerCase().indexOf(_countryCode + ":") === 0;
-          });
+          data = data.filter((d) => d.value.toLowerCase().indexOf(_countryCode + ":") === 0);
         }
         const additionalOptions = (field.options || stringsField.options || []).filter((v) => !data.some((dv) => dv.value === (_isMulti ? field.key + v : v))).map((v) => ({ value: v }));
         _container.classed("empty-combobox", data.length === 0);
         _comboData = data.concat(additionalOptions).map(function(d) {
-          var k = d.value;
+          var v = d.value;
           if (_isMulti)
-            k = k.replace(field.key, "");
-          var isLocalizable = stringsField.hasTextForStringId("options." + k);
-          var label = stringsField.t("options." + k, { default: k });
+            v = v.replace(field.key, "");
+          const labelId = getLabelId(stringsField, v);
+          var isLocalizable = stringsField.hasTextForStringId(labelId);
+          var label = stringsField.t(labelId, { default: v });
           return {
-            key: k,
+            key: v,
             value: label,
-            display: addComboboxIcons(stringsField.t.append("options." + k, { default: k }), k),
-            title: isLocalizable ? k : d.title !== label ? d.title : "",
+            title: stringsField.t(`options.${v}.description`, { default: isLocalizable ? v : d.title !== label ? d.title : "" }),
+            display: addComboboxIcons(stringsField.t.append(labelId, { default: v }), v),
             klass: isLocalizable ? "" : "raw-option"
           };
         });
@@ -58319,11 +60013,12 @@ ${content}</tr>
       });
     }
     function addComboboxIcons(disp, value) {
-      if (valueIcons[field.key]) {
+      const iconsField = field.resolveReference("iconsCrossReference");
+      if (iconsField.icons) {
         return function(selection2) {
           var span = selection2.insert("span", ":first-child").attr("class", "tag-value-icon");
-          if (valueIcons[field.key].indexOf(value) !== -1) {
-            span.call(svgIcon("#iD-" + field.key.replace(/:/g, "_") + "-" + value.replace(/:/g, "_")));
+          if (iconsField.icons[value]) {
+            span.call(svgIcon(`#${iconsField.icons[value]}`));
           }
           disp.call(this, selection2);
         };
@@ -58354,6 +60049,8 @@ ${content}</tr>
         ph = _staticPlaceholder;
       }
       _container.selectAll("input").attr("placeholder", ph);
+      var hideAdd = !_allowCustomValues && !values.length;
+      _container.selectAll(".chiplist .input-wrap").style("display", hideAdd ? "none" : null);
     }
     function change() {
       var t = {};
@@ -58363,7 +60060,8 @@ ${content}</tr>
         if (_isMulti) {
           vals = [tagValue(utilGetSetValue(_input))];
         } else if (_isSemi) {
-          val = tagValue(utilGetSetValue(_input).replace(/,/g, ";")) || "";
+          val = tagValue(utilGetSetValue(_input)) || "";
+          val = val.replace(/,/g, ";");
           vals = val.split(";");
         }
         vals = vals.filter(Boolean);
@@ -58414,13 +60112,23 @@ ${content}</tr>
         }).filter(Boolean);
         arr = utilArrayUniq(arr);
         t[field.key] = arr.length ? arr.join(";") : void 0;
+        _lengthIndicator.update(t[field.key]);
+      }
+      dispatch10.call("change", this, t);
+    }
+    function invertMultikey(d3_event, d) {
+      d3_event.preventDefault();
+      d3_event.stopPropagation();
+      var t = {};
+      if (_isMulti) {
+        t[d.key] = _tags[d.key] === "yes" ? "no" : "yes";
       }
       dispatch10.call("change", this, t);
     }
     function combo(selection2) {
       _container = selection2.selectAll(".form-field-input-wrap").data([0]);
-      var type3 = _isMulti || _isSemi ? "multicombo" : "combo";
-      _container = _container.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + type3).merge(_container);
+      var type2 = _isMulti || _isSemi ? "multicombo" : "combo";
+      _container = _container.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + type2).merge(_container);
       if (_isMulti || _isSemi) {
         _container = _container.selectAll(".chiplist").data([0]);
         var listClass = "chiplist";
@@ -58434,18 +60142,30 @@ ${content}</tr>
         }).merge(_container);
         _inputWrap = _container.selectAll(".input-wrap").data([0]);
         _inputWrap = _inputWrap.enter().append("li").attr("class", "input-wrap").merge(_inputWrap);
+        var hideAdd = !_allowCustomValues && !_comboData.length;
+        _inputWrap.style("display", hideAdd ? "none" : null);
         _input = _inputWrap.selectAll("input").data([0]);
       } else {
         _input = _container.selectAll("input").data([0]);
       }
       _input = _input.enter().append("input").attr("type", "text").attr("id", field.domId).call(utilNoAuto).call(initCombo, selection2).merge(_input);
+      if (_isSemi) {
+        _inputWrap.call(_lengthIndicator);
+      } else if (!_isMulti) {
+        _container.call(_lengthIndicator);
+      }
       if (_isNetwork) {
         var extent = combinedEntityExtent();
         var countryCode = extent && iso1A2Code(extent.center());
         _countryCode = countryCode && countryCode.toLowerCase();
       }
       _input.on("change", change).on("blur", change).on("input", function() {
-        updateIcon(utilGetSetValue(_input));
+        let val = utilGetSetValue(_input);
+        updateIcon(val);
+        if (_isSemi && _tags[field.key]) {
+          val += ";" + _tags[field.key];
+        }
+        _lengthIndicator.update(val);
       });
       _input.on("keydown.field", function(d3_event) {
         switch (d3_event.keyCode) {
@@ -58472,16 +60192,26 @@ ${content}</tr>
     }
     function updateIcon(value) {
       value = tagValue(value);
-      if (valueIcons[field.key]) {
-        _container.selectAll(".tag-value-icon").remove();
-        if (valueIcons[field.key].indexOf(value) !== -1) {
-          _container.selectAll(".tag-value-icon").data([value]).enter().insert("div", "input").attr("class", "tag-value-icon").call(svgIcon("#iD-" + field.key.replace(/:/g, "_") + "-" + value.replace(/:/g, "_")));
+      let container = _container;
+      if (field.type === "multiCombo" || field.type === "semiCombo") {
+        container = _container.select(".input-wrap");
+      }
+      const iconsField = field.resolveReference("iconsCrossReference");
+      if (iconsField.icons) {
+        container.selectAll(".tag-value-icon").remove();
+        if (iconsField.icons[value]) {
+          container.selectAll(".tag-value-icon").data([value]).enter().insert("div", "input").attr("class", "tag-value-icon").call(svgIcon(`#${iconsField.icons[value]}`));
         }
       }
     }
     combo.tags = function(tags) {
       _tags = tags;
       var stringsField = field.resolveReference("stringsCrossReference");
+      var isMixed = Array.isArray(tags[field.key]);
+      var showsValue = (value) => !isMixed && value && !(field.type === "typeCombo" && value === "yes");
+      var isRawValue = (value) => showsValue(value) && !stringsField.hasTextForStringId(`options.${value}`) && !stringsField.hasTextForStringId(`options.${value}.title`);
+      var isKnownValue = (value) => showsValue(value) && !isRawValue(value);
+      var isReadOnly = !_allowCustomValues;
       if (_isMulti || _isSemi) {
         _multiData = [];
         var maxLength;
@@ -58492,13 +60222,12 @@ ${content}</tr>
             if (!field.key && field.keys.indexOf(k) === -1)
               continue;
             var v = tags[k];
-            if (!v || typeof v === "string" && v.toLowerCase() === "no")
-              continue;
             var suffix = field.key ? k.slice(field.key.length) : k;
             _multiData.push({
               key: k,
               value: displayValue(suffix),
-              display: renderValue(suffix),
+              display: addComboboxIcons(renderValue(suffix), suffix),
+              state: typeof v === "string" ? v.toLowerCase() : "",
               isMixed: Array.isArray(v)
             });
           }
@@ -58532,7 +60261,7 @@ ${content}</tr>
             return {
               key: v2,
               value: displayValue(v2),
-              display: renderValue(v2),
+              display: addComboboxIcons(renderValue(v2), v2),
               isMixed: !commonValues.includes(v2)
             };
           });
@@ -58543,11 +60272,9 @@ ${content}</tr>
           }
         }
         maxLength = Math.max(0, maxLength);
-        var allowDragAndDrop = _isSemi && !Array.isArray(tags[field.key]);
-        var available = objectDifference(_comboData, _multiData);
-        _combobox.data(available);
-        var hideAdd = !_allowCustomValues && !available.length || maxLength <= 0;
+        var hideAdd = maxLength <= 0 || !_allowCustomValues && !_comboData.length;
         _container.selectAll(".chiplist .input-wrap").style("display", hideAdd ? "none" : null);
+        var allowDragAndDrop = _isSemi && !Array.isArray(tags[field.key]);
         var chips = _container.selectAll(".chip").data(_multiData);
         chips.exit().remove();
         var enter = chips.enter().insert("li", ".input-wrap").attr("class", "chip");
@@ -58561,8 +60288,18 @@ ${content}</tr>
         }).classed("draggable", allowDragAndDrop).classed("mixed", function(d) {
           return d.isMixed;
         }).attr("title", function(d) {
-          return d.isMixed ? _t("inspector.unshared_value_tooltip") : null;
-        });
+          if (d.isMixed) {
+            return _t("inspector.unshared_value_tooltip");
+          }
+          if (!["yes", "no"].includes(d.state)) {
+            return d.state;
+          }
+          return null;
+        }).classed("negated", (d) => d.state === "no");
+        if (!_isSemi) {
+          chips.selectAll("input[type=checkbox]").remove();
+          chips.insert("input", "span").attr("type", "checkbox").property("checked", (d) => d.state === "yes").property("indeterminate", (d) => d.isMixed || !["yes", "no"].includes(d.state)).on("click", invertMultikey);
+        }
         if (allowDragAndDrop) {
           registerDragAndDrop(chips);
         }
@@ -58576,17 +60313,13 @@ ${content}</tr>
           }
         });
         chips.select("a").attr("href", "#").on("click", removeMultikey).attr("class", "remove").text("\xD7");
+        updateIcon("");
       } else {
-        var isMixed = Array.isArray(tags[field.key]);
         var mixedValues = isMixed && tags[field.key].map(function(val) {
           return displayValue(val);
         }).filter(Boolean);
-        var showsValue = !isMixed && tags[field.key] && !(field.type === "typeCombo" && tags[field.key] === "yes");
-        var isRawValue = showsValue && !stringsField.hasTextForStringId("options." + tags[field.key]);
-        var isKnownValue = showsValue && !isRawValue;
-        var isReadOnly = !_allowCustomValues || isKnownValue;
-        utilGetSetValue(_input, !isMixed ? displayValue(tags[field.key]) : "").classed("raw-value", isRawValue).classed("known-value", isKnownValue).attr("readonly", isReadOnly ? "readonly" : void 0).attr("title", isMixed ? mixedValues.join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : _staticPlaceholder || "").classed("mixed", isMixed).on("keydown.deleteCapture", function(d3_event) {
-          if (isReadOnly && isKnownValue && (d3_event.keyCode === utilKeybinding.keyCodes["\u232B"] || d3_event.keyCode === utilKeybinding.keyCodes["\u2326"])) {
+        utilGetSetValue(_input, !isMixed ? displayValue(tags[field.key]) : "").data([tags[field.key]]).classed("raw-value", isRawValue).classed("known-value", isKnownValue).attr("readonly", isReadOnly ? "readonly" : void 0).attr("title", isMixed ? mixedValues.join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : _staticPlaceholder || "").classed("mixed", isMixed).on("keydown.deleteCapture", function(d3_event) {
+          if (isReadOnly && isKnownValue(tags[field.key]) && (d3_event.keyCode === utilKeybinding.keyCodes["\u232B"] || d3_event.keyCode === utilKeybinding.keyCodes["\u2326"])) {
             d3_event.preventDefault();
             d3_event.stopPropagation();
             var t = {};
@@ -58597,7 +60330,16 @@ ${content}</tr>
         if (!Array.isArray(tags[field.key])) {
           updateIcon(tags[field.key]);
         }
+        if (!isMixed) {
+          _lengthIndicator.update(tags[field.key]);
+        }
       }
+      const refreshStyles = () => {
+        _input.data([tagValue(utilGetSetValue(_input))]).classed("raw-value", isRawValue).classed("known-value", isKnownValue);
+      };
+      _input.on("input.refreshStyles", refreshStyles);
+      _combobox.on("update.refreshStyles", refreshStyles);
+      refreshStyles();
     };
     function registerDragAndDrop(selection2) {
       var dragOrigin, targetIndex;
@@ -58610,7 +60352,8 @@ ${content}</tr>
           targetIndex = null;
         }).on("drag", function(d3_event) {
           var x = d3_event.x - dragOrigin.x, y = d3_event.y - dragOrigin.y;
-          if (!select_default2(this).classed("dragging") && Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5)
+          if (!select_default2(this).classed("dragging") && // don't display drag until dragging beyond a distance threshold
+          Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5)
             return;
           var index = selection2.nodes().indexOf(this);
           select_default2(this).classed("dragging", true);
@@ -58699,14 +60442,20 @@ ${content}</tr>
   }
 
   // modules/ui/fields/input.js
+  var likelyRawNumberFormat = /^-?(0\.\d*|\d*\.\d{0,2}(\d{4,})?|\d{4,}\.\d{3})$/;
   function uiFieldText(field, context) {
     var dispatch10 = dispatch_default("change");
     var input = select_default2(null);
     var outlinkButton = select_default2(null);
     var wrap2 = select_default2(null);
+    var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue());
     var _entityIDs = [];
     var _tags;
     var _phoneFormats = {};
+    const isDirectionField = field.key.split(":").some((keyPart) => keyPart === "direction");
+    const formatFloat = _mainLocalizer.floatFormatter(_mainLocalizer.languageCode());
+    const parseLocaleFloat = _mainLocalizer.floatParser(_mainLocalizer.languageCode());
+    const countDecimalPlaces = _mainLocalizer.decimalPlaceCounter(_mainLocalizer.languageCode());
     if (field.type === "tel") {
       _mainFileFetcher.get("phone_formats").then(function(d) {
         _phoneFormats = d;
@@ -58736,6 +60485,7 @@ ${content}</tr>
       input = wrap2.selectAll("input").data([0]);
       input = input.enter().append("input").attr("type", field.type === "identifier" ? "text" : field.type).attr("id", field.domId).classed(field.type, true).call(utilNoAuto).merge(input);
       input.classed("disabled", !!isLocked).attr("readonly", isLocked || null).on("input", change(true)).on("blur", change()).on("change", change());
+      wrap2.call(_lengthIndicator);
       if (field.type === "tel") {
         updatePhonePlaceholder();
       } else if (field.type === "number") {
@@ -58751,16 +60501,31 @@ ${content}</tr>
           return _t(`inspector.${which}`);
         }).merge(buttons).on("click", function(d3_event, d) {
           d3_event.preventDefault();
+          var isMixed = Array.isArray(_tags[field.key]);
+          if (isMixed)
+            return;
           var raw_vals = input.node().value || "0";
           var vals = raw_vals.split(";");
           vals = vals.map(function(v) {
-            var num = parseFloat(v.trim(), 10);
-            if (isFinite(num))
-              return clamped(num + d);
-            const compassDir = cardinal[v.trim().toLowerCase()];
-            if (compassDir !== void 0)
-              return clamped(compassDir + d);
-            return v.trim();
+            v = v.trim();
+            const isRawNumber = likelyRawNumberFormat.test(v);
+            var num = isRawNumber ? parseFloat(v) : parseLocaleFloat(v);
+            if (isDirectionField) {
+              const compassDir = cardinal[v.toLowerCase()];
+              if (compassDir !== void 0) {
+                num = compassDir;
+              }
+            }
+            if (!isFinite(num))
+              return v;
+            num = parseFloat(num);
+            if (!isFinite(num))
+              return v;
+            num += d;
+            if (isDirectionField) {
+              num = (num % 360 + 360) % 360;
+            }
+            return formatFloat(clamped(num), isRawNumber ? v.includes(".") ? v.split(".")[1].length : 0 : countDecimalPlaces(v));
           });
           input.node().value = vals.join(";");
           change()();
@@ -58795,24 +60560,29 @@ ${content}</tr>
       } else if (field.type === "colour") {
         input.attr("type", "text");
         updateColourPreview();
+      } else if (field.type === "date") {
+        input.attr("type", "text");
+        updateDateField();
       }
     }
-    function isColourValid(colour) {
-      if (!colour.match(/^(#([0-9a-fA-F]{3}){1,2}|\w+)$/)) {
-        return false;
-      } else if (!CSS.supports("color", colour) || ["unset", "inherit", "initial", "revert"].includes(colour)) {
-        return false;
-      }
-      return true;
-    }
     function updateColourPreview() {
+      function isColourValid(colour2) {
+        if (!colour2.match(/^(#([0-9a-fA-F]{3}){1,2}|\w+)$/)) {
+          return false;
+        } else if (!CSS.supports("color", colour2) || ["unset", "inherit", "initial", "revert"].includes(colour2)) {
+          return false;
+        }
+        return true;
+      }
       wrap2.selectAll(".colour-preview").remove();
       const colour = utilGetSetValue(input);
-      if (!isColourValid(colour) && colour !== "")
+      if (!isColourValid(colour) && colour !== "") {
+        wrap2.selectAll("input.colour-selector").remove();
+        wrap2.selectAll(".form-field-button").remove();
         return;
+      }
       var colourSelector = wrap2.selectAll(".colour-selector").data([0]);
-      outlinkButton = wrap2.selectAll(".colour-preview").data([colour]);
-      colourSelector.enter().append("input").attr("type", "color").attr("class", "form-field-button colour-selector").attr("value", colour).on("input", debounce_default(function(d3_event) {
+      colourSelector.enter().append("input").attr("type", "color").attr("class", "colour-selector").on("input", debounce_default(function(d3_event) {
         d3_event.preventDefault();
         var colour2 = this.value;
         if (!isColourValid(colour2))
@@ -58821,11 +60591,51 @@ ${content}</tr>
         change()();
         updateColourPreview();
       }, 100));
-      outlinkButton = outlinkButton.enter().append("div").attr("class", "form-field-button colour-preview").append("div").style("background-color", (d) => d).attr("class", "colour-box");
+      wrap2.selectAll("input.colour-selector").attr("value", colour);
+      var chooserButton = wrap2.selectAll(".colour-preview").data([colour]);
+      chooserButton = chooserButton.enter().append("div").attr("class", "form-field-button colour-preview").append("div").style("background-color", (d) => d).attr("class", "colour-box");
       if (colour === "") {
-        outlinkButton = outlinkButton.call(svgIcon("#iD-icon-edit"));
+        chooserButton = chooserButton.call(svgIcon("#iD-icon-edit"));
+      }
+      chooserButton.on("click", () => wrap2.select(".colour-selector").node().showPicker());
+    }
+    function updateDateField() {
+      function isDateValid(date2) {
+        return date2.match(/^[0-9]{4}(-[0-9]{2}(-[0-9]{2})?)?$/);
+      }
+      const date = utilGetSetValue(input);
+      const now3 = /* @__PURE__ */ new Date();
+      const today = new Date(now3.getTime() - now3.getTimezoneOffset() * 6e4).toISOString().split("T")[0];
+      if ((field.key === "check_date" || field.key === "survey:date") && date !== today) {
+        wrap2.selectAll(".date-set-today").data([0]).enter().append("button").attr("class", "form-field-button date-set-today").call(svgIcon("#fas-rotate")).call(uiTooltip().title(() => _t.append("inspector.set_today"))).on("click", () => {
+          utilGetSetValue(input, today);
+          change()();
+          updateDateField();
+        });
+      } else {
+        wrap2.selectAll(".date-set-today").remove();
+      }
+      if (!isDateValid(date) && date !== "") {
+        wrap2.selectAll("input.date-selector").remove();
+        wrap2.selectAll(".date-calendar").remove();
+        return;
+      }
+      if (utilDetect().browser !== "Safari") {
+        var dateSelector = wrap2.selectAll(".date-selector").data([0]);
+        dateSelector.enter().append("input").attr("type", "date").attr("class", "date-selector").on("input", debounce_default(function(d3_event) {
+          d3_event.preventDefault();
+          var date2 = this.value;
+          if (!isDateValid(date2))
+            return;
+          utilGetSetValue(input, this.value);
+          change()();
+          updateDateField();
+        }, 100));
+        wrap2.selectAll("input.date-selector").attr("value", date);
+        var calendarButton = wrap2.selectAll(".date-calendar").data([date]);
+        calendarButton = calendarButton.enter().append("button").attr("class", "form-field-button date-calendar").call(svgIcon("#fas-calendar-days"));
+        calendarButton.on("click", () => wrap2.select(".date-selector").node().showPicker());
       }
-      outlinkButton.on("click", () => wrap2.select(".colour-selector").node().click()).merge(outlinkButton);
     }
     function updatePhonePlaceholder() {
       if (input.empty() || !Object.keys(_phoneFormats).length)
@@ -58859,27 +60669,53 @@ ${content}</tr>
       }
       return num;
     }
+    function getVals(tags) {
+      if (field.keys) {
+        const multiSelection = context.selectedIDs();
+        tags = multiSelection.length > 1 ? context.selectedIDs().map((id2) => context.graph().entity(id2)).map((entity) => entity.tags) : [tags];
+        return tags.map((tags2) => new Set(field.keys.reduce((acc, key) => acc.concat(tags2[key]), []).filter(Boolean))).map((vals) => vals.size === 0 ? /* @__PURE__ */ new Set([void 0]) : vals).reduce((a, b) => /* @__PURE__ */ new Set([...a, ...b]));
+      } else {
+        return new Set([].concat(tags[field.key]));
+      }
+    }
     function change(onInput) {
       return function() {
         var t = {};
         var val = utilGetSetValue(input);
         if (!onInput)
           val = context.cleanTagValue(val);
-        if (!val && Array.isArray(_tags[field.key]))
+        if (!val && getVals(_tags).size > 1)
           return;
-        if (!onInput) {
-          if (field.type === "number" && val) {
-            var vals = val.split(";");
-            vals = vals.map(function(v) {
-              var num = parseFloat(v.trim(), 10);
-              return isFinite(num) ? clamped(num) : v.trim();
-            });
-            val = vals.join(";");
-          }
-          utilGetSetValue(input, val);
+        var displayVal = val;
+        if (field.type === "number" && val) {
+          var numbers2 = val.split(";");
+          numbers2 = numbers2.map(function(v) {
+            if (likelyRawNumberFormat.test(v)) {
+              return v;
+            }
+            var num = parseLocaleFloat(v);
+            const fractionDigits = countDecimalPlaces(v);
+            return isFinite(num) ? clamped(num).toFixed(fractionDigits) : v;
+          });
+          val = numbers2.join(";");
         }
+        if (!onInput)
+          utilGetSetValue(input, displayVal);
         t[field.key] = val || void 0;
-        dispatch10.call("change", this, t, onInput);
+        if (field.keys) {
+          dispatch10.call("change", this, (tags) => {
+            if (field.keys.some((key) => tags[key])) {
+              field.keys.filter((key) => tags[key]).forEach((key) => {
+                tags[key] = val || void 0;
+              });
+            } else {
+              tags[field.key] = val || void 0;
+            }
+            return tags;
+          }, onInput);
+        } else {
+          dispatch10.call("change", this, t, onInput);
+        }
       };
     }
     i2.entityIDs = function(val) {
@@ -58890,16 +60726,56 @@ ${content}</tr>
     };
     i2.tags = function(tags) {
       _tags = tags;
-      var isMixed = Array.isArray(tags[field.key]);
-      utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : "").attr("title", isMixed ? tags[field.key].filter(Boolean).join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder() || _t("inspector.unknown")).classed("mixed", isMixed);
+      const vals = getVals(tags);
+      const isMixed = vals.size > 1;
+      var val = vals.size === 1 ? [...vals][0] : "";
+      var shouldUpdate;
+      if (field.type === "number" && val) {
+        var numbers2 = val.split(";");
+        var oriNumbers = utilGetSetValue(input).split(";");
+        if (numbers2.length !== oriNumbers.length)
+          shouldUpdate = true;
+        numbers2 = numbers2.map(function(v) {
+          v = v.trim();
+          var num = Number(v);
+          if (!isFinite(num) || v === "")
+            return v;
+          const fractionDigits = v.includes(".") ? v.split(".")[1].length : 0;
+          return formatFloat(num, fractionDigits);
+        });
+        val = numbers2.join(";");
+        shouldUpdate = (inputValue, setValue) => {
+          const inputNums = inputValue.split(";").map(
+            (setVal) => likelyRawNumberFormat.test(setVal) ? parseFloat(setVal) : parseLocaleFloat(setVal)
+          );
+          const setNums = setValue.split(";").map(parseLocaleFloat);
+          return !isEqual_default(inputNums, setNums);
+        };
+      }
+      utilGetSetValue(input, val, shouldUpdate).attr("title", isMixed ? [...vals].join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder() || _t("inspector.unknown")).classed("mixed", isMixed);
+      if (field.type === "number") {
+        const buttons = wrap2.selectAll(".increment, .decrement");
+        if (isMixed) {
+          buttons.attr("disabled", "disabled").classed("disabled", true);
+        } else {
+          var raw_vals = tags[field.key] || "0";
+          const canIncDec = raw_vals.split(";").some((val2) => isFinite(Number(val2)) || isDirectionField && cardinal[val2.trim().toLowerCase()]);
+          buttons.attr("disabled", canIncDec ? null : "disabled").classed("disabled", !canIncDec);
+        }
+      }
       if (field.type === "tel")
         updatePhonePlaceholder();
-      if (field.key.split(":").includes("colour"))
+      if (field.type === "colour")
         updateColourPreview();
+      if (field.type === "date")
+        updateDateField();
       if (outlinkButton && !outlinkButton.empty()) {
         var disabled = !validIdentifierValueForLink();
         outlinkButton.classed("disabled", disabled);
       }
+      if (!isMixed) {
+        _lengthIndicator.update(tags[field.key]);
+      }
     };
     i2.focus = function() {
       var node = input.node();
@@ -58949,7 +60825,7 @@ ${content}</tr>
       tag[d] = value || void 0;
       dispatch10.call("change", this, tag);
     }
-    access.options = function(type3) {
+    access.options = function(type2) {
       var options2 = [
         "yes",
         "no",
@@ -58961,10 +60837,10 @@ ${content}</tr>
         "permit",
         "unknown"
       ];
-      if (type3 === "access") {
+      if (type2 === "access") {
         options2 = options2.filter((v) => v !== "yes" && v !== "designated");
       }
-      if (type3 === "bicycle") {
+      if (type2 === "bicycle") {
         options2.splice(options2.length - 4, 0, "dismount");
       }
       var stringsField = field.resolveReference("stringsCrossReference");
@@ -59201,73 +61077,82 @@ ${content}</tr>
       }
     }).catch(function() {
     });
-    function getNearStreets() {
+    function getNear(isAddressable, type2, searchRadius, resultProp) {
       var extent = combinedEntityExtent();
       var l = extent.center();
-      var box = geoExtent(l).padByMeters(200);
-      var streets = context.history().intersects(box).filter(isAddressable).map(function(d) {
-        var loc = context.projection([
-          (extent[0][0] + extent[1][0]) / 2,
-          (extent[0][1] + extent[1][1]) / 2
-        ]);
-        var choice = geoChooseEdge(context.graph().childNodes(d), loc, context.projection);
+      var box = geoExtent(l).padByMeters(searchRadius);
+      var features = context.history().intersects(box).filter(isAddressable).map((d) => {
+        let dist = geoSphericalDistance(d.extent(context.graph()).center(), l);
+        if (d.type === "way") {
+          var loc = context.projection([
+            (extent[0][0] + extent[1][0]) / 2,
+            (extent[0][1] + extent[1][1]) / 2
+          ]);
+          var choice = geoChooseEdge(context.graph().childNodes(d), loc, context.projection);
+          dist = Math.min(dist, choice.distance);
+        }
+        const value = resultProp && d.tags[resultProp] ? d.tags[resultProp] : d.tags.name;
+        let title = value;
+        if (type2 === "street") {
+          title = `${addrField.t("placeholders.street")}: ${title}`;
+        } else if (type2 === "place") {
+          title = `${addrField.t("placeholders.place")}: ${title}`;
+        }
         return {
-          title: d.tags.name,
-          value: d.tags.name,
-          dist: choice.distance
+          title,
+          value,
+          dist,
+          type: type2,
+          klass: `address-${type2}`
         };
       }).sort(function(a, b) {
         return a.dist - b.dist;
       });
-      return utilArrayUniqBy(streets, "value");
+      return utilArrayUniqBy(features, "value");
+    }
+    function getNearStreets() {
       function isAddressable(d) {
         return d.tags.highway && d.tags.name && d.type === "way";
       }
+      return getNear(isAddressable, "street", 200);
+    }
+    function getNearPlaces() {
+      function isAddressable(d) {
+        if (d.tags.name) {
+          if (d.tags.place)
+            return true;
+          if (d.tags.boundary === "administrative" && d.tags.admin_level > 8)
+            return true;
+        }
+        return false;
+      }
+      return getNear(isAddressable, "place", 200);
     }
     function getNearCities() {
-      var extent = combinedEntityExtent();
-      var l = extent.center();
-      var box = geoExtent(l).padByMeters(200);
-      var cities = context.history().intersects(box).filter(isAddressable).map(function(d) {
-        return {
-          title: d.tags["addr:city"] || d.tags.name,
-          value: d.tags["addr:city"] || d.tags.name,
-          dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
-        };
-      }).sort(function(a, b) {
-        return a.dist - b.dist;
-      });
-      return utilArrayUniqBy(cities, "value");
       function isAddressable(d) {
         if (d.tags.name) {
-          if (d.tags.admin_level === "8" && d.tags.boundary === "administrative")
+          if (d.tags.boundary === "administrative" && d.tags.admin_level === "8")
             return true;
           if (d.tags.border_type === "city")
             return true;
           if (d.tags.place === "city" || d.tags.place === "town" || d.tags.place === "village")
             return true;
         }
-        if (d.tags["addr:city"])
+        if (d.tags[`${field.key}:city`])
           return true;
         return false;
       }
+      return getNear(isAddressable, "city", 200, `${field.key}:city`);
+    }
+    function getNearPostcodes() {
+      return [...new Set([].concat(getNearValues("postcode")).concat(getNear((d) => d.tags.postal_code, "postcode", 200, "postal_code")))];
     }
     function getNearValues(key) {
-      var extent = combinedEntityExtent();
-      var l = extent.center();
-      var box = geoExtent(l).padByMeters(200);
-      var results = context.history().intersects(box).filter(function hasTag(d) {
-        return _entityIDs.indexOf(d.id) === -1 && d.tags[key];
-      }).map(function(d) {
-        return {
-          title: d.tags[key],
-          value: d.tags[key],
-          dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
-        };
-      }).sort(function(a, b) {
-        return a.dist - b.dist;
-      });
-      return utilArrayUniqBy(results, "value");
+      const tagKey = `${field.key}:${key}`;
+      function hasTag(d) {
+        return _entityIDs.indexOf(d.id) === -1 && d.tags[tagKey];
+      }
+      return getNear(hasTag, key, 200, tagKey);
     }
     function updateForCountryCode() {
       if (!_countryCode)
@@ -59295,12 +61180,15 @@ ${content}</tr>
         "quarter",
         "state",
         "street",
+        "street+place",
         "subdistrict",
         "suburb"
       ];
       var widths = addressFormat.widths || {
-        housenumber: 1 / 3,
-        street: 2 / 3,
+        housenumber: 1 / 5,
+        unit: 1 / 5,
+        street: 1 / 2,
+        place: 1 / 2,
         city: 2 / 3,
         state: 1 / 4,
         postcode: 1 / 3
@@ -59328,10 +61216,36 @@ ${content}</tr>
       function addDropdown(d) {
         if (dropdowns.indexOf(d.id) === -1)
           return;
-        var nearValues = d.id === "street" ? getNearStreets : d.id === "city" ? getNearCities : getNearValues;
+        var nearValues;
+        switch (d.id) {
+          case "street":
+            nearValues = getNearStreets;
+            break;
+          case "place":
+            nearValues = getNearPlaces;
+            break;
+          case "street+place":
+            nearValues = () => [].concat(getNearStreets()).concat(getNearPlaces());
+            d.isAutoStreetPlace = true;
+            d.id = _tags[`${field.key}:place`] ? "place" : "street";
+            break;
+          case "city":
+            nearValues = getNearCities;
+            break;
+          case "postcode":
+            nearValues = getNearPostcodes;
+            break;
+          default:
+            nearValues = getNearValues;
+        }
         select_default2(this).call(
-          uiCombobox(context, "address-" + d.id).minItems(1).caseSensitive(true).fetcher(function(value, callback) {
-            callback(nearValues("addr:" + d.id));
+          uiCombobox(context, `address-${d.isAutoStreetPlace ? "street-place" : d.id}`).minItems(1).caseSensitive(true).fetcher(function(typedValue, callback) {
+            typedValue = typedValue.toLowerCase();
+            callback(nearValues(d.id).filter((v) => v.value.toLowerCase().indexOf(typedValue) !== -1));
+          }).on("accept", function(selected) {
+            if (d.isAutoStreetPlace) {
+              d.id = selected ? selected.type : "street";
+            }
           })
         );
       }
@@ -59361,17 +61275,26 @@ ${content}</tr>
     }
     function change(onInput) {
       return function() {
-        var tags = {};
-        _wrap.selectAll("input").each(function(subfield) {
-          var key = field.key + ":" + subfield.id;
-          var value = this.value;
-          if (!onInput)
-            value = context.cleanTagValue(value);
-          if (Array.isArray(_tags[key]) && !value)
-            return;
-          tags[key] = value || void 0;
-        });
-        dispatch10.call("change", this, tags, onInput);
+        setTimeout(() => {
+          var tags = {};
+          _wrap.selectAll("input").each(function(subfield) {
+            var key = field.key + ":" + subfield.id;
+            var value = this.value;
+            if (!onInput)
+              value = context.cleanTagValue(value);
+            if (Array.isArray(_tags[key]) && !value)
+              return;
+            if (subfield.isAutoStreetPlace) {
+              if (subfield.id === "street") {
+                tags[`${field.key}:place`] = void 0;
+              } else if (subfield.id === "place") {
+                tags[`${field.key}:street`] = void 0;
+              }
+            }
+            tags[key] = value || void 0;
+          });
+          dispatch10.call("change", this, tags, onInput);
+        }, 0);
       };
     }
     function updatePlaceholder(inputSelection) {
@@ -59379,16 +61302,35 @@ ${content}</tr>
         if (_tags && Array.isArray(_tags[field.key + ":" + subfield.id])) {
           return _t("inspector.multiple_values");
         }
-        if (_countryCode) {
-          var localkey = subfield.id + "!" + _countryCode;
-          var tkey = addrField.hasTextForStringId("placeholders." + localkey) ? localkey : subfield.id;
-          return addrField.t("placeholders." + tkey);
+        if (subfield.isAutoStreetPlace) {
+          return `${getLocalPlaceholder("street")} / ${getLocalPlaceholder("place")}`;
         }
+        return getLocalPlaceholder(subfield.id);
       });
     }
+    function getLocalPlaceholder(key) {
+      if (_countryCode) {
+        var localkey = key + "!" + _countryCode;
+        var tkey = addrField.hasTextForStringId("placeholders." + localkey) ? localkey : key;
+        return addrField.t("placeholders." + tkey);
+      }
+    }
     function updateTags(tags) {
-      utilGetSetValue(_wrap.selectAll("input"), function(subfield) {
-        var val = tags[field.key + ":" + subfield.id];
+      utilGetSetValue(_wrap.selectAll("input"), (subfield) => {
+        var val;
+        if (subfield.isAutoStreetPlace) {
+          const streetKey = `${field.key}:street`;
+          const placeKey = `${field.key}:place`;
+          if (tags[streetKey] !== void 0 || tags[placeKey] === void 0) {
+            val = tags[streetKey];
+            subfield.id = "street";
+          } else {
+            val = tags[placeKey];
+            subfield.id = "place";
+          }
+        } else {
+          val = tags[`${field.key}:${subfield.id}`];
+        }
         return typeof val === "string" ? val : "";
       }).attr("title", function(subfield) {
         var val = tags[field.key + ":" + subfield.id];
@@ -59418,13 +61360,21 @@ ${content}</tr>
     return utilRebind(address, dispatch10, "on");
   }
 
-  // modules/ui/fields/cycleway.js
-  function uiFieldCycleway(field, context) {
+  // modules/ui/fields/directional_combo.js
+  function uiFieldDirectionalCombo(field, context) {
     var dispatch10 = dispatch_default("change");
     var items = select_default2(null);
     var wrap2 = select_default2(null);
     var _tags;
-    function cycleway(selection2) {
+    var _combos = {};
+    if (field.type === "cycleway") {
+      field = {
+        ...field,
+        key: field.keys[0],
+        keys: field.keys.slice(1)
+      };
+    }
+    function directionalCombo(selection2) {
       function stripcolon(s) {
         return s.replace(":", "");
       }
@@ -59432,100 +61382,60 @@ ${content}</tr>
       wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
       var div = wrap2.selectAll("ul").data([0]);
       div = div.enter().append("ul").attr("class", "rows").merge(div);
-      var keys = ["cycleway:left", "cycleway:right"];
-      items = div.selectAll("li").data(keys);
+      items = div.selectAll("li").data(field.keys);
       var enter = items.enter().append("li").attr("class", function(d) {
-        return "labeled-input preset-cycleway-" + stripcolon(d);
+        return "labeled-input preset-directionalcombo-" + stripcolon(d);
       });
-      enter.append("span").attr("class", "label preset-label-cycleway").attr("for", function(d) {
-        return "preset-input-cycleway-" + stripcolon(d);
+      enter.append("span").attr("class", "label preset-label-directionalcombo").attr("for", function(d) {
+        return "preset-input-directionalcombo-" + stripcolon(d);
       }).html(function(d) {
         return field.t.html("types." + d);
       });
-      enter.append("div").attr("class", "preset-input-cycleway-wrap").append("input").attr("type", "text").attr("class", function(d) {
-        return "preset-input-cycleway preset-input-" + stripcolon(d);
-      }).call(utilNoAuto).each(function(d) {
-        select_default2(this).call(
-          uiCombobox(context, "cycleway-" + stripcolon(d)).data(cycleway.options(d))
-        );
-      });
-      items = items.merge(enter);
-      wrap2.selectAll(".preset-input-cycleway").on("change", change).on("blur", change);
-    }
-    function change(d3_event, key) {
-      var newValue = context.cleanTagValue(utilGetSetValue(select_default2(this)));
-      if (!newValue && (Array.isArray(_tags.cycleway) || Array.isArray(_tags[key])))
-        return;
-      if (newValue === "none" || newValue === "") {
-        newValue = void 0;
-      }
-      var otherKey = key === "cycleway:left" ? "cycleway:right" : "cycleway:left";
-      var otherValue = typeof _tags.cycleway === "string" ? _tags.cycleway : _tags[otherKey];
-      if (otherValue && Array.isArray(otherValue)) {
-        otherValue = otherValue[0];
-      }
-      if (otherValue === "none" || otherValue === "") {
-        otherValue = void 0;
-      }
-      var tag = {};
-      if (newValue === otherValue) {
-        tag = {
-          cycleway: newValue,
-          "cycleway:left": void 0,
-          "cycleway:right": void 0
-        };
-      } else {
-        tag = {
-          cycleway: void 0
-        };
-        tag[key] = newValue;
-        tag[otherKey] = otherValue;
-      }
-      dispatch10.call("change", this, tag);
-    }
-    cycleway.options = function() {
-      var stringsField = field.resolveReference("stringsCrossReference");
-      return field.options.map(function(option) {
-        return {
-          title: stringsField.t("options." + option + ".description"),
-          value: option
+      enter.append("div").attr("class", "preset-input-directionalcombo-wrap form-field-input-wrap").each(function(key) {
+        const subField = {
+          ...field,
+          type: "combo",
+          key
         };
+        const combo = uiFieldCombo(subField, context);
+        combo.on("change", (t) => change(key, t[key]));
+        _combos[key] = combo;
+        select_default2(this).call(combo);
       });
-    };
-    cycleway.tags = function(tags) {
-      _tags = tags;
-      var commonValue = typeof tags.cycleway === "string" && tags.cycleway;
-      utilGetSetValue(items.selectAll(".preset-input-cycleway"), function(d) {
-        if (commonValue)
-          return commonValue;
-        return !tags.cycleway && typeof tags[d] === "string" ? tags[d] : "";
-      }).attr("title", function(d) {
-        if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
-          var vals = [];
-          if (Array.isArray(tags.cycleway)) {
-            vals = vals.concat(tags.cycleway);
-          }
-          if (Array.isArray(tags[d])) {
-            vals = vals.concat(tags[d]);
-          }
-          return vals.filter(Boolean).join("\n");
-        }
-        return null;
-      }).attr("placeholder", function(d) {
-        if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
-          return _t("inspector.multiple_values");
+      items = items.merge(enter);
+      wrap2.selectAll(".preset-input-directionalcombo").on("change", change).on("blur", change);
+    }
+    function change(key, newValue) {
+      const commonKey = field.key;
+      const otherKey = key === field.keys[0] ? field.keys[1] : field.keys[0];
+      dispatch10.call("change", this, (tags) => {
+        const otherValue = tags[otherKey] || tags[commonKey];
+        if (newValue === otherValue) {
+          tags[commonKey] = newValue;
+          delete tags[key];
+          delete tags[otherKey];
+        } else {
+          tags[key] = newValue;
+          delete tags[commonKey];
+          tags[otherKey] = otherValue;
         }
-        return field.placeholder();
-      }).classed("mixed", function(d) {
-        return Array.isArray(tags.cycleway) || Array.isArray(tags[d]);
+        return tags;
       });
+    }
+    directionalCombo.tags = function(tags) {
+      _tags = tags;
+      const commonKey = field.key;
+      for (let key in _combos) {
+        const uniqueValues = [...new Set([].concat(_tags[commonKey]).concat(_tags[key]).filter(Boolean))];
+        _combos[key].tags({ [key]: uniqueValues.length > 1 ? uniqueValues : uniqueValues[0] });
+      }
     };
-    cycleway.focus = function() {
+    directionalCombo.focus = function() {
       var node = wrap2.selectAll("input").node();
       if (node)
         node.focus();
     };
-    return utilRebind(cycleway, dispatch10, "on");
+    return utilRebind(directionalCombo, dispatch10, "on");
   }
 
   // modules/ui/fields/lanes.js
@@ -59592,6 +61502,7 @@ ${content}</tr>
     var wikipedia = services.wikipedia;
     var input = select_default2(null);
     var localizedInputs = select_default2(null);
+    var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue());
     var _countryCode;
     var _tags;
     _mainFileFetcher.get("languages").then(loadLanguagesArray).catch(function() {
@@ -59612,7 +61523,9 @@ ${content}</tr>
         return;
       var replacements = {
         sr: "sr-Cyrl",
+        // in OSM, `sr` implies Cyrillic
         "sr-Cyrl": false
+        // `sr-Cyrl` isn't used in OSM
       };
       for (var code in dataLanguages) {
         if (replacements[code] === false)
@@ -59640,7 +61553,7 @@ ${content}</tr>
         var preset = _mainPresetIndex.match(entity, context.graph());
         if (preset) {
           var isSuggestion = preset.suggestion;
-          var fields = preset.fields();
+          var fields = preset.fields(entity.extent(context.graph()).center());
           var showsBrandField = fields.some(function(d) {
             return d.id === "brand";
           });
@@ -59688,6 +61601,7 @@ ${content}</tr>
       input = wrap2.selectAll(".localized-main").data([0]);
       input = input.enter().append("input").attr("type", "text").attr("id", field.domId).attr("class", "localized-main").call(utilNoAuto).merge(input);
       input.classed("disabled", !!isLocked).attr("readonly", isLocked || null).on("input", change(true)).on("blur", change()).on("change", change());
+      wrap2.call(_lengthIndicator);
       var translateButton = wrap2.selectAll(".localized-add").data([0]);
       translateButton = translateButton.enter().append("button").attr("class", "localized-add form-field-button").attr("aria-label", _t("icons.plus")).call(svgIcon("#iD-icon-plus")).merge(translateButton);
       translateButton.classed("disabled", !!isLocked).call(isLocked ? _buttonTip.destroy : _buttonTip).on("click", addNew);
@@ -59863,6 +61777,9 @@ ${content}</tr>
       utilGetSetValue(input, typeof tags[field.key] === "string" ? tags[field.key] : "").attr("title", isMixed ? tags[field.key].filter(Boolean).join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder()).classed("mixed", isMixed);
       calcMultilingual(tags);
       _selection.call(localized);
+      if (!isMixed) {
+        _lengthIndicator.update(tags[field.key]);
+      }
     };
     localized.focus = function() {
       input.node().focus();
@@ -59896,6 +61813,8 @@ ${content}</tr>
     var _entityIDs = [];
     var _tags;
     var _isImperial;
+    var formatFloat = _mainLocalizer.floatFormatter(_mainLocalizer.languageCode());
+    var parseLocaleFloat = _mainLocalizer.floatParser(_mainLocalizer.languageCode());
     var primaryUnits = [
       {
         value: "m",
@@ -59946,16 +61865,24 @@ ${content}</tr>
         return;
       if (!primaryValue && !secondaryValue) {
         tag[field.key] = void 0;
-      } else if (isNaN(primaryValue) || isNaN(secondaryValue) || !_isImperial) {
-        tag[field.key] = context.cleanTagValue(primaryValue);
       } else {
-        if (primaryValue !== "") {
-          primaryValue = context.cleanTagValue(primaryValue + "'");
-        }
-        if (secondaryValue !== "") {
-          secondaryValue = context.cleanTagValue(secondaryValue + '"');
+        var rawPrimaryValue = likelyRawNumberFormat.test(primaryValue) ? parseFloat(primaryValue) : parseLocaleFloat(primaryValue);
+        if (isNaN(rawPrimaryValue))
+          rawPrimaryValue = primaryValue;
+        var rawSecondaryValue = likelyRawNumberFormat.test(secondaryValue) ? parseFloat(secondaryValue) : parseLocaleFloat(secondaryValue);
+        if (isNaN(rawSecondaryValue))
+          rawSecondaryValue = secondaryValue;
+        if (isNaN(rawPrimaryValue) || isNaN(rawSecondaryValue) || !_isImperial) {
+          tag[field.key] = context.cleanTagValue(rawPrimaryValue);
+        } else {
+          if (rawPrimaryValue !== "") {
+            rawPrimaryValue = rawPrimaryValue + "'";
+          }
+          if (rawSecondaryValue !== "") {
+            rawSecondaryValue = rawSecondaryValue + '"';
+          }
+          tag[field.key] = context.cleanTagValue(rawPrimaryValue + rawSecondaryValue);
         }
-        tag[field.key] = primaryValue + secondaryValue;
       }
       dispatch10.call("change", this, tag);
     }
@@ -59968,20 +61895,28 @@ ${content}</tr>
         if (primaryValue && (primaryValue.indexOf("'") >= 0 || primaryValue.indexOf('"') >= 0)) {
           secondaryValue = primaryValue.match(/(-?[\d.]+)"/);
           if (secondaryValue !== null) {
-            secondaryValue = secondaryValue[1];
+            secondaryValue = formatFloat(parseFloat(secondaryValue[1]));
           }
           primaryValue = primaryValue.match(/(-?[\d.]+)'/);
           if (primaryValue !== null) {
-            primaryValue = primaryValue[1];
+            primaryValue = formatFloat(parseFloat(primaryValue[1]));
           }
           _isImperial = true;
         } else if (primaryValue) {
+          var rawValue = primaryValue;
+          primaryValue = parseFloat(rawValue);
+          if (isNaN(primaryValue)) {
+            primaryValue = rawValue;
+          } else {
+            primaryValue = formatFloat(primaryValue);
+          }
           _isImperial = false;
         }
       }
       setUnitSuggestions();
+      var inchesPlaceholder = formatFloat(0);
       utilGetSetValue(primaryInput, typeof primaryValue === "string" ? primaryValue : "").attr("title", isMixed ? primaryValue.filter(Boolean).join("\n") : null).attr("placeholder", isMixed ? _t("inspector.multiple_values") : _t("inspector.unknown")).classed("mixed", isMixed);
-      utilGetSetValue(secondaryInput, typeof secondaryValue === "string" ? secondaryValue : "").attr("placeholder", isMixed ? _t("inspector.multiple_values") : _isImperial ? "0" : null).classed("mixed", isMixed).classed("disabled", !_isImperial).attr("readonly", _isImperial ? null : "readonly");
+      utilGetSetValue(secondaryInput, typeof secondaryValue === "string" ? secondaryValue : "").attr("placeholder", isMixed ? _t("inspector.multiple_values") : _isImperial ? inchesPlaceholder : null).classed("mixed", isMixed).classed("disabled", !_isImperial).attr("readonly", _isImperial ? null : "readonly");
       secondaryUnitInput.attr("value", _isImperial ? _t("inspector.roadheight.inch") : null);
     };
     roadheight.focus = function() {
@@ -60004,6 +61939,8 @@ ${content}</tr>
     var _entityIDs = [];
     var _tags;
     var _isImperial;
+    var formatFloat = _mainLocalizer.floatFormatter(_mainLocalizer.languageCode());
+    var parseLocaleFloat = _mainLocalizer.floatParser(_mainLocalizer.languageCode());
     var speedCombo = uiCombobox(context, "roadspeed");
     var unitCombo = uiCombobox(context, "roadspeed-unit").data(["km/h", "mph"].map(comboValues));
     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120];
@@ -60037,8 +61974,8 @@ ${content}</tr>
     }
     function comboValues(d) {
       return {
-        value: d.toString(),
-        title: d.toString()
+        value: formatFloat(d),
+        title: formatFloat(d)
       };
     }
     function change() {
@@ -60048,24 +61985,35 @@ ${content}</tr>
         return;
       if (!value) {
         tag[field.key] = void 0;
-      } else if (isNaN(value) || !_isImperial) {
-        tag[field.key] = context.cleanTagValue(value);
       } else {
-        tag[field.key] = context.cleanTagValue(value + " mph");
+        var rawValue = likelyRawNumberFormat.test(value) ? parseFloat(value) : parseLocaleFloat(value);
+        if (isNaN(rawValue))
+          rawValue = value;
+        if (isNaN(rawValue) || !_isImperial) {
+          tag[field.key] = context.cleanTagValue(rawValue);
+        } else {
+          tag[field.key] = context.cleanTagValue(rawValue + " mph");
+        }
       }
       dispatch10.call("change", this, tag);
     }
     roadspeed.tags = function(tags) {
       _tags = tags;
-      var value = tags[field.key];
+      var rawValue = tags[field.key];
+      var value = rawValue;
       var isMixed = Array.isArray(value);
       if (!isMixed) {
-        if (value && value.indexOf("mph") >= 0) {
-          value = parseInt(value, 10).toString();
+        if (rawValue && rawValue.indexOf("mph") >= 0) {
           _isImperial = true;
-        } else if (value) {
+        } else if (rawValue) {
           _isImperial = false;
         }
+        value = parseInt(value, 10);
+        if (isNaN(value)) {
+          value = rawValue;
+        } else {
+          value = formatFloat(value);
+        }
       }
       setUnitSuggestions();
       utilGetSetValue(input, typeof value === "string" ? value : "").attr("title", isMixed ? value.filter(Boolean).join("\n") : null).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder()).classed("mixed", isMixed);
@@ -60119,7 +62067,7 @@ ${content}</tr>
     }
     function structureExtras(selection2, tags) {
       var selected = selectedKey() || tags.layer !== void 0;
-      var type3 = _mainPresetIndex.field(selected);
+      var type2 = _mainPresetIndex.field(selected);
       var layer = _mainPresetIndex.field("layer");
       var showLayer = selected === "bridge" || selected === "tunnel" || tags.layer !== void 0;
       var extrasWrap = selection2.selectAll(".structure-extras-wrap").data(selected ? [0] : []);
@@ -60127,9 +62075,9 @@ ${content}</tr>
       extrasWrap = extrasWrap.enter().append("div").attr("class", "structure-extras-wrap").merge(extrasWrap);
       var list = extrasWrap.selectAll("ul").data([0]);
       list = list.enter().append("ul").attr("class", "rows").merge(list);
-      if (type3) {
+      if (type2) {
         if (!typeField || typeField.id !== selected) {
-          typeField = uiField(context, type3, _entityIDs, { wrap: false }).on("change", changeType);
+          typeField = uiField(context, type2, _entityIDs, { wrap: false }).on("change", changeType);
         }
         typeField.tags(tags);
       } else {
@@ -60307,9 +62255,11 @@ ${content}</tr>
         _graph = context.graph();
         _intersection = osmIntersection(_graph, _vertexID, _maxDistance);
       }
-      var isOK = _intersection && _intersection.vertices.length && _intersection.vertices.filter(function(vertex) {
+      var isOK = _intersection && _intersection.vertices.length && // has vertices
+      _intersection.vertices.filter(function(vertex) {
         return vertex.id === _vertexID;
-      }).length && _intersection.ways.length > 2 && _intersection.ways.filter(function(way) {
+      }).length && _intersection.ways.length > 2 && // has more than 2 ways
+      _intersection.ways.filter(function(way) {
         return way.__to;
       }).length > 1;
       select_default2(selection2.node().parentNode).classed("hide", !isOK);
@@ -60611,6 +62561,7 @@ ${content}</tr>
         var opts;
         if (isImperial) {
           var distToFeet = {
+            // imprecise conversion for prettier display
             20: 70,
             25: 85,
             30: 100,
@@ -60636,8 +62587,8 @@ ${content}</tr>
       var entity = graph.entity(entityID);
       var name = utilDisplayName(entity) || "";
       var matched = _mainPresetIndex.match(entity, graph);
-      var type3 = matched && matched.name() || utilDisplayType(entity.id);
-      return name || type3;
+      var type2 = matched && matched.name() || utilDisplayType(entity.id);
+      return name || type2;
     }
     restrictions.entityIDs = function(val) {
       _intersection = null;
@@ -60663,29 +62614,34 @@ ${content}</tr>
   function uiFieldTextarea(field, context) {
     var dispatch10 = dispatch_default("change");
     var input = select_default2(null);
+    var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue()).silent(field.usage === "changeset" && field.key === "comment");
     var _tags;
     function textarea(selection2) {
       var wrap2 = selection2.selectAll(".form-field-input-wrap").data([0]);
-      wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).merge(wrap2);
+      wrap2 = wrap2.enter().append("div").attr("class", "form-field-input-wrap form-field-input-" + field.type).style("position", "relative").merge(wrap2);
       input = wrap2.selectAll("textarea").data([0]);
       input = input.enter().append("textarea").attr("id", field.domId).call(utilNoAuto).on("input", change(true)).on("blur", change()).on("change", change()).merge(input);
-    }
-    function change(onInput) {
-      return function() {
-        var val = utilGetSetValue(input);
-        if (!onInput)
-          val = context.cleanTagValue(val);
-        if (!val && Array.isArray(_tags[field.key]))
-          return;
-        var t = {};
-        t[field.key] = val || void 0;
-        dispatch10.call("change", this, t, onInput);
-      };
+      wrap2.call(_lengthIndicator);
+      function change(onInput) {
+        return function() {
+          var val = utilGetSetValue(input);
+          if (!onInput)
+            val = context.cleanTagValue(val);
+          if (!val && Array.isArray(_tags[field.key]))
+            return;
+          var t = {};
+          t[field.key] = val || void 0;
+          dispatch10.call("change", this, t, onInput);
+        };
+      }
     }
     textarea.tags = function(tags) {
       _tags = tags;
       var isMixed = Array.isArray(tags[field.key]);
       utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : "").attr("title", isMixed ? tags[field.key].filter(Boolean).join("\n") : void 0).attr("placeholder", isMixed ? _t("inspector.multiple_values") : field.placeholder() || _t("inspector.unknown")).classed("mixed", isMixed);
+      if (!isMixed) {
+        _lengthIndicator.update(tags[field.key]);
+      }
     };
     textarea.focus = function() {
       input.node().focus();
@@ -60763,8 +62719,11 @@ ${content}</tr>
         }
       }
       wikidata.itemsForSearchQuery(q, function(err, data) {
-        if (err)
+        if (err) {
+          if (err !== "No query")
+            console.error(err);
           return;
+        }
         var result = data.map(function(item) {
           return {
             id: item.id,
@@ -61110,7 +63069,10 @@ ${content}</tr>
           const defaultLangInfo = defaultLanguageInfo();
           _wikiURL = `https://${defaultLangInfo[2]}.wikipedia.org/w/index.php?fulltext=1&search=${value}`;
         } else {
-          const shownOrDefaultLangInfo = language(true);
+          const shownOrDefaultLangInfo = language(
+            true
+            /* skipEnglishFallback */
+          );
           utilGetSetValue(_langInput, shownOrDefaultLangInfo[1]);
           _wikiURL = "";
         }
@@ -61136,8 +63098,10 @@ ${content}</tr>
     check: uiFieldCheck,
     colour: uiFieldText,
     combo: uiFieldCombo,
-    cycleway: uiFieldCycleway,
+    cycleway: uiFieldDirectionalCombo,
+    date: uiFieldText,
     defaultCheck: uiFieldCheck,
+    directionalCombo: uiFieldDirectionalCombo,
     email: uiFieldText,
     identifier: uiFieldText,
     lanes: uiFieldLanes,
@@ -61186,7 +63150,6 @@ ${content}</tr>
     }
     var _locked = false;
     var _lockedTip = uiTooltip().title(() => _t.append("inspector.lock.suggestion", { label: field.title })).placement("bottom");
-    field.keys = field.keys || [field.key];
     if (_show && !field.impl) {
       createField();
     }
@@ -61201,19 +63164,26 @@ ${content}</tr>
         }
       }
     }
+    function allKeys() {
+      let keys2 = field.keys || [field.key];
+      if (field.type === "directionalCombo" && field.key) {
+        keys2 = keys2.concat(field.key);
+      }
+      return keys2;
+    }
     function isModified() {
       if (!entityIDs || !entityIDs.length)
         return false;
       return entityIDs.some(function(entityID) {
         var original = context.graph().base().entities[entityID];
         var latest = context.graph().entity(entityID);
-        return field.keys.some(function(key) {
+        return allKeys().some(function(key) {
           return original ? latest.tags[key] !== original.tags[key] : latest.tags[key];
         });
       });
     }
     function tagsContainFieldKey() {
-      return field.keys.some(function(key) {
+      return allKeys().some(function(key) {
         if (field.type === "multiCombo") {
           for (var tagKey in _tags) {
             if (tagKey.indexOf(key) === 0) {
@@ -61230,7 +63200,7 @@ ${content}</tr>
       d3_event.preventDefault();
       if (!entityIDs || _locked)
         return;
-      dispatch10.call("revert", d, d.keys);
+      dispatch10.call("revert", d, allKeys());
     }
     function remove2(d3_event, d) {
       d3_event.stopPropagation();
@@ -61238,7 +63208,7 @@ ${content}</tr>
       if (_locked)
         return;
       var t = {};
-      d.keys.forEach(function(key) {
+      allKeys().forEach(function(key) {
         t[key] = void 0;
       });
       dispatch10.call("change", d, t);
@@ -61353,7 +63323,8 @@ ${content}</tr>
           return false;
       }
       var prerequisiteTag = field.prerequisiteTag;
-      if (entityIDs && !tagsContainFieldKey() && prerequisiteTag) {
+      if (entityIDs && !tagsContainFieldKey() && // ignore tagging prerequisites if a value is already present
+      prerequisiteTag) {
         if (!entityIDs.every(function(entityID) {
           var entity = context.graph().entity(entityID);
           if (prerequisiteTag.key) {
@@ -61530,12 +63501,34 @@ ${content}</tr>
           });
         }
       }
-      var hasGoogle = _tags.comment.match(/google/i);
-      var commentWarning = selection2.select(".form-field-comment").selectAll(".comment-warning").data(hasGoogle ? [0] : []);
+      const warnings = [];
+      if (_tags.comment.match(/google/i)) {
+        warnings.push({
+          id: 'contains "google"',
+          msg: _t.append("commit.google_warning"),
+          link: _t("commit.google_warning_link")
+        });
+      }
+      const maxChars = context.maxCharsForTagValue();
+      const strLen = utilUnicodeCharsCount(utilCleanOsmString(_tags.comment, Number.POSITIVE_INFINITY));
+      if (strLen > maxChars || false) {
+        warnings.push({
+          id: "message too long",
+          msg: _t.append("commit.changeset_comment_length_warning", { maxChars })
+        });
+      }
+      var commentWarning = selection2.select(".form-field-comment").selectAll(".comment-warning").data(warnings, (d) => d.id);
       commentWarning.exit().transition().duration(200).style("opacity", 0).remove();
-      var commentEnter = commentWarning.enter().insert("div", ".tag-reference-body").attr("class", "field-warning comment-warning").style("opacity", 0);
-      commentEnter.append("a").attr("target", "_blank").call(svgIcon("#iD-icon-alert", "inline")).attr("href", _t("commit.google_warning_link")).append("span").call(_t.append("commit.google_warning"));
+      var commentEnter = commentWarning.enter().insert("div", ".comment-warning").attr("class", "comment-warning field-warning").style("opacity", 0);
+      commentEnter.call(svgIcon("#iD-icon-alert", "inline")).append("span");
       commentEnter.transition().duration(200).style("opacity", 1);
+      commentWarning.merge(commentEnter).selectAll("div > span").text("").each(function(d) {
+        let selection3 = select_default2(this);
+        if (d.link) {
+          selection3 = selection3.append("a").attr("target", "_blank").attr("href", d.link);
+        }
+        selection3.call(d.msg);
+      });
     }
     changesetEditor.tags = function(_) {
       if (!arguments.length)
@@ -61589,7 +63582,10 @@ ${content}</tr>
     }
     function createObjTree(oParentNode, nVerb, bFreeze, bNesteAttr) {
       var nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(), bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
-      var sProp, vContent, nLength = 0, sCollectedTxt = "", vResult = bHighVerb ? {} : true;
+      var sProp, vContent, nLength = 0, sCollectedTxt = "", vResult = bHighVerb ? {} : (
+        /* put here the default value for empty nodes: */
+        true
+      );
       if (bChildren) {
         for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
           oNode = oParentNode.childNodes.item(nItem);
@@ -61684,7 +63680,10 @@ ${content}</tr>
       }
     }
     this.build = function(oXMLParent, nVerbosity, bFreeze, bNesteAttributes) {
-      var _nVerb = arguments.length > 1 && typeof nVerbosity === "number" ? nVerbosity & 3 : 1;
+      var _nVerb = arguments.length > 1 && typeof nVerbosity === "number" ? nVerbosity & 3 : (
+        /* put here the default verbosity level: */
+        1
+      );
       return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);
     };
     this.unbuild = function(oObjTree) {
@@ -62467,9 +64466,9 @@ ${content}</tr>
       var buttons = fixesEnter.append("button").on("click", function(d3_event, d) {
         if (select_default2(this).attr("disabled") || !d.onClick)
           return;
-        if (d.issue.dateLastRanFix && new Date() - d.issue.dateLastRanFix < 1e3)
+        if (d.issue.dateLastRanFix && /* @__PURE__ */ new Date() - d.issue.dateLastRanFix < 1e3)
           return;
-        d.issue.dateLastRanFix = new Date();
+        d.issue.dateLastRanFix = /* @__PURE__ */ new Date();
         utilHighlightEntities(d.issue.entityIds.concat(d.entityIds), false, context);
         new Promise(function(resolve, reject) {
           d.onClick(context, resolve, reject);
@@ -62656,7 +64655,8 @@ ${content}</tr>
       const isMaki = picon && /^maki-/.test(picon);
       const isTemaki = picon && /^temaki-/.test(picon);
       const isFa = picon && /^fa[srb]-/.test(picon);
-      const isiDIcon = picon && !(isMaki || isTemaki || isFa);
+      const isR\u00F6ntgen = picon && /^roentgen-/.test(picon);
+      const isiDIcon = picon && !(isMaki || isTemaki || isFa || isR\u00F6ntgen);
       let icon2 = container.selectAll(".preset-icon").data(picon ? [0] : []);
       icon2.exit().remove();
       icon2 = icon2.enter().append("div").attr("class", "preset-icon").call(svgIcon("")).merge(icon2);
@@ -62836,13 +64836,17 @@ ${content}</tr>
           geoms[graph.entity(entityID).geometry(graph)] = true;
           return geoms;
         }, {}));
+        const loc = _entityIDs.reduce(function(extent, entityID) {
+          var entity = context.graph().entity(entityID);
+          return extent.extend(entity.extent(context.graph()));
+        }, geoExtent()).center();
         var presetsManager = _mainPresetIndex;
         var allFields = [];
         var allMoreFields = [];
         var sharedTotalFields;
         _presets.forEach(function(preset) {
-          var fields = preset.fields();
-          var moreFields = preset.moreFields();
+          var fields = preset.fields(loc);
+          var moreFields = preset.moreFields(loc);
           allFields = utilArrayUnion(allFields, fields);
           allMoreFields = utilArrayUnion(allMoreFields, moreFields);
           if (!sharedTotalFields) {
@@ -62887,8 +64891,8 @@ ${content}</tr>
         _fieldsArr.forEach(function(field) {
           field.on("change", function(t, onInput) {
             dispatch10.call("change", field, _entityIDs, t, onInput);
-          }).on("revert", function(keys) {
-            dispatch10.call("revert", field, keys);
+          }).on("revert", function(keys2) {
+            dispatch10.call("revert", field, keys2);
           });
         });
       }
@@ -63073,7 +65077,8 @@ ${content}</tr>
           targetIndex = null;
         }).on("drag", function(d3_event) {
           var x = d3_event.x - dragOrigin.x, y = d3_event.y - dragOrigin.y;
-          if (!select_default2(this).classed("dragging") && Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5)
+          if (!select_default2(this).classed("dragging") && // don't display drag until dragging beyond a distance threshold
+          Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5)
             return;
           var index = items.nodes().indexOf(this);
           select_default2(this).classed("dragging", true);
@@ -63676,14 +65681,18 @@ ${content}</tr>
         var entityID = entityIDs[i2];
         var entity = context.entity(entityID);
         var tags = Object.assign({}, entity.tags);
-        for (var k in changed) {
-          if (!k)
-            continue;
-          var v = changed[k];
-          if (typeof v === "object") {
-            tags[k] = tags[v.oldKey];
-          } else if (v !== void 0 || tags.hasOwnProperty(k)) {
-            tags[k] = v;
+        if (typeof changed === "function") {
+          tags = changed(tags);
+        } else {
+          for (var k in changed) {
+            if (!k)
+              continue;
+            var v = changed[k];
+            if (typeof v === "object") {
+              tags[k] = tags[v.oldKey];
+            } else if (v !== void 0 || tags.hasOwnProperty(k)) {
+              tags[k] = v;
+            }
           }
         }
         if (!onInput) {
@@ -63712,14 +65721,14 @@ ${content}</tr>
         context.validator().validate();
       }
     }
-    function revertTags(keys) {
+    function revertTags(keys2) {
       var actions = [];
       for (var i2 in _entityIDs) {
         var entityID = _entityIDs[i2];
         var original = context.graph().base().entities[entityID];
         var changed = {};
-        for (var j2 in keys) {
-          var key = keys[j2];
+        for (var j2 in keys2) {
+          var key = keys2[j2];
           changed[key] = original ? original.tags[key] : void 0;
         }
         var entity = context.entity(entityID);
@@ -63847,7 +65856,8 @@ ${content}</tr>
       }
       function keypress(d3_event) {
         var q = search.property("value"), items = list.selectAll(".feature-list-item");
-        if (d3_event.keyCode === 13 && q.length && items.size()) {
+        if (d3_event.keyCode === 13 && // ↩ Return
+        q.length && items.size()) {
           click(d3_event, items.datum());
         }
       }
@@ -63864,7 +65874,7 @@ ${content}</tr>
           drawList();
         }
       }
-      function features2() {
+      function features() {
         var result = [];
         var graph = context.graph();
         var visibleCenter = context.map().extent().center();
@@ -63873,7 +65883,7 @@ ${content}</tr>
           return result;
         var locationMatch = sexagesimal.pair(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
         if (locationMatch) {
-          var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
+          var loc = [Number(locationMatch[0]), Number(locationMatch[1])];
           result.push({
             id: -1,
             geometry: "point",
@@ -63882,7 +65892,7 @@ ${content}</tr>
             location: loc
           });
         }
-        var idMatch = !locationMatch && q.match(/(?:^|\W)(node|way|relation|[nwr])\W?0*([1-9]\d*)(?:\W|$)/i);
+        var idMatch = !locationMatch && q.match(/(?:^|\W)(node|way|relation|[nwr])\W{0,2}0*([1-9]\d*)(?:\W|$)/i);
         if (idMatch) {
           var elemType = idMatch[1].charAt(0);
           var elemId = idMatch[2];
@@ -63903,14 +65913,14 @@ ${content}</tr>
           if (name.toLowerCase().indexOf(q) < 0)
             continue;
           var matched = _mainPresetIndex.match(entity, graph);
-          var type3 = matched && matched.name() || utilDisplayType(entity.id);
+          var type2 = matched && matched.name() || utilDisplayType(entity.id);
           var extent = entity.extent(graph);
           var distance = extent ? geoSphericalDistance(visibleCenter, extent.center()) : 0;
           localResults.push({
             id: entity.id,
             entity,
             geometry: entity.geometry(graph),
-            type: type3,
+            type: type2,
             name,
             distance
           });
@@ -63933,15 +65943,15 @@ ${content}</tr>
             var tempEntity = osmEntity(attrs);
             var tempGraph = coreGraph([tempEntity]);
             var matched2 = _mainPresetIndex.match(tempEntity, tempGraph);
-            var type4 = matched2 && matched2.name() || utilDisplayType(id3);
+            var type3 = matched2 && matched2.name() || utilDisplayType(id3);
             result.push({
               id: tempEntity.id,
               geometry: tempEntity.geometry(tempGraph),
-              type: type4,
+              type: type3,
               name: d.display_name,
               extent: new geoExtent(
-                [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
-                [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])]
+                [Number(d.boundingbox[3]), Number(d.boundingbox[0])],
+                [Number(d.boundingbox[2]), Number(d.boundingbox[1])]
               )
             });
           }
@@ -63970,7 +65980,7 @@ ${content}</tr>
       }
       function drawList() {
         var value = search.property("value");
-        var results = features2();
+        var results = features();
         list.classed("filtered", value.length);
         var resultsIndicator = list.selectAll(".no-results-item").data([0]).enter().append("button").property("disabled", true).attr("class", "no-results-item").call(svgIcon("#iD-icon-alert", "pre-text"));
         resultsIndicator.append("span").attr("class", "entity-name");
@@ -64304,7 +66314,8 @@ ${content}</tr>
         }
       }
       function keydown(d3_event) {
-        if (d3_event.keyCode === utilKeybinding.keyCodes["\u2193"] && search.node().selectionStart === search.property("value").length) {
+        if (d3_event.keyCode === utilKeybinding.keyCodes["\u2193"] && // if insertion point is at the end of the string
+        search.node().selectionStart === search.property("value").length) {
           d3_event.preventDefault();
           d3_event.stopPropagation();
           var buttons = list.selectAll(".preset-list-button");
@@ -64314,7 +66325,8 @@ ${content}</tr>
       }
       function keypress(d3_event) {
         var value = search.property("value");
-        if (d3_event.keyCode === 13 && value.length) {
+        if (d3_event.keyCode === 13 && // ↩ Return
+        value.length) {
           list.selectAll(".preset-list-item:first-child").each(function(d) {
             d.choose.call(this);
           });
@@ -65184,7 +67196,8 @@ ${content}</tr>
       }
       noteSave = noteSaveEnter.merge(noteSave).call(userDetails).call(noteSaveButtons);
       function keydown(d3_event) {
-        if (!(d3_event.keyCode === 13 && d3_event.metaKey))
+        if (!(d3_event.keyCode === 13 && // ↩ Return
+        d3_event.metaKey))
           return;
         var osm = services.osm;
         if (!osm)
@@ -65331,7 +67344,7 @@ ${content}</tr>
 
   // modules/ui/source_switch.js
   function uiSourceSwitch(context) {
-    var keys;
+    var keys2;
     function click(d3_event) {
       d3_event.preventDefault();
       var osm = context.connection();
@@ -65347,15 +67360,15 @@ ${content}</tr>
       context.history().clearSaved();
       context.flush();
       select_default2(this).html(isLive ? _t.html("source_switch.live") : _t.html("source_switch.dev")).classed("live", isLive).classed("chip", isLive);
-      osm.switch(isLive ? keys[0] : keys[1]);
+      osm.switch(isLive ? keys2[0] : keys2[1]);
     }
     var sourceSwitch = function(selection2) {
       selection2.append("a").attr("href", "#").call(_t.append("source_switch.live")).attr("class", "live chip").on("click", click);
     };
     sourceSwitch.keys = function(_) {
       if (!arguments.length)
-        return keys;
-      keys = _;
+        return keys2;
+      keys2 = _;
       return sourceSwitch;
     };
     return sourceSwitch;
@@ -65489,12 +67502,12 @@ ${content}</tr>
   }
 
   // node_modules/osm-community-index/lib/simplify.js
-  var import_diacritics3 = __toESM(require_diacritics(), 1);
-  function simplify2(str2) {
+  var import_diacritics2 = __toESM(require_diacritics(), 1);
+  function simplify(str2) {
     if (typeof str2 !== "string")
       return "";
-    return import_diacritics3.default.remove(
-      str2.replace(/&/g, "and").replace(/İ/ig, "i").replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u200b-\u200f\u2016\u2017\u2020-\u2027\u2030-\u2038\u203b-\u203e\u2041-\u2043\u2047-\u2051\u2053\u2055-\u205e\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00\u2e01\u2e06-\u2e08\u2e0b\u2e0e-\u2e16\u2e18\u2e19\u2e1b\u2e1e\u2e1f\u2e2a-\u2e2e\u2e30-\u2e39\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, "").toLowerCase()
+    return import_diacritics2.default.remove(
+      str2.replace(/&/g, "and").replace(/(İ|i̇)/ig, "i").replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u2000-\u206f\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00-\u2e7f\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, "").toLowerCase()
     );
   }
 
@@ -65505,7 +67518,7 @@ ${content}</tr>
     const anyToken = new RegExp(/(\{\w+\})/, "gi");
     if (localizerFn) {
       if (itemStrings.community) {
-        const communityID = simplify2(itemStrings.community);
+        const communityID = simplify(itemStrings.community);
         itemStrings.community = localizerFn(`_communities.${communityID}`);
       }
       ["name", "description", "extendedDescription"].forEach((prop) => {
@@ -65608,6 +67621,7 @@ ${content}</tr>
         } else {
           _oci = {
             resources: [],
+            // no resources?
             defaults: vals[2].defaults
           };
           return _oci;
@@ -65692,7 +67706,7 @@ ${content}</tr>
         return event;
       }).filter((event) => {
         const t = event.date.getTime();
-        const now3 = new Date().setHours(0, 0, 0, 0);
+        const now3 = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);
         return !isNaN(t) && t >= now3;
       }).sort((a, b) => {
         return a.date < b.date ? -1 : a.date > b.date ? 1 : 0;
@@ -66124,9 +68138,7 @@ ${content}</tr>
           query: value2
         }, function(err, data) {
           if (!err) {
-            var filtered = data.filter(function(d) {
-              return _tags[d.value] === void 0;
-            });
+            const filtered = data.filter((d) => _tags[d.value] === void 0).filter((d) => d.value.toLowerCase().includes(value2.toLowerCase()));
             callback(sort(value2, filtered));
           }
         });
@@ -66138,10 +68150,12 @@ ${content}</tr>
           geometry,
           query: value2
         }, function(err, data) {
-          if (!err)
-            callback(sort(value2, data));
+          if (!err) {
+            const filtered = data.filter((d) => d.value.toLowerCase().includes(value2.toLowerCase()));
+            callback(sort(value2, filtered));
+          }
         });
-      }));
+      }).caseSensitive(allowUpperCaseTagValues.test(utilGetSetValue(key))));
       function sort(value2, data) {
         var sameletter = [];
         var other = [];
@@ -66321,11 +68335,11 @@ ${content}</tr>
   // modules/ui/osmose_details.js
   function uiOsmoseDetails(context) {
     let _qaItem;
-    function issueString(d, type3) {
+    function issueString(d, type2) {
       if (!d)
         return "";
       const s = services.osmose.getStrings(d.itemType);
-      return type3 in s ? s[type3] : "";
+      return type2 in s ? s[type2] : "";
     }
     function osmoseDetails(selection2) {
       const details = selection2.selectAll(".error-details").data(
@@ -66832,9 +68846,12 @@ ${content}</tr>
   function modeAddArea(context, mode) {
     mode.id = "add-area";
     var behavior = behaviorAddWay(context).on("start", start2).on("startFromWay", startFromWay).on("startFromNode", startFromNode);
-    var defaultTags = { area: "yes" };
-    if (mode.preset)
-      defaultTags = mode.preset.setTags(defaultTags, "area");
+    function defaultTags(loc) {
+      var defaultTags2 = { area: "yes" };
+      if (mode.preset)
+        defaultTags2 = mode.preset.setTags(defaultTags2, "area", false, loc);
+      return defaultTags2;
+    }
     function actionClose(wayId) {
       return function(graph) {
         return graph.replace(graph.entity(wayId).close());
@@ -66843,7 +68860,7 @@ ${content}</tr>
     function start2(loc) {
       var startGraph = context.graph();
       var node = osmNode({ loc });
-      var way = osmWay({ tags: defaultTags });
+      var way = osmWay({ tags: defaultTags(loc) });
       context.perform(
         actionAddEntity(node),
         actionAddEntity(way),
@@ -66855,7 +68872,7 @@ ${content}</tr>
     function startFromWay(loc, edge) {
       var startGraph = context.graph();
       var node = osmNode({ loc });
-      var way = osmWay({ tags: defaultTags });
+      var way = osmWay({ tags: defaultTags(loc) });
       context.perform(
         actionAddEntity(node),
         actionAddEntity(way),
@@ -66867,7 +68884,7 @@ ${content}</tr>
     }
     function startFromNode(node) {
       var startGraph = context.graph();
-      var way = osmWay({ tags: defaultTags });
+      var way = osmWay({ tags: defaultTags(node.loc) });
       context.perform(
         actionAddEntity(way),
         actionAddVertex(way.id, node.id),
@@ -66888,13 +68905,16 @@ ${content}</tr>
   function modeAddLine(context, mode) {
     mode.id = "add-line";
     var behavior = behaviorAddWay(context).on("start", start2).on("startFromWay", startFromWay).on("startFromNode", startFromNode);
-    var defaultTags = {};
-    if (mode.preset)
-      defaultTags = mode.preset.setTags(defaultTags, "line");
+    function defaultTags(loc) {
+      var defaultTags2 = {};
+      if (mode.preset)
+        defaultTags2 = mode.preset.setTags(defaultTags2, "line", false, loc);
+      return defaultTags2;
+    }
     function start2(loc) {
       var startGraph = context.graph();
       var node = osmNode({ loc });
-      var way = osmWay({ tags: defaultTags });
+      var way = osmWay({ tags: defaultTags(loc) });
       context.perform(
         actionAddEntity(node),
         actionAddEntity(way),
@@ -66905,7 +68925,7 @@ ${content}</tr>
     function startFromWay(loc, edge) {
       var startGraph = context.graph();
       var node = osmNode({ loc });
-      var way = osmWay({ tags: defaultTags });
+      var way = osmWay({ tags: defaultTags(loc) });
       context.perform(
         actionAddEntity(node),
         actionAddEntity(way),
@@ -66916,7 +68936,7 @@ ${content}</tr>
     }
     function startFromNode(node) {
       var startGraph = context.graph();
-      var way = osmWay({ tags: defaultTags });
+      var way = osmWay({ tags: defaultTags(node.loc) });
       context.perform(
         actionAddEntity(way),
         actionAddVertex(way.id, node.id)
@@ -66936,11 +68956,14 @@ ${content}</tr>
   function modeAddPoint(context, mode) {
     mode.id = "add-point";
     var behavior = behaviorDraw(context).on("click", add).on("clickWay", addWay).on("clickNode", addNode).on("cancel", cancel).on("finish", cancel);
-    var defaultTags = {};
-    if (mode.preset)
-      defaultTags = mode.preset.setTags(defaultTags, "point");
+    function defaultTags(loc) {
+      var defaultTags2 = {};
+      if (mode.preset)
+        defaultTags2 = mode.preset.setTags(defaultTags2, "point", false, loc);
+      return defaultTags2;
+    }
     function add(loc) {
-      var node = osmNode({ loc, tags: defaultTags });
+      var node = osmNode({ loc, tags: defaultTags(loc) });
       context.perform(
         actionAddEntity(node),
         _t("operations.add.annotation.point")
@@ -66948,7 +68971,7 @@ ${content}</tr>
       enterSelectMode(node);
     }
     function addWay(loc, edge) {
-      var node = osmNode({ tags: defaultTags });
+      var node = osmNode({ tags: defaultTags(loc) });
       context.perform(
         actionAddMidpoint({ loc, edge }, node),
         _t("operations.add.annotation.vertex")
@@ -66961,13 +68984,14 @@ ${content}</tr>
       );
     }
     function addNode(node) {
-      if (Object.keys(defaultTags).length === 0) {
+      const _defaultTags = defaultTags(node.loc);
+      if (Object.keys(_defaultTags).length === 0) {
         enterSelectMode(node);
         return;
       }
       var tags = Object.assign({}, node.tags);
-      for (var key in defaultTags) {
-        tags[key] = defaultTags[key];
+      for (var key in _defaultTags) {
+        tags[key] = _defaultTags[key];
       }
       context.perform(
         actionChangeTags(node.id, tags),
@@ -67655,7 +69679,10 @@ ${content}</tr>
       icon: "iD-icon-" + (_mainLocalizer.textDirection() === "rtl" ? "undo" : "redo")
     }];
     function editable() {
-      return context.mode() && context.mode().id !== "save" && context.map().editableDataEnabled(true);
+      return context.mode() && context.mode().id !== "save" && context.map().editableDataEnabled(
+        true
+        /* ignore min zoom */
+      );
     }
     tool.render = function(selection2) {
       var tooltipBehavior = uiTooltip().placement("bottom").title(function(d) {
@@ -68096,7 +70123,7 @@ ${content}</tr>
         }
       });
     }
-    function drawListItems(layerList, type3, change, filter2) {
+    function drawListItems(layerList, type2, change, filter2) {
       var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter2).sort(function(a, b) {
         return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
       });
@@ -68110,7 +70137,7 @@ ${content}</tr>
         return d.best();
       });
       var label = enter.append("label");
-      label.append("input").attr("type", type3).attr("name", "background-layer").attr("value", function(d) {
+      label.append("input").attr("type", type2).attr("name", "background-layer").attr("value", function(d) {
         return d.id;
       }).on("change", change);
       label.append("span").each(function(d) {
@@ -68299,7 +70326,7 @@ ${content}</tr>
       _overlayList.call(updateLayerSelections);
       document.activeElement.blur();
     }
-    function drawListItems(layerList, type3, change, filter2) {
+    function drawListItems(layerList, type2, change, filter2) {
       var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter2);
       var layerLinks = layerList.selectAll("li").data(sources, function(d) {
         return d.name();
@@ -68307,7 +70334,7 @@ ${content}</tr>
       layerLinks.exit().remove();
       var enter = layerLinks.enter().append("li");
       var label = enter.append("label");
-      label.append("input").attr("type", type3).attr("name", "layers").on("change", change);
+      label.append("input").attr("type", type2).attr("name", "layers").on("change", change);
       label.append("span").each(function(d) {
         d.label()(select_default2(this));
       });
@@ -68355,6 +70382,7 @@ ${content}</tr>
         "before_start",
         "open_source_h",
         "open_source",
+        "open_source_attribution",
         "open_source_help"
       ]],
       ["overview", [
@@ -68790,7 +70818,9 @@ ${content}</tr>
     function getOptions() {
       return {
         what: corePreferences("validate-what") || "edited",
+        // 'all', 'edited'
         where: corePreferences("validate-where") || "all"
+        // 'all', 'visible'
       };
     }
     function updateOptionValue(d3_event, d, val) {
@@ -68830,7 +70860,7 @@ ${content}</tr>
       container = container.merge(containerEnter);
       container.selectAll(".issue-rules-list").call(drawListItems, _ruleKeys, "checkbox", "rule", toggleRule, isRuleEnabled);
     }
-    function drawListItems(selection2, data, type3, name, change, active) {
+    function drawListItems(selection2, data, type2, name, change, active) {
       var items = selection2.selectAll("li").data(data);
       items.exit().remove();
       var enter = items.enter().append("li");
@@ -68842,7 +70872,7 @@ ${content}</tr>
         );
       }
       var label = enter.append("label");
-      label.append("input").attr("type", type3).attr("name", name).on("change", change);
+      label.append("input").attr("type", type2).attr("name", name).on("change", change);
       label.append("span").html(function(d) {
         var params = {};
         if (d === "unsquare_way") {
@@ -68872,7 +70902,7 @@ ${content}</tr>
     function changeSquare() {
       var input = select_default2(this);
       var degStr = utilGetSetValue(input).trim();
-      var degNum = parseFloat(degStr, 10);
+      var degNum = Number(degStr);
       if (!isFinite(degNum)) {
         degNum = DEFAULTSQUARE;
       } else if (degNum > MAXSQUARE) {
@@ -68937,12 +70967,12 @@ ${content}</tr>
     function setNoIssuesText(selection2) {
       var opts = getOptions();
       function checkForHiddenIssues(cases) {
-        for (var type3 in cases) {
-          var hiddenOpts = cases[type3];
+        for (var type2 in cases) {
+          var hiddenOpts = cases[type2];
           var hiddenIssues = context.validator().getIssues(hiddenOpts);
           if (hiddenIssues.length) {
             selection2.select(".box .details").html("").call(_t.append(
-              "issues.no_issues.hidden_issues." + type3,
+              "issues.no_issues.hidden_issues." + type2,
               { count: hiddenIssues.length.toString() }
             ));
             return;
@@ -69322,7 +71352,7 @@ ${content}</tr>
       container = container.merge(containerEnter);
       container.selectAll(".layer-feature-list").call(drawListItems, _features, "checkbox", "feature", clickFeature, showsFeature);
     }
-    function drawListItems(selection2, data, type3, name, change, active) {
+    function drawListItems(selection2, data, type2, name, change, active) {
       var items = selection2.selectAll("li").data(data);
       items.exit().remove();
       var enter = items.enter().append("li").call(
@@ -69339,7 +71369,7 @@ ${content}</tr>
         }).placement("top")
       );
       var label = enter.append("label");
-      label.append("input").attr("type", type3).attr("name", name).on("change", change);
+      label.append("input").attr("type", type2).attr("name", name).on("change", change);
       label.append("span").html(function(d) {
         return _t.html(name + "." + d + ".description");
       });
@@ -69374,7 +71404,7 @@ ${content}</tr>
         return context.surface().classed("highlight-edited");
       });
     }
-    function drawListItems(selection2, data, type3, name, change, active) {
+    function drawListItems(selection2, data, type2, name, change, active) {
       var items = selection2.selectAll("li").data(data);
       items.exit().remove();
       var enter = items.enter().append("li").call(
@@ -69388,7 +71418,7 @@ ${content}</tr>
         }).placement("top")
       );
       var label = enter.append("label");
-      label.append("input").attr("type", type3).attr("name", name).on("change", change);
+      label.append("input").attr("type", type2).attr("name", name).on("change", change);
       label.append("span").html(function(d) {
         return _t.html(name + "." + d + ".description");
       });
@@ -69604,14 +71634,19 @@ ${content}</tr>
         if (!d3_event.composedPath)
           return;
         var isOkayTarget = d3_event.composedPath().some(function(node) {
-          return node.nodeType === 1 && (node.nodeName === "INPUT" || node.nodeName === "LABEL" || node.nodeName === "A");
+          return node.nodeType === 1 && // clicking <input> focuses it and/or changes a value
+          (node.nodeName === "INPUT" || // clicking <label> affects its <input> by default
+          node.nodeName === "LABEL" || // clicking <a> opens a hyperlink by default
+          node.nodeName === "A");
         });
         if (isOkayTarget)
           return;
         d3_event.preventDefault();
       });
       var detected = utilDetect();
-      if ("GestureEvent" in window && !detected.isMobileWebKit) {
+      if ("GestureEvent" in window && // Listening for gesture events on iOS 13.4+ breaks double-tapping,
+      // but we only need to do this on desktop Safari anyway. – #7694
+      !detected.isMobileWebKit) {
         container.on("gesturestart.ui gesturechange.ui gestureend.ui", function(d3_event) {
           d3_event.preventDefault();
         });
@@ -69788,6 +71823,7 @@ ${content}</tr>
       if (_loadPromise)
         return _loadPromise;
       return _loadPromise = Promise.all([
+        // must have strings and presets before loading the UI
         _mainLocalizer.ensureLoaded(),
         _mainPresetIndex.ensureLoaded()
       ]).then(() => {
@@ -69907,7 +71943,7 @@ ${content}</tr>
     const dispatch10 = dispatch_default("enter", "exit", "change");
     let context = utilRebind({}, dispatch10, "on");
     let _deferred2 = /* @__PURE__ */ new Set();
-    context.version = "2.23.2";
+    context.version = package_default.version;
     context.privacyVersion = "20201202";
     context.initialHashParams = window.location.hash ? utilStringQs(window.location.hash) : {};
     context.changeset = null;
@@ -69996,337 +72032,1151 @@ ${content}</tr>
           }
           return;
         }
-      };
-    }
-    context.loadTiles = (projection2, callback) => {
-      const handle = window.requestIdleCallback(() => {
-        _deferred2.delete(handle);
-        if (_connection && context.editableDataEnabled()) {
-          const cid = _connection.getConnectionId();
-          _connection.loadTiles(projection2, afterLoad(cid, callback));
+      };
+    }
+    context.loadTiles = (projection2, callback) => {
+      const handle = window.requestIdleCallback(() => {
+        _deferred2.delete(handle);
+        if (_connection && context.editableDataEnabled()) {
+          const cid = _connection.getConnectionId();
+          _connection.loadTiles(projection2, afterLoad(cid, callback));
+        }
+      });
+      _deferred2.add(handle);
+    };
+    context.loadTileAtLoc = (loc, callback) => {
+      const handle = window.requestIdleCallback(() => {
+        _deferred2.delete(handle);
+        if (_connection && context.editableDataEnabled()) {
+          const cid = _connection.getConnectionId();
+          _connection.loadTileAtLoc(loc, afterLoad(cid, callback));
+        }
+      });
+      _deferred2.add(handle);
+    };
+    context.loadEntity = (entityID, callback) => {
+      if (_connection) {
+        const cid = _connection.getConnectionId();
+        _connection.loadEntity(entityID, afterLoad(cid, callback));
+        _connection.loadEntityRelations(entityID, afterLoad(cid, callback));
+      }
+    };
+    context.zoomToEntity = (entityID, zoomTo) => {
+      context.loadEntity(entityID, (err, result) => {
+        if (err)
+          return;
+        if (zoomTo !== false) {
+          const entity = result.data.find((e) => e.id === entityID);
+          if (entity) {
+            _map.zoomTo(entity);
+          }
+        }
+      });
+      _map.on("drawn.zoomToEntity", () => {
+        if (!context.hasEntity(entityID))
+          return;
+        _map.on("drawn.zoomToEntity", null);
+        context.on("enter.zoomToEntity", null);
+        context.enter(modeSelect(context, [entityID]));
+      });
+      context.on("enter.zoomToEntity", () => {
+        if (_mode.id !== "browse") {
+          _map.on("drawn.zoomToEntity", null);
+          context.on("enter.zoomToEntity", null);
+        }
+      });
+    };
+    let _minEditableZoom = 16;
+    context.minEditableZoom = function(val) {
+      if (!arguments.length)
+        return _minEditableZoom;
+      _minEditableZoom = val;
+      if (_connection) {
+        _connection.tileZoom(val);
+      }
+      return context;
+    };
+    context.maxCharsForTagKey = () => 255;
+    context.maxCharsForTagValue = () => 255;
+    context.maxCharsForRelationRole = () => 255;
+    context.cleanTagKey = (val) => utilCleanOsmString(val, context.maxCharsForTagKey());
+    context.cleanTagValue = (val) => utilCleanOsmString(val, context.maxCharsForTagValue());
+    context.cleanRelationRole = (val) => utilCleanOsmString(val, context.maxCharsForRelationRole());
+    let _inIntro = false;
+    context.inIntro = function(val) {
+      if (!arguments.length)
+        return _inIntro;
+      _inIntro = val;
+      return context;
+    };
+    context.save = () => {
+      if (_inIntro || context.container().select(".modal").size())
+        return;
+      let canSave;
+      if (_mode && _mode.id === "save") {
+        canSave = false;
+        if (services.osm && services.osm.isChangesetInflight()) {
+          _history.clearSaved();
+          return;
+        }
+      } else {
+        canSave = context.selectedIDs().every((id2) => {
+          const entity = context.hasEntity(id2);
+          return entity && !entity.isDegenerate();
+        });
+      }
+      if (canSave) {
+        _history.save();
+      }
+      if (_history.hasChanges()) {
+        return _t("save.unsaved_changes");
+      }
+    };
+    context.debouncedSave = debounce_default(context.save, 350);
+    function withDebouncedSave(fn) {
+      return function() {
+        const result = fn.apply(_history, arguments);
+        context.debouncedSave();
+        return result;
+      };
+    }
+    context.hasEntity = (id2) => _history.graph().hasEntity(id2);
+    context.entity = (id2) => _history.graph().entity(id2);
+    let _mode;
+    context.mode = () => _mode;
+    context.enter = (newMode) => {
+      if (_mode) {
+        _mode.exit();
+        dispatch10.call("exit", this, _mode);
+      }
+      _mode = newMode;
+      _mode.enter();
+      dispatch10.call("enter", this, _mode);
+    };
+    context.selectedIDs = () => _mode && _mode.selectedIDs && _mode.selectedIDs() || [];
+    context.activeID = () => _mode && _mode.activeID && _mode.activeID();
+    let _selectedNoteID;
+    context.selectedNoteID = function(noteID) {
+      if (!arguments.length)
+        return _selectedNoteID;
+      _selectedNoteID = noteID;
+      return context;
+    };
+    let _selectedErrorID;
+    context.selectedErrorID = function(errorID) {
+      if (!arguments.length)
+        return _selectedErrorID;
+      _selectedErrorID = errorID;
+      return context;
+    };
+    context.install = (behavior) => context.surface().call(behavior);
+    context.uninstall = (behavior) => context.surface().call(behavior.off);
+    let _copyGraph;
+    context.copyGraph = () => _copyGraph;
+    let _copyIDs = [];
+    context.copyIDs = function(val) {
+      if (!arguments.length)
+        return _copyIDs;
+      _copyIDs = val;
+      _copyGraph = _history.graph();
+      return context;
+    };
+    let _copyLonLat;
+    context.copyLonLat = function(val) {
+      if (!arguments.length)
+        return _copyLonLat;
+      _copyLonLat = val;
+      return context;
+    };
+    let _background;
+    context.background = () => _background;
+    let _features;
+    context.features = () => _features;
+    context.hasHiddenConnections = (id2) => {
+      const graph = _history.graph();
+      const entity = graph.entity(id2);
+      return _features.hasHiddenConnections(entity, graph);
+    };
+    let _photos;
+    context.photos = () => _photos;
+    let _map;
+    context.map = () => _map;
+    context.layers = () => _map.layers();
+    context.surface = () => _map.surface;
+    context.editableDataEnabled = () => _map.editableDataEnabled();
+    context.surfaceRect = () => _map.surface.node().getBoundingClientRect();
+    context.editable = () => {
+      const mode = context.mode();
+      if (!mode || mode.id === "save")
+        return false;
+      return _map.editableDataEnabled();
+    };
+    let _debugFlags = {
+      tile: false,
+      // tile boundaries
+      collision: false,
+      // label collision bounding boxes
+      imagery: false,
+      // imagery bounding polygons
+      target: false,
+      // touch targets
+      downloaded: false
+      // downloaded data from osm
+    };
+    context.debugFlags = () => _debugFlags;
+    context.getDebug = (flag) => flag && _debugFlags[flag];
+    context.setDebug = function(flag, val) {
+      if (arguments.length === 1)
+        val = true;
+      _debugFlags[flag] = val;
+      dispatch10.call("change");
+      return context;
+    };
+    let _container = select_default2(null);
+    context.container = function(val) {
+      if (!arguments.length)
+        return _container;
+      _container = val;
+      _container.classed("ideditor", true);
+      return context;
+    };
+    context.containerNode = function(val) {
+      if (!arguments.length)
+        return context.container().node();
+      context.container(select_default2(val));
+      return context;
+    };
+    let _embed;
+    context.embed = function(val) {
+      if (!arguments.length)
+        return _embed;
+      _embed = val;
+      return context;
+    };
+    let _assetPath = "";
+    context.assetPath = function(val) {
+      if (!arguments.length)
+        return _assetPath;
+      _assetPath = val;
+      _mainFileFetcher.assetPath(val);
+      return context;
+    };
+    let _assetMap = {};
+    context.assetMap = function(val) {
+      if (!arguments.length)
+        return _assetMap;
+      _assetMap = val;
+      _mainFileFetcher.assetMap(val);
+      return context;
+    };
+    context.asset = (val) => {
+      if (/^http(s)?:\/\//i.test(val))
+        return val;
+      const filename = _assetPath + val;
+      return _assetMap[filename] || filename;
+    };
+    context.imagePath = (val) => context.asset(`img/${val}`);
+    context.reset = context.flush = () => {
+      context.debouncedSave.cancel();
+      Array.from(_deferred2).forEach((handle) => {
+        window.cancelIdleCallback(handle);
+        _deferred2.delete(handle);
+      });
+      Object.values(services).forEach((service) => {
+        if (service && typeof service.reset === "function") {
+          service.reset(context);
+        }
+      });
+      context.changeset = null;
+      _validator.reset();
+      _features.reset();
+      _history.reset();
+      _uploader.reset();
+      context.container().select(".inspector-wrap *").remove();
+      return context;
+    };
+    context.projection = geoRawMercator();
+    context.curtainProjection = geoRawMercator();
+    context.init = () => {
+      instantiateInternal();
+      initializeDependents();
+      return context;
+      function instantiateInternal() {
+        _history = coreHistory(context);
+        context.graph = _history.graph;
+        context.pauseChangeDispatch = _history.pauseChangeDispatch;
+        context.resumeChangeDispatch = _history.resumeChangeDispatch;
+        context.perform = withDebouncedSave(_history.perform);
+        context.replace = withDebouncedSave(_history.replace);
+        context.pop = withDebouncedSave(_history.pop);
+        context.overwrite = withDebouncedSave(_history.overwrite);
+        context.undo = withDebouncedSave(_history.undo);
+        context.redo = withDebouncedSave(_history.redo);
+        _validator = coreValidator(context);
+        _uploader = coreUploader(context);
+        _background = rendererBackground(context);
+        _features = rendererFeatures(context);
+        _map = rendererMap(context);
+        _photos = rendererPhotos(context);
+        _ui = uiInit(context);
+      }
+      function initializeDependents() {
+        if (context.initialHashParams.presets) {
+          _mainPresetIndex.addablePresetIDs(new Set(context.initialHashParams.presets.split(",")));
+        }
+        if (context.initialHashParams.locale) {
+          _mainLocalizer.preferredLocaleCodes(context.initialHashParams.locale);
+        }
+        _mainLocalizer.ensureLoaded();
+        _mainPresetIndex.ensureLoaded();
+        _background.ensureLoaded();
+        Object.values(services).forEach((service) => {
+          if (service && typeof service.init === "function") {
+            service.init();
+          }
+        });
+        _map.init();
+        _validator.init();
+        _features.init();
+        if (services.maprules && context.initialHashParams.maprules) {
+          json_default(context.initialHashParams.maprules).then((mapcss) => {
+            services.maprules.init();
+            mapcss.forEach((mapcssSelector) => services.maprules.addRule(mapcssSelector));
+          }).catch(() => {
+          });
+        }
+        if (!context.container().empty()) {
+          _ui.ensureLoaded().then(() => {
+            _background.init();
+            _photos.init();
+          });
+        }
+      }
+    };
+    return context;
+  }
+
+  // modules/services/nominatim.js
+  var apibase = nominatimApiUrl;
+  var _inflight = {};
+  var _nominatimCache;
+  var nominatim_default = {
+    init: function() {
+      _inflight = {};
+      _nominatimCache = new import_rbush7.default();
+    },
+    reset: function() {
+      Object.values(_inflight).forEach(function(controller) {
+        controller.abort();
+      });
+      _inflight = {};
+      _nominatimCache = new import_rbush7.default();
+    },
+    countryCode: function(location, callback) {
+      this.reverse(location, function(err, result) {
+        if (err) {
+          return callback(err);
+        } else if (result.address) {
+          return callback(null, result.address.country_code);
+        } else {
+          return callback("Unable to geocode", null);
+        }
+      });
+    },
+    reverse: function(loc, callback) {
+      var cached = _nominatimCache.search(
+        { minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1] }
+      );
+      if (cached.length > 0) {
+        if (callback)
+          callback(null, cached[0].data);
+        return;
+      }
+      var params = { zoom: 13, format: "json", addressdetails: 1, lat: loc[1], lon: loc[0] };
+      var url = apibase + "reverse?" + utilQsString(params);
+      if (_inflight[url])
+        return;
+      var controller = new AbortController();
+      _inflight[url] = controller;
+      json_default(url, {
+        signal: controller.signal,
+        headers: {
+          "Accept-Language": _mainLocalizer.localeCodes().join(",")
+        }
+      }).then(function(result) {
+        delete _inflight[url];
+        if (result && result.error) {
+          throw new Error(result.error);
+        }
+        var extent = geoExtent(loc).padByMeters(200);
+        _nominatimCache.insert(Object.assign(extent.bbox(), { data: result }));
+        if (callback)
+          callback(null, result);
+      }).catch(function(err) {
+        delete _inflight[url];
+        if (err.name === "AbortError")
+          return;
+        if (callback)
+          callback(err.message);
+      });
+    },
+    search: function(val, callback) {
+      var searchVal = encodeURIComponent(val);
+      var url = apibase + "search/" + searchVal + "?limit=10&format=json";
+      if (_inflight[url])
+        return;
+      var controller = new AbortController();
+      _inflight[url] = controller;
+      json_default(url, {
+        signal: controller.signal,
+        headers: {
+          "Accept-Language": _mainLocalizer.localeCodes().join(",")
+        }
+      }).then(function(result) {
+        delete _inflight[url];
+        if (result && result.error) {
+          throw new Error(result.error);
+        }
+        if (callback)
+          callback(null, result);
+      }).catch(function(err) {
+        delete _inflight[url];
+        if (err.name === "AbortError")
+          return;
+        if (callback)
+          callback(err.message);
+      });
+    }
+  };
+
+  // node_modules/name-suggestion-index/lib/matcher.js
+  var import_which_polygon4 = __toESM(require_which_polygon(), 1);
+
+  // node_modules/name-suggestion-index/lib/simplify.js
+  var import_diacritics3 = __toESM(require_diacritics(), 1);
+  function simplify2(str2) {
+    if (typeof str2 !== "string")
+      return "";
+    return import_diacritics3.default.remove(
+      str2.replace(/&/g, "and").replace(/İ/ig, "i").replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u2000-\u206f\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00-\u2e7f\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, "").toLowerCase()
+    );
+  }
+
+  // node_modules/name-suggestion-index/config/matchGroups.json
+  var matchGroups_default = {
+    matchGroups: {
+      adult_gaming_centre: [
+        "amenity/casino",
+        "amenity/gambling",
+        "leisure/adult_gaming_centre"
+      ],
+      beauty: [
+        "shop/beauty",
+        "shop/hairdresser_supply"
+      ],
+      bed: [
+        "shop/bed",
+        "shop/furniture"
+      ],
+      beverages: [
+        "shop/alcohol",
+        "shop/beer",
+        "shop/beverages",
+        "shop/kiosk",
+        "shop/wine"
+      ],
+      camping: [
+        "tourism/camp_site",
+        "tourism/caravan_site"
+      ],
+      car_parts: [
+        "shop/car_parts",
+        "shop/car_repair",
+        "shop/tires",
+        "shop/tyres"
+      ],
+      clinic: [
+        "amenity/clinic",
+        "amenity/doctors",
+        "healthcare/clinic",
+        "healthcare/laboratory",
+        "healthcare/physiotherapist",
+        "healthcare/sample_collection",
+        "healthcare/dialysis"
+      ],
+      convenience: [
+        "shop/beauty",
+        "shop/chemist",
+        "shop/convenience",
+        "shop/cosmetics",
+        "shop/grocery",
+        "shop/kiosk",
+        "shop/newsagent",
+        "shop/perfumery"
+      ],
+      coworking: [
+        "amenity/coworking_space",
+        "office/coworking",
+        "office/coworking_space"
+      ],
+      dentist: [
+        "amenity/dentist",
+        "amenity/doctors",
+        "healthcare/dentist"
+      ],
+      electronics: [
+        "office/telecommunication",
+        "shop/computer",
+        "shop/electronics",
+        "shop/hifi",
+        "shop/kiosk",
+        "shop/mobile",
+        "shop/mobile_phone",
+        "shop/telecommunication"
+      ],
+      fabric: [
+        "shop/fabric",
+        "shop/haberdashery",
+        "shop/sewing"
+      ],
+      fashion: [
+        "shop/accessories",
+        "shop/bag",
+        "shop/boutique",
+        "shop/clothes",
+        "shop/department_store",
+        "shop/fashion",
+        "shop/fashion_accessories",
+        "shop/sports",
+        "shop/shoes"
+      ],
+      financial: [
+        "amenity/bank",
+        "office/accountant",
+        "office/financial",
+        "office/financial_advisor",
+        "office/tax_advisor",
+        "shop/tax"
+      ],
+      fitness: [
+        "leisure/fitness_centre",
+        "leisure/fitness_center",
+        "leisure/sports_centre",
+        "leisure/sports_center"
+      ],
+      food: [
+        "amenity/bar",
+        "amenity/cafe",
+        "amenity/fast_food",
+        "amenity/ice_cream",
+        "amenity/pub",
+        "amenity/restaurant",
+        "shop/bakery",
+        "shop/candy",
+        "shop/chocolate",
+        "shop/coffee",
+        "shop/confectionary",
+        "shop/confectionery",
+        "shop/food",
+        "shop/kiosk",
+        "shop/ice_cream",
+        "shop/pastry",
+        "shop/tea"
+      ],
+      fuel: [
+        "amenity/fuel",
+        "shop/gas",
+        "shop/convenience;gas",
+        "shop/gas;convenience"
+      ],
+      gift: [
+        "shop/gift",
+        "shop/card",
+        "shop/cards",
+        "shop/kiosk",
+        "shop/stationery"
+      ],
+      hardware: [
+        "shop/bathroom_furnishing",
+        "shop/carpet",
+        "shop/diy",
+        "shop/doityourself",
+        "shop/doors",
+        "shop/electrical",
+        "shop/flooring",
+        "shop/hardware",
+        "shop/hardware_store",
+        "shop/power_tools",
+        "shop/tool_hire",
+        "shop/tools",
+        "shop/trade"
+      ],
+      health_food: [
+        "shop/health",
+        "shop/health_food",
+        "shop/herbalist",
+        "shop/nutrition_supplements"
+      ],
+      hobby: [
+        "shop/electronics",
+        "shop/hobby",
+        "shop/books",
+        "shop/games",
+        "shop/collector",
+        "shop/toys",
+        "shop/model",
+        "shop/video_games",
+        "shop/anime"
+      ],
+      hospital: [
+        "amenity/doctors",
+        "amenity/hospital",
+        "healthcare/hospital"
+      ],
+      houseware: [
+        "shop/houseware",
+        "shop/interior_decoration"
+      ],
+      lifeboat_station: [
+        "amenity/lifeboat_station",
+        "emergency/lifeboat_station",
+        "emergency/marine_rescue"
+      ],
+      lodging: [
+        "tourism/hotel",
+        "tourism/motel"
+      ],
+      money_transfer: [
+        "amenity/money_transfer",
+        "shop/money_transfer"
+      ],
+      office_supplies: [
+        "shop/office_supplies",
+        "shop/stationary",
+        "shop/stationery"
+      ],
+      outdoor: [
+        "shop/clothes",
+        "shop/outdoor",
+        "shop/sports"
+      ],
+      parcel_locker: [
+        "amenity/parcel_locker",
+        "amenity/vending_machine"
+      ],
+      pharmacy: [
+        "amenity/doctors",
+        "amenity/pharmacy",
+        "healthcare/pharmacy"
+      ],
+      playground: [
+        "amenity/theme_park",
+        "leisure/amusement_arcade",
+        "leisure/playground"
+      ],
+      rental: [
+        "amenity/bicycle_rental",
+        "amenity/boat_rental",
+        "amenity/car_rental",
+        "amenity/truck_rental",
+        "amenity/vehicle_rental",
+        "shop/kiosk",
+        "shop/rental"
+      ],
+      school: [
+        "amenity/childcare",
+        "amenity/college",
+        "amenity/kindergarten",
+        "amenity/language_school",
+        "amenity/prep_school",
+        "amenity/school",
+        "amenity/university"
+      ],
+      storage: [
+        "shop/storage_units",
+        "shop/storage_rental"
+      ],
+      substation: [
+        "power/station",
+        "power/substation",
+        "power/sub_station"
+      ],
+      supermarket: [
+        "shop/food",
+        "shop/frozen_food",
+        "shop/greengrocer",
+        "shop/grocery",
+        "shop/supermarket",
+        "shop/wholesale"
+      ],
+      variety_store: [
+        "shop/variety_store",
+        "shop/discount",
+        "shop/convenience"
+      ],
+      vending: [
+        "amenity/vending_machine",
+        "shop/kiosk",
+        "shop/vending_machine"
+      ],
+      weight_loss: [
+        "amenity/clinic",
+        "amenity/doctors",
+        "amenity/weight_clinic",
+        "healthcare/counselling",
+        "leisure/fitness_centre",
+        "office/therapist",
+        "shop/beauty",
+        "shop/diet",
+        "shop/food",
+        "shop/health_food",
+        "shop/herbalist",
+        "shop/nutrition",
+        "shop/nutrition_supplements",
+        "shop/weight_loss"
+      ],
+      wholesale: [
+        "shop/wholesale",
+        "shop/supermarket",
+        "shop/department_store"
+      ]
+    }
+  };
+
+  // node_modules/name-suggestion-index/config/genericWords.json
+  var genericWords_default = {
+    genericWords: [
+      "^(barn|bazaa?r|bench|bou?tique|building|casa|church)$",
+      "^(baseball|basketball|football|soccer|softball|tennis(halle)?)\\s?(field|court)?$",
+      "^(club|green|out|ware)\\s?house$",
+      "^(driveway|el \xE1rbol|fountain|generic|golf|government|graveyard)$",
+      "^(fixme|n\\s?\\/?\\s?a|name|no\\s?name|none|null|temporary|test|unknown)$",
+      "^(hofladen|librairie|magazine?|maison)$",
+      "^(mobile home|skate)?\\s?park$",
+      "^(obuwie|pond|pool|sale|shops?|sklep|stores?)$",
+      "^\\?+$",
+      "^private$",
+      "^tattoo( studio)?$",
+      "^windmill$",
+      "^\u0446\u0435\u0440\u043A\u043E\u0432\u043D\u0430\u044F( \u043B\u0430\u0432\u043A\u0430)?$"
+    ]
+  };
+
+  // node_modules/name-suggestion-index/config/trees.json
+  var trees_default = {
+    trees: {
+      brands: {
+        emoji: "\u{1F354}",
+        mainTag: "brand:wikidata",
+        sourceTags: ["brand", "name"],
+        nameTags: {
+          primary: "^(name|name:\\w+)$",
+          alternate: "^(brand|brand:\\w+|operator|operator:\\w+|\\w+_name|\\w+_name:\\w+)$"
+        }
+      },
+      flags: {
+        emoji: "\u{1F6A9}",
+        mainTag: "flag:wikidata",
+        nameTags: {
+          primary: "^(flag:name|flag:name:\\w+)$",
+          alternate: "^(country|country:\\w+|flag|flag:\\w+|subject|subject:\\w+)$"
+        }
+      },
+      operators: {
+        emoji: "\u{1F4BC}",
+        mainTag: "operator:wikidata",
+        sourceTags: ["operator"],
+        nameTags: {
+          primary: "^(name|name:\\w+|operator|operator:\\w+)$",
+          alternate: "^(brand|brand:\\w+|\\w+_name|\\w+_name:\\w+)$"
+        }
+      },
+      transit: {
+        emoji: "\u{1F687}",
+        mainTag: "network:wikidata",
+        sourceTags: ["network"],
+        nameTags: {
+          primary: "^network$",
+          alternate: "^(operator|operator:\\w+|network:\\w+|\\w+_name|\\w+_name:\\w+)$"
+        }
+      }
+    }
+  };
+
+  // node_modules/name-suggestion-index/lib/matcher.js
+  var matchGroups = matchGroups_default.matchGroups;
+  var trees = trees_default.trees;
+  var Matcher = class {
+    //
+    // `constructor`
+    // initialize the genericWords regexes
+    constructor() {
+      this.matchIndex = void 0;
+      this.genericWords = /* @__PURE__ */ new Map();
+      (genericWords_default.genericWords || []).forEach((s) => this.genericWords.set(s, new RegExp(s, "i")));
+      this.itemLocation = void 0;
+      this.locationSets = void 0;
+      this.locationIndex = void 0;
+      this.warnings = [];
+    }
+    //
+    // `buildMatchIndex()`
+    // Call this to prepare the matcher for use
+    //
+    // `data` needs to be an Object indexed on a 'tree/key/value' path.
+    // (e.g. cache filled by `fileTree.read` or data found in `dist/nsi.json`)
+    // {
+    //    'brands/amenity/bank': { properties: {}, items: [ {}, {}, … ] },
+    //    'brands/amenity/bar':  { properties: {}, items: [ {}, {}, … ] },
+    //    …
+    // }
+    //
+    buildMatchIndex(data) {
+      const that = this;
+      if (that.matchIndex)
+        return;
+      that.matchIndex = /* @__PURE__ */ new Map();
+      const seenTree = /* @__PURE__ */ new Map();
+      Object.keys(data).forEach((tkv) => {
+        const category = data[tkv];
+        const parts = tkv.split("/", 3);
+        const t = parts[0];
+        const k = parts[1];
+        const v = parts[2];
+        const thiskv = `${k}/${v}`;
+        const tree = trees[t];
+        let branch = that.matchIndex.get(thiskv);
+        if (!branch) {
+          branch = {
+            primary: /* @__PURE__ */ new Map(),
+            alternate: /* @__PURE__ */ new Map(),
+            excludeGeneric: /* @__PURE__ */ new Map(),
+            excludeNamed: /* @__PURE__ */ new Map()
+          };
+          that.matchIndex.set(thiskv, branch);
+        }
+        const properties = category.properties || {};
+        const exclude = properties.exclude || {};
+        (exclude.generic || []).forEach((s) => branch.excludeGeneric.set(s, new RegExp(s, "i")));
+        (exclude.named || []).forEach((s) => branch.excludeNamed.set(s, new RegExp(s, "i")));
+        const excludeRegexes = [...branch.excludeGeneric.values(), ...branch.excludeNamed.values()];
+        let items = category.items;
+        if (!Array.isArray(items) || !items.length)
+          return;
+        const primaryName = new RegExp(tree.nameTags.primary, "i");
+        const alternateName = new RegExp(tree.nameTags.alternate, "i");
+        const notName = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i;
+        const skipGenericKV = skipGenericKVMatches(t, k, v);
+        const genericKV = /* @__PURE__ */ new Set([`${k}/yes`, `building/yes`]);
+        const matchGroupKV = /* @__PURE__ */ new Set();
+        Object.values(matchGroups).forEach((matchGroup) => {
+          const inGroup = matchGroup.some((otherkv) => otherkv === thiskv);
+          if (!inGroup)
+            return;
+          matchGroup.forEach((otherkv) => {
+            if (otherkv === thiskv)
+              return;
+            matchGroupKV.add(otherkv);
+            const otherk = otherkv.split("/", 2)[0];
+            genericKV.add(`${otherk}/yes`);
+          });
+        });
+        items.forEach((item) => {
+          if (!item.id)
+            return;
+          if (Array.isArray(item.matchTags) && item.matchTags.length) {
+            item.matchTags = item.matchTags.filter((matchTag) => !matchGroupKV.has(matchTag) && !genericKV.has(matchTag));
+            if (!item.matchTags.length)
+              delete item.matchTags;
+          }
+          let kvTags = [`${thiskv}`].concat(item.matchTags || []);
+          if (!skipGenericKV) {
+            kvTags = kvTags.concat(Array.from(genericKV));
+          }
+          Object.keys(item.tags).forEach((osmkey) => {
+            if (notName.test(osmkey))
+              return;
+            const osmvalue = item.tags[osmkey];
+            if (!osmvalue || excludeRegexes.some((regex) => regex.test(osmvalue)))
+              return;
+            if (primaryName.test(osmkey)) {
+              kvTags.forEach((kv) => insertName("primary", t, kv, simplify2(osmvalue), item.id));
+            } else if (alternateName.test(osmkey)) {
+              kvTags.forEach((kv) => insertName("alternate", t, kv, simplify2(osmvalue), item.id));
+            }
+          });
+          let keepMatchNames = /* @__PURE__ */ new Set();
+          (item.matchNames || []).forEach((matchName) => {
+            const nsimple = simplify2(matchName);
+            kvTags.forEach((kv) => {
+              const branch2 = that.matchIndex.get(kv);
+              const primaryLeaf = branch2 && branch2.primary.get(nsimple);
+              const alternateLeaf = branch2 && branch2.alternate.get(nsimple);
+              const inPrimary = primaryLeaf && primaryLeaf.has(item.id);
+              const inAlternate = alternateLeaf && alternateLeaf.has(item.id);
+              if (!inPrimary && !inAlternate) {
+                insertName("alternate", t, kv, nsimple, item.id);
+                keepMatchNames.add(matchName);
+              }
+            });
+          });
+          if (keepMatchNames.size) {
+            item.matchNames = Array.from(keepMatchNames);
+          } else {
+            delete item.matchNames;
+          }
+        });
+      });
+      function insertName(which, t, kv, nsimple, itemID) {
+        if (!nsimple) {
+          that.warnings.push(`Warning: skipping empty ${which} name for item ${t}/${kv}: ${itemID}`);
+          return;
+        }
+        let branch = that.matchIndex.get(kv);
+        if (!branch) {
+          branch = {
+            primary: /* @__PURE__ */ new Map(),
+            alternate: /* @__PURE__ */ new Map(),
+            excludeGeneric: /* @__PURE__ */ new Map(),
+            excludeNamed: /* @__PURE__ */ new Map()
+          };
+          that.matchIndex.set(kv, branch);
         }
-      });
-      _deferred2.add(handle);
-    };
-    context.loadTileAtLoc = (loc, callback) => {
-      const handle = window.requestIdleCallback(() => {
-        _deferred2.delete(handle);
-        if (_connection && context.editableDataEnabled()) {
-          const cid = _connection.getConnectionId();
-          _connection.loadTileAtLoc(loc, afterLoad(cid, callback));
+        let leaf = branch[which].get(nsimple);
+        if (!leaf) {
+          leaf = /* @__PURE__ */ new Set();
+          branch[which].set(nsimple, leaf);
         }
-      });
-      _deferred2.add(handle);
-    };
-    context.loadEntity = (entityID, callback) => {
-      if (_connection) {
-        const cid = _connection.getConnectionId();
-        _connection.loadEntity(entityID, afterLoad(cid, callback));
-        _connection.loadEntityRelations(entityID, afterLoad(cid, callback));
-      }
-    };
-    context.zoomToEntity = (entityID, zoomTo) => {
-      context.loadEntity(entityID, (err, result) => {
-        if (err)
-          return;
-        if (zoomTo !== false) {
-          const entity = result.data.find((e) => e.id === entityID);
-          if (entity) {
-            _map.zoomTo(entity);
+        leaf.add(itemID);
+        if (!/yes$/.test(kv)) {
+          const kvnsimple = `${kv}/${nsimple}`;
+          const existing = seenTree.get(kvnsimple);
+          if (existing && existing !== t) {
+            const items = Array.from(leaf);
+            that.warnings.push(`Duplicate cache key "${kvnsimple}" in trees "${t}" and "${existing}", check items: ${items}`);
+            return;
           }
+          seenTree.set(kvnsimple, t);
         }
-      });
-      _map.on("drawn.zoomToEntity", () => {
-        if (!context.hasEntity(entityID))
-          return;
-        _map.on("drawn.zoomToEntity", null);
-        context.on("enter.zoomToEntity", null);
-        context.enter(modeSelect(context, [entityID]));
-      });
-      context.on("enter.zoomToEntity", () => {
-        if (_mode.id !== "browse") {
-          _map.on("drawn.zoomToEntity", null);
-          context.on("enter.zoomToEntity", null);
-        }
-      });
-    };
-    let _minEditableZoom = 16;
-    context.minEditableZoom = function(val) {
-      if (!arguments.length)
-        return _minEditableZoom;
-      _minEditableZoom = val;
-      if (_connection) {
-        _connection.tileZoom(val);
       }
-      return context;
-    };
-    context.maxCharsForTagKey = () => 255;
-    context.maxCharsForTagValue = () => 255;
-    context.maxCharsForRelationRole = () => 255;
-    function cleanOsmString(val, maxChars) {
-      if (val === void 0 || val === null) {
-        val = "";
-      } else {
-        val = val.toString();
+      function skipGenericKVMatches(t, k, v) {
+        return t === "flags" || t === "transit" || k === "landuse" || v === "atm" || v === "bicycle_parking" || v === "car_sharing" || v === "caravan_site" || v === "charging_station" || v === "dog_park" || v === "parking" || v === "phone" || v === "playground" || v === "post_box" || v === "public_bookcase" || v === "recycling" || v === "vending_machine";
       }
-      val = val.trim();
-      if (val.normalize)
-        val = val.normalize("NFC");
-      return utilUnicodeCharsTruncated(val, maxChars);
     }
-    context.cleanTagKey = (val) => cleanOsmString(val, context.maxCharsForTagKey());
-    context.cleanTagValue = (val) => cleanOsmString(val, context.maxCharsForTagValue());
-    context.cleanRelationRole = (val) => cleanOsmString(val, context.maxCharsForRelationRole());
-    let _inIntro = false;
-    context.inIntro = function(val) {
-      if (!arguments.length)
-        return _inIntro;
-      _inIntro = val;
-      return context;
-    };
-    context.save = () => {
-      if (_inIntro || context.container().select(".modal").size())
+    //
+    // `buildLocationIndex()`
+    // Call this to prepare a which-polygon location index.
+    // This *resolves* all the locationSets into GeoJSON, which takes some time.
+    // You can skip this step if you don't care about matching within a location.
+    //
+    // `data` needs to be an Object indexed on a 'tree/key/value' path.
+    // (e.g. cache filled by `fileTree.read` or data found in `dist/nsi.json`)
+    // {
+    //    'brands/amenity/bank': { properties: {}, items: [ {}, {}, … ] },
+    //    'brands/amenity/bar':  { properties: {}, items: [ {}, {}, … ] },
+    //    …
+    // }
+    //
+    buildLocationIndex(data, loco) {
+      const that = this;
+      if (that.locationIndex)
         return;
-      let canSave;
-      if (_mode && _mode.id === "save") {
-        canSave = false;
-        if (services.osm && services.osm.isChangesetInflight()) {
-          _history.clearSaved();
+      that.itemLocation = /* @__PURE__ */ new Map();
+      that.locationSets = /* @__PURE__ */ new Map();
+      Object.keys(data).forEach((tkv) => {
+        const items = data[tkv].items;
+        if (!Array.isArray(items) || !items.length)
           return;
-        }
-      } else {
-        canSave = context.selectedIDs().every((id2) => {
-          const entity = context.hasEntity(id2);
-          return entity && !entity.isDegenerate();
+        items.forEach((item) => {
+          if (that.itemLocation.has(item.id))
+            return;
+          let resolved;
+          try {
+            resolved = loco.resolveLocationSet(item.locationSet);
+          } catch (err) {
+            console.warn(`buildLocationIndex: ${err.message}`);
+          }
+          if (!resolved || !resolved.id)
+            return;
+          that.itemLocation.set(item.id, resolved.id);
+          if (that.locationSets.has(resolved.id))
+            return;
+          let feature3 = _cloneDeep2(resolved.feature);
+          feature3.id = resolved.id;
+          feature3.properties.id = resolved.id;
+          if (!feature3.geometry.coordinates.length || !feature3.properties.area) {
+            console.warn(`buildLocationIndex: locationSet ${resolved.id} for ${item.id} resolves to an empty feature:`);
+            console.warn(JSON.stringify(feature3));
+            return;
+          }
+          that.locationSets.set(resolved.id, feature3);
         });
+      });
+      that.locationIndex = (0, import_which_polygon4.default)({ type: "FeatureCollection", features: [...that.locationSets.values()] });
+      function _cloneDeep2(obj) {
+        return JSON.parse(JSON.stringify(obj));
       }
-      if (canSave) {
-        _history.save();
-      }
-      if (_history.hasChanges()) {
-        return _t("save.unsaved_changes");
-      }
-    };
-    context.debouncedSave = debounce_default(context.save, 350);
-    function withDebouncedSave(fn) {
-      return function() {
-        const result = fn.apply(_history, arguments);
-        context.debouncedSave();
-        return result;
-      };
     }
-    context.hasEntity = (id2) => _history.graph().hasEntity(id2);
-    context.entity = (id2) => _history.graph().entity(id2);
-    let _mode;
-    context.mode = () => _mode;
-    context.enter = (newMode) => {
-      if (_mode) {
-        _mode.exit();
-        dispatch10.call("exit", this, _mode);
+    //
+    // `match()`
+    // Pass parts and return an Array of matches.
+    // `k` - key
+    // `v` - value
+    // `n` - namelike
+    // `loc` - optional - [lon,lat] location to search
+    //
+    // 1. If the [k,v,n] tuple matches a canonical item…
+    // Return an Array of match results.
+    // Each result will include the area in km² that the item is valid.
+    //
+    // Order of results:
+    // Primary ordering will be on the "match" column:
+    //   "primary" - where the query matches the `name` tag, followed by
+    //   "alternate" - where the query matches an alternate name tag (e.g. short_name, brand, operator, etc)
+    // Secondary ordering will be on the "area" column:
+    //   "area descending" if no location was provided, (worldwide before local)
+    //   "area ascending" if location was provided (local before worldwide)
+    //
+    // [
+    //   { match: 'primary',   itemID: String,  area: Number,  kv: String,  nsimple: String },
+    //   { match: 'primary',   itemID: String,  area: Number,  kv: String,  nsimple: String },
+    //   { match: 'alternate', itemID: String,  area: Number,  kv: String,  nsimple: String },
+    //   { match: 'alternate', itemID: String,  area: Number,  kv: String,  nsimple: String },
+    //   …
+    // ]
+    //
+    // -or-
+    //
+    // 2. If the [k,v,n] tuple matches an exclude pattern…
+    // Return an Array with a single exclude result, either
+    //
+    // [ { match: 'excludeGeneric', pattern: String,  kv: String } ]  // "generic" e.g. "Food Court"
+    //   or
+    // [ { match: 'excludeNamed', pattern: String,  kv: String } ]    // "named", e.g. "Kebabai"
+    //
+    // About results
+    //   "generic" - a generic word that is probably not really a name.
+    //     For these, iD should warn the user "Hey don't put 'food court' in the name tag".
+    //   "named" - a real name like "Kebabai" that is just common, but not a brand.
+    //     For these, iD should just let it be. We don't include these in NSI, but we don't want to nag users about it either.
+    //
+    // -or-
+    //
+    // 3. If the [k,v,n] tuple matches nothing of any kind, return `null`
+    //
+    //
+    match(k, v, n2, loc) {
+      const that = this;
+      if (!that.matchIndex) {
+        throw new Error("match:  matchIndex not built.");
       }
-      _mode = newMode;
-      _mode.enter();
-      dispatch10.call("enter", this, _mode);
-    };
-    context.selectedIDs = () => _mode && _mode.selectedIDs && _mode.selectedIDs() || [];
-    context.activeID = () => _mode && _mode.activeID && _mode.activeID();
-    let _selectedNoteID;
-    context.selectedNoteID = function(noteID) {
-      if (!arguments.length)
-        return _selectedNoteID;
-      _selectedNoteID = noteID;
-      return context;
-    };
-    let _selectedErrorID;
-    context.selectedErrorID = function(errorID) {
-      if (!arguments.length)
-        return _selectedErrorID;
-      _selectedErrorID = errorID;
-      return context;
-    };
-    context.install = (behavior) => context.surface().call(behavior);
-    context.uninstall = (behavior) => context.surface().call(behavior.off);
-    let _copyGraph;
-    context.copyGraph = () => _copyGraph;
-    let _copyIDs = [];
-    context.copyIDs = function(val) {
-      if (!arguments.length)
-        return _copyIDs;
-      _copyIDs = val;
-      _copyGraph = _history.graph();
-      return context;
-    };
-    let _copyLonLat;
-    context.copyLonLat = function(val) {
-      if (!arguments.length)
-        return _copyLonLat;
-      _copyLonLat = val;
-      return context;
-    };
-    let _background;
-    context.background = () => _background;
-    let _features;
-    context.features = () => _features;
-    context.hasHiddenConnections = (id2) => {
-      const graph = _history.graph();
-      const entity = graph.entity(id2);
-      return _features.hasHiddenConnections(entity, graph);
-    };
-    let _photos;
-    context.photos = () => _photos;
-    let _map;
-    context.map = () => _map;
-    context.layers = () => _map.layers();
-    context.surface = () => _map.surface;
-    context.editableDataEnabled = () => _map.editableDataEnabled();
-    context.surfaceRect = () => _map.surface.node().getBoundingClientRect();
-    context.editable = () => {
-      const mode = context.mode();
-      if (!mode || mode.id === "save")
-        return false;
-      return _map.editableDataEnabled();
-    };
-    let _debugFlags = {
-      tile: false,
-      collision: false,
-      imagery: false,
-      target: false,
-      downloaded: false
-    };
-    context.debugFlags = () => _debugFlags;
-    context.getDebug = (flag) => flag && _debugFlags[flag];
-    context.setDebug = function(flag, val) {
-      if (arguments.length === 1)
-        val = true;
-      _debugFlags[flag] = val;
-      dispatch10.call("change");
-      return context;
-    };
-    let _container = select_default2(null);
-    context.container = function(val) {
-      if (!arguments.length)
-        return _container;
-      _container = val;
-      _container.classed("ideditor", true);
-      return context;
-    };
-    context.containerNode = function(val) {
-      if (!arguments.length)
-        return context.container().node();
-      context.container(select_default2(val));
-      return context;
-    };
-    let _embed;
-    context.embed = function(val) {
-      if (!arguments.length)
-        return _embed;
-      _embed = val;
-      return context;
-    };
-    let _assetPath = "";
-    context.assetPath = function(val) {
-      if (!arguments.length)
-        return _assetPath;
-      _assetPath = val;
-      _mainFileFetcher.assetPath(val);
-      return context;
-    };
-    let _assetMap = {};
-    context.assetMap = function(val) {
-      if (!arguments.length)
-        return _assetMap;
-      _assetMap = val;
-      _mainFileFetcher.assetMap(val);
-      return context;
-    };
-    context.asset = (val) => {
-      if (/^http(s)?:\/\//i.test(val))
-        return val;
-      const filename = _assetPath + val;
-      return _assetMap[filename] || filename;
-    };
-    context.imagePath = (val) => context.asset(`img/${val}`);
-    context.reset = context.flush = () => {
-      context.debouncedSave.cancel();
-      Array.from(_deferred2).forEach((handle) => {
-        window.cancelIdleCallback(handle);
-        _deferred2.delete(handle);
-      });
-      Object.values(services).forEach((service) => {
-        if (service && typeof service.reset === "function") {
-          service.reset(context);
-        }
-      });
-      context.changeset = null;
-      _validator.reset();
-      _features.reset();
-      _history.reset();
-      _uploader.reset();
-      context.container().select(".inspector-wrap *").remove();
-      return context;
-    };
-    context.projection = geoRawMercator();
-    context.curtainProjection = geoRawMercator();
-    context.init = () => {
-      instantiateInternal();
-      initializeDependents();
-      return context;
-      function instantiateInternal() {
-        _history = coreHistory(context);
-        context.graph = _history.graph;
-        context.pauseChangeDispatch = _history.pauseChangeDispatch;
-        context.resumeChangeDispatch = _history.resumeChangeDispatch;
-        context.perform = withDebouncedSave(_history.perform);
-        context.replace = withDebouncedSave(_history.replace);
-        context.pop = withDebouncedSave(_history.pop);
-        context.overwrite = withDebouncedSave(_history.overwrite);
-        context.undo = withDebouncedSave(_history.undo);
-        context.redo = withDebouncedSave(_history.redo);
-        _validator = coreValidator(context);
-        _uploader = coreUploader(context);
-        _background = rendererBackground(context);
-        _features = rendererFeatures(context);
-        _map = rendererMap(context);
-        _photos = rendererPhotos(context);
-        _ui = uiInit(context);
+      let matchLocations;
+      if (Array.isArray(loc) && that.locationIndex) {
+        matchLocations = that.locationIndex([loc[0], loc[1], loc[0], loc[1]], true);
       }
-      function initializeDependents() {
-        if (context.initialHashParams.presets) {
-          _mainPresetIndex.addablePresetIDs(new Set(context.initialHashParams.presets.split(",")));
+      const nsimple = simplify2(n2);
+      let seen = /* @__PURE__ */ new Set();
+      let results = [];
+      gatherResults("primary");
+      gatherResults("alternate");
+      if (results.length)
+        return results;
+      gatherResults("exclude");
+      return results.length ? results : null;
+      function gatherResults(which) {
+        const kv = `${k}/${v}`;
+        let didMatch = tryMatch(which, kv);
+        if (didMatch)
+          return;
+        for (let mg in matchGroups) {
+          const matchGroup = matchGroups[mg];
+          const inGroup = matchGroup.some((otherkv) => otherkv === kv);
+          if (!inGroup)
+            continue;
+          for (let i2 = 0; i2 < matchGroup.length; i2++) {
+            const otherkv = matchGroup[i2];
+            if (otherkv === kv)
+              continue;
+            didMatch = tryMatch(which, otherkv);
+            if (didMatch)
+              return;
+          }
         }
-        if (context.initialHashParams.locale) {
-          _mainLocalizer.preferredLocaleCodes(context.initialHashParams.locale);
+        if (which === "exclude") {
+          const regex = [...that.genericWords.values()].find((regex2) => regex2.test(n2));
+          if (regex) {
+            results.push({ match: "excludeGeneric", pattern: String(regex) });
+            return;
+          }
         }
-        _mainLocalizer.ensureLoaded();
-        _mainPresetIndex.ensureLoaded();
-        _background.ensureLoaded();
-        Object.values(services).forEach((service) => {
-          if (service && typeof service.init === "function") {
-            service.init();
+      }
+      function tryMatch(which, kv) {
+        const branch = that.matchIndex.get(kv);
+        if (!branch)
+          return;
+        if (which === "exclude") {
+          let regex = [...branch.excludeNamed.values()].find((regex2) => regex2.test(n2));
+          if (regex) {
+            results.push({ match: "excludeNamed", pattern: String(regex), kv });
+            return;
+          }
+          regex = [...branch.excludeGeneric.values()].find((regex2) => regex2.test(n2));
+          if (regex) {
+            results.push({ match: "excludeGeneric", pattern: String(regex), kv });
+            return;
+          }
+          return;
+        }
+        const leaf = branch[which].get(nsimple);
+        if (!leaf || !leaf.size)
+          return;
+        let hits = Array.from(leaf).map((itemID) => {
+          let area = Infinity;
+          if (that.itemLocation && that.locationSets) {
+            const location = that.locationSets.get(that.itemLocation.get(itemID));
+            area = location && location.properties.area || Infinity;
           }
+          return { match: which, itemID, area, kv, nsimple };
         });
-        _map.init();
-        _validator.init();
-        _features.init();
-        if (services.maprules && context.initialHashParams.maprules) {
-          json_default(context.initialHashParams.maprules).then((mapcss) => {
-            services.maprules.init();
-            mapcss.forEach((mapcssSelector) => services.maprules.addRule(mapcssSelector));
-          }).catch(() => {
-          });
+        let sortFn = byAreaDescending;
+        if (matchLocations) {
+          hits = hits.filter(isValidLocation);
+          sortFn = byAreaAscending;
         }
-        if (!context.container().empty()) {
-          _ui.ensureLoaded().then(() => {
-            _background.init();
-            _photos.init();
-          });
+        if (!hits.length)
+          return;
+        hits.sort(sortFn).forEach((hit) => {
+          if (seen.has(hit.itemID))
+            return;
+          seen.add(hit.itemID);
+          results.push(hit);
+        });
+        return true;
+        function isValidLocation(hit) {
+          if (!that.itemLocation)
+            return true;
+          return matchLocations.find((props) => props.id === that.itemLocation.get(hit.itemID));
+        }
+        function byAreaAscending(hitA, hitB) {
+          return hitA.area - hitB.area;
+        }
+        function byAreaDescending(hitA, hitB) {
+          return hitB.area - hitA.area;
         }
       }
-    };
-    return context;
-  }
+    }
+    //
+    // `getWarnings()`
+    // Return any warnings discovered when buiding the index.
+    // (currently this does nothing)
+    //
+    getWarnings() {
+      return this.warnings;
+    }
+  };
 
   // modules/services/nsi.js
+  var import_vparse2 = __toESM(require_vparse());
   var _nsiStatus = "loading";
   var _nsi = {};
   var buildingPreset = {
@@ -70381,12 +73231,19 @@ ${content}</tr>
     ]).then((vals) => {
       _nsi = {
         data: vals[0].nsi,
+        // the raw name-suggestion-index data
         dissolved: vals[1].dissolved,
+        // list of dissolved items
         replacements: vals[2].replacements,
+        // trivial old->new qid replacements
         trees: vals[3].trees,
+        // metadata about trees, main tags
         kvt: /* @__PURE__ */ new Map(),
+        // Map (k -> Map (v -> t) )
         qids: /* @__PURE__ */ new Map(),
+        // Map (wd/wp tag values -> qids)
         ids: /* @__PURE__ */ new Map()
+        // Map (id -> NSI item)
       };
       const matcher = _nsi.matcher = new Matcher();
       matcher.buildMatchIndex(_nsi.data);
@@ -70513,6 +73370,7 @@ ${content}</tr>
       patterns2 = {
         primary: /^(flag:name|flag:name:\w+)$/i,
         alternate: /^(flag|flag:\w+|subject|subject:\w+)$/i
+        // note: no `country`, we special-case it below
       };
     } else if (t === "brands") {
       testNameFragments = true;
@@ -70655,7 +73513,11 @@ ${content}</tr>
         const mainTag = item.mainTag;
         const itemQID = item.tags[mainTag];
         const notQID = newTags[`not:${mainTag}`];
-        if (!itemQID || itemQID === notQID || newTags.office && !item.tags.office) {
+        if (
+          // Exceptions, skip this hit
+          !itemQID || itemQID === notQID || // No `*:wikidata` or matched a `not:*:wikidata`
+          newTags.office && !item.tags.office
+        ) {
           item = null;
           continue;
         } else {
@@ -70752,15 +73614,55 @@ ${content}</tr>
     return false;
   }
   var nsi_default = {
+    // `init()`
+    // On init, start preparing the name-suggestion-index
+    //
     init: () => {
       setNsiSources();
       _mainPresetIndex.ensureLoaded().then(() => loadNsiPresets()).then(() => loadNsiData()).then(() => _nsiStatus = "ok").catch(() => _nsiStatus = "failed");
     },
+    // `reset()`
+    // Reset is called when user saves data to OSM (does nothing here)
+    //
     reset: () => {
     },
+    // `status()`
+    // To let other code know how it's going...
+    //
+    // Returns
+    //   `String`: 'loading', 'ok', 'failed'
+    //
     status: () => _nsiStatus,
+    // `isGenericName()`
+    // Is the `name` tag generic?
+    //
+    // Arguments
+    //   `tags`: `Object` containing the feature's OSM tags
+    // Returns
+    //   `true` if it is generic, `false` if not
+    //
     isGenericName: (tags) => _isGenericName(tags),
+    // `upgradeTags()`
+    // Suggest tag upgrades.
+    // This function will not modify the input tags, it makes a copy.
+    //
+    // Arguments
+    //   `tags`: `Object` containing the feature's OSM tags
+    //   `loc`: Location where this feature exists, as a [lon, lat]
+    // Returns
+    //   `Object` containing the result, or `null` if no changes needed:
+    //   {
+    //     'newTags': `Object` - The tags the the feature should have
+    //     'matched': `Object` - The matched item
+    //   }
+    //
     upgradeTags: (tags, loc) => _upgradeTags(tags, loc),
+    // `cache()`
+    // Direct access to the NSI cache, useful for testing or breaking things
+    //
+    // Returns
+    //   `Object`: the internal NSI cache
+    //
     cache: () => _nsi
   };
 
@@ -70817,6 +73719,7 @@ ${content}</tr>
     var params = utilQsString({
       ipp: maxResults,
       page: nextPage,
+      // client_id: clientId,
       bbTopLeft: [bbox2.maxY, bbox2.minX].join(","),
       bbBottomRight: [bbox2.minY, bbox2.maxX].join(",")
     }, true);
@@ -70839,7 +73742,7 @@ ${content}</tr>
       if (!data || !data.currentPageItems || !data.currentPageItems.length) {
         throw new Error("No Data");
       }
-      var features2 = data.currentPageItems.map(function(item) {
+      var features = data.currentPageItems.map(function(item) {
         var loc = [+item.lng, +item.lat];
         var d;
         if (which === "images") {
@@ -70869,7 +73772,7 @@ ${content}</tr>
           data: d
         };
       });
-      cache.rtree.load(features2);
+      cache.rtree.load(features);
       if (data.currentPageItems.length === maxResults) {
         cache.nextPage[tile.id] = nextPage + 1;
         loadNextTilePage(which, currZoom, url, tile);
@@ -71083,6 +73986,9 @@ ${content}</tr>
     getSequenceKeyForImage: function(d) {
       return d && d.sequence_id;
     },
+    // Updates the currently highlighted sequence and selected bubble.
+    // Reset is only necessary when interacting with the viewport because
+    // this implicitly changes the currently selected bubble/sequence
     setStyles: function(context, hovered, reset) {
       if (reset) {
         context.container().selectAll(".viewfield-group").classed("highlighted", false).classed("hovered", false).classed("currentView", false);
@@ -71168,14 +74074,21 @@ ${content}</tr>
         response_type: "code",
         scope: o.scope
       });
-      if (!o.singlepage) {
+      if (o.singlepage) {
+        var params = utilStringQs2(window.location.search.slice(1));
+        if (params.code) {
+          getAccessToken(params.code);
+        } else {
+          window.location = url;
+        }
+      } else {
         var w = 600;
         var h = 550;
         var settings = [
           ["width", w],
           ["height", h],
-          ["left", screen.width / 2 - w / 2],
-          ["top", screen.height / 2 - h / 2]
+          ["left", window.screen.width / 2 - w / 2],
+          ["top", window.screen.height / 2 - h / 2]
         ].map(function(x) {
           return x.join("=");
         }).join(",");
@@ -71189,8 +74102,8 @@ ${content}</tr>
         }
       }
       window.authComplete = function(url2) {
-        var params = utilStringQs2(url2.split("?")[1]);
-        getAccessToken(params.code);
+        var params2 = utilStringQs2(url2.split("?")[1]);
+        getAccessToken(params2.code);
         delete window.authComplete;
       };
       function getAccessToken(auth_code) {
@@ -71250,6 +74163,42 @@ ${content}</tr>
       }
       getAccessToken(auth_code);
     };
+    oauth2.fetch = function(path, options2, callback) {
+      if (oauth2.authenticated()) {
+        return run();
+      } else {
+        if (o.auto) {
+          oauth2.authenticate(run);
+          return;
+        } else {
+          callback("not authenticated", null);
+          return;
+        }
+      }
+      function run() {
+        var url = options2.prefix !== false ? o.url + path : path;
+        var headers = options2.headers || { "Content-Type": "application/x-www-form-urlencoded" };
+        headers.Authorization = "Bearer " + token("oauth2_access_token");
+        return fetch(url, {
+          method: options2.method,
+          body: options2.body,
+          headers
+        }).then((resp) => {
+          var contentType = resp.headers.get("content-type").split(";")[0];
+          switch (contentType) {
+            case "text/html":
+            case "text/xml":
+              return resp.text().then(
+                (txt) => new window.DOMParser().parseFromString(txt, contentType)
+              );
+            case "application/html":
+              return resp.json();
+            default:
+              return resp.text();
+          }
+        });
+      }
+    };
     oauth2.xhr = function(options2, callback) {
       if (oauth2.authenticated()) {
         return run();
@@ -71425,7 +74374,7 @@ ${content}</tr>
   function getLoc(attrs) {
     var lon = attrs.lon && attrs.lon.value;
     var lat = attrs.lat && attrs.lat.value;
-    return [parseFloat(lon), parseFloat(lat)];
+    return [Number(lon), Number(lat)];
   }
   function getNodes(obj) {
     var elems = obj.getElementsByTagName("nd");
@@ -71527,7 +74476,7 @@ ${content}</tr>
         timestamp: obj.timestamp,
         user: obj.user,
         uid: obj.uid && obj.uid.toString(),
-        loc: [parseFloat(obj.lon), parseFloat(obj.lat)],
+        loc: [Number(obj.lon), Number(obj.lat)],
         tags: obj.tags
       });
     },
@@ -71862,6 +74811,8 @@ ${content}</tr>
     noteReportURL: function(note) {
       return urlroot + "/reports/new?reportable_type=Note&reportable_id=" + note.id;
     },
+    // Generic method to load data from the OSM API
+    // Can handle either auth or unauth calls.
     loadFromAPI: function(path, callback, options2) {
       options2 = Object.assign({ skipSeen: true }, options2);
       var that = this;
@@ -71923,12 +74874,16 @@ ${content}</tr>
         return controller;
       }
     },
+    // Load a single entity by id (ways and relations use the `/full` call to include
+    // nodes and members). Parent relations are not included, see `loadEntityRelations`.
+    // GET /api/0.6/node/#id
+    // GET /api/0.6/[way|relation]/#id/full
     loadEntity: function(id2, callback) {
-      var type3 = osmEntity.id.type(id2);
+      var type2 = osmEntity.id.type(id2);
       var osmID = osmEntity.id.toOSM(id2);
       var options2 = { skipSeen: false };
       this.loadFromAPI(
-        "/api/0.6/" + type3 + "/" + osmID + (type3 !== "node" ? "/full" : "") + ".json",
+        "/api/0.6/" + type2 + "/" + osmID + (type2 !== "node" ? "/full" : "") + ".json",
         function(err, entities) {
           if (callback)
             callback(err, { data: entities });
@@ -71936,12 +74891,14 @@ ${content}</tr>
         options2
       );
     },
+    // Load a single entity with a specific version
+    // GET /api/0.6/[node|way|relation]/#id/#version
     loadEntityVersion: function(id2, version, callback) {
-      var type3 = osmEntity.id.type(id2);
+      var type2 = osmEntity.id.type(id2);
       var osmID = osmEntity.id.toOSM(id2);
       var options2 = { skipSeen: false };
       this.loadFromAPI(
-        "/api/0.6/" + type3 + "/" + osmID + "/" + version + ".json",
+        "/api/0.6/" + type2 + "/" + osmID + "/" + version + ".json",
         function(err, entities) {
           if (callback)
             callback(err, { data: entities });
@@ -71949,12 +74906,14 @@ ${content}</tr>
         options2
       );
     },
+    // Load the relations of a single entity with the given.
+    // GET /api/0.6/[node|way|relation]/#id/relations
     loadEntityRelations: function(id2, callback) {
-      var type3 = osmEntity.id.type(id2);
+      var type2 = osmEntity.id.type(id2);
       var osmID = osmEntity.id.toOSM(id2);
       var options2 = { skipSeen: false };
       this.loadFromAPI(
-        "/api/0.6/" + type3 + "/" + osmID + "/relations.json",
+        "/api/0.6/" + type2 + "/" + osmID + "/relations.json",
         function(err, entities) {
           if (callback)
             callback(err, { data: entities });
@@ -71962,18 +74921,22 @@ ${content}</tr>
         options2
       );
     },
+    // Load multiple entities in chunks
+    // (note: callback may be called multiple times)
+    // Unlike `loadEntity`, child nodes and members are not fetched
+    // GET /api/0.6/[nodes|ways|relations]?#parameters
     loadMultiple: function(ids, callback) {
       var that = this;
       var groups = utilArrayGroupBy(utilArrayUniq(ids), osmEntity.id.type);
       Object.keys(groups).forEach(function(k) {
-        var type3 = k + "s";
+        var type2 = k + "s";
         var osmIDs = groups[k].map(function(id2) {
           return osmEntity.id.toOSM(id2);
         });
         var options2 = { skipSeen: false };
         utilArrayChunk(osmIDs, 150).forEach(function(arr) {
           that.loadFromAPI(
-            "/api/0.6/" + type3 + ".json?" + type3 + "=" + arr.join(),
+            "/api/0.6/" + type2 + ".json?" + type2 + "=" + arr.join(),
             function(err, entities) {
               if (callback)
                 callback(err, { data: entities });
@@ -71983,6 +74946,10 @@ ${content}</tr>
         });
       });
     },
+    // Create, upload, and close a changeset
+    // PUT /api/0.6/changeset/create
+    // POST /api/0.6/changeset/#id/upload
+    // PUT /api/0.6/changeset/#id/close
     putChangeset: function(changeset, changes, callback) {
       var cid = _connectionID;
       if (_changeset.inflight) {
@@ -72038,6 +75005,9 @@ ${content}</tr>
         }
       }
     },
+    // Load multiple users in chunks
+    // (note: callback may be called multiple times)
+    // GET /api/0.6/users?users=#id1,#id2,...,#idn
     loadUsers: function(uids, callback) {
       var toLoad = [];
       var cached = [];
@@ -72071,6 +75041,8 @@ ${content}</tr>
         }, options2);
       }
     },
+    // Load a given user by id
+    // GET /api/0.6/user/#id
     loadUser: function(uid, callback) {
       if (_userCache.user[uid] || !this.authenticated()) {
         delete _userCache.toLoad[uid];
@@ -72091,6 +75063,8 @@ ${content}</tr>
         }, options2);
       }
     },
+    // Load the details of the logged-in user
+    // GET /api/0.6/user/details
     userDetails: function(callback) {
       if (_userDetails) {
         return callback(void 0, _userDetails);
@@ -72111,6 +75085,8 @@ ${content}</tr>
         }, options2);
       }
     },
+    // Load previous changesets for the logged in user
+    // GET /api/0.6/changesets?user=#id
     userChangesets: function(callback) {
       if (_userChangesets) {
         return callback(void 0, _userChangesets);
@@ -72143,6 +75119,8 @@ ${content}</tr>
         return callback(void 0, _userChangesets);
       }
     },
+    // Fetch the status of the OSM API
+    // GET /api/capabilities
     status: function(callback) {
       var url = urlroot + "/api/capabilities";
       var errback = wrapcb(this, done, _connectionID);
@@ -72183,6 +75161,8 @@ ${content}</tr>
         }
       }
     },
+    // Calls `status` and dispatches an `apiStatusChange` event if the returned
+    // status differs from the cached status.
     reloadApiStatus: function() {
       if (!this.throttledReloadApiStatus) {
         var that = this;
@@ -72197,9 +75177,12 @@ ${content}</tr>
       }
       this.throttledReloadApiStatus();
     },
+    // Returns the maximum number of nodes a single way can have
     maxWayNodes: function() {
       return _maxWayNodes;
     },
+    // Load data (entities) from the API in tiles
+    // GET /api/0.6/map?bbox=
     loadTiles: function(projection2, callback) {
       if (_off)
         return;
@@ -72213,6 +75196,8 @@ ${content}</tr>
         this.loadTile(tile, callback);
       }, this);
     },
+    // Load a single data tile
+    // GET /api/0.6/map?bbox=
     loadTile: function(tile, callback) {
       if (_off)
         return;
@@ -72249,6 +75234,7 @@ ${content}</tr>
       var bbox2 = { minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1] };
       return _tileCache.rtree.collides(bbox2);
     },
+    // load the tile that covers the given `loc`
     loadTileAtLoc: function(loc, callback) {
       if (Object.keys(_tileCache.toLoad).length > 50)
         return;
@@ -72263,6 +75249,8 @@ ${content}</tr>
         this.loadTile(tile, callback);
       }, this);
     },
+    // Load notes from the API in tiles
+    // GET /api/0.6/notes?bbox=
     loadNotes: function(projection2, noteOptions) {
       noteOptions = Object.assign({ limit: 1e4, closed: 7 }, noteOptions);
       if (_off)
@@ -72296,6 +75284,8 @@ ${content}</tr>
         );
       });
     },
+    // Create a note
+    // POST /api/0.6/notes?params
     postNoteCreate: function(note, callback) {
       if (!this.authenticated()) {
         return callback({ message: "Not Authenticated", status: -3 }, note);
@@ -72330,6 +75320,10 @@ ${content}</tr>
         }, options2);
       }
     },
+    // Update a note
+    // POST /api/0.6/notes/#id/comment?text=comment
+    // POST /api/0.6/notes/#id/close?text=comment
+    // POST /api/0.6/notes/#id/reopen?text=comment
     postNoteUpdate: function(note, newStatus, callback) {
       if (!this.authenticated()) {
         return callback({ message: "Not Authenticated", status: -3 }, note);
@@ -72376,6 +75370,7 @@ ${content}</tr>
         }, options2);
       }
     },
+    /* connection options for source switcher (optional) */
     apiConnections: function(val) {
       if (!arguments.length)
         return _apiConnections;
@@ -72399,6 +75394,9 @@ ${content}</tr>
     isChangesetInflight: function() {
       return !!_changeset.inflight;
     },
+    // get/set cached data
+    // This is used to save/restore the state when entering/exiting the walkthrough
+    // Also used for testing purposes.
     caches: function(obj) {
       function cloneCache(source) {
         var target = {};
@@ -72488,6 +75486,7 @@ ${content}</tr>
       _tileZoom4 = val;
       return this;
     },
+    // get all cached notes covering the viewport
     notes: function(projection2) {
       var viewport = projection2.clipExtent();
       var min3 = [viewport[0][0], viewport[1][1]];
@@ -72497,15 +75496,18 @@ ${content}</tr>
         return d.data;
       });
     },
+    // get a single note from the cache
     getNote: function(id2) {
       return _noteCache.note[id2];
     },
+    // remove a single note from the cache
     removeNote: function(note) {
       if (!(note instanceof osmNote) || !note.id)
         return;
       delete _noteCache.note[note.id];
       updateRtree4(encodeNoteRtree(note), false);
     },
+    // replace a single note in the cache
     replaceNote: function(note) {
       if (!(note instanceof osmNote) || !note.id)
         return;
@@ -72513,6 +75515,8 @@ ${content}</tr>
       updateRtree4(encodeNoteRtree(note), true);
       return note;
     },
+    // Get an array of note IDs closed during this session.
+    // Used to populate `closed:note` changeset tag
     getClosedIDs: function() {
       return Object.keys(_noteCache.closed).sort();
     }
@@ -72553,6 +75557,12 @@ ${content}</tr>
       });
       _inflight2 = {};
     },
+    /**
+     * Get the best value for the property, or undefined if not found
+     * @param entity object from wikibase
+     * @param property string e.g. 'P4' for image
+     * @param langCode string e.g. 'fr' for French
+     */
     claimToValue: function(entity, property, langCode) {
       if (!entity.claims[property])
         return void 0;
@@ -72574,6 +75584,11 @@ ${content}</tr>
         return void 0;
       }
     },
+    /**
+     * Convert monolingual property into a key-value object (language -> value)
+     * @param entity object from wikibase
+     * @param property string e.g. 'P31' for monolingual wiki page title
+     */
     monolingualClaimToValueObj: function(entity, property) {
       if (!entity || !entity.claims[property])
         return void 0;
@@ -72587,6 +75602,14 @@ ${content}</tr>
       var result = value ? "Tag:" + key + "=" + value : "Key:" + key;
       return result.replace(/_/g, " ").trim();
     },
+    //
+    // Pass params object of the form:
+    // {
+    //   key: 'string',
+    //   value: 'string',
+    //   langCode: 'string'
+    // }
+    //
     getEntity: function(params, callback) {
       var doRequest = params.debounce ? debouncedRequest : request;
       var that = this;
@@ -72636,6 +75659,9 @@ ${content}</tr>
         languagefallback: 1,
         origin: "*",
         format: "json"
+        // There is an MW Wikibase API bug https://phabricator.wikimedia.org/T212069
+        // We shouldn't use v1 until it gets fixed, but should switch to it afterwards
+        // formatversion: 2,
       };
       var url = apibase3 + "?" + utilQsString(obj);
       doRequest(url, function(err, d) {
@@ -72673,6 +75699,22 @@ ${content}</tr>
         }
       });
     },
+    //
+    // Pass params object of the form:
+    // {
+    //   key: 'string',     // required
+    //   value: 'string'    // optional
+    // }
+    //
+    // Get an result object used to display tag documentation
+    // {
+    //   title:        'string',
+    //   description:  'string',
+    //   editURL:      'string',
+    //   imageURL:     'string',
+    //   wiki:         { title: 'string', text: 'string', url: 'string' }
+    // }
+    //
     getDocs: function(params, callback) {
       var that = this;
       var langCodes = _mainLocalizer.localeCodes().map(function(code) {
@@ -72884,7 +75926,7 @@ ${content}</tr>
       if (!bubbles)
         return;
       bubbles.shift();
-      const features2 = bubbles.map((bubble) => {
+      const features = bubbles.map((bubble) => {
         if (cache.points[bubble.id])
           return null;
         const loc = [bubble.lo, bubble.la];
@@ -72894,8 +75936,14 @@ ${content}</tr>
           ca: bubble.he,
           captured_at: bubble.cd,
           captured_by: "microsoft",
+          // nbn: bubble.nbn,
+          // pbn: bubble.pbn,
+          // ad: bubble.ad,
+          // rn: bubble.rn,
           pr: bubble.pr,
+          // previous
           ne: bubble.ne,
+          // next
           pano: true,
           sequenceKey: null
         };
@@ -72911,7 +75959,7 @@ ${content}</tr>
           data: d
         };
       }).filter(Boolean);
-      cache.rtree.load(features2);
+      cache.rtree.load(features);
       connectSequences();
       if (which === "bubbles") {
         dispatch8.call("loadedImages");
@@ -73394,12 +76442,18 @@ ${content}</tr>
     return quadKeys;
   }
   var streetside_default = {
+    /**
+     * init() initialize streetside.
+     */
     init: function() {
       if (!_ssCache) {
         this.reset();
       }
       this.event = utilRebind(this, dispatch8, "on");
     },
+    /**
+     * reset() reset the cache.
+     */
     reset: function() {
       if (_ssCache) {
         Object.values(_ssCache.bubbles.inflight).forEach(abortRequest6);
@@ -73409,6 +76463,9 @@ ${content}</tr>
         sequences: {}
       };
     },
+    /**
+     * bubbles()
+     */
     bubbles: function(projection2) {
       const limit = 5;
       return searchLimited3(limit, projection2, _ssCache.bubbles.rtree);
@@ -73432,6 +76489,9 @@ ${content}</tr>
       });
       return results;
     },
+    /**
+     * loadBubbles()
+     */
     loadBubbles: function(projection2, margin) {
       if (margin === void 0)
         margin = 2;
@@ -73565,6 +76625,9 @@ ${content}</tr>
       _sceneOptions.yaw = yaw;
       return this;
     },
+    /**
+     * showViewer()
+     */
     showViewer: function(context) {
       let wrap2 = context.container().select(".photoviewer").classed("hide", false);
       let isHidden = wrap2.selectAll(".photo-wrapper.ms-wrapper.hide").size();
@@ -73574,6 +76637,9 @@ ${content}</tr>
       }
       return this;
     },
+    /**
+     * hideViewer()
+     */
     hideViewer: function(context) {
       let viewer = context.container().select(".photoviewer");
       if (!viewer.empty())
@@ -73583,6 +76649,9 @@ ${content}</tr>
       this.updateUrlImage(null);
       return this.setStyles(context, null, true);
     },
+    /**
+     * selectImage().
+     */
     selectImage: function(context, key) {
       let that = this;
       let d = this.cachedImage(key);
@@ -73616,7 +76685,7 @@ ${content}</tr>
       label.append("span").call(_t.append("streetside.hires"));
       let captureInfo = line1.append("div").attr("class", "attribution-capture-info");
       if (d.captured_by) {
-        const yyyy = new Date().getFullYear();
+        const yyyy = (/* @__PURE__ */ new Date()).getFullYear();
         captureInfo.append("a").attr("class", "captured_by").attr("target", "_blank").attr("href", "https://www.microsoft.com/en-us/maps/streetside").text("\xA9" + yyyy + " Microsoft");
         captureInfo.append("span").text("|");
       }
@@ -73632,7 +76701,7 @@ ${content}</tr>
         bubbleIdQuadKey = "0" + bubbleIdQuadKey;
       }
       const imgUrlPrefix = streetsideImagesApi + "hs" + bubbleIdQuadKey;
-      const imgUrlSuffix = ".jpg?g=6338&n=z";
+      const imgUrlSuffix = ".jpg?g=13515&n=z";
       const faceKeys = ["01", "02", "03", "10", "11", "12"];
       let quadKeys = getQuadKeys();
       let faces = faceKeys.map((faceKey) => {
@@ -73664,6 +76733,9 @@ ${content}</tr>
     getSequenceKeyForBubble: function(d) {
       return d && d.sequenceKey;
     },
+    // Updates the currently highlighted sequence and selected bubble.
+    // Reset is only necessary when interacting with the viewport because
+    // this implicitly changes the currently selected bubble/sequence
     setStyles: function(context, hovered, reset) {
       if (reset) {
         context.container().selectAll(".viewfield-group").classed("highlighted", false).classed("hovered", false).classed("currentView", false);
@@ -73704,6 +76776,9 @@ ${content}</tr>
         window.location.replace("#" + utilQsString(hash, true));
       }
     },
+    /**
+     * cache().
+     */
     cache: function() {
       return _ssCache;
     }
@@ -73758,10 +76833,10 @@ ${content}</tr>
   function clean(params) {
     return utilObjectOmit(params, ["geometry", "debounce"]);
   }
-  function filterKeys(type3) {
-    var count_type = type3 ? "count_" + type3 : "count_all";
+  function filterKeys(type2) {
+    var count_type = type2 ? "count_" + type2 : "count_all";
     return function(d) {
-      return parseFloat(d[count_type]) > 2500 || d.in_wiki;
+      return Number(d[count_type]) > 2500 || d.in_wiki;
     };
   }
   function filterMultikeys(prefix) {
@@ -73786,7 +76861,7 @@ ${content}</tr>
         return false;
       if (d.role.match(/[A-Z*;,]/) !== null)
         return false;
-      return parseFloat(d[tag_members_fractions[geometry]]) > 0;
+      return Number(d[tag_members_fractions[geometry]]) > 0;
     };
   }
   function valKey(d) {
@@ -73853,6 +76928,7 @@ ${content}</tr>
       _inflight3 = {};
       _taginfoCache = {};
       _popularKeys = {
+        // manually exclude some keys – #5377, #7485
         postal_code: true,
         full_name: true,
         loc_name: true,
@@ -73954,8 +77030,7 @@ ${content}</tr>
         if (err) {
           callback(err);
         } else {
-          var re2 = /network|taxon|genus|species|brand|grape_variety|royal_cypher|listed_status|booth|rating|stars|:output|_hours|_times|_ref|manufacturer|country|target|brewery|cai_scale/;
-          var allowUpperCase = re2.test(params.key);
+          var allowUpperCase = allowUpperCaseTagValues.test(params.key);
           var f2 = filterValues(allowUpperCase);
           var result = d.data.filter(f2).map(valKeyDescription);
           _taginfoCache[url] = result;
@@ -74031,7 +77106,7 @@ ${content}</tr>
     if (!Array.isArray(layers)) {
       layers = [layers];
     }
-    var features2 = [];
+    var features = [];
     layers.forEach(function(layerID) {
       var layer = vectorTile.layers[layerID];
       if (layer) {
@@ -74058,7 +77133,7 @@ ${content}</tr>
           feature3.__layerID__ = layerID.replace(/[^_a-zA-Z0-9\-]/g, "_");
           feature3.__featurehash__ = featurehash;
           feature3.__propertyhash__ = propertyhash;
-          features2.push(feature3);
+          features.push(feature3);
           if (isClipped && geometry.type === "MultiPolygon") {
             var merged = mergeCache[propertyhash];
             if (merged && merged.length) {
@@ -74082,7 +77157,7 @@ ${content}</tr>
         }
       }
     });
-    return features2;
+    return features;
   }
   function loadTile2(source, tile) {
     if (source.loaded[tile.id] || source.inflight[tile.id])
@@ -74143,11 +77218,11 @@ ${content}</tr>
       var seen = {};
       var results = [];
       for (var i2 = 0; i2 < tiles.length; i2++) {
-        var features2 = source.loaded[tiles[i2].id];
-        if (!features2 || !features2.length)
+        var features = source.loaded[tiles[i2].id];
+        if (!features || !features.length)
           continue;
-        for (var j2 = 0; j2 < features2.length; j2++) {
-          var feature3 = features2[j2];
+        for (var j2 = 0; j2 < features.length; j2++) {
+          var feature3 = features[j2];
           var hash = feature3.__featurehash__;
           if (seen[hash])
             continue;
@@ -74190,7 +77265,8 @@ ${content}</tr>
     reset: function() {
       _wikidataCache = {};
     },
-    itemsForSearchQuery: function(query, callback) {
+    // Search for Wikidata items matching the query
+    itemsForSearchQuery: function(query, callback, language) {
       if (!query) {
         if (callback)
           callback("No query", {});
@@ -74203,14 +77279,21 @@ ${content}</tr>
         formatversion: 2,
         search: query,
         type: "item",
-        language: lang,
+        // the language to search
+        language: language || lang,
+        // the language for the label and description in the result
         uselang: lang,
         limit: 10,
         origin: "*"
       });
-      json_default(url).then(function(result) {
+      json_default(url).then((result) => {
         if (result && result.error) {
-          throw new Error(result.error);
+          if (result.error.code === "badvalue" && result.error.info.includes(lang) && !language && lang.includes("-")) {
+            this.itemsForSearchQuery(query, callback, lang.split("-")[0]);
+            return;
+          } else {
+            throw new Error(result.error);
+          }
         }
         if (callback)
           callback(null, result.search || {});
@@ -74219,6 +77302,8 @@ ${content}</tr>
           callback(err.message, {});
       });
     },
+    // Given a Wikipedia language and article title,
+    // return an array of corresponding Wikidata entities.
     itemsByTitle: function(lang, title, callback) {
       if (!title) {
         if (callback)
@@ -74233,6 +77318,7 @@ ${content}</tr>
         sites: lang.replace(/-/g, "_") + "wiki",
         titles: title,
         languages: "en",
+        // shrink response by filtering to one language
         origin: "*"
       });
       json_default(url).then(function(result) {
@@ -74288,6 +77374,20 @@ ${content}</tr>
           callback(err.message, {});
       });
     },
+    // Pass `params` object of the form:
+    // {
+    //   qid: 'string'      // brand wikidata  (e.g. 'Q37158')
+    // }
+    //
+    // Get an result object used to display tag documentation
+    // {
+    //   title:        'string',
+    //   description:  'string',
+    //   editURL:      'string',
+    //   imageURL:     'string',
+    //   wiki:         { title: 'string', text: 'string', url: 'string' }
+    // }
+    //
     getDocs: function(params, callback) {
       var langs = this.languagesToQuery();
       this.entityByQID(params.qid, function(err, entity) {
@@ -74630,7 +77730,8 @@ ${content}</tr>
         if (activeNode && (/* @__PURE__ */ new Set(["INPUT", "TEXTAREA"])).has(activeNode.nodeName))
           return;
       }
-      if (d3_event.keyCode === 93 || d3_event.keyCode === 32) {
+      if (d3_event.keyCode === 93 || // context menu key
+      d3_event.keyCode === 32) {
         d3_event.preventDefault();
       }
       if (d3_event.repeat)
@@ -74741,7 +77842,12 @@ ${content}</tr>
         }
       } else {
         _lastMouseEvent = d3_event;
-        _lastInteractionType = "rightclick";
+        if (d3_event.pointerType === "touch" || d3_event.pointerType === "pen" || d3_event.mozInputSource && // firefox doesn't give a pointerType on contextmenu events
+        (d3_event.mozInputSource === MouseEvent.MOZ_SOURCE_TOUCH || d3_event.mozInputSource === MouseEvent.MOZ_SOURCE_PEN)) {
+          _lastInteractionType = "touch";
+        } else {
+          _lastInteractionType = "rightclick";
+        }
       }
       _showMenu = true;
       click(d3_event, d3_event);
@@ -74767,7 +77873,10 @@ ${content}</tr>
           _downPointers[selectPointerInfo.pointerId].done = true;
         }
       }
-      var isMultiselect = context.mode().id === "select" && (lastEvent && lastEvent.shiftKey || context.surface().select(".lasso").node() || _multiselectionPointerId && !multiselectEntityId);
+      var isMultiselect = context.mode().id === "select" && // and shift key is down
+      (lastEvent && lastEvent.shiftKey || // or we're lasso-selecting
+      context.surface().select(".lasso").node() || // or a pointer is down over a selected feature
+      _multiselectionPointerId && !multiselectEntityId);
       processClick(targetDatum, isMultiselect, p2, multiselectEntityId);
       function mapContains(event) {
         var rect = mapNode.getBoundingClientRect();
@@ -75240,17 +78349,17 @@ ${content}</tr>
       _affectedFeatureCount = 0;
       for (var i2 in entityIds) {
         var entityID = entityIds[i2];
-        var type3 = downgradeTypeForEntityID(entityID);
-        if (type3) {
+        var type2 = downgradeTypeForEntityID(entityID);
+        if (type2) {
           _affectedFeatureCount += 1;
-          if (downgradeType && type3 !== downgradeType) {
-            if (downgradeType !== "generic" && type3 !== "generic") {
+          if (downgradeType && type2 !== downgradeType) {
+            if (downgradeType !== "generic" && type2 !== "generic") {
               downgradeType = "building_address";
             } else {
               downgradeType = "generic";
             }
           } else {
-            downgradeType = type3;
+            downgradeType = type2;
           }
         }
       }
@@ -75282,18 +78391,18 @@ ${content}</tr>
       context.perform(function(graph) {
         for (var i2 in selectedIDs) {
           var entityID = selectedIDs[i2];
-          var type3 = downgradeTypeForEntityID(entityID);
-          if (!type3)
+          var type2 = downgradeTypeForEntityID(entityID);
+          if (!type2)
             continue;
           var tags = Object.assign({}, graph.entity(entityID).tags);
           for (var key in tags) {
-            if (type3 === "address" && addressKeysToKeep.indexOf(key) !== -1)
+            if (type2 === "address" && addressKeysToKeep.indexOf(key) !== -1)
               continue;
-            if (type3 === "building") {
+            if (type2 === "building") {
               if (buildingKeysToKeep.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/))
                 continue;
             }
-            if (type3 !== "generic") {
+            if (type2 !== "generic") {
               if (key.match(/^addr:.{1,}/) || key.match(/^source:.{1,}/))
                 continue;
             }
@@ -75413,9 +78522,9 @@ ${content}</tr>
       var join = actionJoin(selectedIDs);
       if (!join.disabled(context.graph()))
         return join;
-      var merge3 = actionMerge(selectedIDs);
-      if (!merge3.disabled(context.graph()))
-        return merge3;
+      var merge2 = actionMerge(selectedIDs);
+      if (!merge2.disabled(context.graph()))
+        return merge2;
       var mergePolygon = actionMergePolygon(selectedIDs);
       if (!mergePolygon.disabled(context.graph()))
         return mergePolygon;
@@ -75424,8 +78533,8 @@ ${content}</tr>
         return mergeNodes;
       if (join.disabled(context.graph()) !== "not_eligible")
         return join;
-      if (merge3.disabled(context.graph()) !== "not_eligible")
-        return merge3;
+      if (merge2.disabled(context.graph()) !== "not_eligible")
+        return merge2;
       if (mergePolygon.disabled(context.graph()) !== "not_eligible")
         return mergePolygon;
       return mergeNodes;
@@ -75931,6 +79040,7 @@ ${content}</tr>
       }).filter(function(o) {
         return o.id !== "delete" && o.id !== "downgrade" && o.id !== "copy";
       }).concat([
+        // group copy/downgrade/delete operation together at the end of the list
         operationCopy(context, selectedIDs),
         operationDowngrade(context, selectedIDs),
         operationDelete(context, selectedIDs)
@@ -76102,7 +79212,12 @@ ${content}</tr>
           surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed("related", true);
         }
         if (context.map().withinEditableZoom()) {
-          surface.selectAll(utilDeepMemberSelector(selectedIDs, context.graph(), true)).classed("selected-member", true);
+          surface.selectAll(utilDeepMemberSelector(
+            selectedIDs,
+            context.graph(),
+            true
+            /* skipMultipolgonMembers */
+          )).classed("selected-member", true);
           surface.selectAll(utilEntityOrDeepMemberSelector(selectedIDs, context.graph())).classed("selected", true);
         }
       }
@@ -76250,8 +79365,15 @@ ${content}</tr>
       context.ui().sidebar.hide();
       context.features().forceVisible([]);
       var entity = singular();
-      if (_newFeature && entity && entity.type === "relation" && Object.keys(entity.tags).length === 0 && context.graph().parentRelations(entity).length === 0 && (entity.members.length === 0 || entity.members.length === 1 && !entity.members[0].role)) {
-        var deleteAction = actionDeleteRelation(entity.id, true);
+      if (_newFeature && entity && entity.type === "relation" && // no tags
+      Object.keys(entity.tags).length === 0 && // no parent relations
+      context.graph().parentRelations(entity).length === 0 && // no members or one member with no role
+      (entity.members.length === 0 || entity.members.length === 1 && !entity.members[0].role)) {
+        var deleteAction = actionDeleteRelation(
+          entity.id,
+          true
+          /* don't delete untagged members */
+        );
         context.perform(deleteAction, _t("operations.delete.annotation.relation"));
         context.validator().validate();
       }
@@ -76290,7 +79412,10 @@ ${content}</tr>
           return [];
         var graph = context.graph();
         var limitToNodes;
-        if (context.map().editableDataEnabled(true) && context.map().isInWideSelection()) {
+        if (context.map().editableDataEnabled(
+          true
+          /* skipZoomCheck */
+        ) && context.map().isInWideSelection()) {
           limitToNodes = new Set(utilGetAllNodes(context.selectedIDs(), graph));
         } else if (!context.map().editableDataEnabled()) {
           return [];
@@ -76309,7 +79434,7 @@ ${content}</tr>
               var sharedParentNodes = sharedParents[0].nodes;
               return sharedParentNodes.indexOf(node1.id) - sharedParentNodes.indexOf(node2.id);
             } else {
-              return parseFloat(parents1[0].id.slice(1)) - parseFloat(parents2[0].id.slice(1));
+              return Number(parents1[0].id.slice(1)) - Number(parents2[0].id.slice(1));
             }
           } else if (parents1.length || parents2.length) {
             return parents1.length - parents2.length;
@@ -76500,8 +79625,14 @@ ${content}</tr>
       var latestHash = computedHash();
       if (_cachedHash !== latestHash) {
         _cachedHash = latestHash;
-        window.history.replaceState(null, computedTitle(false), latestHash);
-        updateTitle(true);
+        window.history.replaceState(null, computedTitle(
+          false
+          /* includeChangeCount */
+        ), latestHash);
+        updateTitle(
+          true
+          /* includeChangeCount */
+        );
         const q = utilStringQs(latestHash);
         if (q.map) {
           corePreferences("map-location", q.map);
@@ -76510,7 +79641,10 @@ ${content}</tr>
     }
     var _throttledUpdate = throttle_default(updateHashIfNeeded, 500);
     var _throttledUpdateTitle = throttle_default(function() {
-      updateTitle(true);
+      updateTitle(
+        true
+        /* includeChangeCount */
+      );
     }, 500);
     function hashchange() {
       if (window.location.hash === _cachedHash)
@@ -76587,7 +79721,7 @@ ${content}</tr>
   }
   var X = {
     name: "x",
-    handles: ["w", "e"].map(type2),
+    handles: ["w", "e"].map(type),
     input: function(x, e) {
       return x == null ? null : [[+x[0], e[0][1]], [+x[1], e[1][1]]];
     },
@@ -76597,7 +79731,7 @@ ${content}</tr>
   };
   var Y = {
     name: "y",
-    handles: ["n", "s"].map(type2),
+    handles: ["n", "s"].map(type),
     input: function(y, e) {
       return y == null ? null : [[e[0][0], +y[0]], [e[1][0], +y[1]]];
     },
@@ -76607,7 +79741,7 @@ ${content}</tr>
   };
   var XY = {
     name: "xy",
-    handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(type2),
+    handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(type),
     input: function(xy) {
       return xy == null ? null : number22(xy);
     },
@@ -76615,7 +79749,7 @@ ${content}</tr>
       return xy;
     }
   };
-  function type2(t) {
+  function type(t) {
     return { type: t };
   }