]> git.openstreetmap.org Git - rails.git/blobdiff - vendor/assets/iD/iD.js
Update Potlatch 2 to 2.3-645-g81e8bcb build
[rails.git] / vendor / assets / iD / iD.js
index e71d245835b0625f19eade0aaf4aaf9c7db91698..11c3eb29ba1371f42429a41988249deac01098f3 100644 (file)
@@ -6100,8 +6100,12 @@ d3.combobox = function() {
                         // on mousedown
                         d3.event.stopPropagation();
                         d3.event.preventDefault();
-                        input.node().focus();
-                        fetch('', render);
+                        if (!shown) {
+                            input.node().focus();
+                            fetch('', render);
+                        } else {
+                            hide();
+                        }
                     });
             });
 
@@ -7050,7 +7054,7 @@ var JXON = new (function () {
 /**
  * @license
  * Lo-Dash 2.3.0 (Custom Build) <http://lodash.com/>
- * Build: `lodash include="any,assign,bind,clone,compact,contains,debounce,difference,each,every,extend,filter,find,first,forEach,groupBy,indexOf,intersection,isEmpty,isEqual,isFunction,keys,last,map,omit,pairs,pluck,reject,some,throttle,union,uniq,unique,values,without,flatten,value,chain,cloneDeep,merge" exports="global,node"`
+ * Build: `lodash --debug --output js/lib/lodash.js include="any,assign,bind,clone,compact,contains,debounce,difference,each,every,extend,filter,find,first,forEach,groupBy,indexOf,intersection,isEmpty,isEqual,isFunction,keys,last,map,omit,pairs,pluck,reject,some,throttle,union,uniq,unique,values,without,flatten,value,chain,cloneDeep,merge,pick,reduce" exports="global,node"`
  * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
  * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
  * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
@@ -9353,6 +9357,57 @@ var JXON = new (function () {
     return result;
   }
 
+  /**
+   * Creates a shallow clone of `object` composed of the specified properties.
+   * Property names may be specified as individual arguments or as arrays of
+   * property names. If a callback is provided it will be executed for each
+   * property of `object` picking the properties the callback returns truey
+   * for. The callback is bound to `thisArg` and invoked with three arguments;
+   * (value, key, object).
+   *
+   * @static
+   * @memberOf _
+   * @category Objects
+   * @param {Object} object The source object.
+   * @param {Function|...string|string[]} [callback] The function called per
+   *  iteration or property names to pick, specified as individual property
+   *  names or arrays of property names.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {Object} Returns an object composed of the picked properties.
+   * @example
+   *
+   * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
+   * // => { 'name': 'fred' }
+   *
+   * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
+   *   return key.charAt(0) != '_';
+   * });
+   * // => { 'name': 'fred' }
+   */
+  function pick(object, callback, thisArg) {
+    var result = {};
+    if (typeof callback != 'function') {
+      var index = -1,
+          props = baseFlatten(arguments, true, false, 1),
+          length = isObject(object) ? props.length : 0;
+
+      while (++index < length) {
+        var key = props[index];
+        if (key in object) {
+          result[key] = object[key];
+        }
+      }
+    } else {
+      callback = lodash.createCallback(callback, thisArg, 3);
+      forIn(object, function(value, key, object) {
+        if (callback(value, key, object)) {
+          result[key] = value;
+        }
+      });
+    }
+    return result;
+  }
+
   /**
    * Creates an array composed of the own enumerable property values of `object`.
    *
@@ -9782,6 +9837,60 @@ var JXON = new (function () {
    */
   var pluck = map;
 
+  /**
+   * Reduces a collection to a value which is the accumulated result of running
+   * each element in the collection through the callback, where each successive
+   * callback execution consumes the return value of the previous execution. If
+   * `accumulator` is not provided the first element of the collection will be
+   * used as the initial `accumulator` value. The callback is bound to `thisArg`
+   * and invoked with four arguments; (accumulator, value, index|key, collection).
+   *
+   * @static
+   * @memberOf _
+   * @alias foldl, inject
+   * @category Collections
+   * @param {Array|Object|string} collection The collection to iterate over.
+   * @param {Function} [callback=identity] The function called per iteration.
+   * @param {*} [accumulator] Initial value of the accumulator.
+   * @param {*} [thisArg] The `this` binding of `callback`.
+   * @returns {*} Returns the accumulated value.
+   * @example
+   *
+   * var sum = _.reduce([1, 2, 3], function(sum, num) {
+   *   return sum + num;
+   * });
+   * // => 6
+   *
+   * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
+   *   result[key] = num * 3;
+   *   return result;
+   * }, {});
+   * // => { 'a': 3, 'b': 6, 'c': 9 }
+   */
+  function reduce(collection, callback, accumulator, thisArg) {
+    var noaccum = arguments.length < 3;
+    callback = lodash.createCallback(callback, thisArg, 4);
+
+    if (isArray(collection)) {
+      var index = -1,
+          length = collection.length;
+
+      if (noaccum) {
+        accumulator = collection[++index];
+      }
+      while (++index < length) {
+        accumulator = callback(accumulator, collection[index], index, collection);
+      }
+    } else {
+      baseEach(collection, function(value, index, collection) {
+        accumulator = noaccum
+          ? (noaccum = false, value)
+          : callback(accumulator, value, index, collection)
+      });
+    }
+    return accumulator;
+  }
+
   /**
    * The opposite of `_.filter` this method returns the elements of a
    * collection that the callback does **not** return truey for.
@@ -10879,6 +10988,7 @@ var JXON = new (function () {
   lodash.merge = merge;
   lodash.omit = omit;
   lodash.pairs = pairs;
+  lodash.pick = pick;
   lodash.pluck = pluck;
   lodash.reject = reject;
   lodash.throttle = throttle;
@@ -10918,6 +11028,7 @@ var JXON = new (function () {
   lodash.isString = isString;
   lodash.mixin = mixin;
   lodash.noop = noop;
+  lodash.reduce = reduce;
   lodash.some = some;
   lodash.sortedIndex = sortedIndex;
 
@@ -10926,7 +11037,9 @@ var JXON = new (function () {
   lodash.any = some;
   lodash.detect = find;
   lodash.findWhere = find;
+  lodash.foldl = reduce;
   lodash.include = contains;
+  lodash.inject = reduce;
 
   forOwn(lodash, function(func, methodName) {
     if (!lodash.prototype[methodName]) {
@@ -14606,7 +14719,79 @@ if (typeof define === 'function' && define.amd) {
 }
 
 })();
-toGeoJSON = (function() {
+(function(e){if("function"==typeof bootstrap)bootstrap("sexagesimal",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeSexagesimal=e}else"undefined"!=typeof window?window.sexagesimal=e():global.sexagesimal=e()})(function(){var define,ses,bootstrap,module,exports;
+return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+module.exports = element;
+module.exports.pair = pair;
+module.exports.format = format;
+module.exports.formatPair = formatPair;
+
+function element(x, dims) {
+    return search(x, dims).val;
+}
+
+function formatPair(x) {
+    return format(x.lat, 'lat') + ' ' + format(x.lon, 'lon');
+}
+
+// Is 0 North or South?
+function format(x, dim) {
+    var dirs = {
+            lat: ['N', 'S'],
+            lon: ['E', 'W']
+        }[dim] || '',
+        dir = dirs[x >= 0 ? 0 : 1],
+        abs = Math.abs(x),
+        whole = Math.floor(abs),
+        fraction = abs - whole,
+        fractionMinutes = fraction * 60,
+        minutes = Math.floor(fractionMinutes),
+        seconds = Math.floor((fractionMinutes - minutes) * 60);
+
+    return whole + '° ' +
+        (minutes ? minutes + "' " : '') +
+        (seconds ? seconds + '" ' : '') + dir;
+}
+
+function search(x, dims, r) {
+    if (!dims) dims = 'NSEW';
+    if (typeof x !== 'string') return { val: null, regex: r };
+    r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
+    var m = r.exec(x);
+    if (!m) return { val: null, regex: r };
+    else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
+    else return {
+        val: (((m[1]) ? parseFloat(m[1]) : 0) +
+            ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
+            ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
+            ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
+        regex: r,
+        raw: m[0],
+        dim: m[4]
+    };
+}
+
+function pair(x, dims) {
+    x = x.trim();
+    var one = search(x, dims);
+    if (one.val === null) return null;
+    var two = search(x, dims, one.regex);
+    if (two.val === null) return null;
+    // null if one/two are not contiguous.
+    if (one.raw + two.raw !== x) return null;
+    if (one.dim) return swapdim(one.val, two.val, one.dim);
+    else return [one.val, two.val];
+}
+
+function swapdim(a, b, dim) {
+    if (dim == 'N' || dim == 'S') return [a, b];
+    if (dim == 'W' || dim == 'E') return [b, a];
+}
+
+},{}]},{},[1])
+(1)
+});
+;toGeoJSON = (function() {
     'use strict';
 
     var removeSpace = (/\s*/g),
@@ -16158,52 +16343,7 @@ window.iD = function () {
     };
 
     /* Projection */
-    function rawMercator() {
-        var project = d3.geo.mercator.raw,
-            k = 512 / Math.PI, // scale
-            x = 0, y = 0, // translate
-            clipExtent = [[0, 0], [0, 0]];
-
-        function projection(point) {
-            point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
-            return [point[0] * k + x, y - point[1] * k];
-        }
-
-        projection.invert = function(point) {
-            point = project.invert((point[0] - x) / k, (y - point[1]) / k);
-            return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
-        };
-
-        projection.scale = function(_) {
-            if (!arguments.length) return k;
-            k = +_;
-            return projection;
-        };
-
-        projection.translate = function(_) {
-            if (!arguments.length) return [x, y];
-            x = +_[0];
-            y = +_[1];
-            return projection;
-        };
-
-        projection.clipExtent = function(_) {
-            if (!arguments.length) return clipExtent;
-            clipExtent = _;
-            return projection;
-        };
-
-        projection.stream = d3.geo.transform({
-            point: function(x, y) {
-                x = projection([x, y]);
-                this.stream.point(x[0], x[1]);
-            }
-        }).stream;
-
-        return projection;
-    }
-
-    context.projection = rawMercator();
+    context.projection = iD.geo.RawMercator();
 
     /* Background */
     var background = iD.Background(context);
@@ -16271,7 +16411,7 @@ window.iD = function () {
     return d3.rebind(context, dispatch, 'on');
 };
 
-iD.version = '1.3.10';
+iD.version = '1.5.4';
 
 (function() {
     var detected = {};
@@ -16305,6 +16445,44 @@ iD.version = '1.3.10';
 
     iD.detect = function() { return detected; };
 })();
+iD.countryCode  = function() {
+    var countryCode = {},
+        endpoint = 'https://nominatim.openstreetmap.org/reverse?';
+
+    if (!iD.countryCode.cache) {
+        iD.countryCode.cache = rbush();
+    }
+
+    var cache = iD.countryCode.cache;
+
+    countryCode.search = function(location, callback) {
+        var countryCodes = cache.search([location[0], location[1], location[0], location[1]]);
+
+        if (countryCodes.length > 0)
+            return callback(null, countryCodes[0][4]);
+
+        d3.json(endpoint +
+            iD.util.qsString({
+                format: 'json',
+                addressdetails: 1,
+                lat: location[1],
+                lon: location[0]
+            }), function(err, result) {
+                if (err)
+                    return callback(err);
+                else if (result && result.error)
+                    return callback(result.error);
+
+                var extent = iD.geo.Extent(location).padByMeters(1000);
+
+                cache.insert([extent[0][0], extent[0][1], extent[1][0], extent[1][1], result.address.country_code]);
+
+                callback(null, result.address.country_code);
+            });
+    };
+
+    return countryCode;
+};
 iD.taginfo = function() {
     var taginfo = {},
         endpoint = 'https://taginfo.openstreetmap.org/api/4/',
@@ -16754,11 +16932,38 @@ iD.geo.euclideanDistance = function(a, b) {
     var x = a[0] - b[0], y = a[1] - b[1];
     return Math.sqrt((x * x) + (y * y));
 };
+
+// using WGS84 polar radius (6356752.314245179 m)
+// const = 2 * PI * r / 360
+iD.geo.latToMeters = function(dLat) {
+    return dLat * 110946.257617;
+};
+
+// using WGS84 equatorial radius (6378137.0 m)
+// const = 2 * PI * r / 360
+iD.geo.lonToMeters = function(dLon, atLat) {
+    return Math.abs(atLat) >= 90 ? 0 :
+        dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
+};
+
+// using WGS84 polar radius (6356752.314245179 m)
+// const = 2 * PI * r / 360
+iD.geo.metersToLat = function(m) {
+    return m / 110946.257617;
+};
+
+// using WGS84 equatorial radius (6378137.0 m)
+// const = 2 * PI * r / 360
+iD.geo.metersToLon = function(m, atLat) {
+    return Math.abs(atLat) >= 90 ? 0 :
+        m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
+};
+
 // Equirectangular approximation of spherical distances on Earth
 iD.geo.sphericalDistance = function(a, b) {
-    var x = Math.cos(a[1]*Math.PI/180) * (a[0] - b[0]),
-        y = a[1] - b[1];
-    return 6.3710E6 * Math.sqrt((x * x) + (y * y)) * Math.PI/180;
+    var x = iD.geo.lonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
+        y = iD.geo.latToMeters(a[1] - b[1]);
+    return Math.sqrt((x * x) + (y * y));
 };
 
 iD.geo.edgeEqual = function(a, b) {
@@ -16766,6 +16971,14 @@ iD.geo.edgeEqual = function(a, b) {
         (a[0] === b[1] && a[1] === b[0]);
 };
 
+// Return the counterclockwise angle in the range (-pi, pi)
+// between the positive X axis and the line intersecting a and b.
+iD.geo.angle = function(a, b, projection) {
+    a = projection(a.loc);
+    b = projection(b.loc);
+    return Math.atan2(b[1] - a[1], b[0] - a[0]);
+};
+
 // Choose the edge with the minimal distance from `point` to its orthogonal
 // projection onto that edge, if such a projection exists, or the distance to
 // the closest vertex on that edge. Returns an object with the `index` of the
@@ -16812,6 +17025,39 @@ iD.geo.chooseEdge = function(nodes, point, projection) {
     };
 };
 
+// Return the intersection point of 2 line segments.
+// From https://github.com/pgkelley4/line-segments-intersect
+// This uses the vector cross product approach described below:
+//  http://stackoverflow.com/a/565282/786339
+iD.geo.lineIntersection = function(a, b) {
+    function subtractPoints(point1, point2) {
+        return [point1[0] - point2[0], point1[1] - point2[1]];
+    }
+    function crossProduct(point1, point2) {
+        return point1[0] * point2[1] - point1[1] * point2[0];
+    }
+
+    var p = [a[0][0], a[0][1]],
+        p2 = [a[1][0], a[1][1]],
+        q = [b[0][0], b[0][1]],
+        q2 = [b[1][0], b[1][1]],
+        r = subtractPoints(p2, p),
+        s = subtractPoints(q2, q),
+        uNumerator = crossProduct(subtractPoints(q, p), r),
+        denominator = crossProduct(r, s);
+
+    if (uNumerator && denominator) {
+        var u = uNumerator / denominator,
+            t = crossProduct(subtractPoints(q, p), s) / denominator;
+
+        if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
+            return iD.geo.interp(p, p2, t);
+        }
+    }
+
+    return null;
+};
+
 // Return whether point is contained in polygon.
 //
 // `point` should be a 2-item array of coordinates.
@@ -16919,9 +17165,21 @@ _.extend(iD.geo.Extent.prototype, {
                                   Math.min(obj[1][1], this[1][1])]);
     },
 
+    percentContainedIn: function(obj) {
+        if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
+        var a1 = this.intersection(obj).area(),
+            a2 = this.area();
+
+        if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
+            return 0;
+        } else {
+            return a1 / a2;
+        }
+    },
+
     padByMeters: function(meters) {
-        var dLat = meters / 111200,
-            dLon = meters / 111200 / Math.abs(Math.cos(this.center()[1]));
+        var dLat = iD.geo.metersToLat(meters),
+            dLon = iD.geo.metersToLon(meters, this.center()[1]);
         return iD.geo.Extent(
                 [this[0][0] - dLon, this[0][1] - dLat],
                 [this[1][0] + dLon, this[1][1] + dLat]);
@@ -16930,7 +17188,148 @@ _.extend(iD.geo.Extent.prototype, {
     toParam: function() {
         return [this[0][0], this[0][1], this[1][0], this[1][1]].join(',');
     }
+
 });
+iD.geo.Turn = function(turn) {
+    if (!(this instanceof iD.geo.Turn))
+        return new iD.geo.Turn(turn);
+    _.extend(this, turn);
+};
+
+iD.geo.Intersection = function(graph, vertexId) {
+    var vertex = graph.entity(vertexId),
+        highways = [];
+
+    // Pre-split ways that would need to be split in
+    // order to add a restriction. The real split will
+    // happen when the restriction is added.
+    graph.parentWays(vertex).forEach(function(way) {
+        if (!way.tags.highway || way.isArea() || way.isDegenerate())
+            return;
+
+        if (way.affix(vertexId)) {
+            highways.push(way);
+        } else {
+            var idx = _.indexOf(way.nodes, vertex.id, 1),
+                wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, idx + 1)}),
+                wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(idx)});
+
+            graph = graph.replace(wayA);
+            graph = graph.replace(wayB);
+
+            highways.push(wayA);
+            highways.push(wayB);
+        }
+    });
+
+    var intersection = {
+        highways: highways,
+        graph: graph
+    };
+
+    intersection.turns = function(fromNodeID) {
+        if (!fromNodeID)
+            return [];
+
+        var way = _.find(highways, function(way) { return way.contains(fromNodeID); });
+        if (way.first() === vertex.id && way.tags.oneway === 'yes')
+            return [];
+        if (way.last() === vertex.id && way.tags.oneway === '-1')
+            return [];
+
+        function withRestriction(turn) {
+            graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
+                if (relation.tags.type !== 'restriction')
+                    return;
+
+                var f = relation.memberByRole('from'),
+                    t = relation.memberByRole('to'),
+                    v = relation.memberByRole('via');
+
+                if (f && f.id === turn.from.way &&
+                    v && v.id === turn.via.node &&
+                    t && t.id === turn.to.way) {
+                    turn.restriction = relation.id;
+                } else if (/^only_/.test(relation.tags.restriction) &&
+                    f && f.id === turn.from.way &&
+                    v && v.id === turn.via.node &&
+                    t && t.id !== turn.to.way) {
+                    turn.restriction = relation.id;
+                    turn.indirect_restriction = true;
+                }
+            });
+
+            return iD.geo.Turn(turn);
+        }
+
+        var from = {
+                node: way.nodes[way.first() === vertex.id ? 1 : way.nodes.length - 2],
+                way: way.id.split(/-(a|b)/)[0]
+            },
+            via = {node: vertex.id},
+            turns = [];
+
+        highways.forEach(function(parent) {
+            if (parent === way)
+                return;
+
+            var index = parent.nodes.indexOf(vertex.id);
+
+            // backward
+            if (parent.first() !== vertex.id && parent.tags.oneway !== 'yes') {
+                turns.push(withRestriction({
+                    from: from,
+                    via: via,
+                    to: {node: parent.nodes[index - 1], way: parent.id.split(/-(a|b)/)[0]}
+                }));
+            }
+
+            // forward
+            if (parent.last() !== vertex.id && parent.tags.oneway !== '-1') {
+                turns.push(withRestriction({
+                    from: from,
+                    via: via,
+                    to: {node: parent.nodes[index + 1], way: parent.id.split(/-(a|b)/)[0]}
+                }));
+            }
+        });
+
+        // U-turn
+        if (way.tags.oneway !== 'yes' && way.tags.oneway !== '-1') {
+            turns.push(withRestriction({
+                from: from,
+                via: via,
+                to: from,
+                u: true
+            }));
+        }
+
+        return turns;
+    };
+
+    return intersection;
+};
+
+iD.geo.inferRestriction = function(from, via, to, projection) {
+    var angle = iD.geo.angle(via, from, projection) -
+                iD.geo.angle(via, to, projection);
+
+    angle = angle * 180 / Math.PI;
+
+    while (angle < 0)
+        angle += 360;
+
+    if (angle < 23)
+        return 'no_u_turn';
+    if (angle < 158)
+        return 'no_right_turn';
+    if (angle < 202)
+        return 'no_straight_on';
+    if (angle < 336)
+        return 'no_left_turn';
+
+    return 'no_u_turn';
+};
 // For fixing up rendering of multipolygons with tags on the outer member.
 // https://github.com/openstreetmap/iD/issues/613
 iD.geo.isSimpleMultipolygonOuterMember = function(entity, graph) {
@@ -17066,67 +17465,55 @@ iD.geo.joinWays = function(array, graph) {
 
     return joined;
 };
-iD.geo.turns = function(graph, entityID) {
-    var way = graph.entity(entityID);
-    if (way.type !== 'way' || !way.tags.highway || way.isArea())
-        return [];
-
-    function withRestriction(turn) {
-        graph.parentRelations(turn.from).forEach(function(relation) {
-            if (relation.tags.type !== 'restriction')
-                return;
-
-            var f = relation.memberByRole('from'),
-                t = relation.memberByRole('to'),
-                v = relation.memberByRole('via');
-
-            if (f && f.id === turn.from.id &&
-                t && t.id === turn.to.id &&
-                v && v.id === turn.via.id) {
-                turn.restriction = relation;
-            }
-        });
+/*
+    Bypasses features of D3's default projection stream pipeline that are unnecessary:
+    * Antimeridian clipping
+    * Spherical rotation
+    * Resampling
+*/
+iD.geo.RawMercator = function () {
+    var project = d3.geo.mercator.raw,
+        k = 512 / Math.PI, // scale
+        x = 0, y = 0, // translate
+        clipExtent = [[0, 0], [0, 0]];
 
-        return turn;
+    function projection(point) {
+        point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
+        return [point[0] * k + x, y - point[1] * k];
     }
 
-    var turns = [];
+    projection.invert = function(point) {
+        point = project.invert((point[0] - x) / k, (y - point[1]) / k);
+        return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
+    };
 
-    [way.first(), way.last()].forEach(function(nodeID) {
-        var node = graph.entity(nodeID);
-        graph.parentWays(node).forEach(function(parent) {
-            if (parent === way || parent.isDegenerate() || !parent.tags.highway)
-                return;
-            if (way.first() === node.id && way.tags.oneway === 'yes')
-                return;
-            if (way.last() === node.id && way.tags.oneway === '-1')
-                return;
+    projection.scale = function(_) {
+        if (!arguments.length) return k;
+        k = +_;
+        return projection;
+    };
 
-            var index = parent.nodes.indexOf(node.id);
+    projection.translate = function(_) {
+        if (!arguments.length) return [x, y];
+        x = +_[0];
+        y = +_[1];
+        return projection;
+    };
 
-            // backward
-            if (parent.first() !== node.id && parent.tags.oneway !== 'yes') {
-                turns.push(withRestriction({
-                    from: way,
-                    to: parent,
-                    via: node,
-                    toward: graph.entity(parent.nodes[index - 1])
-                }));
-            }
+    projection.clipExtent = function(_) {
+        if (!arguments.length) return clipExtent;
+        clipExtent = _;
+        return projection;
+    };
 
-            // forward
-            if (parent.last() !== node.id && parent.tags.oneway !== '-1') {
-                turns.push(withRestriction({
-                    from: way,
-                    to: parent,
-                    via: node,
-                    toward: graph.entity(parent.nodes[index + 1])
-                }));
-            }
-       });
-    });
+    projection.stream = d3.geo.transform({
+        point: function(x, y) {
+            x = projection([x, y]);
+            this.stream.point(x[0], x[1]);
+        }
+    }).stream;
 
-    return turns;
+    return projection;
 };
 iD.actions = {};
 iD.actions.AddEntity = function(way) {
@@ -17442,7 +17829,15 @@ iD.actions.Connect = function(nodeIds) {
 };
 iD.actions.DeleteMember = function(relationId, memberIndex) {
     return function(graph) {
-        return graph.replace(graph.entity(relationId).removeMember(memberIndex));
+        var relation = graph.entity(relationId)
+            .removeMember(memberIndex);
+
+        graph = graph.replace(relation);
+
+        if (relation.isDegenerate())
+            graph = iD.actions.DeleteRelation(relation.id)(graph);
+
+        return graph;
     };
 };
 iD.actions.DeleteMultiple = function(ids) {
@@ -18172,6 +18567,95 @@ iD.actions.Orthogonalize = function(wayId, projection) {
 
     return action;
 };
+// Create a restriction relation for `turn`, which must have the following structure:
+//
+//     {
+//         from: { node: <node ID>, way: <way ID> },
+//         via:  { node: <node ID> },
+//         to:   { node: <node ID>, way: <way ID> },
+//         restriction: <'no_right_turn', 'no_left_turn', etc.>
+//     }
+//
+// This specifies a restriction of type `restriction` when traveling from
+// `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
+// (The action does not check that these entities form a valid intersection.)
+//
+// If `restriction` is not provided, it is automatically determined by the
+// angle of the turn:
+//
+//    0-23  degrees: no_u_turn
+//   23-158 degrees: no_right_turn
+//  158-202 degrees: no_straight_on
+//  202-326 degrees: no_left_turn
+//  336-360 degrees: no_u_turn
+//
+// If necessary, the `from` and `to` ways are split. In these cases, `from.node`
+// and `to.node` are used to determine which portion of the split ways become
+// members of the restriction.
+//
+// For testing convenience, accepts an ID to assign to the new relation.
+// Normally, this will be undefined and the relation will automatically
+// be assigned a new ID.
+//
+iD.actions.RestrictTurn = function(turn, projection, restrictionId) {
+    return function(graph) {
+        var from = graph.entity(turn.from.way),
+            via  = graph.entity(turn.via.node),
+            to   = graph.entity(turn.to.way);
+
+        function split(toOrFrom) {
+            var newID = toOrFrom.newID || iD.Way().id;
+            graph = iD.actions.Split(via.id, [newID])
+                .limitWays([toOrFrom.way])(graph);
+
+            var a = graph.entity(newID),
+                b = graph.entity(toOrFrom.way);
+
+            if (a.nodes.indexOf(toOrFrom.node) !== -1) {
+                return [a, b];
+            } else {
+                return [b, a];
+            }
+        }
+
+        if (!from.affix(via.id)) {
+            if (turn.from.node === turn.to.node) {
+                // U-turn
+                from = to = split(turn.from)[0];
+            } else if (turn.from.way === turn.to.way) {
+                // Straight-on
+                var s = split(turn.from);
+                from = s[0];
+                to   = s[1];
+            } else {
+                // Other
+                from = split(turn.from)[0];
+            }
+        }
+
+        if (!to.affix(via.id)) {
+            to = split(turn.to)[0];
+        }
+
+        return graph.replace(iD.Relation({
+            id: restrictionId,
+            tags: {
+                type: 'restriction',
+                restriction: turn.restriction ||
+                    iD.geo.inferRestriction(
+                        graph.entity(turn.from.node),
+                        via,
+                        graph.entity(turn.to.node),
+                        projection)
+            },
+            members: [
+                {id: from.id, type: 'way',  role: 'from'},
+                {id: via.id,  type: 'node', role: 'via'},
+                {id: to.id,   type: 'way',  role: 'to'}
+            ]
+        }));
+    };
+};
 /*
   Order the nodes of a way in reverse order and reverse any direction dependent tags
   other than `oneway`. (We assume that correcting a backwards oneway is the primary
@@ -18546,6 +19030,29 @@ iD.actions.Straighten = function(wayId, projection) {
 
     return action;
 };
+// Remove the effects of `turn.restriction` on `turn`, which must have the
+// following structure:
+//
+//     {
+//         from: { node: <node ID>, way: <way ID> },
+//         via:  { node: <node ID> },
+//         to:   { node: <node ID>, way: <way ID> },
+//         restriction: <relation ID>
+//     }
+//
+// In the simple case, `restriction` is a reference to a `no_*` restriction
+// on the turn itself. In this case, it is simply deleted.
+//
+// The more complex case is where `restriction` references an `only_*`
+// restriction on a different turn in the same intersection. In that case,
+// that restriction is also deleted, but at the same time restrictions on
+// the turns other than the first two are created.
+//
+iD.actions.UnrestrictTurn = function(turn) {
+    return function(graph) {
+        return iD.actions.DeleteRelation(turn.restriction)(graph);
+    };
+};
 iD.behavior = {};
 iD.behavior.AddWay = function(context) {
     var event = d3.dispatch('start', 'startFromWay', 'startFromNode'),
@@ -18676,6 +19183,9 @@ iD.behavior.drag = function() {
             var p = point(),
                 dx = p[0] - origin_[0],
                 dy = p[1] - origin_[1];
+            
+            if (dx === 0 && dy === 0)
+                return;
 
             if (!started) {
                 started = true;
@@ -19152,15 +19662,29 @@ iD.behavior.Hash = function(context) {
     };
 
     var formatter = function(map) {
-        var center = map.center(),
+        var mode = context.mode(),
+            center = map.center(),
             zoom = map.zoom(),
-            precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
-        var q = iD.util.stringQs(location.hash.substring(1));
-        return '#' + iD.util.qsString(_.assign(q, {
-                map: zoom.toFixed(2) +
-                    '/' + center[0].toFixed(precision) +
-                    '/' + center[1].toFixed(precision)
-            }), true);
+            precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
+            q = iD.util.stringQs(location.hash.substring(1)),
+            newParams = {};
+
+        if (mode && mode.id === 'browse') {
+            delete q.id;
+        } else {
+            var selected = context.selectedIDs().filter(function(id) {
+                return !context.entity(id).isNew();
+            });
+            if (selected.length) {
+                newParams.id = selected.join(',');
+            }
+        }
+
+        newParams.map = zoom.toFixed(2) +
+                '/' + center[0].toFixed(precision) +
+                '/' + center[1].toFixed(precision);
+
+        return '#' + iD.util.qsString(_.assign(q, newParams), true);
     };
 
     function update() {
@@ -19168,7 +19692,7 @@ iD.behavior.Hash = function(context) {
         if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
     }
 
-    var move = _.throttle(update, 500);
+    var throttledUpdate = _.throttle(update, 500);
 
     function hashchange() {
         if (location.hash === s0) return; // ignore spurious hashchange events
@@ -19179,14 +19703,17 @@ iD.behavior.Hash = function(context) {
 
     function hash() {
         context.map()
-            .on('move.hash', move);
+            .on('move.hash', throttledUpdate);
+
+        context
+            .on('enter.hash', throttledUpdate);
 
         d3.select(window)
             .on('hashchange.hash', hashchange);
 
         if (location.hash) {
             var q = iD.util.stringQs(location.hash.substring(1));
-            if (q.id) context.loadEntity(q.id, !q.map);
+            if (q.id) context.loadEntity(q.id.split(',')[0], !q.map);
             hashchange();
             if (q.map) hash.hadHash = true;
         }
@@ -19196,6 +19723,9 @@ iD.behavior.Hash = function(context) {
         context.map()
             .on('move.hash', null);
 
+        context
+            .on('enter.hash', null);
+
         d3.select(window)
             .on('hashchange.hash', null);
 
@@ -19349,8 +19879,6 @@ iD.behavior.Lasso = function(context) {
                     .on('mouseup.lasso', mouseup);
 
                 d3.event.stopPropagation();
-                d3.event.preventDefault();
-
             }
         }
 
@@ -19733,8 +20261,7 @@ iD.modes.Browse = function(context) {
         button: 'browse',
         id: 'browse',
         title: t('modes.browse.title'),
-        description: t('modes.browse.description'),
-        key: '1'
+        description: t('modes.browse.description')
     }, sidebar;
 
     var behaviors = [
@@ -20445,17 +20972,6 @@ iD.modes.Select = function(context, selectedIDs) {
             });
         });
 
-        var notNew = selectedIDs.filter(function(id) {
-            return !context.entity(id).isNew();
-        });
-
-        if (notNew.length) {
-            var q = iD.util.stringQs(location.hash.substring(1));
-            location.replace('#' + iD.util.qsString(_.assign(q, {
-                id: notNew.join(',')
-            }), true));
-        }
-
         context.ui().sidebar
             .select(singular() ? singular().id : null, newFeature);
 
@@ -20539,9 +21055,6 @@ iD.modes.Select = function(context, selectedIDs) {
             context.uninstall(behavior);
         });
 
-        var q = iD.util.stringQs(location.hash.substring(1));
-        location.replace('#' + iD.util.qsString(_.omit(q, 'id'), true));
-
         keybinding.off();
 
         context.history()
@@ -20563,6 +21076,8 @@ iD.modes.Select = function(context, selectedIDs) {
 iD.operations = {};
 iD.operations.Circularize = function(selectedIDs, context) {
     var entityId = selectedIDs[0],
+        entity = context.entity(entityId),
+        extent = entity.extent(context.graph()),
         geometry = context.geometry(entityId),
         action = iD.actions.Circularize(entityId, context.projection);
 
@@ -20572,24 +21087,17 @@ iD.operations.Circularize = function(selectedIDs, context) {
     };
 
     operation.available = function() {
-        var entity = context.entity(entityId);
         return selectedIDs.length === 1 &&
             entity.type === 'way' &&
             _.uniq(entity.nodes).length > 1;
     };
 
     operation.disabled = function() {
-        var way = context.entity(entityId),
-            wayExtent = way.extent(context.graph()),
-            mapExtent = context.extent(),
-            intersection = mapExtent.intersection(wayExtent),
-            pctVisible = intersection.area() / wayExtent.area();
-
-        if (pctVisible < 0.8) {
-            return 'too_large';
-        } else {
-            return action.disabled(context.graph());
+        var reason;
+        if (extent.percentContainedIn(context.extent()) < 0.8) {
+            reason = 'too_large';
         }
+        return action.disabled(context.graph()) || reason;
     };
 
     operation.tooltip = function() {
@@ -20692,15 +21200,15 @@ iD.operations.Delete = function(selectedIDs, context) {
             }
         }
 
-        context.perform(
-            action,
-            annotation);
-
         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
             context.enter(iD.modes.Select(context, [nextSelectedID]));
         } else {
             context.enter(iD.modes.Browse(context));
         }
+
+        context.perform(
+            action,
+            annotation);
     };
 
     operation.available = function() {
@@ -20817,6 +21325,10 @@ iD.operations.Merge = function(selectedIDs, context) {
     return operation;
 };
 iD.operations.Move = function(selectedIDs, context) {
+    var extent = selectedIDs.reduce(function(extent, id) {
+            return extent.extend(context.entity(id).extent(context.graph()));
+        }, iD.geo.Extent());
+
     var operation = function() {
         context.enter(iD.modes.Move(context, selectedIDs));
     };
@@ -20827,8 +21339,11 @@ iD.operations.Move = function(selectedIDs, context) {
     };
 
     operation.disabled = function() {
-        return iD.actions.Move(selectedIDs)
-            .disabled(context.graph());
+        var reason;
+        if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
+            reason = 'too_large';
+        }
+        return iD.actions.Move(selectedIDs).disabled(context.graph()) || reason;
     };
 
     operation.tooltip = function() {
@@ -20846,16 +21361,17 @@ iD.operations.Move = function(selectedIDs, context) {
 };
 iD.operations.Orthogonalize = function(selectedIDs, context) {
     var entityId = selectedIDs[0],
+        entity = context.entity(entityId),
+        extent = entity.extent(context.graph()),
         geometry = context.geometry(entityId),
         action = iD.actions.Orthogonalize(entityId, context.projection);
 
-    function operation() {
+    var operation = function() {
         var annotation = t('operations.orthogonalize.annotation.' + geometry);
         context.perform(action, annotation);
-    }
+    };
 
     operation.available = function() {
-        var entity = context.entity(entityId);
         return selectedIDs.length === 1 &&
             entity.type === 'way' &&
             entity.isClosed() &&
@@ -20863,17 +21379,11 @@ iD.operations.Orthogonalize = function(selectedIDs, context) {
     };
 
     operation.disabled = function() {
-        var way = context.entity(entityId),
-            wayExtent = way.extent(context.graph()),
-            mapExtent = context.extent(),
-            intersection = mapExtent.intersection(wayExtent),
-            pctVisible = intersection.area() / wayExtent.area();
-
-        if (pctVisible < 0.8) {
-            return 'too_large';
-        } else {
-            return action.disabled(context.graph());
+        var reason;
+        if (extent.percentContainedIn(context.extent()) < 0.8) {
+            reason = 'too_large';
         }
+        return action.disabled(context.graph()) || reason;
     };
 
     operation.tooltip = function() {
@@ -20918,33 +21428,39 @@ iD.operations.Reverse = function(selectedIDs, context) {
     return operation;
 };
 iD.operations.Rotate = function(selectedIDs, context) {
-    var entityId = selectedIDs[0];
+    var entityId = selectedIDs[0],
+        entity = context.entity(entityId),
+        extent = entity.extent(context.graph()),
+        geometry = context.geometry(entityId);
 
     var operation = function() {
         context.enter(iD.modes.RotateWay(context, entityId));
     };
 
     operation.available = function() {
-        var graph = context.graph(),
-            entity = graph.entity(entityId);
-
-        if (selectedIDs.length !== 1 ||
-            entity.type !== 'way')
+        if (selectedIDs.length !== 1 || entity.type !== 'way')
             return false;
-        if (context.geometry(entityId) === 'area')
+        if (geometry === 'area')
             return true;
         if (entity.isClosed() &&
-            graph.parentRelations(entity).some(function(r) { return r.isMultipolygon(); }))
+            context.graph().parentRelations(entity).some(function(r) { return r.isMultipolygon(); }))
             return true;
         return false;
     };
 
     operation.disabled = function() {
-        return false;
+        if (extent.percentContainedIn(context.extent()) < 0.8) {
+            return 'too_large';
+        } else {
+            return false;
+        }
     };
 
     operation.tooltip = function() {
-        return t('operations.rotate.description');
+        var disable = operation.disabled();
+        return disable ?
+            t('operations.rotate.' + disable) :
+            t('operations.rotate.description');
     };
 
     operation.id = 'rotate';
@@ -21204,7 +21720,7 @@ iD.areaKeys = {
         var elems = obj.getElementsByTagName(ndStr),
             nodes = new Array(elems.length);
         for (var i = 0, l = elems.length; i < l; i++) {
-            nodes[i] = 'n' + elems[i].attributes.ref.nodeValue;
+            nodes[i] = 'n' + elems[i].attributes.ref.value;
         }
         return nodes;
     }
@@ -21214,7 +21730,7 @@ iD.areaKeys = {
             tags = {};
         for (var i = 0, l = elems.length; i < l; i++) {
             var attrs = elems[i].attributes;
-            tags[attrs.k.nodeValue] = attrs.v.nodeValue;
+            tags[attrs.k.value] = attrs.v.value;
         }
         return tags;
     }
@@ -21225,9 +21741,9 @@ iD.areaKeys = {
         for (var i = 0, l = elems.length; i < l; i++) {
             var attrs = elems[i].attributes;
             members[i] = {
-                id: attrs.type.nodeValue[0] + attrs.ref.nodeValue,
-                type: attrs.type.nodeValue,
-                role: attrs.role.nodeValue
+                id: attrs.type.value[0] + attrs.ref.value,
+                type: attrs.type.value,
+                role: attrs.role.value
             };
         }
         return members;
@@ -21237,10 +21753,10 @@ iD.areaKeys = {
         node: function nodeData(obj) {
             var attrs = obj.attributes;
             return new iD.Node({
-                id: iD.Entity.id.fromOSM(nodeStr, attrs.id.nodeValue),
-                loc: [parseFloat(attrs.lon.nodeValue), parseFloat(attrs.lat.nodeValue)],
-                version: attrs.version.nodeValue,
-                user: attrs.user && attrs.user.nodeValue,
+                id: iD.Entity.id.fromOSM(nodeStr, attrs.id.value),
+                loc: [parseFloat(attrs.lon.value), parseFloat(attrs.lat.value)],
+                version: attrs.version.value,
+                user: attrs.user && attrs.user.value,
                 tags: getTags(obj)
             });
         },
@@ -21248,9 +21764,9 @@ iD.areaKeys = {
         way: function wayData(obj) {
             var attrs = obj.attributes;
             return new iD.Way({
-                id: iD.Entity.id.fromOSM(wayStr, attrs.id.nodeValue),
-                version: attrs.version.nodeValue,
-                user: attrs.user && attrs.user.nodeValue,
+                id: iD.Entity.id.fromOSM(wayStr, attrs.id.value),
+                version: attrs.version.value,
+                user: attrs.user && attrs.user.value,
                 tags: getTags(obj),
                 nodes: getNodes(obj)
             });
@@ -21259,9 +21775,9 @@ iD.areaKeys = {
         relation: function relationData(obj) {
             var attrs = obj.attributes;
             return new iD.Relation({
-                id: iD.Entity.id.fromOSM(relationStr, attrs.id.nodeValue),
-                version: attrs.version.nodeValue,
-                user: attrs.user && attrs.user.nodeValue,
+                id: iD.Entity.id.fromOSM(relationStr, attrs.id.value),
+                version: attrs.version.value,
+                user: attrs.user && attrs.user.value,
                 tags: getTags(obj),
                 members: getMembers(obj)
             });
@@ -21339,7 +21855,7 @@ iD.areaKeys = {
 
     connection.changesetTags = function(comment, imageryUsed) {
         var tags = {
-            imagery_used: imageryUsed.join(';'),
+            imagery_used: imageryUsed.join(';').substr(0, 255),
             created_by: 'iD ' + iD.version
         };
 
@@ -21395,9 +21911,9 @@ iD.areaKeys = {
             }
 
             userDetails = {
-                display_name: u.attributes.display_name.nodeValue,
+                display_name: u.attributes.display_name.value,
                 image_url: image_url,
-                id: u.attributes.id.nodeValue
+                id: u.attributes.id.value
             };
 
             callback(undefined, userDetails);
@@ -21821,6 +22337,10 @@ iD.Entity.prototype = {
         });
     },
 
+    isHighwayIntersection: function() {
+        return false;
+    },
+
     deprecatedTags: function() {
         var tags = _.pairs(this.tags);
         var deprecated = {};
@@ -22469,6 +22989,14 @@ _.extend(iD.Node.prototype, {
         });
     },
 
+    isHighwayIntersection: function(resolver) {
+        return resolver.transient(this, 'isHighwayIntersection', function() {
+            return resolver.parentWays(this).filter(function(parent) {
+                return parent.tags.highway && parent.geometry(resolver) === 'line';
+            }).length > 1;
+        });
+    },
+
     asJXON: function(changeset_id) {
         var r = {
             node: {
@@ -22492,6 +23020,37 @@ _.extend(iD.Node.prototype, {
         };
     }
 });
+iD.oneWayTags = {
+    'aerialway': {
+        'chair_lift': true,
+        'mixed_lift': true,
+        't-bar': true,
+        'j-bar': true,
+        'platter': true,
+        'rope_tow': true,
+        'magic_carpet': true,
+        'yes': true
+    },
+    'highway': {
+        'motorway': true,
+        'motorway_link': true
+    },
+    'junction': {
+        'roundabout': true
+    },
+    'man_made': {
+        'piste:halfpipe': true
+    },
+    'piste:type': {
+        'downhill': true,
+        'sled': true,
+        'yes': true
+    },
+    'waterway': {
+        'river': true,
+        'stream': true
+    }
+};
 iD.Relation = iD.Entity.relation = function iD_Relation() {
     if (!(this instanceof iD_Relation)) {
         return (new iD_Relation()).initialize(arguments);
@@ -22880,17 +23439,40 @@ _.extend(iD.Way.prototype, {
         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
     },
 
+    layer: function() {
+        // explicit layer tag, clamp between -10, 10..
+        if (this.tags.layer !== undefined) {
+            return Math.max(-10, Math.min(+(this.tags.layer), 10));
+        }
+
+        // implied layer tag..
+        if (this.tags.location === 'overground') return 1;
+        if (this.tags.location === 'underground') return -1;
+        if (this.tags.location === 'underwater') return -10;
+
+        if (this.tags.power === 'line') return 10;
+        if (this.tags.power === 'minor_line') return 10;
+        if (this.tags.aerialway) return 10;
+        if (this.tags.bridge) return 1;
+        if (this.tags.cutting) return -1;
+        if (this.tags.tunnel) return -1;
+        if (this.tags.waterway) return -1;
+        if (this.tags.man_made === 'pipeline') return -10;
+        if (this.tags.boundary) return -10;
+        return 0;
+    },
+
     isOneWay: function() {
         // explicit oneway tag..
         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
 
         // implied oneway tag..
-        return this.tags.waterway === 'river' ||
-            this.tags.waterway === 'stream' ||
-            this.tags.highway === 'motorway' ||
-            this.tags.highway === 'motorway_link' ||
-            this.tags.junction === 'roundabout';
+        for (var key in this.tags) {
+            if (key in iD.oneWayTags && (this.tags[key] in iD.oneWayTags[key]))
+                return true;
+        }
+        return false;
     },
 
     isClosed: function() {
@@ -23206,8 +23788,15 @@ iD.Background = function(context) {
 
     background.zoomToGpxLayer = function() {
         if (background.hasGpxLayer()) {
-            context.map()
-                .extent(d3.geo.bounds(gpxLayer.geojson()));
+            var viewport = context.map().extent().polygon(),
+                coords = _.reduce(gpxLayer.geojson().features, function(coords, feature) {
+                    var c = feature.geometry.coordinates;
+                    return _.union(coords, feature.geometry.type === 'Point' ? [c] : c);
+                }, []);
+
+            if (!iD.geo.polygonIntersectsPolygon(viewport, coords)) {
+                context.map().extent(d3.geo.bounds(gpxLayer.geojson()));
+            }
         }
     };
 
@@ -23482,7 +24071,7 @@ iD.GpxLayer = function(context) {
                 .append('text')
                 .attr('class', 'gpx')
                 .text(function(d) {
-                    return d.properties.name;
+                    return d.properties.desc || d.properties.name;
                 })
                 .attr('x', function(d) {
                     var centroid = path.centroid(d);
@@ -23619,10 +24208,9 @@ iD.Map = function(context) {
             if (map.editable() && !transformed) {
                 var all = context.intersects(map.extent()),
                     filter = d3.functor(true),
-                    extent = map.extent(),
                     graph = context.graph();
-                surface.call(vertices, graph, all, filter, extent, map.zoom());
-                surface.call(midpoints, graph, all, filter, extent);
+                surface.call(vertices, graph, all, filter, map.extent(), map.zoom());
+                surface.call(midpoints, graph, all, filter, map.trimmedExtent());
                 dispatch.drawn({full: false});
             }
         });
@@ -23641,30 +24229,7 @@ iD.Map = function(context) {
         if (difference) {
             var complete = difference.complete(map.extent());
             all = _.compact(_.values(complete));
-            filter = function(d) {
-                if (d.type === 'midpoint') {
-
-                    var a = d.edge[0],
-                        b = d.edge[1];
-
-                    // redraw a midpoint if it needs to be
-                    // - moved (either edge node moved)
-                    // - deleted (edge nodes not consecutive in any parent way)
-                    if (a in complete || b in complete) return true;
-
-                    var parentsWays = graph.parentWays({ id: a });
-                    for (var i = 0; i < parentsWays.length; i++) {
-                        var nodes = parentsWays[i].nodes;
-                        for (var n = 0; n < nodes.length; n++) {
-                            if (nodes[n] === a && (nodes[n - 1] === b || nodes[n + 1] === b)) return false;
-                        }
-                    }
-                    return true;
-
-                } else {
-                    return d.id in complete;
-                }
-            };
+            filter = function(d) { return d.id in complete; };
 
         } else if (extent) {
             all = context.intersects(map.extent().intersection(extent));
@@ -23680,7 +24245,7 @@ iD.Map = function(context) {
             .call(vertices, graph, all, filter, map.extent(), map.zoom())
             .call(lines, graph, all, filter)
             .call(areas, graph, all, filter)
-            .call(midpoints, graph, all, filter, map.extent())
+            .call(midpoints, graph, all, filter, map.trimmedExtent())
             .call(labels, graph, all, filter, dimensions, !difference && !extent);
 
         if (points.points(context.intersects(map.extent()), 100).length >= 100) {
@@ -23693,8 +24258,12 @@ iD.Map = function(context) {
     }
 
     function editOff() {
+        var mode = context.mode();
         surface.selectAll('.layer *').remove();
         dispatch.drawn({full: true});
+        if (!(mode && mode.id === 'browse')) {
+            context.enter(iD.modes.Browse(context));
+        }
     }
 
     function zoomPan() {
@@ -23932,6 +24501,12 @@ iD.Map = function(context) {
         }
     };
 
+    map.trimmedExtent = function() {
+        var headerY = 60, footerY = 30, pad = 10;
+        return new iD.geo.Extent(projection.invert([pad, dimensions[1] - footerY - pad]),
+                projection.invert([dimensions[0] - pad, headerY + pad]));
+    };
+
     map.extentZoom = function(_) {
         var extent = iD.geo.Extent(_),
             tl = projection([extent[0][0], extent[1][1]]),
@@ -24030,6 +24605,7 @@ iD.TileLayer = function() {
             tile().forEach(function(d) {
                 addSource(d);
                 if (d[3] === '') return;
+                if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
                 requests.push(d);
                 if (cache[d[3]] === false && lookUp(d)) {
                     requests.push(addSource(lookUp(d)));
@@ -24168,6 +24744,7 @@ iD.svg = {
                 i = 0,
                 offset = dt,
                 segments = [],
+                viewport = iD.geo.Extent(projection.clipExtent()),
                 coordinates = graph.childNodes(entity).map(function(n) {
                     return n.loc;
                 });
@@ -24186,9 +24763,10 @@ iD.svg = {
                     b = [x, y];
 
                     if (a) {
-                        var span = iD.geo.euclideanDistance(a, b) - offset;
+                        var extent = iD.geo.Extent(a).extend(b),
+                            span = iD.geo.euclideanDistance(a, b) - offset;
 
-                        if (span >= 0) {
+                        if (extent.intersects(viewport) && span >= 0) {
                             var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
                                 dx = dt * Math.cos(angle),
                                 dy = dt * Math.sin(angle),
@@ -24251,6 +24829,12 @@ iD.svg.Areas = function(projection) {
 
     var patternKeys = ['landuse', 'natural', 'amenity'];
 
+    var clipped = ['residential', 'commercial', 'retail', 'industrial'];
+
+    function clip(entity) {
+        return clipped.indexOf(entity.tags.landuse) !== -1;
+    }
+
     function setPattern(d) {
         for (var i = 0; i < patternKeys.length; i++) {
             if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
@@ -24293,13 +24877,39 @@ iD.svg.Areas = function(projection) {
         });
 
         var data = {
+            clip: areas.filter(clip),
             shadow: strokes,
             stroke: strokes,
             fill: areas
         };
 
-        var paths = surface.selectAll('.layer-shadow, .layer-stroke, .layer-fill')
-            .selectAll('path.area')
+        var clipPaths = surface.selectAll('defs').selectAll('.clipPath')
+           .filter(filter)
+           .data(data.clip, iD.Entity.key);
+
+        clipPaths.enter()
+           .append('clipPath')
+           .attr('class', 'clipPath')
+           .attr('id', function(entity) { return entity.id + '-clippath'; })
+           .append('path');
+
+        clipPaths.selectAll('path')
+           .attr('d', path);
+
+        clipPaths.exit()
+           .remove();
+
+        var areagroup = surface
+            .select('.layer-areas')
+            .selectAll('g.areagroup')
+            .data(['fill', 'shadow', 'stroke']);
+
+        areagroup.enter()
+            .append('g')
+            .attr('class', function(d) { return 'layer areagroup area-' + d; });
+
+        var paths = areagroup
+            .selectAll('path')
             .filter(filter)
             .data(function(layer) { return data[layer]; }, iD.Entity.key);
 
@@ -24308,7 +24918,7 @@ iD.svg.Areas = function(projection) {
         paths.exit()
             .remove();
 
-        var fills = surface.selectAll('.layer-fill path.area')[0];
+        var fills = surface.selectAll('.area-fill path.area')[0];
 
         var bisect = d3.bisector(function(node) {
             return -node.__data__.area(graph);
@@ -24327,6 +24937,10 @@ iD.svg.Areas = function(projection) {
 
                 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
 
+                if (layer === 'fill' && clip(entity)) {
+                    this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
+                }
+
                 if (layer === 'fill') {
                     setPattern.apply(this, arguments);
                 }
@@ -24337,6 +24951,135 @@ iD.svg.Areas = function(projection) {
             .attr('d', path);
     };
 };
+/*
+    A standalone SVG element that contains only a `defs` sub-element. To be
+    used once globally, since defs IDs must be unique within a document.
+*/
+iD.svg.Defs = function(context) {
+    function autosize(image) {
+        var img = document.createElement('img');
+        img.src = image.attr('xlink:href');
+        img.onload = function() {
+            image.attr({
+                width: img.width,
+                height: img.height
+            });
+        };
+    }
+
+    function SpriteDefinition(id, href, data) {
+        return function(defs) {
+            defs.append('image')
+                .attr('id', id)
+                .attr('xlink:href', href)
+                .call(autosize);
+
+            defs.selectAll()
+                .data(data)
+                .enter().append('use')
+                .attr('id', function(d) { return d.key; })
+                .attr('transform', function(d) { return 'translate(-' + d.value[0] + ',-' + d.value[1] + ')'; })
+                .attr('xlink:href', '#' + id);
+        };
+    }
+
+    return function (selection) {
+        var defs = selection.append('defs');
+
+        defs.append('marker')
+            .attr({
+                id: 'oneway-marker',
+                viewBox: '0 0 10 10',
+                refY: 2.5,
+                refX: 5,
+                markerWidth: 2,
+                markerHeight: 2,
+                orient: 'auto'
+            })
+            .append('path')
+            .attr('d', 'M 5 3 L 0 3 L 0 2 L 5 2 L 5 0 L 10 2.5 L 5 5 z');
+
+        var patterns = defs.selectAll('pattern')
+            .data([
+                // pattern name, pattern image name
+                ['wetland', 'wetland'],
+                ['construction', 'construction'],
+                ['cemetery', 'cemetery'],
+                ['orchard', 'orchard'],
+                ['farmland', 'farmland'],
+                ['beach', 'dots'],
+                ['scrub', 'dots'],
+                ['meadow', 'dots']
+            ])
+            .enter()
+            .append('pattern')
+            .attr({
+                id: function (d) {
+                    return 'pattern-' + d[0];
+                },
+                width: 32,
+                height: 32,
+                patternUnits: 'userSpaceOnUse'
+            });
+
+        patterns.append('rect')
+            .attr({
+                x: 0,
+                y: 0,
+                width: 32,
+                height: 32,
+                'class': function (d) {
+                    return 'pattern-color-' + d[0];
+                }
+            });
+
+        patterns.append('image')
+            .attr({
+                x: 0,
+                y: 0,
+                width: 32,
+                height: 32
+            })
+            .attr('xlink:href', function (d) {
+                return context.imagePath('pattern/' + d[1] + '.png');
+            });
+
+        defs.selectAll()
+            .data([12, 18, 20, 32, 45])
+            .enter().append('clipPath')
+            .attr('id', function (d) {
+                return 'clip-square-' + d;
+            })
+            .append('rect')
+            .attr('x', 0)
+            .attr('y', 0)
+            .attr('width', function (d) {
+                return d;
+            })
+            .attr('height', function (d) {
+                return d;
+            });
+
+        var maki = [];
+        _.forEach(iD.data.featureIcons, function (dimensions, name) {
+            if (dimensions['12'] && dimensions['18'] && dimensions['24']) {
+                maki.push({key: 'maki-' + name + '-12', value: dimensions['12']});
+                maki.push({key: 'maki-' + name + '-18', value: dimensions['18']});
+                maki.push({key: 'maki-' + name + '-24', value: dimensions['24']});
+            }
+        });
+
+        defs.call(SpriteDefinition(
+            'sprite',
+            context.imagePath('sprite.svg'),
+            d3.entries(iD.data.operations)));
+
+        defs.call(SpriteDefinition(
+            'maki-sprite',
+            context.imagePath('maki-sprite.png'),
+            maki));
+    };
+};
 iD.svg.Labels = function(projection, context) {
     var path = d3.geo.path().projection(projection);
 
@@ -24796,80 +25539,98 @@ iD.svg.Lines = function(projection) {
     };
 
     function waystack(a, b) {
-        if (!a || !b || !a.tags || !b.tags) return 0;
-        if (a.tags.layer !== undefined && b.tags.layer !== undefined) {
-            return a.tags.layer - b.tags.layer;
-        }
-        if (a.tags.bridge) return 1;
-        if (b.tags.bridge) return -1;
-        if (a.tags.tunnel) return -1;
-        if (b.tags.tunnel) return 1;
         var as = 0, bs = 0;
-        if (a.tags.highway && b.tags.highway) {
-            as -= highway_stack[a.tags.highway];
-            bs -= highway_stack[b.tags.highway];
-        }
+
+        if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
+        if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
         return as - bs;
     }
 
     return function drawLines(surface, graph, entities, filter) {
-        var lines = [],
-            path = iD.svg.Path(projection, graph);
+        var ways = [], pathdata = {}, onewaydata = {},
+            getPath = iD.svg.Path(projection, graph);
 
         for (var i = 0; i < entities.length; i++) {
             var entity = entities[i],
                 outer = iD.geo.simpleMultipolygonOuterMember(entity, graph);
             if (outer) {
-                lines.push(entity.mergeTags(outer.tags));
+                ways.push(entity.mergeTags(outer.tags));
             } else if (entity.geometry(graph) === 'line') {
-                lines.push(entity);
+                ways.push(entity);
             }
         }
 
-        lines = lines.filter(path);
-        lines.sort(waystack);
+        ways = ways.filter(getPath);
 
-        function drawPaths(klass) {
-            var paths = surface.select('.layer-' + klass)
-                .selectAll('path.line')
-                .filter(filter)
-                .data(lines, iD.Entity.key);
+        pathdata = _.groupBy(ways, function(way) { return way.layer(); });
 
-            var enter = paths.enter()
-                .append('path')
-                .attr('class', function(d) { return 'way line ' + klass + ' ' + d.id; });
+        _.forOwn(pathdata, function(v, k) {
+            onewaydata[k] = _(v)
+                .filter(function(d) { return d.isOneWay(); })
+                .map(iD.svg.OneWaySegments(projection, graph, 35))
+                .flatten()
+                .valueOf();
+        });
 
-            // Optimization: call simple TagClasses only on enter selection. This
-            // works because iD.Entity.key is defined to include the entity v attribute.
-            if (klass !== 'stroke') {
-                enter.call(iD.svg.TagClasses());
-            } else {
-                paths.call(iD.svg.TagClasses()
-                    .tags(iD.svg.MultipolygonMemberTags(graph)));
-            }
+        var layergroup = surface
+            .select('.layer-lines')
+            .selectAll('g.layergroup')
+            .data(d3.range(-10, 11));
 
-            paths
-                .order()
-                .attr('d', path);
+        layergroup.enter()
+            .append('g')
+            .attr('class', function(d) { return 'layer layergroup layer' + String(d); });
 
-            paths.exit()
-                .remove();
-        }
 
-        drawPaths('shadow');
-        drawPaths('casing');
-        drawPaths('stroke');
+        var linegroup = layergroup
+            .selectAll('g.linegroup')
+            .data(['shadow', 'casing', 'stroke']);
+
+        linegroup.enter()
+            .append('g')
+            .attr('class', function(d) { return 'layer linegroup line-' + d; });
 
-        var segments = _(lines)
-            .filter(function(d) { return d.isOneWay(); })
-            .map(iD.svg.OneWaySegments(projection, graph, 35))
-            .flatten()
-            .valueOf();
 
-        var oneways = surface.select('.layer-oneway')
-            .selectAll('path.oneway')
+        var lines = linegroup
+            .selectAll('path')
             .filter(filter)
-            .data(segments, function(d) { return [d.id, d.index]; });
+            .data(
+                function() { return pathdata[this.parentNode.parentNode.__data__] || []; },
+                iD.Entity.key
+            );
+
+        // Optimization: call simple TagClasses only on enter selection. This
+        // works because iD.Entity.key is defined to include the entity v attribute.
+        lines.enter()
+            .append('path')
+            .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
+            .call(iD.svg.TagClasses());
+
+        lines
+            .sort(waystack)
+            .attr('d', getPath)
+            .call(iD.svg.TagClasses().tags(iD.svg.MultipolygonMemberTags(graph)));
+
+        lines.exit()
+            .remove();
+
+
+        var onewaygroup = layergroup
+            .selectAll('g.onewaygroup')
+            .data(['oneway']);
+
+        onewaygroup.enter()
+            .append('g')
+            .attr('class', 'layer onewaygroup');
+
+
+        var oneways = onewaygroup
+            .selectAll('path')
+            .filter(filter)
+            .data(
+                function() { return onewaydata[this.parentNode.parentNode.__data__] || []; },
+                function(d) { return [d.id, d.index]; }
+            );
 
         oneways.enter()
             .append('path')
@@ -24877,72 +25638,113 @@ iD.svg.Lines = function(projection) {
             .attr('marker-mid', 'url(#oneway-marker)');
 
         oneways
-            .order()
             .attr('d', function(d) { return d.d; });
 
         oneways.exit()
             .remove();
+
     };
 };
 iD.svg.Midpoints = function(projection, context) {
     return function drawMidpoints(surface, graph, entities, filter, extent) {
-        var midpoints = {};
+        var poly = extent.polygon(),
+            midpoints = {};
 
         for (var i = 0; i < entities.length; i++) {
             var entity = entities[i];
 
-            if (entity.type !== 'way') continue;
-            if (context.selectedIDs().indexOf(entity.id) < 0) continue;
+            if (entity.type !== 'way')
+                continue;
+            if (!filter(entity))
+                continue;
+            if (context.selectedIDs().indexOf(entity.id) < 0)
+                continue;
 
             var nodes = graph.childNodes(entity);
-
-            // skip the last node because it is always repeated
             for (var j = 0; j < nodes.length - 1; j++) {
 
                 var a = nodes[j],
                     b = nodes[j + 1],
                     id = [a.id, b.id].sort().join('-');
 
-                // Redraw midpoints in two cases:
-                //   1. One of the two endpoint nodes changed (e.g. was moved).
-                //   2. A node was deleted. The midpoint between the two new
-                //      endpoints needs to be redrawn. In this case only the
-                //      way will be in the diff.
-                if (!midpoints[id] && (filter(a) || filter(b) || filter(entity))) {
-                    var loc = iD.geo.interp(a.loc, b.loc, 0.5);
-                    if (extent.intersects(loc) && iD.geo.euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
-                        midpoints[id] = {
-                            type: 'midpoint',
-                            id: id,
-                            loc: loc,
-                            edge: [a.id, b.id]
-                        };
+                if (midpoints[id]) {
+                    midpoints[id].parents.push(entity);
+                } else {
+                    if (iD.geo.euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
+                        var point = iD.geo.interp(a.loc, b.loc, 0.5),
+                            loc = null;
+
+                        if (extent.intersects(point)) {
+                            loc = point;
+                        } else {
+                            for (var k = 0; k < 4; k++) {
+                                point = iD.geo.lineIntersection([a.loc, b.loc], [poly[k], poly[k+1]]);
+                                if (point &&
+                                    iD.geo.euclideanDistance(projection(a.loc), projection(point)) > 20 &&
+                                    iD.geo.euclideanDistance(projection(b.loc), projection(point)) > 20)
+                                {
+                                    loc = point;
+                                    break;
+                                }
+                            }
+                        }
+
+                        if (loc) {
+                            midpoints[id] = {
+                                type: 'midpoint',
+                                id: id,
+                                loc: loc,
+                                edge: [a.id, b.id],
+                                parents: [entity]
+                            };
+                        }
                     }
                 }
             }
         }
 
+        function midpointFilter(d) {
+            if (midpoints[d.id])
+                return true;
+
+            for (var i = 0; i < d.parents.length; i++)
+                if (filter(d.parents[i]))
+                    return true;
+
+            return false;
+        }
+
         var groups = surface.select('.layer-hit').selectAll('g.midpoint')
-            .filter(filter)
+            .filter(midpointFilter)
             .data(_.values(midpoints), function(d) { return d.id; });
 
-        var group = groups.enter()
+        var enter = groups.enter()
             .insert('g', ':first-child')
             .attr('class', 'midpoint');
 
-        group.append('circle')
-            .attr('r', 7)
+        enter.append('polygon')
+            .attr('points', '-6,8 10,0 -6,-8')
             .attr('class', 'shadow');
 
-        group.append('circle')
-            .attr('r', 3)
+        enter.append('polygon')
+            .attr('points', '-3,4 5,0 -3,-4')
             .attr('class', 'fill');
 
-        groups.attr('transform', iD.svg.PointTransform(projection));
+        groups
+            .attr('transform', function(d) {
+                var translate = iD.svg.PointTransform(projection),
+                    a = context.entity(d.edge[0]),
+                    b = context.entity(d.edge[1]),
+                    angle = Math.round(iD.geo.angle(a, b, projection) * (180 / Math.PI));
+                return translate(d) + ' rotate(' + angle + ')';
+            })
+            .call(iD.svg.TagClasses().tags(
+                function(d) { return d.parents[0].tags; }
+            ));
 
         // Propagate data bindings.
-        groups.select('circle.shadow');
-        groups.select('circle.fill');
+        groups.select('polygon.shadow');
+        groups.select('polygon.fill');
 
         groups.exit()
             .remove();
@@ -25017,194 +25819,15 @@ iD.svg.Points = function(projection, context) {
 
     return drawPoints;
 };
-iD.svg.Restrictions = function(context) {
-    var projection = context.projection;
-
-    function drawRestrictions(surface) {
-        var turns = drawRestrictions.turns(context.graph(), context.selectedIDs());
-
-        var groups = surface.select('.layer-hit').selectAll('g.restriction')
-            .data(turns, iD.Entity.key);
-
-        var enter = groups.enter().append('g')
-            .attr('class', 'restriction');
-
-        enter.append('circle')
-            .attr('class', 'restriction')
-            .attr('r', 4);
-
-        groups
-            .attr('transform', function(restriction) {
-                var via = context.entity(restriction.memberByRole('via').id);
-                return iD.svg.PointTransform(projection)(via);
-            });
-
-        groups.exit()
-            .remove();
-
-        return this;
-    }
-
-    drawRestrictions.turns = function (graph, selectedIDs) {
-        if (selectedIDs.length !== 1)
-            return [];
-
-        var from = graph.entity(selectedIDs[0]);
-        if (from.type !== 'way')
-            return [];
-
-        return graph.parentRelations(from).filter(function(relation) {
-            var f = relation.memberById(from.id),
-                t = relation.memberByRole('to'),
-                v = relation.memberByRole('via');
-
-            return relation.tags.type === 'restriction' && f.role === 'from' &&
-                t && t.type === 'way' && graph.hasEntity(t.id) &&
-                v && v.type === 'node' && graph.hasEntity(v.id) &&
-                !graph.entity(t.id).isDegenerate() &&
-                !graph.entity(f.id).isDegenerate() &&
-                graph.entity(t.id).affix(v.id) &&
-                graph.entity(f.id).affix(v.id);
-        });
-    };
-
-    drawRestrictions.datum = function(graph, from, restriction, projection) {
-        var to = graph.entity(restriction.memberByRole('to').id),
-            a = graph.entity(restriction.memberByRole('via').id),
-            b;
-
-        if (to.first() === a.id) {
-            b = graph.entity(to.nodes[1]);
-        } else {
-            b = graph.entity(to.nodes[to.nodes.length - 2]);
-        }
-
-        a = projection(a.loc);
-        b = projection(b.loc);
-
-        return {
-            from: from,
-            to: to,
-            restriction: restriction,
-            angle: Math.atan2(b[1] - a[1], b[0] - a[0])
-        };
-    };
-
-    return drawRestrictions;
-};
-iD.svg.Surface = function(context) {
-    function autosize(image) {
-        var img = document.createElement('img');
-        img.src = image.attr('xlink:href');
-        img.onload = function() {
-            image.attr({
-                width: img.width,
-                height: img.height
-            });
-        };
-    }
-
-    function SpriteDefinition(id, href, data) {
-        return function(defs) {
-            defs.append('image')
-                .attr('id', id)
-                .attr('xlink:href', href)
-                .call(autosize);
-
-            defs.selectAll()
-                .data(data)
-                .enter().append('use')
-                .attr('id', function(d) { return d.key; })
-                .attr('transform', function(d) { return 'translate(-' + d.value[0] + ',-' + d.value[1] + ')'; })
-                .attr('xlink:href', '#' + id);
-        };
-    }
-
-    return function drawSurface(selection) {
-        var defs = selection.append('defs');
-
-        defs.append('marker')
-            .attr({
-                id: 'oneway-marker',
-                viewBox: '0 0 10 10',
-                refY: 2.5,
-                refX: 5,
-                markerWidth: 2,
-                markerHeight: 2,
-                orient: 'auto'
-            })
-            .append('path')
-            .attr('d', 'M 5 3 L 0 3 L 0 2 L 5 2 L 5 0 L 10 2.5 L 5 5 z');
-
-        var patterns = defs.selectAll('pattern')
-            .data([
-                // pattern name, pattern image name
-                ['wetland', 'wetland'],
-                ['construction', 'construction'],
-                ['cemetery', 'cemetery'],
-                ['orchard', 'orchard'],
-                ['farmland', 'farmland'],
-                ['beach', 'dots'],
-                ['scrub', 'dots'],
-                ['meadow', 'dots']])
+iD.svg.Surface = function() {
+    return function (selection) {
+        selection.selectAll('defs')
+            .data([0])
             .enter()
-            .append('pattern')
-                .attr({
-                    id: function(d) { return 'pattern-' + d[0]; },
-                    width: 32,
-                    height: 32,
-                    patternUnits: 'userSpaceOnUse'
-                });
-
-        patterns.append('rect')
-            .attr({
-                x: 0,
-                y: 0,
-                width: 32,
-                height: 32,
-                'class': function(d) { return 'pattern-color-' + d[0]; }
-            });
-
-        patterns.append('image')
-            .attr({
-                x: 0,
-                y: 0,
-                width: 32,
-                height: 32
-            })
-            .attr('xlink:href', function(d) { return context.imagePath('pattern/' + d[1] + '.png'); });
-
-        defs.selectAll()
-            .data([12, 18, 20])
-            .enter().append('clipPath')
-            .attr('id', function(d) { return 'clip-square-' + d; })
-            .append('rect')
-            .attr('x', 0)
-            .attr('y', 0)
-            .attr('width', function(d) { return d; })
-            .attr('height', function(d) { return d; });
-
-        var maki = [];
-        _.forEach(iD.data.featureIcons, function(dimensions, name) {
-            if (dimensions['12'] && dimensions['18'] && dimensions['24']) {
-                maki.push({key: 'maki-' + name + '-12', value: dimensions['12']});
-                maki.push({key: 'maki-' + name + '-18', value: dimensions['18']});
-                maki.push({key: 'maki-' + name + '-24', value: dimensions['24']});
-            }
-        });
-
-        defs.call(SpriteDefinition(
-            'sprite',
-            context.imagePath('sprite.svg'),
-            d3.entries(iD.data.operations)));
-
-        defs.call(SpriteDefinition(
-            'maki-sprite',
-            context.imagePath('maki-sprite.png'),
-            maki));
+            .append('defs');
 
         var layers = selection.selectAll('.layer')
-            .data(['fill', 'shadow', 'casing', 'stroke', 'oneway', 'hit', 'halo', 'label']);
+            .data(['areas', 'lines', 'hit', 'halo', 'label']);
 
         layers.enter().append('g')
             .attr('class', function(d) { return 'layer layer-' + d; });
@@ -25265,6 +25888,77 @@ iD.svg.TagClasses = function() {
 
     return tagClasses;
 };
+iD.svg.Turns = function(projection) {
+    return function(surface, graph, turns) {
+        function key(turn) {
+            return [turn.from.node + turn.via.node + turn.to.node].join('-');
+        }
+
+        function icon(turn) {
+            var u = turn.u ? '-u' : '';
+            if (!turn.restriction)
+                return '#icon-restriction-yes' + u;
+            var restriction = graph.entity(turn.restriction).tags.restriction;
+            return '#icon-restriction-' +
+                (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
+        }
+
+        var groups = surface.select('.layer-hit').selectAll('g.turn')
+            .data(turns, key);
+
+        // Enter
+
+        var enter = groups.enter().append('g')
+            .attr('class', 'turn');
+
+        var nEnter = enter.filter(function (turn) { return !turn.u; });
+
+        nEnter.append('rect')
+            .attr('transform', 'translate(-12, -12)')
+            .attr('width', '45')
+            .attr('height', '25');
+
+        nEnter.append('use')
+            .attr('transform', 'translate(-12, -12)')
+            .attr('clip-path', 'url(#clip-square-45)');
+
+        var uEnter = enter.filter(function (turn) { return turn.u; });
+
+        uEnter.append('circle')
+            .attr('r', '16');
+
+        uEnter.append('use')
+            .attr('transform', 'translate(-16, -16)')
+            .attr('clip-path', 'url(#clip-square-32)');
+
+        // Update
+
+        groups
+            .attr('transform', function (turn) {
+                var v = graph.entity(turn.via.node),
+                    t = graph.entity(turn.to.node),
+                    a = iD.geo.angle(v, t, projection),
+                    p = projection(v.loc),
+                    r = turn.u ? 0 : 60;
+
+                return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' +
+                    'rotate(' + a * 180 / Math.PI + ')';
+            });
+
+        groups.select('use')
+            .attr('xlink:href', icon);
+
+        groups.select('rect');
+        groups.select('circle');
+
+        // Exit
+
+        groups.exit()
+            .remove();
+
+        return this;
+    };
+};
 iD.svg.Vertices = function(projection, context) {
     var radiuses = {
         //       z16-, z17, z18+, tagged
@@ -25311,49 +26005,74 @@ iD.svg.Vertices = function(projection, context) {
         return vertices;
     }
 
-    function draw(groups, vertices, klass, graph, zoom) {
-        groups = groups.data(vertices, function(entity) {
-            return iD.Entity.key(entity) + ',' + zoom;
-        });
+    function draw(selection, vertices, klass, graph, zoom) {
+        var icons = {},
+            z;
 
         if (zoom < 17) {
-            zoom = 0;
+            z = 0;
         } else if (zoom < 18) {
-            zoom = 1;
+            z = 1;
         } else {
-            zoom = 2;
+            z = 2;
         }
 
-        var icons = {};
+        var groups = selection.data(vertices, function(entity) {
+            return iD.Entity.key(entity);
+        });
+
         function icon(entity) {
             if (entity.id in icons) return icons[entity.id];
-            icons[entity.id] = zoom !== 0 &&
+            icons[entity.id] =
                 entity.hasInterestingTags() &&
                 context.presets().match(entity, graph).icon;
             return icons[entity.id];
         }
 
-        function circle(klass) {
-            var rads = radiuses[klass];
+        function classCircle(klass) {
             return function(entity) {
-                var i = icon(entity),
-                    c = i ? 0.5 : 0,
-                    r = rads[i ? 3 : zoom];
                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
-                this.setAttribute('cx', c);
-                this.setAttribute('cy', -c);
-                this.setAttribute('r', r);
             };
         }
 
-        var enter = groups.enter().append('g')
+        function setAttributes(selection) {
+            ['shadow','stroke','fill'].forEach(function(klass) {
+                var rads = radiuses[klass];
+                selection.selectAll('.' + klass)
+                    .each(function(entity) {
+                        var i = z && icon(entity),
+                            c = i ? 0.5 : 0,
+                            r = rads[i ? 3 : z];
+                        this.setAttribute('cx', c);
+                        this.setAttribute('cy', -c);
+                        this.setAttribute('r', r);
+                        if (i && klass === 'fill') {
+                            this.setAttribute('visibility', 'hidden');
+                        } else {
+                            this.removeAttribute('visibility');
+                        }
+                    });
+            });
+
+            selection.selectAll('use')
+                .each(function() {
+                    if (z) {
+                        this.removeAttribute('visibility');
+                    } else {
+                        this.setAttribute('visibility', 'hidden');
+                    }
+                });
+        }
+
+        var enter = groups.enter()
+            .append('g')
             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
 
         enter.append('circle')
-            .each(circle('shadow'));
+            .each(classCircle('shadow'));
 
         enter.append('circle')
-            .each(circle('stroke'));
+            .each(classCircle('stroke'));
 
         // Vertices with icons get a `use`.
         enter.filter(function(d) { return icon(d); })
@@ -25362,14 +26081,15 @@ iD.svg.Vertices = function(projection, context) {
             .attr('clip-path', 'url(#clip-square-12)')
             .attr('xlink:href', function(d) { return '#maki-' + icon(d) + '-12'; });
 
-        // Vertices with tags get a `circle`.
-        enter.filter(function(d) { return !icon(d) && d.hasInterestingTags(); })
+        // Vertices with tags get a fill.
+        enter.filter(function(d) { return d.hasInterestingTags(); })
             .append('circle')
-            .each(circle('fill'));
+            .each(classCircle('fill'));
 
         groups
             .attr('transform', iD.svg.PointTransform(projection))
-            .classed('shared', function(entity) { return graph.isShared(entity); });
+            .classed('shared', function(entity) { return graph.isShared(entity); })
+            .call(setAttributes);
 
         groups.exit()
             .remove();
@@ -25429,6 +26149,10 @@ iD.ui = function(context) {
             map.centerZoom([-77.02271, 38.90085], 20);
         }
 
+        container.append('svg')
+            .attr('id', 'defs')
+            .call(iD.svg.Defs(context));
+
         container.append('div')
             .attr('id', 'sidebar')
             .attr('class', 'col4')
@@ -25493,23 +26217,24 @@ iD.ui = function(context) {
             .attr('class', 'map-control help-control')
             .call(iD.ui.Help(context));
 
-        var about = content.append('div')
-            .attr('class','col12 about-block fillD');
+        var footer = content.append('div')
+            .attr('id', 'footer')
+            .attr('class', 'fillD');
 
-        about.append('div')
-            .attr('class', 'api-status')
-            .call(iD.ui.Status(context));
+        footer.append('div')
+            .attr('id', 'scale-block')
+            .call(iD.ui.Scale(context));
+
+        var linkList = footer.append('div')
+            .attr('id', 'info-block')
+            .append('ul')
+            .attr('id', 'about-list')
+            .attr('class', 'link-list');
 
         if (!context.embed()) {
-            about.append('div')
-                .attr('class', 'account')
-                .call(iD.ui.Account(context));
+            linkList.call(iD.ui.Account(context));
         }
 
-        var linkList = about.append('ul')
-            .attr('id', 'about')
-            .attr('class', 'link-list');
-
         linkList.append('li')
             .append('a')
             .attr('target', '_blank')
@@ -25536,6 +26261,10 @@ iD.ui = function(context) {
             .attr('tabindex', -1)
             .call(iD.ui.Contributors(context));
 
+        footer.append('div')
+            .attr('class', 'api-status')
+            .call(iD.ui.Status(context));
+
         window.onbeforeunload = function() {
             return context.save();
         };
@@ -25606,20 +26335,25 @@ iD.ui.Account = function(context) {
 
     function update(selection) {
         if (!connection.authenticated()) {
-            selection.html('')
+            selection.selectAll('#userLink, #logoutLink')
                 .style('display', 'none');
             return;
         }
 
-        selection.style('display', 'block');
-
         connection.userDetails(function(err, details) {
-            selection.html('');
+            var userLink = selection.select('#userLink'),
+                logoutLink = selection.select('#logoutLink');
+
+            userLink.html('');
+            logoutLink.html('');
 
             if (err) return;
 
+            selection.selectAll('#userLink, #logoutLink')
+                .style('display', 'list-item');
+
             // Link
-            var userLink = selection.append('a')
+            userLink.append('a')
                 .attr('href', connection.userURL(details.display_name))
                 .attr('target', '_blank');
 
@@ -25638,7 +26372,7 @@ iD.ui.Account = function(context) {
                 .attr('class', 'label')
                 .text(details.display_name);
 
-            selection.append('a')
+            logoutLink.append('a')
                 .attr('class', 'logout')
                 .attr('href', '#')
                 .text(t('logout'))
@@ -25650,7 +26384,15 @@ iD.ui.Account = function(context) {
     }
 
     return function(selection) {
-        connection.on('auth', function() { update(selection); });
+        selection.append('li')
+            .attr('id', 'logoutLink')
+            .style('display', 'none');
+
+        selection.append('li')
+            .attr('id', 'userLink')
+            .style('display', 'none');
+
+        connection.on('auth.account', function() { update(selection); });
         update(selection);
     };
 };
@@ -26491,6 +27233,8 @@ iD.ui.EntityEditor = function(context) {
         preset,
         reference;
 
+    var presetEditor = iD.ui.preset(context)
+        .on('change', changeTags);
     var rawTagEditor = iD.ui.RawTagEditor(context)
         .on('change', changeTags);
 
@@ -26577,12 +27321,11 @@ iD.ui.EntityEditor = function(context) {
             .text(preset.name());
 
         $body.select('.inspector-preset')
-            .call(iD.ui.preset(context)
+            .call(presetEditor
                 .preset(preset)
                 .entityID(id)
                 .tags(tags)
-                .state(state)
-                .on('change', changeTags));
+                .state(state));
 
         $body.select('.raw-tag-editor')
             .call(rawTagEditor
@@ -26619,11 +27362,13 @@ iD.ui.EntityEditor = function(context) {
 
     function clean(o) {
         var out = {}, k, v;
+        /*jshint -W083 */
         for (k in o) {
             if (k && (v = o[k]) !== undefined) {
-                out[k] = v.trim();
+                out[k] = v.split(';').map(function(s) { return s.trim(); }).join(';');
             }
         }
+        /*jshint +W083 */
         return out;
     }
 
@@ -26732,15 +27477,16 @@ iD.ui.FeatureList = function(context) {
                 });
             }
 
-            var locationMatch = q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
+            var locationMatch = sexagesimal.pair(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
 
             if (locationMatch) {
+                var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
                 result.push({
                     id: -1,
                     geometry: 'point',
                     type: t('inspector.location'),
-                    name: locationMatch[0],
-                    location: [parseFloat(locationMatch[1]), parseFloat(locationMatch[2])]
+                    name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
+                    location: loc
                 });
             }
 
@@ -27141,7 +27887,12 @@ iD.ui.Inspector = function(context) {
         var $presetPane = $wrap.select('.preset-list-pane');
         var $editorPane = $wrap.select('.entity-editor-pane');
 
-        var showEditor = state === 'hover' || context.entity(entityID).isUsed(context.graph());
+        var graph = context.graph(),
+            entity = context.entity(entityID),
+            showEditor = state === 'hover' ||
+                entity.isUsed(graph) ||
+                entity.isHighwayIntersection(graph);
+
         if (showEditor) {
             $wrap.style('right', '0%');
             $editorPane.call(entityEditor);
@@ -27669,6 +28420,10 @@ iD.ui.preset = function(context) {
                 }
             });
 
+            if (entity.isHighwayIntersection(context.graph())) {
+                fields.push(UIField(context.presets().field('restrictions'), entity, true));
+            }
+
             context.presets().universal().forEach(function(field) {
                 if (preset.fields.indexOf(field) < 0) {
                     fields.push(UIField(field, entity));
@@ -27793,6 +28548,7 @@ iD.ui.preset = function(context) {
 
     presets.preset = function(_) {
         if (!arguments.length) return preset;
+        if (preset && preset.id === _.id) return presets;
         preset = _;
         fields = null;
         return presets;
@@ -27813,6 +28569,7 @@ iD.ui.preset = function(context) {
 
     presets.entityID = function(_) {
         if (!arguments.length) return id;
+        if (id === _) return presets;
         id = _;
         fields = null;
         return presets;
@@ -28270,6 +29027,10 @@ iD.ui.RawMemberEditor = function(context) {
         context.perform(
             iD.actions.DeleteMember(d.relation.id, d.index),
             t('operations.delete_member.annotation'));
+
+        if (!context.hasEntity(d.relation.id)) {
+            context.enter(iD.modes.Browse(context));
+        }
     }
 
     function rawMemberEditor(selection) {
@@ -28917,6 +29678,88 @@ iD.ui.Save = function(context) {
         });
     };
 };
+iD.ui.Scale = function(context) {
+    var projection = context.projection,
+        imperial = (iD.detect().locale.toLowerCase() === 'en-us'),
+        maxLength = 180,
+        tickHeight = 8;
+
+    function scaleDefs(loc1, loc2) {
+        var lat = (loc2[1] + loc1[1]) / 2,
+            conversion = (imperial ? 3.28084 : 1),
+            dist = iD.geo.lonToMeters(loc2[0] - loc1[0], lat) * conversion,
+            scale = { dist: 0, px: 0, text: '' },
+            buckets, i, val, dLon;
+
+        if (imperial) {
+            buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
+        } else {
+            buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
+        }
+
+        // determine a user-friendly endpoint for the scale
+        for (i = 0; i < buckets.length; i++) {
+            val = buckets[i];
+            if (dist >= val) {
+                scale.dist = Math.floor(dist / val) * val;
+                break;
+            }
+        }
+
+        dLon = iD.geo.metersToLon(scale.dist / conversion, lat);
+        scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
+
+        if (imperial) {
+            if (scale.dist >= 5280) {
+                scale.dist /= 5280;
+                scale.text = String(scale.dist) + ' mi';
+            } else {
+                scale.text = String(scale.dist) + ' ft';
+            }
+        } else {
+            if (scale.dist >= 1000) {
+                scale.dist /= 1000;
+                scale.text = String(scale.dist) + ' km';
+            } else {
+                scale.text = String(scale.dist) + ' m';
+            }
+        }
+
+        return scale;
+    }
+
+    function update(selection) {
+        // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
+        var dims = context.map().dimensions(),
+            loc1 = projection.invert([0, dims[1]]),
+            loc2 = projection.invert([maxLength, dims[1]]),
+            scale = scaleDefs(loc1, loc2);
+
+        selection.select('#scalepath')
+            .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
+
+        selection.select('#scaletext')
+            .attr('x', scale.px + 8)
+            .attr('y', tickHeight)
+            .text(scale.text);
+    }
+
+    return function(selection) {
+        var g = selection.append('svg')
+            .attr('id', 'scale')
+            .append('g')
+            .attr('transform', 'translate(10,11)');
+
+        g.append('path').attr('id', 'scalepath');
+        g.append('text').attr('id', 'scaletext');
+
+        update(selection);
+
+        context.map().on('move.scale', function() {
+            update(selection);
+        });
+    };
+};
 iD.ui.SelectionList = function(context, selectedIDs) {
 
     function selectionList(selection) {
@@ -29054,6 +29897,7 @@ iD.ui.Sidebar = function(context) {
 
         sidebar.hide = function() {
             featureListWrap.classed('inspector-hidden', false);
+            inspectorWrap.classed('inspector-hidden', true);
             if (current) current.remove();
             current = null;
         };
@@ -29758,12 +30602,17 @@ iD.ui.preset.access = function(field) {
     return d3.rebind(access, event, 'on');
 };
 iD.ui.preset.address = function(field, context) {
-    var event = d3.dispatch('change'),
-        housenumber,
-        street,
-        city,
-        postcode,
-        entity;
+    var event = d3.dispatch('init', 'change'),
+        wrap,
+        entity,
+        isInitialized;
+
+    var widths = {
+        housenumber: 1/3,
+        street: 2/3,
+        city: 2/3,
+        postcode: 1/3
+    };
 
     function getStreets() {
         var extent = entity.extent(context.graph()),
@@ -29848,71 +30697,95 @@ iD.ui.preset.address = function(field, context) {
     }
 
     function address(selection) {
-        var wrap = selection.selectAll('.preset-input-wrap')
-            .data([0]);
+        selection.selectAll('.preset-input-wrap')
+            .remove();
+
+        var center = entity.extent(context.graph()).center(),
+            addressFormat;
 
         // Enter
 
-        var enter = wrap.enter().append('div')
+        wrap = selection.append('div')
             .attr('class', 'preset-input-wrap');
 
-        enter.append('input')
-            .property('type', 'text')
-            .attr('placeholder', field.t('placeholders.number'))
-            .attr('class', 'addr-number');
+        iD.countryCode().search(center, function (err, countryCode) {
+            addressFormat = _.find(iD.data.addressFormats, function (a) {
+                return a && a.countryCodes && _.contains(a.countryCodes, countryCode);
+            }) || _.first(iD.data.addressFormats);
 
-        enter.append('input')
-            .property('type', 'text')
-            .attr('placeholder', field.t('placeholders.street'))
-            .attr('class', 'addr-street');
+            function row(r) {
+                // Normalize widths.
+                var total = _.reduce(r, function(sum, field) {
+                    return sum + (widths[field] || 0.5);
+                }, 0);
 
-        enter.append('input')
-            .property('type', 'text')
-            .attr('placeholder', field.t('placeholders.city'))
-            .attr('class', 'addr-city');
+                return r.map(function (field) {
+                    return {
+                        id: field,
+                        width: (widths[field] || 0.5) / total
+                    };
+                });
+            }
 
-        enter.append('input')
-            .property('type', 'text')
-            .attr('placeholder', field.t('placeholders.postcode'))
-            .attr('class', 'addr-postcode');
+            wrap.selectAll('div')
+                .data(addressFormat.format)
+                .enter()
+                .append('div')
+                .attr('class', 'addr-row')
+                .selectAll('input')
+                .data(row)
+                .enter()
+                .append('input')
+                .property('type', 'text')
+                .attr('placeholder', function (d) { return field.t('placeholders.' + d.id); })
+                .attr('class', function (d) { return 'addr-' + d.id; })
+                .style('width', function (d) { return d.width * 100 + '%'; });
 
-        // Update
+            // Update
 
-        housenumber = wrap.select('.addr-number');
-        street = wrap.select('.addr-street');
-        city = wrap.select('.addr-city');
-        postcode = wrap.select('.addr-postcode');
+            wrap.selectAll('.addr-street')
+                .call(d3.combobox()
+                    .fetcher(function(value, callback) {
+                        callback(getStreets());
+                    }));
 
-        wrap.selectAll('input')
-            .on('blur', change)
-            .on('change', change);
+            wrap.selectAll('.addr-city')
+                .call(d3.combobox()
+                    .fetcher(function(value, callback) {
+                        callback(getCities());
+                    }));
 
-        street
-            .call(d3.combobox()
-                .fetcher(function(value, callback) {
-                    callback(getStreets());
-                }));
+            wrap.selectAll('.addr-postcode')
+                .call(d3.combobox()
+                    .fetcher(function(value, callback) {
+                        callback(getPostCodes());
+                    }));
 
-        city
-            .call(d3.combobox()
-                .fetcher(function(value, callback) {
-                    callback(getCities());
-                }));
+            wrap.selectAll('input')
+                .on('blur', change)
+                .on('change', change);
 
-        postcode
-            .call(d3.combobox()
-                .fetcher(function(value, callback) {
-                    callback(getPostCodes());
-                }));
+            event.init();
+            isInitialized = true;
+        });
     }
 
     function change() {
-        event.change({
-            'addr:housenumber': housenumber.value() || undefined,
-            'addr:street': street.value() || undefined,
-            'addr:city': city.value() || undefined,
-            'addr:postcode': postcode.value() || undefined
-        });
+        var tags = {};
+
+        wrap.selectAll('input')
+            .each(function (field) {
+                tags['addr:' + field.id] = this.value || undefined;
+            });
+
+        event.change(tags);
+    }
+
+    function updateTags(tags) {
+        wrap.selectAll('input')
+            .value(function (field) {
+                return tags['addr:' + field.id] || '';
+            });
     }
 
     address.entity = function(_) {
@@ -29922,14 +30795,17 @@ iD.ui.preset.address = function(field, context) {
     };
 
     address.tags = function(tags) {
-        housenumber.value(tags['addr:housenumber'] || '');
-        street.value(tags['addr:street'] || '');
-        city.value(tags['addr:city'] || '');
-        postcode.value(tags['addr:postcode'] || '');
+        if (isInitialized) {
+            updateTags(tags);
+        } else {
+            event.on('init', function () {
+                updateTags(tags);
+            });
+        }
     };
 
     address.focus = function() {
-        housenumber.node().focus();
+        wrap.selectAll('input').node().focus();
     };
 
     return d3.rebind(address, event, 'on');
@@ -29937,15 +30813,37 @@ iD.ui.preset.address = function(field, context) {
 iD.ui.preset.check =
 iD.ui.preset.defaultcheck = function(field) {
     var event = d3.dispatch('change'),
-        values = field.type === 'check' ?
-            [undefined, 'yes', 'no'] :
-            [undefined, 'yes'],
-        value,
-        box,
-        text,
-        label;
+        options = field.strings && field.strings.options,
+        values = [],
+        texts = [],
+        entity, value, box, text, label;
+
+    if (options) {
+        for (var k in options) {
+            values.push(k === 'undefined' ? undefined : k);
+            texts.push(field.t('options.' + k, { 'default': options[k] }));
+        }
+    } else {
+        values = [undefined, 'yes'];
+        texts = [t('inspector.unknown'), t('inspector.check.yes')];
+        if (field.type === 'check') {
+            values.push('no');
+            texts.push(t('inspector.check.no'));
+        }
+    }
 
     var check = function(selection) {
+        // hack: pretend oneway field is a oneway_yes field
+        // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
+        if (field.id === 'oneway') {
+            for (var key in entity.tags) {
+                if (key in iD.oneWayTags && (entity.tags[key] in iD.oneWayTags[key])) {
+                    texts[0] = t('presets.fields.oneway_yes.options.undefined');
+                    break;
+                }
+            }
+        }
+
         selection.classed('checkselect', 'true');
 
         label = selection.selectAll('.preset-input-wrap')
@@ -29960,7 +30858,7 @@ iD.ui.preset.defaultcheck = function(field) {
             .attr('id', 'preset-input-' + field.id);
 
         enter.append('span')
-            .text(t('inspector.unknown'))
+            .text(texts[0])
             .attr('class', 'value');
 
         box = label.select('input')
@@ -29974,12 +30872,17 @@ iD.ui.preset.defaultcheck = function(field) {
         text = label.select('span.value');
     };
 
+    check.entity = function(_) {
+        if (!arguments.length) return entity;
+        entity = _;
+        return check;
+    };
+
     check.tags = function(tags) {
         value = tags[field.key];
         box.property('indeterminate', field.type === 'check' && !value);
         box.property('checked', value === 'yes');
-        text.text(value ? t('inspector.check.' + value, {default: value}) :
-            field.type === 'check' ? t('inspector.unknown') : t('inspector.check.no'));
+        text.text(texts[values.indexOf(value)]);
         label.classed('set', !!value);
     };
 
@@ -29992,6 +30895,9 @@ iD.ui.preset.defaultcheck = function(field) {
 iD.ui.preset.combo =
 iD.ui.preset.typeCombo = function(field) {
     var event = d3.dispatch('change'),
+        optstrings = field.strings && field.strings.options,
+        optarray = field.options,
+        strings = {},
         input;
 
     function combo(selection) {
@@ -30000,42 +30906,67 @@ iD.ui.preset.typeCombo = function(field) {
         input = selection.selectAll('input')
             .data([0]);
 
-        input.enter().append('input')
+        var enter = input.enter()
+            .append('input')
             .attr('type', 'text')
             .attr('id', 'preset-input-' + field.id);
 
+        if (optstrings) { enter.attr('readonly', 'readonly'); }
+
         input
+            .call(combobox)
             .on('change', change)
             .on('blur', change)
             .each(function() {
-                if (field.options) {
-                    options(field.options);
+                if (optstrings) {
+                    _.each(optstrings, function(v, k) {
+                        strings[k] = field.t('options.' + k, { 'default': v });
+                    });
+                    stringsLoaded();
+                } else if (optarray) {
+                    _.each(optarray, function(k) {
+                        strings[k] = k.replace(/_+/g, ' ');
+                    });
+                    stringsLoaded();
                 } else {
-                    iD.taginfo().values({
-                        key: field.key
-                    }, function(err, data) {
-                        if (!err) options(_.pluck(data, 'value'));
+                    iD.taginfo().values({key: field.key}, function(err, data) {
+                        if (!err) {
+                            _.each(_.pluck(data, 'value'), function(k) {
+                                strings[k] = k.replace(/_+/g, ' ');
+                            });
+                            stringsLoaded();
+                        }
                     });
                 }
-            })
-            .call(combobox);
+            });
 
-        function options(opts) {
-            combobox.data(opts.map(function(d) {
-                var o = {};
-                o.title = o.value = d.replace('_', ' ');
+        function stringsLoaded() {
+            var keys = _.keys(strings),
+                strs = [],
+                placeholders;
+
+            combobox.data(keys.map(function(k) {
+                var s = strings[k],
+                    o = {};
+                o.title = o.value = s;
+                if (s.length < 20) { strs.push(s); }
                 return o;
             }));
 
-            input.attr('placeholder', function() {
-                if (opts.length < 3) return '';
-                return opts.slice(0, 3).join(', ') + '...';
-            });
+            placeholders = strs.length > 1 ? strs : keys;
+            input.attr('placeholder', field.placeholder() ||
+                (placeholders.slice(0, 3).join(', ') + '...'));
         }
     }
 
     function change() {
-        var value = input.value().replace(' ', '_');
+        var optstring = _.find(_.keys(strings), function(k) { return strings[k] === input.value(); }),
+            value = optstring || (input.value()
+                .split(';')
+                .map(function(s) { return s.trim(); })
+                .join(';')
+                .replace(/\s+/g, '_'));
+
         if (field.type === 'typeCombo' && !value) value = 'yes';
 
         var t = {};
@@ -30044,8 +30975,9 @@ iD.ui.preset.typeCombo = function(field) {
     }
 
     combo.tags = function(tags) {
-        var value = tags[field.key] || '';
-        if (field.type === 'typeCombo' && value === 'yes') value = '';
+        var key = tags[field.key],
+            value = strings[key] || key || '';
+        if (field.type === 'typeCombo' && value.toLowerCase() === 'yes') value = '';
         input.value(value);
     };
 
@@ -30137,10 +31069,6 @@ iD.ui.preset.localized = function(field, context) {
             .attr('class', 'localized-main')
             .attr('placeholder', field.placeholder());
 
-        input
-            .on('blur', change)
-            .on('change', change);
-
         if (field.id === 'name') {
             var preset = context.presets().match(entity, context.graph());
             input.call(d3.combobox().fetcher(
@@ -30148,6 +31076,10 @@ iD.ui.preset.localized = function(field, context) {
             ));
         }
 
+        input
+            .on('blur', change)
+            .on('change', change);
+
         var translateButton = selection.selectAll('.localized-add')
             .data([0]);
 
@@ -30377,9 +31309,9 @@ iD.ui.preset.maxspeed = function(field, context) {
             .attr('placeholder', field.placeholder());
 
         input
+            .call(combobox)
             .on('change', change)
-            .on('blur', change)
-            .call(combobox);
+            .on('blur', change);
 
         var childNodes = context.graph().childNodes(context.entity(entity.id)),
             loc = childNodes[~~(childNodes.length/2)].loc;
@@ -30539,6 +31471,145 @@ iD.ui.preset.radio = function(field) {
 
     return d3.rebind(radio, event, 'on');
 };
+iD.ui.preset.restrictions = function(field, context) {
+    var event = d3.dispatch('change'),
+        vertexID,
+        fromNodeID;
+
+    function restrictions(selection) {
+        var wrap = selection.selectAll('.preset-input-wrap')
+            .data([0]);
+
+        var enter = wrap.enter().append('div')
+            .attr('class', 'preset-input-wrap');
+
+        enter.append('div')
+            .attr('class', 'restriction-help');
+
+        enter.append('svg')
+            .call(iD.svg.Surface(context))
+            .call(iD.behavior.Hover(context));
+
+        var intersection = iD.geo.Intersection(context.graph(), vertexID),
+            graph = intersection.graph,
+            vertex = graph.entity(vertexID),
+            surface = wrap.selectAll('svg'),
+            filter = function () { return true; },
+            extent = iD.geo.Extent(),
+            projection = iD.geo.RawMercator(),
+            lines = iD.svg.Lines(projection, context),
+            vertices = iD.svg.Vertices(projection, context),
+            turns = iD.svg.Turns(projection, context);
+
+        var d = wrap.dimensions(),
+            c = [d[0] / 2, d[1] / 2],
+            z = 21;
+
+        projection
+            .scale(256 * Math.pow(2, z) / (2 * Math.PI));
+
+        var s = projection(vertex.loc);
+
+        projection
+            .translate([c[0] - s[0], c[1] - s[1]])
+            .clipExtent([[0, 0], d]);
+
+        surface
+            .call(vertices, graph, [vertex], filter, extent, z)
+            .call(lines, graph, intersection.highways, filter)
+            .call(turns, graph, intersection.turns(fromNodeID));
+
+        surface
+            .on('click.restrictions', click)
+            .on('mouseover.restrictions', mouseover)
+            .on('mouseout.restrictions', mouseout);
+
+        surface
+            .selectAll('.selected')
+            .classed('selected', false);
+
+        if (fromNodeID) {
+            surface
+                .selectAll('.' + _.find(intersection.highways, function(way) { return way.contains(fromNodeID); }).id)
+                .classed('selected', true);
+        }
+
+        mouseout();
+
+        context.history()
+            .on('change.restrictions', render);
+
+        d3.select(window)
+            .on('resize.restrictions', render);
+
+        function click() {
+            var datum = d3.event.target.__data__;
+            if (datum instanceof iD.Entity) {
+                fromNodeID = datum.nodes[(datum.first() === vertexID) ? 1 : datum.nodes.length - 2];
+                render();
+            } else if (datum instanceof iD.geo.Turn) {
+                if (datum.restriction) {
+                    context.perform(
+                        iD.actions.UnrestrictTurn(datum, projection),
+                        t('operations.restriction.annotation.delete'));
+                } else {
+                    context.perform(
+                        iD.actions.RestrictTurn(datum, projection),
+                        t('operations.restriction.annotation.create'));
+                }
+            }
+        }
+
+        function mouseover() {
+            var datum = d3.event.target.__data__;
+            if (datum instanceof iD.geo.Turn) {
+                var graph = context.graph(),
+                    presets = context.presets(),
+                    preset;
+
+                if (datum.restriction) {
+                    preset = presets.match(graph.entity(datum.restriction), graph);
+                } else {
+                    preset = presets.item('type/restriction/' +
+                        iD.geo.inferRestriction(
+                            graph.entity(datum.from.node),
+                            graph.entity(datum.via.node),
+                            graph.entity(datum.to.node),
+                            projection));
+                }
+
+                wrap.selectAll('.restriction-help')
+                    .text(t('operations.restriction.help.' +
+                        (datum.restriction ? 'toggle_off' : 'toggle_on'),
+                        {restriction: preset.name()}));
+            }
+        }
+
+        function mouseout() {
+            wrap.selectAll('.restriction-help')
+                .text(t('operations.restriction.help.' +
+                    (fromNodeID ? 'toggle' : 'select')));
+        }
+
+        function render() {
+            if (context.hasEntity(vertexID)) {
+                restrictions(selection);
+            }
+        }
+    }
+
+    restrictions.entity = function(_) {
+        if (!vertexID || vertexID !== _.id) {
+            fromNodeID = null;
+            vertexID = _.id;
+        }
+    };
+
+    restrictions.tags = function() {};
+    restrictions.focus = function() {};
+
+    return d3.rebind(restrictions, event, 'on');
+};
 iD.ui.preset.textarea = function(field) {
 
     var event = d3.dispatch('change'),
@@ -30617,9 +31688,9 @@ iD.ui.preset.wikipedia = function(field, context) {
             .value('English');
 
         lang
+            .call(langcombo)
             .on('blur', changeLang)
-            .on('change', changeLang)
-            .call(langcombo);
+            .on('change', changeLang);
 
         title = selection.selectAll('input.wiki-title')
             .data([0]);
@@ -30630,9 +31701,9 @@ iD.ui.preset.wikipedia = function(field, context) {
             .attr('id', 'preset-input-' + field.id);
 
         title
+            .call(titlecombo)
             .on('blur', change)
-            .on('change', change)
-            .call(titlecombo);
+            .on('change', change);
 
         link = selection.selectAll('a.wiki-link')
             .data([0]);
@@ -31483,7 +32554,7 @@ iD.presets.Field = function(id, field) {
     field.id = id;
 
     field.matchGeometry = function(geometry) {
-        return !field.geometry || field.geometry.indexOf(geometry) >= 0;
+        return !field.geometry || field.geometry === geometry;
     };
 
     field.t = function(scope, options) {
@@ -31645,7 +32716,7 @@ iD.validate = function(changes, graph) {
         if ((geometry === 'point' || geometry === 'line' || geometry === 'area') && !change.isUsed(graph)) {
             warnings.push({
                 message: t('validations.untagged_' + geometry),
-                tooltip: t('validations.untagged_tooltip', {geometry: geometry}),
+                tooltip: t('validations.untagged_' + geometry + '_tooltip'),
                 entity: change
             });
         }
@@ -41978,7 +43049,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "name": "Locator Overlay",
             "type": "tms",
             "description": "Shows major features to help orient you.",
-            "template": "http://{switch:a,b,c}.tiles.mapbox.com/v3/openstreetmap.map-btyhiati/{zoom}/{x}/{y}.png",
+            "template": "http://{switch:a,b,c}.tiles.mapbox.com/v4/openstreetmap.map-inh76ba2/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJhNVlHd29ZIn0.ti6wATGDWOmCnCYen-Ip7Q",
             "scaleExtent": [
                 0,
                 16
@@ -41998,7 +43069,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "name": "Mapbox Satellite",
             "type": "tms",
             "description": "Satellite and aerial imagery.",
-            "template": "http://{switch:a,b,c}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{zoom}/{x}/{y}.png",
+            "template": "http://{switch:a,b,c}.tiles.mapbox.com/v4/openstreetmap.map-inh7ifmo/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJhNVlHd29ZIn0.ti6wATGDWOmCnCYen-Ip7Q",
             "scaleExtent": [
                 0,
                 19
@@ -63504,6 +64575,19 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "name": "Boat Rental"
             },
+            "amenity/bus_station": {
+                "geometry": [
+                    "point",
+                    "area"
+                ],
+                "tags": {
+                    "amenity": "bus_station"
+                },
+                "fields": [
+                    "operator"
+                ],
+                "name": "Bus Station"
+            },
             "amenity/cafe": {
                 "icon": "cafe",
                 "fields": [
@@ -63760,6 +64844,26 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "opening_hours"
                 ]
             },
+            "amenity/dojo": {
+                "icon": "pitch",
+                "geometry": [
+                    "point",
+                    "area"
+                ],
+                "terms": [
+                    "martial arts",
+                    "dojo",
+                    "dojang"
+                ],
+                "tags": {
+                    "amenity": "dojo"
+                },
+                "fields": [
+                    "address",
+                    "sport"
+                ],
+                "name": "Dojo / Martial Arts Academy"
+            },
             "amenity/drinking_water": {
                 "icon": "water",
                 "geometry": [
@@ -64637,8 +65741,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "toilets/disposal",
                     "operator",
                     "building_area",
-                    "fee",
-                    "access_simple"
+                    "access_toilets"
                 ],
                 "geometry": [
                     "point",
@@ -66328,7 +67431,8 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "address",
                     "operator",
                     "opening_hours"
-                ]
+                ],
+                "searchable": false
             },
             "craft/tiler": {
                 "name": "Tiler",
@@ -66504,7 +67608,9 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "fields": [
                     "crossing",
                     "access",
-                    "surface"
+                    "surface",
+                    "sloped_curb",
+                    "tactile_paving"
                 ],
                 "geometry": [
                     "line"
@@ -66513,11 +67619,30 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "highway": "footway",
                     "footway": "crossing"
                 },
+                "terms": [],
+                "name": "Crossing"
+            },
+            "footway/crosswalk": {
+                "fields": [
+                    "crossing",
+                    "access",
+                    "surface",
+                    "sloped_curb",
+                    "tactile_paving"
+                ],
+                "geometry": [
+                    "line"
+                ],
+                "tags": {
+                    "highway": "footway",
+                    "footway": "crossing",
+                    "crossing": "zebra"
+                },
                 "terms": [
                     "crosswalk",
                     "zebra crossing"
                 ],
-                "name": "Crossing"
+                "name": "Crosswalk"
             },
             "footway/sidewalk": {
                 "fields": [
@@ -66718,11 +67843,27 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "tags": {
                     "highway": "crossing"
                 },
+                "terms": [],
+                "name": "Crossing"
+            },
+            "highway/crosswalk": {
+                "fields": [
+                    "crossing",
+                    "sloped_curb",
+                    "tactile_paving"
+                ],
+                "geometry": [
+                    "vertex"
+                ],
+                "tags": {
+                    "highway": "crossing",
+                    "crossing": "zebra"
+                },
                 "terms": [
                     "crosswalk",
                     "zebra crossing"
                 ],
-                "name": "Crossing"
+                "name": "Crosswalk"
             },
             "highway/cycleway": {
                 "icon": "highway-cycleway",
@@ -66819,7 +67960,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "highway/motorway": {
                 "icon": "highway-motorway",
                 "fields": [
-                    "oneway",
+                    "oneway_yes",
                     "maxspeed",
                     "structure",
                     "access",
@@ -66846,7 +67987,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "fields": [
                     "ref"
                 ],
-                "name": "Motorway Junction"
+                "name": "Motorway Junction / Exit"
             },
             "highway/motorway_link": {
                 "icon": "highway-motorway-link",
@@ -66878,9 +68019,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "width",
                     "structure",
                     "access",
-                    "sac_scale",
                     "incline",
+                    "sac_scale",
                     "trail_visibility",
+                    "mtb/scale",
+                    "mtb/scale/uphill",
+                    "mtb/scale/imba",
                     "ref"
                 ],
                 "geometry": [
@@ -67196,6 +68340,27 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "name": "Stop Sign"
             },
+            "highway/street_lamp": {
+                "geometry": [
+                    "point",
+                    "vertex"
+                ],
+                "tags": {
+                    "highway": "street_lamp"
+                },
+                "fields": [
+                    "lamp_type",
+                    "ref"
+                ],
+                "terms": [
+                    "streetlight",
+                    "street light",
+                    "lamp",
+                    "light",
+                    "gaslight"
+                ],
+                "name": "Street Lamp"
+            },
             "highway/tertiary": {
                 "icon": "highway-tertiary",
                 "fields": [
@@ -67242,12 +68407,16 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "highway/track": {
                 "icon": "highway-track",
                 "fields": [
-                    "tracktype",
-                    "oneway",
-                    "maxspeed",
+                    "surface",
+                    "width",
                     "structure",
                     "access",
-                    "surface"
+                    "incline",
+                    "tracktype",
+                    "smoothness",
+                    "mtb/scale",
+                    "mtb/scale/uphill",
+                    "mtb/scale/imba"
                 ],
                 "geometry": [
                     "line"
@@ -68042,6 +69211,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "name": "Slipway"
             },
             "leisure/sports_center": {
+                "icon": "pitch",
                 "geometry": [
                     "point",
                     "area"
@@ -68052,10 +69222,13 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "terms": [
                     "gym"
                 ],
-                "icon": "sports",
-                "name": "Sports Center"
+                "fields": [
+                    "sport"
+                ],
+                "name": "Sports Center / Gym"
             },
             "leisure/stadium": {
+                "icon": "pitch",
                 "geometry": [
                     "point",
                     "area"
@@ -70505,6 +71678,27 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 },
                 "name": "Supermarket"
             },
+            "shop/tailor": {
+                "name": "Tailor",
+                "geometry": [
+                    "point",
+                    "area"
+                ],
+                "terms": [
+                    "tailor",
+                    "clothes"
+                ],
+                "tags": {
+                    "shop": "tailor"
+                },
+                "icon": "clothing-store",
+                "fields": [
+                    "building_area",
+                    "address",
+                    "operator",
+                    "opening_hours"
+                ]
+            },
             "shop/toys": {
                 "icon": "shop",
                 "fields": [
@@ -70984,9 +72178,108 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "name": "Restriction",
                 "icon": "restriction",
                 "fields": [
-                    "restriction"
+                    "restriction",
+                    "except"
                 ]
             },
+            "type/restriction/no_left_turn": {
+                "name": "No Left Turn",
+                "geometry": [
+                    "relation"
+                ],
+                "tags": {
+                    "type": "restriction",
+                    "restriction": "no_left_turn"
+                },
+                "fields": [
+                    "except"
+                ],
+                "icon": "restriction-no-left-turn"
+            },
+            "type/restriction/no_right_turn": {
+                "name": "No Right Turn",
+                "geometry": [
+                    "relation"
+                ],
+                "tags": {
+                    "type": "restriction",
+                    "restriction": "no_right_turn"
+                },
+                "fields": [
+                    "except"
+                ],
+                "icon": "restriction-no-right-turn"
+            },
+            "type/restriction/no_straight_on": {
+                "name": "No Straight On",
+                "geometry": [
+                    "relation"
+                ],
+                "tags": {
+                    "type": "restriction",
+                    "restriction": "no_straight_on"
+                },
+                "fields": [
+                    "except"
+                ],
+                "icon": "restriction-no-straight-on"
+            },
+            "type/restriction/no_u_turn": {
+                "name": "No U-turn",
+                "geometry": [
+                    "relation"
+                ],
+                "tags": {
+                    "type": "restriction",
+                    "restriction": "no_u_turn"
+                },
+                "fields": [
+                    "except"
+                ],
+                "icon": "restriction-no-u-turn"
+            },
+            "type/restriction/only_left_turn": {
+                "name": "Left Turn Only",
+                "geometry": [
+                    "relation"
+                ],
+                "tags": {
+                    "type": "restriction",
+                    "restriction": "only_left_turn"
+                },
+                "fields": [
+                    "except"
+                ],
+                "icon": "restriction-only-left-turn"
+            },
+            "type/restriction/only_right_turn": {
+                "name": "Right Turn Only",
+                "geometry": [
+                    "relation"
+                ],
+                "tags": {
+                    "type": "restriction",
+                    "restriction": "only_right_turn"
+                },
+                "fields": [
+                    "except"
+                ],
+                "icon": "restriction-only-right-turn"
+            },
+            "type/restriction/only_straight_on": {
+                "name": "No Turns",
+                "geometry": [
+                    "relation"
+                ],
+                "tags": {
+                    "type": "restriction",
+                    "restriction": "only_straight_on"
+                },
+                "fields": [
+                    "except"
+                ],
+                "icon": "restriction-only-straight-on"
+            },
             "type/route": {
                 "geometry": [
                     "relation"
@@ -71597,25 +72890,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Sainsbury's": {
-                "tags": {
-                    "name": "Sainsbury's",
-                    "amenity": "fuel"
-                },
-                "name": "Sainsbury's",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/OMV": {
                 "tags": {
                     "name": "OMV",
@@ -71654,25 +72928,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Tesco": {
-                "tags": {
-                    "name": "Tesco",
-                    "amenity": "fuel"
-                },
-                "name": "Tesco",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/JET": {
                 "tags": {
                     "name": "JET",
@@ -71692,25 +72947,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Morrisons": {
-                "tags": {
-                    "name": "Morrisons",
-                    "amenity": "fuel"
-                },
-                "name": "Morrisons",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/United": {
                 "tags": {
                     "name": "United",
@@ -71730,25 +72966,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Canadian Tire": {
-                "tags": {
-                    "name": "Canadian Tire",
-                    "amenity": "fuel"
-                },
-                "name": "Canadian Tire",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Mobil": {
                 "tags": {
                     "name": "Mobil",
@@ -71825,25 +73042,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/ABC": {
-                "tags": {
-                    "name": "ABC",
-                    "amenity": "fuel"
-                },
-                "name": "ABC",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/ARAL": {
                 "tags": {
                     "name": "ARAL",
@@ -71920,25 +73118,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Intermarché": {
-                "tags": {
-                    "name": "Intermarché",
-                    "amenity": "fuel"
-                },
-                "name": "Intermarché",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Total Access": {
                 "tags": {
                     "name": "Total Access",
@@ -71958,44 +73137,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Super U": {
-                "tags": {
-                    "name": "Super U",
-                    "amenity": "fuel"
-                },
-                "name": "Super U",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
-            "amenity/fuel/Auchan": {
-                "tags": {
-                    "name": "Auchan",
-                    "amenity": "fuel"
-                },
-                "name": "Auchan",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Elf": {
                 "tags": {
                     "name": "Elf",
@@ -72015,25 +73156,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Carrefour": {
-                "tags": {
-                    "name": "Carrefour",
-                    "amenity": "fuel"
-                },
-                "name": "Carrefour",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Station Service E. Leclerc": {
                 "tags": {
                     "name": "Station Service E. Leclerc",
@@ -72376,25 +73498,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Raiffeisenbank": {
-                "tags": {
-                    "name": "Raiffeisenbank",
-                    "amenity": "fuel"
-                },
-                "name": "Raiffeisenbank",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Tamoil": {
                 "tags": {
                     "name": "Tamoil",
@@ -72490,25 +73593,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Coop": {
-                "tags": {
-                    "name": "Coop",
-                    "amenity": "fuel"
-                },
-                "name": "Coop",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Orlen": {
                 "tags": {
                     "name": "Orlen",
@@ -72718,25 +73802,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/7-Eleven": {
-                "tags": {
-                    "name": "7-Eleven",
-                    "amenity": "fuel"
-                },
-                "name": "7-Eleven",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Agrola": {
                 "tags": {
                     "name": "Agrola",
@@ -73858,25 +74923,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Wawa": {
-                "tags": {
-                    "name": "Wawa",
-                    "amenity": "fuel"
-                },
-                "name": "Wawa",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Pertamina": {
                 "tags": {
                     "name": "Pertamina",
@@ -74372,25 +75418,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Circle K": {
-                "tags": {
-                    "name": "Circle K",
-                    "amenity": "fuel"
-                },
-                "name": "Circle K",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Posto Ipiranga": {
                 "tags": {
                     "name": "Posto Ipiranga",
@@ -74543,25 +75570,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/Stewart's": {
-                "tags": {
-                    "name": "Stewart's",
-                    "amenity": "fuel"
-                },
-                "name": "Stewart's",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Posto BR": {
                 "tags": {
                     "name": "Posto BR",
@@ -74733,25 +75741,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/fuel/H-E-B": {
-                "tags": {
-                    "name": "H-E-B",
-                    "amenity": "fuel"
-                },
-                "name": "H-E-B",
-                "icon": "fuel",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "address",
-                    "building_area"
-                ],
-                "suggestion": true
-            },
             "amenity/fuel/Укрнафта": {
                 "tags": {
                     "name": "Укрнафта",
@@ -75828,6 +76817,28 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "amenity/fast_food/Subway": {
+                "tags": {
+                    "name": "Subway",
+                    "cuisine": "sandwich",
+                    "amenity": "fast_food"
+                },
+                "name": "Subway",
+                "icon": "fast-food",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "cuisine",
+                    "building_area",
+                    "address",
+                    "opening_hours",
+                    "smoking"
+                ],
+                "suggestion": true
+            },
             "amenity/fast_food/Burger King": {
                 "tags": {
                     "name": "Burger King",
@@ -80535,6 +81546,26 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "amenity/bank/Raiffeisenbank": {
+                "tags": {
+                    "name": "Raiffeisenbank",
+                    "amenity": "bank"
+                },
+                "name": "Raiffeisenbank",
+                "icon": "bank",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "atm",
+                    "building_area",
+                    "address",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "amenity/bank/Yorkshire Bank": {
                 "tags": {
                     "name": "Yorkshire Bank",
@@ -86254,26 +87285,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "amenity/pharmacy/Радуга": {
-                "tags": {
-                    "name": "Радуга",
-                    "amenity": "pharmacy"
-                },
-                "name": "Радуга",
-                "icon": "pharmacy",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address",
-                    "opening_hours"
-                ],
-                "suggestion": true
-            },
             "amenity/pharmacy/サンドラッグ": {
                 "tags": {
                     "name": "サンドラッグ",
@@ -87434,6 +88445,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/supermarket/Morrisons": {
+                "tags": {
+                    "name": "Morrisons",
+                    "shop": "supermarket"
+                },
+                "name": "Morrisons",
+                "icon": "grocery",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "operator",
+                    "building_area",
+                    "address"
+                ],
+                "suggestion": true
+            },
             "shop/supermarket/Interspar": {
                 "tags": {
                     "name": "Interspar",
@@ -87472,6 +88502,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/supermarket/Sainsbury's": {
+                "tags": {
+                    "name": "Sainsbury's",
+                    "shop": "supermarket"
+                },
+                "name": "Sainsbury's",
+                "icon": "grocery",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "operator",
+                    "building_area",
+                    "address"
+                ],
+                "suggestion": true
+            },
             "shop/supermarket/Lidl": {
                 "tags": {
                     "name": "Lidl",
@@ -87548,6 +88597,44 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/supermarket/Coop": {
+                "tags": {
+                    "name": "Coop",
+                    "shop": "supermarket"
+                },
+                "name": "Coop",
+                "icon": "grocery",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "operator",
+                    "building_area",
+                    "address"
+                ],
+                "suggestion": true
+            },
+            "shop/supermarket/Tesco": {
+                "tags": {
+                    "name": "Tesco",
+                    "shop": "supermarket"
+                },
+                "name": "Tesco",
+                "icon": "grocery",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "operator",
+                    "building_area",
+                    "address"
+                ],
+                "suggestion": true
+            },
             "shop/supermarket/Woolworths": {
                 "tags": {
                     "name": "Woolworths",
@@ -87890,25 +88977,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Tesco Express": {
-                "tags": {
-                    "name": "Tesco Express",
-                    "shop": "supermarket"
-                },
-                "name": "Tesco Express",
-                "icon": "grocery",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address"
-                ],
-                "suggestion": true
-            },
             "shop/supermarket/King Soopers": {
                 "tags": {
                     "name": "King Soopers",
@@ -88023,6 +89091,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/supermarket/Carrefour": {
+                "tags": {
+                    "name": "Carrefour",
+                    "shop": "supermarket"
+                },
+                "name": "Carrefour",
+                "icon": "grocery",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "operator",
+                    "building_area",
+                    "address"
+                ],
+                "suggestion": true
+            },
             "shop/supermarket/Waitrose": {
                 "tags": {
                     "name": "Waitrose",
@@ -88422,6 +89509,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/supermarket/Super U": {
+                "tags": {
+                    "name": "Super U",
+                    "shop": "supermarket"
+                },
+                "name": "Super U",
+                "icon": "grocery",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "operator",
+                    "building_area",
+                    "address"
+                ],
+                "suggestion": true
+            },
             "shop/supermarket/Metro": {
                 "tags": {
                     "name": "Metro",
@@ -88650,25 +89756,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/COOP Jednota": {
-                "tags": {
-                    "name": "COOP Jednota",
-                    "shop": "supermarket"
-                },
-                "name": "COOP Jednota",
-                "icon": "grocery",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address"
-                ],
-                "suggestion": true
-            },
             "shop/supermarket/Rema 1000": {
                 "tags": {
                     "name": "Rema 1000",
@@ -89296,6 +90383,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/supermarket/Auchan": {
+                "tags": {
+                    "name": "Auchan",
+                    "shop": "supermarket"
+                },
+                "name": "Auchan",
+                "icon": "grocery",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "operator",
+                    "building_area",
+                    "address"
+                ],
+                "suggestion": true
+            },
             "shop/supermarket/Mercadona": {
                 "tags": {
                     "name": "Mercadona",
@@ -89448,12 +90554,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Costcutter": {
+            "shop/supermarket/Maxi": {
                 "tags": {
-                    "name": "Costcutter",
+                    "name": "Maxi",
                     "shop": "supermarket"
                 },
-                "name": "Costcutter",
+                "name": "Maxi",
                 "icon": "grocery",
                 "geometry": [
                     "point",
@@ -89467,12 +90573,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Maxi": {
+            "shop/supermarket/Colruyt": {
                 "tags": {
-                    "name": "Maxi",
+                    "name": "Colruyt",
                     "shop": "supermarket"
                 },
-                "name": "Maxi",
+                "name": "Colruyt",
                 "icon": "grocery",
                 "geometry": [
                     "point",
@@ -89486,12 +90592,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Colruyt": {
+            "shop/supermarket/The Co-operative": {
                 "tags": {
-                    "name": "Colruyt",
+                    "name": "The Co-operative",
                     "shop": "supermarket"
                 },
-                "name": "Colruyt",
+                "name": "The Co-operative",
                 "icon": "grocery",
                 "geometry": [
                     "point",
@@ -89505,12 +90611,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/The Co-operative": {
+            "shop/supermarket/Intermarché": {
                 "tags": {
-                    "name": "The Co-operative",
+                    "name": "Intermarché",
                     "shop": "supermarket"
                 },
-                "name": "The Co-operative",
+                "name": "Intermarché",
                 "icon": "grocery",
                 "geometry": [
                     "point",
@@ -89695,25 +90801,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/dm": {
-                "tags": {
-                    "name": "dm",
-                    "shop": "supermarket"
-                },
-                "name": "dm",
-                "icon": "grocery",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address"
-                ],
-                "suggestion": true
-            },
             "shop/supermarket/Kvickly": {
                 "tags": {
                     "name": "Kvickly",
@@ -89961,25 +91048,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Petit Casino": {
-                "tags": {
-                    "name": "Petit Casino",
-                    "shop": "supermarket"
-                },
-                "name": "Petit Casino",
-                "icon": "grocery",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address"
-                ],
-                "suggestion": true
-            },
             "shop/supermarket/Wasgau": {
                 "tags": {
                     "name": "Wasgau",
@@ -90569,25 +91637,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Fressnapf": {
-                "tags": {
-                    "name": "Fressnapf",
-                    "shop": "supermarket"
-                },
-                "name": "Fressnapf",
-                "icon": "grocery",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address"
-                ],
-                "suggestion": true
-            },
             "shop/supermarket/Coop Konsum": {
                 "tags": {
                     "name": "Coop Konsum",
@@ -90835,25 +91884,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Centra": {
-                "tags": {
-                    "name": "Centra",
-                    "shop": "supermarket"
-                },
-                "name": "Centra",
-                "icon": "grocery",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address"
-                ],
-                "suggestion": true
-            },
             "shop/supermarket/Квартал": {
                 "tags": {
                     "name": "Квартал",
@@ -91443,12 +92473,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Атак": {
+            "shop/supermarket/H-E-B": {
                 "tags": {
-                    "name": "Атак",
+                    "name": "H-E-B",
                     "shop": "supermarket"
                 },
-                "name": "Атак",
+                "name": "H-E-B",
                 "icon": "grocery",
                 "geometry": [
                     "point",
@@ -91462,12 +92492,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Ð\9fолÑ\83Ñ\88ка": {
+            "shop/supermarket/Ð\90Ñ\82ак": {
                 "tags": {
-                    "name": "Ð\9fолÑ\83Ñ\88ка",
+                    "name": "Ð\90Ñ\82ак",
                     "shop": "supermarket"
                 },
-                "name": "Ð\9fолÑ\83Ñ\88ка",
+                "name": "Ð\90Ñ\82ак",
                 "icon": "grocery",
                 "geometry": [
                     "point",
@@ -91481,12 +92511,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Extra": {
+            "shop/supermarket/Полушка": {
                 "tags": {
-                    "name": "Extra",
+                    "name": "Полушка",
                     "shop": "supermarket"
                 },
-                "name": "Extra",
+                "name": "Полушка",
                 "icon": "grocery",
                 "geometry": [
                     "point",
@@ -91500,12 +92530,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Lewiatan": {
+            "shop/supermarket/Extra": {
                 "tags": {
-                    "name": "Lewiatan",
+                    "name": "Extra",
                     "shop": "supermarket"
                 },
-                "name": "Lewiatan",
+                "name": "Extra",
                 "icon": "grocery",
                 "geometry": [
                     "point",
@@ -91557,25 +92587,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Społem": {
-                "tags": {
-                    "name": "Społem",
-                    "shop": "supermarket"
-                },
-                "name": "Społem",
-                "icon": "grocery",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address"
-                ],
-                "suggestion": true
-            },
             "shop/supermarket/Bodega Aurrera": {
                 "tags": {
                     "name": "Bodega Aurrera",
@@ -91652,25 +92663,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/supermarket/Магазин": {
-                "tags": {
-                    "name": "Магазин",
-                    "shop": "supermarket"
-                },
-                "name": "Магазин",
-                "icon": "grocery",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "operator",
-                    "building_area",
-                    "address"
-                ],
-                "suggestion": true
-            },
             "shop/supermarket/Монетка": {
                 "tags": {
                     "name": "Монетка",
@@ -92108,6 +93100,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Tesco Express": {
+                "tags": {
+                    "name": "Tesco Express",
+                    "shop": "convenience"
+                },
+                "name": "Tesco Express",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/One Stop": {
                 "tags": {
                     "name": "One Stop",
@@ -92146,6 +93157,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/7-Eleven": {
+                "tags": {
+                    "name": "7-Eleven",
+                    "shop": "convenience"
+                },
+                "name": "7-Eleven",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Sale": {
                 "tags": {
                     "name": "Sale",
@@ -92184,6 +93214,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/COOP Jednota": {
+                "tags": {
+                    "name": "COOP Jednota",
+                    "shop": "convenience"
+                },
+                "name": "COOP Jednota",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Mac's": {
                 "tags": {
                     "name": "Mac's",
@@ -92260,6 +93309,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Costcutter": {
+                "tags": {
+                    "name": "Costcutter",
+                    "shop": "convenience"
+                },
+                "name": "Costcutter",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Valintatalo": {
                 "tags": {
                     "name": "Valintatalo",
@@ -92279,6 +93347,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Circle K": {
+                "tags": {
+                    "name": "Circle K",
+                    "shop": "convenience"
+                },
+                "name": "Circle K",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/セブンイレブン": {
                 "tags": {
                     "name": "セブンイレブン",
@@ -92319,6 +93406,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Petit Casino": {
+                "tags": {
+                    "name": "Petit Casino",
+                    "shop": "convenience"
+                },
+                "name": "Petit Casino",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Mace": {
                 "tags": {
                     "name": "Mace",
@@ -92528,6 +93634,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/ABC": {
+                "tags": {
+                    "name": "ABC",
+                    "shop": "convenience"
+                },
+                "name": "ABC",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/ミニストップ": {
                 "tags": {
                     "name": "ミニストップ",
@@ -92759,6 +93884,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Магазин": {
+                "tags": {
+                    "name": "Магазин",
+                    "shop": "convenience"
+                },
+                "name": "Магазин",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Гастроном": {
                 "tags": {
                     "name": "Гастроном",
@@ -92797,6 +93941,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Centra": {
+                "tags": {
+                    "name": "Centra",
+                    "shop": "convenience"
+                },
+                "name": "Centra",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/サークルK": {
                 "tags": {
                     "name": "サークルK",
@@ -92817,6 +93980,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Wawa": {
+                "tags": {
+                    "name": "Wawa",
+                    "shop": "convenience"
+                },
+                "name": "Wawa",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Proxi": {
                 "tags": {
                     "name": "Proxi",
@@ -92988,6 +94170,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Społem": {
+                "tags": {
+                    "name": "Społem",
+                    "shop": "convenience"
+                },
+                "name": "Społem",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Cumberland Farms": {
                 "tags": {
                     "name": "Cumberland Farms",
@@ -93026,6 +94227,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Kiosk": {
+                "tags": {
+                    "name": "Kiosk",
+                    "shop": "convenience"
+                },
+                "name": "Kiosk",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/24 часа": {
                 "tags": {
                     "name": "24 часа",
@@ -93121,6 +94341,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Stewart's": {
+                "tags": {
+                    "name": "Stewart's",
+                    "shop": "convenience"
+                },
+                "name": "Stewart's",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Продукти": {
                 "tags": {
                     "name": "Продукти",
@@ -93159,6 +94398,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Радуга": {
+                "tags": {
+                    "name": "Радуга",
+                    "shop": "convenience"
+                },
+                "name": "Радуга",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/ローソンストア100": {
                 "tags": {
                     "name": "ローソンストア100",
@@ -93539,6 +94797,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Lewiatan": {
+                "tags": {
+                    "name": "Lewiatan",
+                    "shop": "convenience"
+                },
+                "name": "Lewiatan",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/Продуктовый магазин": {
                 "tags": {
                     "name": "Продуктовый магазин",
@@ -93767,6 +95044,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/convenience/Boutique": {
+                "tags": {
+                    "name": "Boutique",
+                    "shop": "convenience"
+                },
+                "name": "Boutique",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/convenience/მარკეტი (Market)": {
                 "tags": {
                     "name": "მარკეტი (Market)",
@@ -93805,6 +95101,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/chemist/dm": {
+                "tags": {
+                    "name": "dm",
+                    "shop": "chemist"
+                },
+                "name": "dm",
+                "icon": "chemist",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/chemist/Müller": {
                 "tags": {
                     "name": "Müller",
@@ -93976,25 +95291,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/car_repair/Peugeot": {
-                "tags": {
-                    "name": "Peugeot",
-                    "shop": "car_repair"
-                },
-                "name": "Peugeot",
-                "icon": "car",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "address",
-                    "building_area",
-                    "opening_hours"
-                ],
-                "suggestion": true
-            },
             "shop/car_repair/Kwik Fit": {
                 "tags": {
                     "name": "Kwik Fit",
@@ -94128,44 +95424,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/car_repair/Автозапчасти": {
-                "tags": {
-                    "name": "Автозапчасти",
-                    "shop": "car_repair"
-                },
-                "name": "Автозапчасти",
-                "icon": "car",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "address",
-                    "building_area",
-                    "opening_hours"
-                ],
-                "suggestion": true
-            },
-            "shop/car_repair/Renault": {
-                "tags": {
-                    "name": "Renault",
-                    "shop": "car_repair"
-                },
-                "name": "Renault",
-                "icon": "car",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "address",
-                    "building_area",
-                    "opening_hours"
-                ],
-                "suggestion": true
-            },
             "shop/car_repair/Pit Stop": {
                 "tags": {
                     "name": "Pit Stop",
@@ -94299,25 +95557,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/car_repair/Citroen": {
-                "tags": {
-                    "name": "Citroen",
-                    "shop": "car_repair"
-                },
-                "name": "Citroen",
-                "icon": "car",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "address",
-                    "building_area",
-                    "opening_hours"
-                ],
-                "suggestion": true
-            },
             "shop/car_repair/Euromaster": {
                 "tags": {
                     "name": "Euromaster",
@@ -94926,6 +96165,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/doityourself/Canadian Tire": {
+                "tags": {
+                    "name": "Canadian Tire",
+                    "shop": "doityourself"
+                },
+                "name": "Canadian Tire",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/doityourself/Leroy Merlin": {
                 "tags": {
                     "name": "Leroy Merlin",
@@ -95154,25 +96412,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/doityourself/Хозтовары": {
-                "tags": {
-                    "name": "Хозтовары",
-                    "shop": "doityourself"
-                },
-                "name": "Хозтовары",
-                "icon": "shop",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "address",
-                    "building_area",
-                    "opening_hours"
-                ],
-                "suggestion": true
-            },
             "shop/doityourself/Стройматериалы": {
                 "tags": {
                     "name": "Стройматериалы",
@@ -95342,6 +96581,42 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/car/Citroen": {
+                "tags": {
+                    "name": "Citroen",
+                    "shop": "car"
+                },
+                "name": "Citroen",
+                "icon": "car",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
+            "shop/car/Renault": {
+                "tags": {
+                    "name": "Renault",
+                    "shop": "car"
+                },
+                "name": "Renault",
+                "icon": "car",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/car/Mercedes-Benz": {
                 "tags": {
                     "name": "Mercedes-Benz",
@@ -95378,6 +96653,24 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/car/Ford": {
+                "tags": {
+                    "name": "Ford",
+                    "shop": "car"
+                },
+                "name": "Ford",
+                "icon": "car",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/car/Volkswagen": {
                 "tags": {
                     "name": "Volkswagen",
@@ -95450,6 +96743,24 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/car/Автозапчасти": {
+                "tags": {
+                    "name": "Автозапчасти",
+                    "shop": "car"
+                },
+                "name": "Автозапчасти",
+                "icon": "car",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/car/Opel": {
                 "tags": {
                     "name": "Opel",
@@ -95558,6 +96869,24 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/car/Peugeot": {
+                "tags": {
+                    "name": "Peugeot",
+                    "shop": "car"
+                },
+                "name": "Peugeot",
+                "icon": "car",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/car/Hyundai": {
                 "tags": {
                     "name": "Hyundai",
@@ -96105,25 +97434,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
-            "shop/clothes/Deichmann": {
-                "tags": {
-                    "name": "Deichmann",
-                    "shop": "clothes"
-                },
-                "name": "Deichmann",
-                "icon": "clothing-store",
-                "geometry": [
-                    "point",
-                    "vertex",
-                    "area"
-                ],
-                "fields": [
-                    "address",
-                    "building_area",
-                    "opening_hours"
-                ],
-                "suggestion": true
-            },
             "shop/clothes/Lindex": {
                 "tags": {
                     "name": "Lindex",
@@ -98404,6 +99714,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/pet/Fressnapf": {
+                "tags": {
+                    "name": "Fressnapf",
+                    "shop": "pet"
+                },
+                "name": "Fressnapf",
+                "icon": "dog-park",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/pet/PetSmart": {
                 "tags": {
                     "name": "PetSmart",
@@ -98499,6 +99828,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/shoes/Deichmann": {
+                "tags": {
+                    "name": "Deichmann",
+                    "shop": "shoes"
+                },
+                "name": "Deichmann",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/shoes/Reno": {
                 "tags": {
                     "name": "Reno",
@@ -99810,6 +101158,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 ],
                 "suggestion": true
             },
+            "shop/hardware/Хозтовары": {
+                "tags": {
+                    "name": "Хозтовары",
+                    "shop": "hardware"
+                },
+                "name": "Хозтовары",
+                "icon": "shop",
+                "geometry": [
+                    "point",
+                    "vertex",
+                    "area"
+                ],
+                "fields": [
+                    "address",
+                    "building_area",
+                    "opening_hours"
+                ],
+                "suggestion": true
+            },
             "shop/motorcycle/Yamaha": {
                 "tags": {
                     "name": "Yamaha",
@@ -99862,7 +101229,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "point"
             ],
             "vertex": [
-                "highway/crossing",
+                "highway/crosswalk",
                 "railway/level_crossing",
                 "highway/traffic_signals",
                 "highway/turning_circle",
@@ -99872,8 +101239,8 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             ],
             "relation": [
                 "category-route",
+                "category-restriction",
                 "type/boundary",
-                "type/restriction",
                 "type/multipolygon",
                 "relation"
             ]
@@ -99948,6 +101315,21 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "railway/abandoned"
                 ]
             },
+            "category-restriction": {
+                "geometry": "relation",
+                "name": "Restriction",
+                "icon": "restriction",
+                "members": [
+                    "type/restriction/no_left_turn",
+                    "type/restriction/no_right_turn",
+                    "type/restriction/no_straight_on",
+                    "type/restriction/no_u_turn",
+                    "type/restriction/only_left_turn",
+                    "type/restriction/only_right_turn",
+                    "type/restriction/only_straight_on",
+                    "type/restriction"
+                ]
+            },
             "category-road": {
                 "geometry": "line",
                 "name": "Road",
@@ -100066,6 +101448,18 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 }
             },
             "access_simple": {
+                "key": "access",
+                "type": "combo",
+                "label": "Access",
+                "placeholder": "yes",
+                "options": [
+                    "permissive",
+                    "private",
+                    "customers",
+                    "no"
+                ]
+            },
+            "access_toilets": {
                 "key": "access",
                 "type": "combo",
                 "label": "Access",
@@ -100079,6 +101473,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "address": {
                 "type": "address",
                 "keys": [
+                    "addr:housename",
                     "addr:housenumber",
                     "addr:street",
                     "addr:city",
@@ -100092,10 +101487,19 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "label": "Address",
                 "strings": {
                     "placeholders": {
-                        "number": "123",
+                        "housename": "Housename",
+                        "housenumber": "123",
                         "street": "Street",
                         "city": "City",
-                        "postcode": "Postal code"
+                        "postcode": "Postcode",
+                        "place": "Place",
+                        "hamlet": "Hamlet",
+                        "suburb": "Suburb",
+                        "subdistrict": "Subdistrict",
+                        "district": "District",
+                        "province": "Province",
+                        "state": "State",
+                        "country": "Country"
                     }
                 }
             },
@@ -100112,12 +101516,14 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "aerialway/access": {
                 "key": "aerialway:access",
                 "type": "combo",
-                "options": [
-                    "entry",
-                    "exit",
-                    "both"
-                ],
-                "label": "Access"
+                "label": "Access",
+                "strings": {
+                    "options": {
+                        "entry": "Entry",
+                        "exit": "Exit",
+                        "both": "Both"
+                    }
+                }
             },
             "aerialway/bubble": {
                 "key": "aerialway:bubble",
@@ -100150,12 +101556,14 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "aerialway/summer/access": {
                 "key": "aerialway:summer:access",
                 "type": "combo",
-                "options": [
-                    "entry",
-                    "exit",
-                    "both"
-                ],
-                "label": "Access (summer)"
+                "label": "Access (summer)",
+                "strings": {
+                    "options": {
+                        "entry": "Entry",
+                        "exit": "Exit",
+                        "both": "Both"
+                    }
+                }
             },
             "aeroway": {
                 "key": "aeroway",
@@ -100223,32 +101631,31 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "cardinal_direction": {
                 "key": "direction",
                 "type": "combo",
-                "options": [
-                    "N",
-                    "E",
-                    "S",
-                    "W",
-                    "NE",
-                    "SE",
-                    "SW",
-                    "NNE",
-                    "ENE",
-                    "ESE",
-                    "SSE",
-                    "SSW",
-                    "WSW",
-                    "WNW",
-                    "NNW"
-                ],
-                "label": "Direction"
+                "label": "Direction",
+                "strings": {
+                    "options": {
+                        "N": "North",
+                        "E": "East",
+                        "S": "South",
+                        "W": "West",
+                        "NE": "Northeast",
+                        "SE": "Southeast",
+                        "SW": "Southwest",
+                        "NW": "Northwest",
+                        "NNE": "North-northeast",
+                        "ENE": "East-northeast",
+                        "ESE": "East-southeast",
+                        "SSE": "South-southeast",
+                        "SSW": "South-southwest",
+                        "WSW": "West-southwest",
+                        "WNW": "West-northwest",
+                        "NNW": "North-northwest"
+                    }
+                }
             },
             "clock_direction": {
                 "key": "direction",
                 "type": "combo",
-                "options": [
-                    "clockwise",
-                    "anticlockwise"
-                ],
                 "label": "Direction",
                 "strings": {
                     "options": {
@@ -100290,7 +101697,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "cuisine": {
                 "key": "cuisine",
                 "type": "combo",
-                "indexed": true,
                 "label": "Cuisine"
             },
             "denomination": {
@@ -100312,12 +101718,15 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "key": "electrified",
                 "type": "combo",
                 "label": "Electrification",
-                "options": [
-                    "contact_line",
-                    "rail",
-                    "yes",
-                    "no"
-                ]
+                "placeholder": "Contact Line, Electrified Rail...",
+                "strings": {
+                    "options": {
+                        "contact_line": "Contact Line",
+                        "rail": "Electrified Rail",
+                        "yes": "Yes (unspecified)",
+                        "no": "No"
+                    }
+                }
             },
             "elevation": {
                 "key": "ele",
@@ -100336,6 +101745,11 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "type": "typeCombo",
                 "label": "Type"
             },
+            "except": {
+                "key": "except",
+                "type": "combo",
+                "label": "Exceptions"
+            },
             "fax": {
                 "key": "fax",
                 "type": "tel",
@@ -100350,13 +101764,15 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "fire_hydrant/type": {
                 "key": "fire_hydrant:type",
                 "type": "combo",
-                "options": [
-                    "pillar",
-                    "pond",
-                    "underground",
-                    "wall"
-                ],
-                "label": "Type"
+                "label": "Type",
+                "strings": {
+                    "options": {
+                        "pillar": "Pillar/Aboveground",
+                        "underground": "Underground",
+                        "wall": "Wall",
+                        "pond": "Pond"
+                    }
+                }
             },
             "fixme": {
                 "key": "fixme",
@@ -100484,13 +101900,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "internet_access": {
                 "key": "internet_access",
                 "type": "combo",
-                "options": [
-                    "yes",
-                    "no",
-                    "wlan",
-                    "wired",
-                    "terminal"
-                ],
                 "label": "Internet Access",
                 "strings": {
                     "options": {
@@ -100502,6 +101911,11 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     }
                 }
             },
+            "lamp_type": {
+                "key": "lamp_type",
+                "type": "combo",
+                "label": "Type"
+            },
             "landuse": {
                 "key": "landuse",
                 "type": "typeCombo",
@@ -100555,6 +101969,54 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "label": "Speed Limit",
                 "placeholder": "40, 50, 60..."
             },
+            "mtb/scale": {
+                "key": "mtb:scale",
+                "type": "combo",
+                "label": "Mountain Biking Difficulty",
+                "placeholder": "0, 1, 2, 3...",
+                "strings": {
+                    "options": {
+                        "0": "0: Solid gravel/packed earth, no obstacles, wide curves",
+                        "1": "1: Some loose surface, small obstacles, wide curves",
+                        "2": "2: Much loose surface, large obstacles, easy hairpins",
+                        "3": "3: Slippery surface, large obstacles, tight hairpins",
+                        "4": "4: Loose surface or boulders, dangerous hairpins",
+                        "5": "5: Maximum difficulty, boulder fields, landslides",
+                        "6": "6: Not rideable except by the very best mountain bikers"
+                    }
+                }
+            },
+            "mtb/scale/imba": {
+                "key": "mtb:scale:imba",
+                "type": "combo",
+                "label": "IMBA Trail Difficulty",
+                "placeholder": "Easy, Medium, Difficult...",
+                "strings": {
+                    "options": {
+                        "0": "Easiest (white circle)",
+                        "1": "Easy (green circle)",
+                        "2": "Medium (blue square)",
+                        "3": "Difficult (black diamond)",
+                        "4": "Extremely Difficult (double black diamond)"
+                    }
+                }
+            },
+            "mtb/scale/uphill": {
+                "key": "mtb:scale:uphill",
+                "type": "combo",
+                "label": "Mountain Biking Uphill Difficulty",
+                "placeholder": "0, 1, 2, 3...",
+                "strings": {
+                    "options": {
+                        "0": "0: Avg. incline <10%, gravel/packed earth, no obstacles",
+                        "1": "1: Avg. incline <15%, gravel/packed earth, few small objects",
+                        "2": "2: Avg. incline <20%, stable surface, fistsize rocks/roots",
+                        "3": "3: Avg. incline <25%, variable surface, fistsize rocks/branches",
+                        "4": "4: Avg. incline <30%, poor condition, big rocks/branches",
+                        "5": "5: Very steep, bike generally needs to be pushed or carried"
+                    }
+                }
+            },
             "name": {
                 "key": "name",
                 "type": "localized",
@@ -100586,13 +102048,26 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "oneway": {
                 "key": "oneway",
                 "type": "check",
-                "label": "One Way"
+                "label": "One Way",
+                "strings": {
+                    "options": {
+                        "undefined": "Assumed to be No",
+                        "yes": "Yes",
+                        "no": "No"
+                    }
+                }
             },
             "oneway_yes": {
                 "key": "oneway",
                 "type": "check",
-                "default": "yes",
-                "label": "One Way"
+                "label": "One Way",
+                "strings": {
+                    "options": {
+                        "undefined": "Assumed to be Yes",
+                        "yes": "Yes",
+                        "no": "No"
+                    }
+                }
             },
             "opening_hours": {
                 "key": "opening_hours",
@@ -100618,16 +102093,18 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "parking": {
                 "key": "parking",
                 "type": "combo",
-                "options": [
-                    "surface",
-                    "multi-storey",
-                    "underground",
-                    "sheds",
-                    "carports",
-                    "garage_boxes",
-                    "lane"
-                ],
-                "label": "Type"
+                "label": "Type",
+                "strings": {
+                    "options": {
+                        "surface": "Surface",
+                        "multi-storey": "Multilevel",
+                        "underground": "Underground",
+                        "sheds": "Sheds",
+                        "carports": "Carports",
+                        "garage_boxes": "Garage Boxes",
+                        "lane": "Roadside Lane"
+                    }
+                }
             },
             "phone": {
                 "key": "phone",
@@ -100640,17 +102117,52 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "piste/difficulty": {
                 "key": "piste:difficulty",
                 "type": "combo",
-                "label": "Difficulty"
+                "label": "Difficulty",
+                "placeholder": "Easy, Intermediate, Advanced...",
+                "strings": {
+                    "options": {
+                        "novice": "Novice (instructional)",
+                        "easy": "Easy (green circle)",
+                        "intermediate": "Intermediate (blue square)",
+                        "advanced": "Advanced (black diamond)",
+                        "expert": "Expert (double black diamond)",
+                        "freeride": "Freeride (off-piste)",
+                        "extreme": "Extreme (climbing equipment required)"
+                    }
+                }
             },
             "piste/grooming": {
                 "key": "piste:grooming",
                 "type": "combo",
-                "label": "Grooming"
+                "label": "Grooming",
+                "strings": {
+                    "options": {
+                        "classic": "Classic",
+                        "mogul": "Mogul",
+                        "backcountry": "Backcountry",
+                        "classic+skating": "Classic and Skating",
+                        "scooter": "Scooter/Snowmobile",
+                        "skating": "Skating"
+                    }
+                }
             },
             "piste/type": {
                 "key": "piste:type",
                 "type": "typeCombo",
-                "label": "Type"
+                "label": "Type",
+                "strings": {
+                    "options": {
+                        "downhill": "Downhill",
+                        "nordic": "Nordic",
+                        "skitour": "Skitour",
+                        "sled": "Sled",
+                        "hike": "Hike",
+                        "sleigh": "Sleigh",
+                        "ice_skate": "Ice Skate",
+                        "snow_park": "Snow Park",
+                        "playground": "Playground"
+                    }
+                }
             },
             "place": {
                 "key": "place",
@@ -100705,33 +102217,22 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "religion": {
                 "key": "religion",
                 "type": "combo",
-                "options": [
-                    "christian",
-                    "muslim",
-                    "buddhist",
-                    "jewish",
-                    "hindu",
-                    "shinto",
-                    "taoist"
-                ],
-                "label": "Religion",
-                "strings": {
-                    "options": {
-                        "christian": "Christian",
-                        "muslim": "Muslim",
-                        "buddhist": "Buddhist",
-                        "jewish": "Jewish",
-                        "hindu": "Hindu",
-                        "shinto": "Shinto",
-                        "taoist": "Taoist"
-                    }
-                }
+                "label": "Religion"
             },
             "restriction": {
                 "key": "restriction",
                 "type": "combo",
                 "label": "Type"
             },
+            "restrictions": {
+                "type": "restrictions",
+                "geometry": "vertex",
+                "icon": "restrictions",
+                "reference": {
+                    "rtype": "restriction"
+                },
+                "label": "Turn Restrictions"
+            },
             "route": {
                 "key": "route",
                 "type": "combo",
@@ -100745,7 +102246,18 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "sac_scale": {
                 "key": "sac_scale",
                 "type": "combo",
-                "label": "Path Difficulty"
+                "label": "Hiking Difficulty",
+                "placeholder": "Mountain Hiking, Alpine Hiking...",
+                "strings": {
+                    "options": {
+                        "hiking": "T1: Hiking",
+                        "mountain_hiking": "T2: Mountain Hiking",
+                        "demanding_mountain_hiking": "T3: Demanding Mountain Hiking",
+                        "alpine_hiking": "T4: Alpine Hiking",
+                        "demanding_alpine_hiking": "T5: Demanding Alpine Hiking",
+                        "difficult_alpine_hiking": "T6: Difficult Alpine Hiking"
+                    }
+                }
             },
             "seasonal": {
                 "key": "seasonal",
@@ -100755,14 +102267,14 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "service": {
                 "key": "service",
                 "type": "combo",
+                "label": "Type",
                 "options": [
                     "parking_aisle",
                     "driveway",
                     "alley",
-                    "drive-through",
-                    "emergency_access"
-                ],
-                "label": "Type"
+                    "emergency_access",
+                    "drive-through"
+                ]
             },
             "shelter": {
                 "key": "shelter",
@@ -100772,15 +102284,6 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "shelter_type": {
                 "key": "shelter_type",
                 "type": "combo",
-                "options": [
-                    "public_transport",
-                    "picnic_shelter",
-                    "weather_shelter",
-                    "lean_to",
-                    "basic_hut",
-                    "field_shelter",
-                    "rock_shelter"
-                ],
                 "label": "Type"
             },
             "shop": {
@@ -100796,13 +102299,36 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "smoking": {
                 "key": "smoking",
                 "type": "combo",
-                "options": [
-                    "no",
-                    "outside",
-                    "separated",
-                    "yes"
-                ],
-                "label": "Smoking"
+                "label": "Smoking",
+                "placeholder": "No, Separated, Yes...",
+                "strings": {
+                    "options": {
+                        "no": "No smoking anywhere",
+                        "separated": "In smoking areas, not physically isolated",
+                        "isolated": "In smoking areas, physically isolated",
+                        "outside": "Allowed outside",
+                        "yes": "Allowed everywhere",
+                        "dedicated": "Dedicated to smokers (e.g. smokers' club)"
+                    }
+                }
+            },
+            "smoothness": {
+                "key": "smoothness",
+                "type": "combo",
+                "label": "Smoothness",
+                "placeholder": "Thin Rollers, Wheels, Off-Road...",
+                "strings": {
+                    "options": {
+                        "excellent": "Thin Rollers: rollerblade, skateboard",
+                        "good": "Thin Wheels: racing bike",
+                        "intermediate": "Wheels: city bike, wheelchair, scooter",
+                        "bad": "Robust Wheels: trekking bike, car, rickshaw",
+                        "very_bad": "High Clearance: light duty off-road vehicle",
+                        "horrible": "Off-Road: heavy duty off-road vehicle",
+                        "very_horrible": "Specialized off-road: tractor, ATV",
+                        "impassible": "Impassible / No wheeled vehicle"
+                    }
+                }
             },
             "social_facility_for": {
                 "key": "social_facility:for",
@@ -100841,14 +102367,14 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "sport_ice": {
                 "key": "sport",
                 "type": "combo",
+                "label": "Sport",
                 "options": [
                     "skating",
                     "hockey",
                     "multi",
                     "curling",
                     "ice_stock"
-                ],
-                "label": "Sport"
+                ]
             },
             "structure": {
                 "type": "radio",
@@ -100874,11 +102400,11 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "studio_type": {
                 "key": "type",
                 "type": "combo",
+                "label": "Type",
                 "options": [
                     "audio",
                     "video"
-                ],
-                "label": "Type"
+                ]
             },
             "supervised": {
                 "key": "supervised",
@@ -100898,7 +102424,15 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "toilets/disposal": {
                 "key": "toilets:disposal",
                 "type": "combo",
-                "label": "Disposal"
+                "label": "Disposal",
+                "strings": {
+                    "options": {
+                        "flush": "Flush",
+                        "pitlatrine": "Pit/Latrine",
+                        "chemical": "Chemical",
+                        "bucket": "Bucket"
+                    }
+                }
             },
             "tourism": {
                 "key": "tourism",
@@ -100913,22 +102447,43 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "tracktype": {
                 "key": "tracktype",
                 "type": "combo",
-                "label": "Type"
+                "label": "Track Type",
+                "placeholder": "Solid, Mostly Solid, Soft...",
+                "strings": {
+                    "options": {
+                        "grade1": "Solid: paved or heavily compacted hardcore surface",
+                        "grade2": "Mostly Solid: gravel/rock with some soft material mixed in",
+                        "grade3": "Even mixture of hard and soft materials",
+                        "grade4": "Mostly Soft: soil/sand/grass with some hard material mixed in",
+                        "grade5": "Soft: soil/sand/grass"
+                    }
+                }
             },
             "trail_visibility": {
                 "key": "trail_visibility",
                 "type": "combo",
-                "label": "Trail Visibility"
+                "label": "Trail Visibility",
+                "placeholder": "Excellent, Good, Bad...",
+                "strings": {
+                    "options": {
+                        "excellent": "Excellent: unambiguous path or markers everywhere",
+                        "good": "Good: markers visible, sometimes require searching",
+                        "intermediate": "Intermediate: few markers, path mostly visible",
+                        "bad": "Bad: no markers, path sometimes invisible/pathless",
+                        "horrible": "Horrible: often pathless, some orientation skills required",
+                        "no": "No: pathless, excellent orientation skills required"
+                    }
+                }
             },
             "tree_type": {
                 "key": "type",
                 "type": "combo",
+                "label": "Type",
                 "options": [
                     "broad_leaved",
                     "conifer",
                     "palm"
-                ],
-                "label": "Type"
+                ]
             },
             "trees": {
                 "key": "trees",
@@ -112794,6 +114349,48 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 920,
                 25
             ]
+        },
+        "restriction-no-straight-on": {
+            "relation": [
+                980,
+                25
+            ]
+        },
+        "restriction-no-u-turn": {
+            "relation": [
+                1040,
+                25
+            ]
+        },
+        "restriction-no-left-turn": {
+            "relation": [
+                1100,
+                25
+            ]
+        },
+        "restriction-no-right-turn": {
+            "relation": [
+                1160,
+                25
+            ]
+        },
+        "restriction-only-straight-on": {
+            "relation": [
+                1220,
+                25
+            ]
+        },
+        "restriction-only-left-turn": {
+            "relation": [
+                1280,
+                25
+            ]
+        },
+        "restriction-only-right-turn": {
+            "relation": [
+                1340,
+                25
+            ]
         }
     },
     "operations": {
@@ -112892,6 +114489,30 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
         "icon-operation-disabled-continue": [
             220,
             160
+        ],
+        "icon-restriction-yes": [
+            50,
+            80
+        ],
+        "icon-restriction-no": [
+            95,
+            80
+        ],
+        "icon-restriction-only": [
+            140,
+            80
+        ],
+        "icon-restriction-yes-u": [
+            185,
+            80
+        ],
+        "icon-restriction-no-u": [
+            230,
+            80
+        ],
+        "icon-restriction-only-u": [
+            275,
+            80
         ]
     },
     "locales": [
@@ -113055,7 +114676,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             },
             "delete": {
                 "title": "Delete",
-                "description": "Remove this from the map.",
+                "description": "Delete object permanently.",
                 "annotation": {
                     "point": "Deleted a point.",
                     "vertex": "Deleted a node from a way.",
@@ -113108,7 +114729,8 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "area": "Moved an area.",
                     "multiple": "Moved multiple objects."
                 },
-                "incomplete_relation": "This feature can't be moved because it hasn't been fully downloaded."
+                "incomplete_relation": "This feature can't be moved because it hasn't been fully downloaded.",
+                "too_large": "This can't be moved because not enough of it is currently visible."
             },
             "rotate": {
                 "title": "Rotate",
@@ -113117,7 +114739,8 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "annotation": {
                     "line": "Rotated a line.",
                     "area": "Rotated an area."
-                }
+                },
+                "too_large": "This can't be rotated because not enough of it is currently visible."
             },
             "reverse": {
                 "title": "Reverse",
@@ -113140,6 +114763,18 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 },
                 "not_eligible": "Lines can't be split at their beginning or end.",
                 "multiple_ways": "There are too many lines here to split."
+            },
+            "restriction": {
+                "help": {
+                    "select": "Click to select a road segment.",
+                    "toggle": "Click to toggle turn restrictions.",
+                    "toggle_on": "Click to add a \"{restriction}\" restriction.",
+                    "toggle_off": "Click to remove the \"{restriction}\" restriction."
+                },
+                "annotation": {
+                    "create": "Added a turn restriction",
+                    "delete": "Deleted a turn restriction"
+                }
             }
         },
         "undo": {
@@ -113282,7 +114917,9 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
             "untagged_area": "Untagged area",
             "many_deletions": "You're deleting {n} objects. Are you sure you want to do this? This will delete them from the map that everyone else sees on openstreetmap.org.",
             "tag_suggests_area": "The tag {tag} suggests line should be area, but it is not an area",
-            "untagged_tooltip": "Select a feature type that describes what this {geometry} is.",
+            "untagged_point_tooltip": "Select a feature type that describes what this point is.",
+            "untagged_line_tooltip": "Select a feature type that describes what this line is.",
+            "untagged_area_tooltip": "Select a feature type that describes what this area is.",
             "deprecated_tags": "Deprecated tags: {tags}"
         },
         "zoom": {
@@ -113374,6 +115011,9 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "category-rail": {
                     "name": "Rail"
                 },
+                "category-restriction": {
+                    "name": "Restriction"
+                },
                 "category-road": {
                     "name": "Road"
                 },
@@ -113426,15 +115066,28 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     }
                 },
                 "access_simple": {
+                    "label": "Access",
+                    "placeholder": "yes"
+                },
+                "access_toilets": {
                     "label": "Access"
                 },
                 "address": {
                     "label": "Address",
                     "placeholders": {
-                        "number": "123",
+                        "housename": "Housename",
+                        "housenumber": "123",
                         "street": "Street",
                         "city": "City",
-                        "postcode": "Postal code"
+                        "postcode": "Postcode",
+                        "place": "Place",
+                        "hamlet": "Hamlet",
+                        "suburb": "Suburb",
+                        "subdistrict": "Subdistrict",
+                        "district": "District",
+                        "province": "Province",
+                        "state": "State",
+                        "country": "Country"
                     }
                 },
                 "admin_level": {
@@ -113444,7 +115097,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Type"
                 },
                 "aerialway/access": {
-                    "label": "Access"
+                    "label": "Access",
+                    "options": {
+                        "entry": "Entry",
+                        "exit": "Exit",
+                        "both": "Both"
+                    }
                 },
                 "aerialway/bubble": {
                     "label": "Bubble"
@@ -113465,7 +115123,12 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "placeholder": "2, 4, 8..."
                 },
                 "aerialway/summer/access": {
-                    "label": "Access (summer)"
+                    "label": "Access (summer)",
+                    "options": {
+                        "entry": "Entry",
+                        "exit": "Exit",
+                        "both": "Both"
+                    }
                 },
                 "aeroway": {
                     "label": "Type"
@@ -113505,7 +115168,25 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "placeholder": "50, 100, 200..."
                 },
                 "cardinal_direction": {
-                    "label": "Direction"
+                    "label": "Direction",
+                    "options": {
+                        "N": "North",
+                        "E": "East",
+                        "S": "South",
+                        "W": "West",
+                        "NE": "Northeast",
+                        "SE": "Southeast",
+                        "SW": "Southwest",
+                        "NW": "Northwest",
+                        "NNE": "North-northeast",
+                        "ENE": "East-northeast",
+                        "ESE": "East-southeast",
+                        "SSE": "South-southeast",
+                        "SSW": "South-southwest",
+                        "WSW": "West-southwest",
+                        "WNW": "West-northwest",
+                        "NNW": "North-northwest"
+                    }
                 },
                 "clock_direction": {
                     "label": "Direction",
@@ -113545,7 +115226,14 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Description"
                 },
                 "electrified": {
-                    "label": "Electrification"
+                    "label": "Electrification",
+                    "placeholder": "Contact Line, Electrified Rail...",
+                    "options": {
+                        "contact_line": "Contact Line",
+                        "rail": "Electrified Rail",
+                        "yes": "Yes (unspecified)",
+                        "no": "No"
+                    }
                 },
                 "elevation": {
                     "label": "Elevation"
@@ -113556,6 +115244,9 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 "entrance": {
                     "label": "Type"
                 },
+                "except": {
+                    "label": "Exceptions"
+                },
                 "fax": {
                     "label": "Fax",
                     "placeholder": "+31 42 123 4567"
@@ -113564,7 +115255,13 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Fee"
                 },
                 "fire_hydrant/type": {
-                    "label": "Type"
+                    "label": "Type",
+                    "options": {
+                        "pillar": "Pillar/Aboveground",
+                        "underground": "Underground",
+                        "wall": "Wall",
+                        "pond": "Pond"
+                    }
                 },
                 "fixme": {
                     "label": "Fix Me"
@@ -113651,6 +115348,9 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                         "terminal": "Terminal"
                     }
                 },
+                "lamp_type": {
+                    "label": "Type"
+                },
                 "landuse": {
                     "label": "Type"
                 },
@@ -113684,6 +115384,42 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Speed Limit",
                     "placeholder": "40, 50, 60..."
                 },
+                "mtb/scale": {
+                    "label": "Mountain Biking Difficulty",
+                    "placeholder": "0, 1, 2, 3...",
+                    "options": {
+                        "0": "0: Solid gravel/packed earth, no obstacles, wide curves",
+                        "1": "1: Some loose surface, small obstacles, wide curves",
+                        "2": "2: Much loose surface, large obstacles, easy hairpins",
+                        "3": "3: Slippery surface, large obstacles, tight hairpins",
+                        "4": "4: Loose surface or boulders, dangerous hairpins",
+                        "5": "5: Maximum difficulty, boulder fields, landslides",
+                        "6": "6: Not rideable except by the very best mountain bikers"
+                    }
+                },
+                "mtb/scale/imba": {
+                    "label": "IMBA Trail Difficulty",
+                    "placeholder": "Easy, Medium, Difficult...",
+                    "options": {
+                        "0": "Easiest (white circle)",
+                        "1": "Easy (green circle)",
+                        "2": "Medium (blue square)",
+                        "3": "Difficult (black diamond)",
+                        "4": "Extremely Difficult (double black diamond)"
+                    }
+                },
+                "mtb/scale/uphill": {
+                    "label": "Mountain Biking Uphill Difficulty",
+                    "placeholder": "0, 1, 2, 3...",
+                    "options": {
+                        "0": "0: Avg. incline <10%, gravel/packed earth, no obstacles",
+                        "1": "1: Avg. incline <15%, gravel/packed earth, few small objects",
+                        "2": "2: Avg. incline <20%, stable surface, fistsize rocks/roots",
+                        "3": "3: Avg. incline <25%, variable surface, fistsize rocks/branches",
+                        "4": "4: Avg. incline <30%, poor condition, big rocks/branches",
+                        "5": "5: Very steep, bike generally needs to be pushed or carried"
+                    }
+                },
                 "name": {
                     "label": "Name",
                     "placeholder": "Common name (if any)"
@@ -113701,10 +115437,20 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Type"
                 },
                 "oneway": {
-                    "label": "One Way"
+                    "label": "One Way",
+                    "options": {
+                        "undefined": "Assumed to be No",
+                        "yes": "Yes",
+                        "no": "No"
+                    }
                 },
                 "oneway_yes": {
-                    "label": "One Way"
+                    "label": "One Way",
+                    "options": {
+                        "undefined": "Assumed to be Yes",
+                        "yes": "Yes",
+                        "no": "No"
+                    }
                 },
                 "opening_hours": {
                     "label": "Hours"
@@ -113720,20 +115466,58 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Park and Ride"
                 },
                 "parking": {
-                    "label": "Type"
+                    "label": "Type",
+                    "options": {
+                        "surface": "Surface",
+                        "multi-storey": "Multilevel",
+                        "underground": "Underground",
+                        "sheds": "Sheds",
+                        "carports": "Carports",
+                        "garage_boxes": "Garage Boxes",
+                        "lane": "Roadside Lane"
+                    }
                 },
                 "phone": {
                     "label": "Phone",
                     "placeholder": "+31 42 123 4567"
                 },
                 "piste/difficulty": {
-                    "label": "Difficulty"
+                    "label": "Difficulty",
+                    "placeholder": "Easy, Intermediate, Advanced...",
+                    "options": {
+                        "novice": "Novice (instructional)",
+                        "easy": "Easy (green circle)",
+                        "intermediate": "Intermediate (blue square)",
+                        "advanced": "Advanced (black diamond)",
+                        "expert": "Expert (double black diamond)",
+                        "freeride": "Freeride (off-piste)",
+                        "extreme": "Extreme (climbing equipment required)"
+                    }
                 },
                 "piste/grooming": {
-                    "label": "Grooming"
+                    "label": "Grooming",
+                    "options": {
+                        "classic": "Classic",
+                        "mogul": "Mogul",
+                        "backcountry": "Backcountry",
+                        "classic+skating": "Classic and Skating",
+                        "scooter": "Scooter/Snowmobile",
+                        "skating": "Skating"
+                    }
                 },
                 "piste/type": {
-                    "label": "Type"
+                    "label": "Type",
+                    "options": {
+                        "downhill": "Downhill",
+                        "nordic": "Nordic",
+                        "skitour": "Skitour",
+                        "sled": "Sled",
+                        "hike": "Hike",
+                        "sleigh": "Sleigh",
+                        "ice_skate": "Ice Skate",
+                        "snow_park": "Snow Park",
+                        "playground": "Playground"
+                    }
                 },
                 "place": {
                     "label": "Type"
@@ -113766,20 +115550,14 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Type"
                 },
                 "religion": {
-                    "label": "Religion",
-                    "options": {
-                        "christian": "Christian",
-                        "muslim": "Muslim",
-                        "buddhist": "Buddhist",
-                        "jewish": "Jewish",
-                        "hindu": "Hindu",
-                        "shinto": "Shinto",
-                        "taoist": "Taoist"
-                    }
+                    "label": "Religion"
                 },
                 "restriction": {
                     "label": "Type"
                 },
+                "restrictions": {
+                    "label": "Turn Restrictions"
+                },
                 "route": {
                     "label": "Type"
                 },
@@ -113787,7 +115565,16 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Type"
                 },
                 "sac_scale": {
-                    "label": "Path Difficulty"
+                    "label": "Hiking Difficulty",
+                    "placeholder": "Mountain Hiking, Alpine Hiking...",
+                    "options": {
+                        "hiking": "T1: Hiking",
+                        "mountain_hiking": "T2: Mountain Hiking",
+                        "demanding_mountain_hiking": "T3: Demanding Mountain Hiking",
+                        "alpine_hiking": "T4: Alpine Hiking",
+                        "demanding_alpine_hiking": "T5: Demanding Alpine Hiking",
+                        "difficult_alpine_hiking": "T6: Difficult Alpine Hiking"
+                    }
                 },
                 "seasonal": {
                     "label": "Seasonal"
@@ -113808,7 +115595,30 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Sloped Curb"
                 },
                 "smoking": {
-                    "label": "Smoking"
+                    "label": "Smoking",
+                    "placeholder": "No, Separated, Yes...",
+                    "options": {
+                        "no": "No smoking anywhere",
+                        "separated": "In smoking areas, not physically isolated",
+                        "isolated": "In smoking areas, physically isolated",
+                        "outside": "Allowed outside",
+                        "yes": "Allowed everywhere",
+                        "dedicated": "Dedicated to smokers (e.g. smokers' club)"
+                    }
+                },
+                "smoothness": {
+                    "label": "Smoothness",
+                    "placeholder": "Thin Rollers, Wheels, Off-Road...",
+                    "options": {
+                        "excellent": "Thin Rollers: rollerblade, skateboard",
+                        "good": "Thin Wheels: racing bike",
+                        "intermediate": "Wheels: city bike, wheelchair, scooter",
+                        "bad": "Robust Wheels: trekking bike, car, rickshaw",
+                        "very_bad": "High Clearance: light duty off-road vehicle",
+                        "horrible": "Off-Road: heavy duty off-road vehicle",
+                        "very_horrible": "Specialized off-road: tractor, ATV",
+                        "impassible": "Impassible / No wheeled vehicle"
+                    }
                 },
                 "social_facility_for": {
                     "label": "People served",
@@ -113847,7 +115657,13 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Tactile Paving"
                 },
                 "toilets/disposal": {
-                    "label": "Disposal"
+                    "label": "Disposal",
+                    "options": {
+                        "flush": "Flush",
+                        "pitlatrine": "Pit/Latrine",
+                        "chemical": "Chemical",
+                        "bucket": "Bucket"
+                    }
                 },
                 "tourism": {
                     "label": "Type"
@@ -113856,10 +115672,27 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "label": "Tower type"
                 },
                 "tracktype": {
-                    "label": "Type"
+                    "label": "Track Type",
+                    "placeholder": "Solid, Mostly Solid, Soft...",
+                    "options": {
+                        "grade1": "Solid: paved or heavily compacted hardcore surface",
+                        "grade2": "Mostly Solid: gravel/rock with some soft material mixed in",
+                        "grade3": "Even mixture of hard and soft materials",
+                        "grade4": "Mostly Soft: soil/sand/grass with some hard material mixed in",
+                        "grade5": "Soft: soil/sand/grass"
+                    }
                 },
                 "trail_visibility": {
-                    "label": "Trail Visibility"
+                    "label": "Trail Visibility",
+                    "placeholder": "Excellent, Good, Bad...",
+                    "options": {
+                        "excellent": "Excellent: unambiguous path or markers everywhere",
+                        "good": "Good: markers visible, sometimes require searching",
+                        "intermediate": "Intermediate: few markers, path mostly visible",
+                        "bad": "Bad: no markers, path sometimes invisible/pathless",
+                        "horrible": "Horrible: often pathless, some orientation skills required",
+                        "no": "No: pathless, excellent orientation skills required"
+                    }
                 },
                 "tree_type": {
                     "label": "Type"
@@ -114020,6 +115853,10 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "name": "Boat Rental",
                     "terms": ""
                 },
+                "amenity/bus_station": {
+                    "name": "Bus Station",
+                    "terms": ""
+                },
                 "amenity/cafe": {
                     "name": "Cafe",
                     "terms": "coffee,tea,coffee shop"
@@ -114076,6 +115913,10 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "name": "Doctor",
                     "terms": "doctor,doctor's office"
                 },
+                "amenity/dojo": {
+                    "name": "Dojo / Martial Arts Academy",
+                    "terms": "martial arts,dojo,dojang"
+                },
                 "amenity/drinking_water": {
                     "name": "Drinking Water",
                     "terms": "water fountain,potable water"
@@ -114662,6 +116503,10 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 },
                 "footway/crossing": {
                     "name": "Crossing",
+                    "terms": ""
+                },
+                "footway/crosswalk": {
+                    "name": "Crosswalk",
                     "terms": "crosswalk,zebra crossing"
                 },
                 "footway/sidewalk": {
@@ -114718,6 +116563,10 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 },
                 "highway/crossing": {
                     "name": "Crossing",
+                    "terms": ""
+                },
+                "highway/crosswalk": {
+                    "name": "Crosswalk",
                     "terms": "crosswalk,zebra crossing"
                 },
                 "highway/cycleway": {
@@ -114741,7 +116590,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "terms": ""
                 },
                 "highway/motorway_junction": {
-                    "name": "Motorway Junction",
+                    "name": "Motorway Junction / Exit",
                     "terms": ""
                 },
                 "highway/motorway_link": {
@@ -114820,6 +116669,10 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "name": "Stop Sign",
                     "terms": "stop sign"
                 },
+                "highway/street_lamp": {
+                    "name": "Street Lamp",
+                    "terms": "streetlight,street light,lamp,light,gaslight"
+                },
                 "highway/tertiary": {
                     "name": "Tertiary Road",
                     "terms": ""
@@ -115053,7 +116906,7 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "terms": ""
                 },
                 "leisure/sports_center": {
-                    "name": "Sports Center",
+                    "name": "Sports Center / Gym",
                     "terms": "gym"
                 },
                 "leisure/stadium": {
@@ -115680,6 +117533,10 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "name": "Supermarket",
                     "terms": "bazaar,boutique,chain,co-op,cut-rate store,discount store,five-and-dime,flea market,galleria,grocery store,mall,mart,outlet,outlet store,shop,shopping center,shopping centre,shopping plaza,stand,store,supermarket,thrift shop"
                 },
+                "shop/tailor": {
+                    "name": "Tailor",
+                    "terms": "tailor,clothes"
+                },
                 "shop/toys": {
                     "name": "Toy Store",
                     "terms": ""
@@ -115792,6 +117649,34 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                     "name": "Restriction",
                     "terms": ""
                 },
+                "type/restriction/no_left_turn": {
+                    "name": "No Left Turn",
+                    "terms": ""
+                },
+                "type/restriction/no_right_turn": {
+                    "name": "No Right Turn",
+                    "terms": ""
+                },
+                "type/restriction/no_straight_on": {
+                    "name": "No Straight On",
+                    "terms": ""
+                },
+                "type/restriction/no_u_turn": {
+                    "name": "No U-turn",
+                    "terms": ""
+                },
+                "type/restriction/only_left_turn": {
+                    "name": "Left Turn Only",
+                    "terms": ""
+                },
+                "type/restriction/only_right_turn": {
+                    "name": "Right Turn Only",
+                    "terms": ""
+                },
+                "type/restriction/only_straight_on": {
+                    "name": "No Turns",
+                    "terms": ""
+                },
                 "type/route": {
                     "name": "Route",
                     "terms": ""
@@ -120722,5 +122607,151 @@ iD.introGraph = '{"n185954700":{"id":"n185954700","loc":[-85.642244,41.939081],"
                 }
             }
         }
-    }
+    },
+    "addressFormats": [
+        {
+            "format": [
+                [
+                    "housenumber",
+                    "street"
+                ],
+                [
+                    "city",
+                    "postcode"
+                ]
+            ]
+        },
+        {
+            "countryCodes": [
+                "gb"
+            ],
+            "format": [
+                [
+                    "housename"
+                ],
+                [
+                    "housenumber",
+                    "street"
+                ],
+                [
+                    "city",
+                    "postcode"
+                ]
+            ]
+        },
+        {
+            "countryCodes": [
+                "ie"
+            ],
+            "format": [
+                [
+                    "housename"
+                ],
+                [
+                    "housenumber",
+                    "street"
+                ],
+                [
+                    "city"
+                ]
+            ]
+        },
+        {
+            "countryCodes": [
+                "ad",
+                "at",
+                "ba",
+                "be",
+                "ch",
+                "cz",
+                "de",
+                "dk",
+                "es",
+                "fi",
+                "gr",
+                "hr",
+                "is",
+                "it",
+                "li",
+                "nl",
+                "no",
+                "pl",
+                "pt",
+                "se",
+                "si",
+                "sk",
+                "sm",
+                "va"
+            ],
+            "format": [
+                [
+                    "street",
+                    "housenumber"
+                ],
+                [
+                    "postcode",
+                    "city"
+                ]
+            ]
+        },
+        {
+            "countryCodes": [
+                "fr",
+                "lu",
+                "mo"
+            ],
+            "format": [
+                [
+                    "housenumber",
+                    "street"
+                ],
+                [
+                    "postcode",
+                    "city"
+                ]
+            ]
+        },
+        {
+            "countryCodes": [
+                "br"
+            ],
+            "format": [
+                [
+                    "street"
+                ],
+                [
+                    "housenumber",
+                    "suburb"
+                ],
+                [
+                    "city",
+                    "postcode"
+                ]
+            ]
+        },
+        {
+            "countryCodes": [
+                "vn"
+            ],
+            "format": [
+                [
+                    "housenumber",
+                    "street"
+                ],
+                [
+                    "subdistrict"
+                ],
+                [
+                    "district"
+                ],
+                [
+                    "city"
+                ],
+                [
+                    "province",
+                    "postcode"
+                ]
+            ]
+        }
+    ]
 };
\ No newline at end of file