restore .hg...

Mon, 14 Sep 2020 22:55:45 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Mon, 14 Sep 2020 22:55:45 +0300
changeset 0
b0eb3af2f9ee
child 1
959dc869b765

restore .hg...

.hgignore file | annotate | diff | comparison | revisions
Makefile file | annotate | diff | comparison | revisions
empty.png file | annotate | diff | comparison | revisions
external-data.yml file | annotate | diff | comparison | revisions
flex.lua file | annotate | diff | comparison | revisions
project.mml file | annotate | diff | comparison | revisions
scripts/generate_shields.py file | annotate | diff | comparison | revisions
scripts/get-external-data.py file | annotate | diff | comparison | revisions
style/amenity.mss file | annotate | diff | comparison | revisions
style/buildings.mss file | annotate | diff | comparison | revisions
style/places.mss file | annotate | diff | comparison | revisions
style/roadref.mss file | annotate | diff | comparison | revisions
style/roads.mss file | annotate | diff | comparison | revisions
style/shapefiles.mss file | annotate | diff | comparison | revisions
style/style.mss file | annotate | diff | comparison | revisions
symbols/aerodrome.svg file | annotate | diff | comparison | revisions
symbols/bus-station.svg file | annotate | diff | comparison | revisions
symbols/train-station.svg file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,5 @@
+syntax:glob
+data
+symbols/shields
+project-spaces.mml
+mapnik.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,36 @@
+SHELL=/bin/bash
+
+all:
+	echo
+
+clear-cache:
+	rm -rf /var/lib/mod_tile/ajt
+
+restart:
+	sudo service renderd stop
+	rm -rf /var/lib/mod_tile/ajt
+	sudo service renderd start
+
+update: build-style clear-cache restart
+build-shields:
+	python3 scripts/generate_shields.py
+
+build-style: build-shields
+	sed 's/\t/  /g' project.mml >project-spaces.mml
+	carto project-spaces.mml > mapnik.xml
+
+test-style: clear-cache
+	renderd -f -c /usr/local/etc/renderd.conf
+
+import:
+	osm2pgsql \
+		-d gis \
+		--create \
+		--slim \
+		-G \
+		--hstore \
+		--tag-transform-script ~/style/openstreetmap-carto.lua \
+		-C 9000 \
+		--number-processes 8 \
+		-S ~/style/openstreetmap-carto.style \
+		~/data/map.pbf
Binary file empty.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/external-data.yml	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,81 @@
+settings:
+  temp_schema: loading
+  schema: public
+  data_dir: data
+  database: gis
+  metadata_table: external_data
+sources:
+  simplified_water_polygons:
+    # The type of file this source is
+    type: shp
+    # Where to get it
+    url: https://osmdata.openstreetmap.de/download/simplified-water-polygons-split-3857.zip
+    # The location within the archive
+    file: simplified-water-polygons-split-3857/simplified_water_polygons.shp
+    archive:
+      format: zip
+      # Files to extract from the archive
+      files:
+        - simplified-water-polygons-split-3857/simplified_water_polygons.cpg
+        - simplified-water-polygons-split-3857/simplified_water_polygons.dbf
+        - simplified-water-polygons-split-3857/simplified_water_polygons.prj
+        - simplified-water-polygons-split-3857/simplified_water_polygons.shp
+        - simplified-water-polygons-split-3857/simplified_water_polygons.shx
+  water_polygons:
+    type: shp
+    url: https://osmdata.openstreetmap.de/download/water-polygons-split-3857.zip
+    file: water-polygons-split-3857/water_polygons.shp
+    archive:
+      format: zip
+      files:
+        - water-polygons-split-3857/water_polygons.cpg
+        - water-polygons-split-3857/water_polygons.dbf
+        - water-polygons-split-3857/water_polygons.prj
+        - water-polygons-split-3857/water_polygons.shp
+        - water-polygons-split-3857/water_polygons.shx
+  icesheet_polygons:
+    type: shp
+    url: https://osmdata.openstreetmap.de/download/antarctica-icesheet-polygons-3857.zip
+    file: antarctica-icesheet-polygons-3857/icesheet_polygons.shp
+    archive:
+      format: zip
+      files:
+        - antarctica-icesheet-polygons-3857/icesheet_polygons.cpg
+        - antarctica-icesheet-polygons-3857/icesheet_polygons.dbf
+        - antarctica-icesheet-polygons-3857/icesheet_polygons.prj
+        - antarctica-icesheet-polygons-3857/icesheet_polygons.shp
+        - antarctica-icesheet-polygons-3857/icesheet_polygons.shx
+  icesheet_outlines:
+    type: shp
+    url: https://osmdata.openstreetmap.de/download/antarctica-icesheet-outlines-3857.zip
+    file: antarctica-icesheet-outlines-3857/icesheet_outlines.shp
+    ogropts:
+      - "-explodecollections"
+    archive:
+      format: zip
+      files:
+        - antarctica-icesheet-outlines-3857/icesheet_outlines.cpg
+        - antarctica-icesheet-outlines-3857/icesheet_outlines.dbf
+        - antarctica-icesheet-outlines-3857/icesheet_outlines.prj
+        - antarctica-icesheet-outlines-3857/icesheet_outlines.shp
+        - antarctica-icesheet-outlines-3857/icesheet_outlines.shx
+
+  ne_110m_admin_0_boundary_lines_land:
+    type: shp
+    url: http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_0_boundary_lines_land.zip
+    file: ne_110m_admin_0_boundary_lines_land.shp
+    ogropts: &ne_opts
+      - "--config"
+      - "SHAPE_ENCODING"
+      - "WINDOWS-1252"
+      - "-explodecollections"
+      # needs reprojecting
+      - '-t_srs'
+      - 'EPSG:3857'
+    archive:
+      format: zip
+      files:
+        - ne_110m_admin_0_boundary_lines_land.dbf
+        - ne_110m_admin_0_boundary_lines_land.prj
+        - ne_110m_admin_0_boundary_lines_land.shp
+        - ne_110m_admin_0_boundary_lines_land.shx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flex.lua	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,1011 @@
+-- This configuration for the flex backend tries to be compatible with the
+-- original pgsql c-transform backend. There might be some corner cases but
+-- it should mostly do exactly the same.
+
+-- Set this to true if you were using option -K|--keep-coastlines.
+local keep_coastlines = true
+
+-- Set this to the table name prefix (what used to be option -p|--prefix).
+local prefix = 'planet_osm'
+
+-- Set this to true if multipolygons should be written as polygons into db
+-- (what used to be option -G|--multi-geometry).
+local multi_geometry = true
+
+-- Set this to true if you want an hstore column (what used to be option
+-- -k|--hstore). Can not be true if "hstore_all" is true.
+local hstore = true
+
+-- Set this to true if you want all tags in an hstore column (what used to
+-- be option -j|--hstore-all). Can not be true if "hstore" is true.
+local hstore_all = false
+
+-- Only keep objects that have a value in one of the non-hstore columns
+-- (normal action with --hstore is to keep all objects). Equivalent to
+-- what used to be set through option --hstore-match-only.
+local hstore_match_only = true
+
+-- Set this to add an additional hstore (key/value) column containing all tags
+-- that start with the specified string, eg "name:". Will produce an extra
+-- hstore column that contains all "name:xx" tags. Equivalent to what used to
+-- be set through option -z|--hstore-column.
+local hstore_column = nil
+
+-- There is some very old specialized handling of route relations in osm2pgsql,
+-- which you probably don't need. This is disabled here, but you can enable
+-- it by setting this to true. If you don't understand this, leave it alone.
+local enable_legacy_route_processing = false
+
+-- ---------------------------------------------------------------------------
+
+if hstore and hstore_all then
+    error("hstore and hstore_all can't be both true")
+end
+
+-- Used for splitting up long linestrings
+if osm2pgsql.srid == 4326 then
+    max_length = 1
+else
+    max_length = 100000
+end
+
+-- Ways with any of the following keys will be treated as polygon
+local polygon_keys = {
+    'aeroway',
+    'amenity',
+    'building',
+    'harbour',
+    'historic',
+    'landuse',
+    'leisure',
+    'man_made',
+    'military',
+    'natural',
+    'office',
+    'place',
+    'power',
+    'public_transport',
+    'shop',
+    'sport',
+    'tourism',
+    'water',
+    'waterway',
+    'wetland',
+    'abandoned:aeroway',
+    'abandoned:amenity',
+    'abandoned:building',
+    'abandoned:landuse',
+    'abandoned:power',
+    'area:highway'
+}
+
+-- Objects without any of the following keys will be deleted
+local generic_keys = {
+    'access',
+    'addr:housename',
+    'addr:housenumber',
+    'addr:interpolation',
+    'admin_level',
+    'aerialway',
+    'aeroway',
+    'amenity',
+    'area',
+    'barrier',
+    'bicycle',
+    'boundary',
+    'brand',
+    'bridge',
+    'building',
+    'capital',
+    'construction',
+    'covered',
+    'culvert',
+    'cutting',
+    'denomination',
+    'disused',
+    'ele',
+    'embankment',
+    'foot',
+    'generation:source',
+    'harbour',
+    'healthcare',
+    'highway',
+    'historic',
+    'hours',
+    'intermittent',
+    'junction',
+    'landuse',
+    'layer',
+    'leisure',
+    'lock',
+    'man_made',
+    'military',
+    'motorcar',
+    'name',
+    'natural',
+    'office',
+    'oneway',
+    'operator',
+    'place',
+    'population',
+    'power',
+    'power_source',
+    'public_transport',
+    'railway',
+    'ref',
+    'religion',
+    'route',
+    'service',
+    'shop',
+    'sport',
+    'surface',
+    'toll',
+    'tourism',
+    'tower:type',
+    'tracktype',
+    'tunnel',
+    'water',
+    'waterway',
+    'wetland',
+    'width',
+    'wood',
+    'abandoned:aeroway',
+    'abandoned:amenity',
+    'abandoned:building',
+    'abandoned:landuse',
+    'abandoned:power',
+    'area:highway'
+}
+
+-- The following keys will be deleted
+local delete_keys = {
+    'attribution',
+    'comment',
+    'created_by',
+    'fixme',
+    'note',
+    'note:*',
+    'odbl',
+    'odbl:note',
+    'source',
+    'source:*',
+    'source_ref',
+    'way',
+    'way_area',
+    'z_order',
+}
+
+local point_columns = {
+    'access',
+    'addr:housename',
+    'addr:housenumber',
+    'addr:interpolation',
+    'admin_level',
+    'aerialway',
+    'aeroway',
+    'amenity',
+    'area',
+    'barrier',
+    'bicycle',
+    'brand',
+    'bridge',
+    'boundary',
+    'building',
+    'capital',
+    'construction',
+    'covered',
+    'culvert',
+    'cutting',
+    'denomination',
+    'disused',
+    'ele',
+    'embankment',
+    'foot',
+    'generator:source',
+    'harbour',
+    'highway',
+    'historic',
+    'horse',
+    'intermittent',
+    'junction',
+    'landuse',
+    'layer',
+    'leisure',
+    'lock',
+    'man_made',
+    'military',
+    'motorcar',
+    'name',
+    'name:fi',
+    'name:sv',
+    'minority_name',
+    'majority_name',
+    'bilingual_name',
+    'natural',
+    'office',
+    'oneway',
+    'operator',
+    'place',
+    'population',
+    'power',
+    'power_source',
+    'public_transport',
+    'railway',
+    'ref',
+    'religion',
+    'route',
+    'service',
+    'shop',
+    'sport',
+    'surface',
+    'toll',
+    'tourism',
+    'tower:type',
+    'tunnel',
+    'water',
+    'waterway',
+    'wetland',
+    'width',
+    'wood',
+}
+
+local non_point_columns = {
+    'access',
+    'addr:housename',
+    'addr:housenumber',
+    'addr:interpolation',
+    'admin_level',
+    'aerialway',
+    'aeroway',
+    'amenity',
+    'area',
+    'barrier',
+    'bicycle',
+    'brand',
+    'bridge',
+    'boundary',
+    'building',
+    'construction',
+    'covered',
+    'culvert',
+    'cutting',
+    'denomination',
+    'disused',
+    'embankment',
+    'foot',
+    'generator:source',
+    'harbour',
+    'highway',
+    'historic',
+    'horse',
+    'intermittent',
+    'junction',
+    'landuse',
+    'layer',
+    'leisure',
+    'lock',
+    'man_made',
+    'military',
+    'motorcar',
+    'name',
+    'name:fi',
+    'name:sv',
+    'minority_name',
+    'majority_name',
+    'bilingual_name',
+    'natural',
+    'office',
+    'oneway',
+    'operator',
+    'place',
+    'population',
+    'power',
+    'power_source',
+    'public_transport',
+    'railway',
+    'ref',
+    'ref_class',
+    'ref_width',
+    'religion',
+    'route',
+    'service',
+    'shop',
+    'sport',
+    'surface',
+    'toll',
+    'tourism',
+    'tower:type',
+    'tracktype',
+    'tunnel',
+    'water',
+    'waterway',
+    'wetland',
+    'width',
+    'wood',
+}
+
+-- highlight some suburbs in the capital region
+boroughs = {
+    -- Helsinki
+    ["Q2116584"] = 1, -- Vuosaari / Nordsjö
+    ["Q2510635"] = 1, -- Oulunkylä / Åggelby
+    ["Q3130945"] = 1, -- Viikki / Vik
+    ["Q1614778"] = 1, -- Herttoniemi / Hertonäs
+    -- Espoo
+    ["Q166942"] = 1, -- Leppävaara / Alberga
+    ["Q3107346"] = 1, -- Matinkylä / Mattby
+    ["Q211491"] = 1, -- Espoonlahti / Esboviken
+    ["Q211489"] = 1, -- Espoon keskus / Esbo centrum
+    ["Q219044"] = 1, -- Kauklahti / Köklax
+    ["Q1668730"] = 1, -- Tapiola / Hagalund
+    -- Vantaa
+    ["Q2640455"] = 1, -- Tikkurila / Dickursby
+    ["Q4412122"] = 1, -- Aviapolis
+    ["Q3736737"] = 1, -- Myyrmäki / Myrbacka
+    ["Q4557316"] = 1, -- Kivistö
+    ["Q4556551"] = 1, -- Koivukylä / Björkby
+    ["Q3742144"] = 1, -- Korso
+    ["Q4556262"] = 1, -- Hakunila / Håkansböle
+}
+
+--
+-- Name in majority language for object. This is name unless both name:fi and
+-- name:sv disagree with name.
+-- @param tags Raw OSM tags
+-- @return Bilingual name
+--
+function majority_name(tags)
+    if tags.name ~= nil and tags['name:sv'] ~= nil and tags['name:fi'] and tags.name ~= tags['name:fi'] and tags.name ~= tags['name:sv']
+    then
+        return tags['name:fi']
+    else
+        return tags.name
+    end
+end
+--
+-- Name in minority language for object. This is the Swedish name if name is in
+-- Finnish, and the Finnish name if name is in Swedish.
+-- @param tags Raw OSM tags
+-- @return Bilingual name
+--
+function minority_name(tags)
+    if tags['name:sv'] ~= nil and tags['name'] ~= tags['name:sv']
+    then
+        return tags['name:sv']
+    elseif tags['name:fi'] ~= nil and tags['name'] ~= tags['name:fi']
+    then
+        return tags['name:fi']
+    else
+        return nil
+    end
+end
+
+function bilingual_name(tags)
+    if tags.majority_name ~= nil and tags.minority_name ~= nil
+    then
+        return tags.majority_name .. '\n' .. tags.minority_name
+    else
+        return tags.majority_name
+    end
+end
+
+-- Makes highway classes more sensible
+function highway_class(tags)
+    if string.match(tags.highway, '_link$')
+    then
+        if tags.tags.functional_class == 'service' or tags.tags.functional_class == 'unclassified'
+        then
+            return tags.tags.functional_class
+        elseif tags.tags.functional_class ~= nil
+        then
+            return tags.tags.functional_class..'_link'
+        elseif tags.highway == 'motorway_link'
+        then
+            return 'trunk_link'
+        else
+            return tags.highway
+        end
+    elseif tags.highway == 'motorway'
+    then
+        if tags.tags.functional_class == 'primary' or tags.tags.functional_class == 'secondary' or tags.tags.functional_class == 'tertiary'
+        then
+            return tags.tags.functional_class
+        elseif tags.tags.functional_class == 'service'
+        then
+            return 'service'
+        else
+            return 'trunk'
+        end
+    else
+        if tags.highway ~= nil and tags.tags.functional_class ~= nil
+        then
+            return tags.tags.functional_class
+        else
+            return tags.highway
+        end
+    end
+end
+
+function has_shields(tags)
+    return (tags.highway == 'trunk' or tags.highway == 'primary' or tags.highway == 'secondary' or tags.highway == 'tertiary') 
+end
+
+-- https://stackoverflow.com/a/7615129
+function mysplit(inputstr, sep)
+        if sep == nil then
+                sep = "%s"
+        end
+        local t={}
+        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
+                table.insert(t, str)
+        end
+        return t
+end
+
+function combine_stringlists(a, b)
+    if a ~= nil and a ~= ''
+    then
+        if b ~= nil and b ~= ''
+        then
+            return a..';'..b
+        else
+            return a
+        end
+    else
+        return b
+    end
+end
+
+function combine_refs(a, b)
+    return combine_stringlists(a, b)
+end
+
+-- Widths of ref characters in Liikenne font, used to calculate shield sizes
+character_widths = {
+    ['0'] = 616,
+    ['1'] = 337,
+    ['2'] = 600,
+    ['3'] = 621,
+    ['4'] = 689,
+    ['5'] = 623,
+    ['6'] = 566,
+    ['7'] = 499,
+    ['8'] = 616,
+    ['9'] = 566,
+    [' '] = 260,
+    ['E'] = 613,
+}
+
+function ref_width(ref)
+    local result = 0
+    for i = 1, #ref
+    do
+        result = result + (character_widths[ref:sub(i, i)] or 0)
+    end
+    return math.max(math.ceil((result - 1000) / 77), 1)
+end
+
+function ref_widths(refs)
+    local result = ''
+    for _, ref in ipairs(mysplit(refs, ';'))
+    do
+        result = combine_stringlists(result, ref_width(ref))
+    end
+    return result
+end
+
+-- Makes refs more sensible.
+-- 5-digit refs are not found on the ground so they are omitted.
+-- int_ref is added to refs.
+function highway_refs(tags)
+    if has_shields(tags) and (tags.ref ~= nil or tags.tags.int_ref ~= nil)
+    then
+        if tags.junction == 'roundabout'
+        then
+            return nil
+        else
+            local result = ''
+            local all_refs = combine_refs(tags.ref, tags.tags.int_ref)
+            for _, ref in ipairs(mysplit(all_refs, ';'))
+            do
+                if tonumber(ref) == nil or tonumber(ref) < 10000
+                then
+                    ref = string.gsub(ref, '^E 0', 'E ')
+                    result = combine_refs(result, ref)
+                end
+            end
+            return result
+        end
+    else
+        return tags.ref
+    end
+end
+
+-- classify road type by number
+function road_class_by_ref(ref)
+    local n = tonumber(ref)
+    if n ~= nil and n > 0
+    then
+        if n < 40
+        then
+            return 'valtatie'
+        elseif n < 100
+        then
+            return 'kantatie'
+        elseif n < 1000
+        then
+            return 'seututie'
+        else
+            return 'yhdystie'
+        end
+    elseif string.match(ref, '^E ?%d+$')
+    then
+        return 'eurooppatie'
+    else
+        return 'unknown'
+    end
+end
+
+function classify_road_numbers(refs)
+    local result = ''
+    for _, ref in ipairs(mysplit(refs, ';'))
+    do
+        result = combine_stringlists(result, road_class_by_ref(ref))
+    end
+    return result
+end
+
+function gen_columns(text_columns, with_hstore, area, geometry_type)
+    columns = {}
+
+    local add_column = function (name, type)
+        columns[#columns + 1] = { column = name, type = type }
+    end
+
+    for _, c in ipairs(text_columns) do
+        add_column(c, 'text')
+    end
+
+    add_column('z_order', 'int')
+
+    if area ~= nil then
+        if area then
+            add_column('way_area', 'area')
+        else
+            add_column('way_area', 'real')
+        end
+    end
+
+    if hstore_column then
+        add_column(hstore_column, 'hstore')
+    end
+
+    if with_hstore then
+        add_column('tags', 'hstore')
+    end
+
+    add_column('way', geometry_type)
+
+    return columns
+end
+
+local tables = {}
+
+tables.point = osm2pgsql.define_table{
+    name = prefix .. '_point',
+    ids = { type = 'node', id_column = 'osm_id' },
+    columns = gen_columns(point_columns, hstore or hstore_all, nil, 'point')
+}
+
+tables.line = osm2pgsql.define_table{
+    name = prefix .. '_line',
+    ids = { type = 'way', id_column = 'osm_id' },
+    columns = gen_columns(non_point_columns, hstore or hstore_all, false, 'linestring')
+}
+
+tables.polygon = osm2pgsql.define_table{
+    name = prefix .. '_polygon',
+    ids = { type = 'area', id_column = 'osm_id' },
+    columns = gen_columns(non_point_columns, hstore or hstore_all, true, 'geometry')
+}
+
+tables.roads = osm2pgsql.define_table{
+    name = prefix .. '_roads',
+    ids = { type = 'way', id_column = 'osm_id' },
+    columns = gen_columns(non_point_columns, hstore or hstore_all, false, 'linestring')
+}
+
+local z_order_lookup = {
+    proposed = {1, false},
+    construction = {2, false},
+    steps = {10, false},
+    cycleway = {10, false},
+    bridleway = {10, false},
+    footway = {10, false},
+    path = {10, false},
+    track = {11, false},
+    service = {15, false},
+
+    tertiary_link = {24, false},
+    secondary_link = {25, true},
+    primary_link = {27, true},
+    trunk_link = {28, true},
+    motorway_link = {29, true},
+
+    raceway = {30, false},
+    pedestrian = {31, false},
+    living_street = {32, false},
+    road = {33, false},
+    unclassified = {33, false},
+    residential = {33, false},
+    tertiary = {34, false},
+    secondary = {36, true},
+    primary = {37, true},
+    trunk = {38, true},
+    motorway = {39, true}
+}
+
+function as_bool(value)
+    return value == 'yes' or value == 'true' or value == '1'
+end
+
+function get_z_order(tags)
+    local z_order = 100 * math.floor(tonumber(tags.layer or '0') or 0)
+    local roads = false
+
+    local highway = tags['highway']
+    if highway then
+        local r = z_order_lookup[highway] or {0, false}
+        z_order = z_order + r[1]
+        roads = r[2]
+    end
+
+    if tags.railway then
+        z_order = z_order + 35
+        roads = true
+    end
+
+    if tags.boundary and tags.boundary == 'administrative' then
+        roads = true
+    end
+
+    if as_bool(tags.bridge) then
+        z_order = z_order + 100
+    end
+
+    if as_bool(tags.tunnel) then
+        z_order = z_order - 100
+    end
+
+    return z_order, roads
+end
+
+function make_check_in_list_func(list)
+    local h = {}
+    for _, k in ipairs(list) do
+        h[k] = true
+    end
+    return function(tags)
+        for k, _ in pairs(tags) do
+            if h[k] then
+                return true
+            end
+        end
+        return false
+    end
+end
+
+local is_polygon = make_check_in_list_func(polygon_keys)
+local clean_tags = osm2pgsql.make_clean_tags_func(delete_keys)
+
+function make_column_hash(columns)
+    local h = {}
+
+    for _, k in ipairs(columns) do
+        h[k] = true
+    end
+
+    return h
+end
+
+function make_get_output(columns, hstore_all)
+    local h = make_column_hash(columns)
+    if hstore_all then
+        return function(tags)
+            local output = {}
+            local hstore_entries = {}
+
+            for k, _ in pairs(tags) do
+                if h[k] then
+                    output[k] = tags[k]
+                end
+                hstore_entries[k] = tags[k]
+            end
+
+            return output, hstore_entries
+        end
+    else
+        return function(tags)
+            local output = {}
+            local hstore_entries = {}
+
+            for k, _ in pairs(tags) do
+                if h[k] then
+                    output[k] = tags[k]
+                else
+                    hstore_entries[k] = tags[k]
+                end
+            end
+
+            return output, hstore_entries
+        end
+    end
+end
+
+local has_generic_tag = make_check_in_list_func(generic_keys)
+
+local get_point_output = make_get_output(point_columns, hstore_all)
+local get_non_point_output = make_get_output(non_point_columns, hstore_all)
+
+function get_hstore_column(tags)
+    local len = #hstore_column
+    local h = {}
+    for k, v in pairs(tags) do
+        if k:sub(1, len) == hstore_column then
+            h[k:sub(len + 1)] = v
+        end
+    end
+
+    if next(h) then
+        return h
+    end
+    return nil
+end
+
+function add_generic_tags(object, output)
+    output.majority_name = majority_name(output)
+    output.minority_name = minority_name(output)
+    output.bilingual_name = bilingual_name(output)
+    return output
+end
+
+function osm2pgsql.process_node(object)
+    if clean_tags(object.tags) then
+        return
+    end
+
+    if object.tags.layer then
+        object.tags.layer = tonumber(object.tags.layer)
+    end
+
+    local output
+    local output_hstore = {}
+    if hstore or hstore_all then
+        output, output_hstore = get_point_output(object.tags)
+        if not next(output) and not next(output_hstore) then
+            return
+        end
+        if hstore_match_only and not has_generic_tag(object.tags) then
+            return
+        end
+    else
+        output = object.tags
+        if not has_generic_tag(object.tags) then
+            return
+        end
+    end
+
+    output = add_generic_tags(object, output)
+    output.tags = output_hstore
+
+    if hstore_column then
+        output[hstore_column] = get_hstore_column(object.tags)
+    end
+
+    tables.point:add_row(output)
+end
+
+function osm2pgsql.process_way(object)
+    if clean_tags(object.tags) then
+        return
+    end
+ 
+    if object.tags.layer then
+        object.tags.layer = tonumber(object.tags.layer)
+    end
+
+
+    local add_area = false
+    if object.tags.natural == 'coastline' then
+        add_area = true
+        if not keep_coastlines then
+            object.tags.natural = nil
+        end
+    end
+
+    local output
+    local output_hstore = {}
+    if hstore or hstore_all then
+        output, output_hstore = get_non_point_output(object.tags)
+        if not next(output) and not next(output_hstore) then
+            return
+        end
+        if hstore_match_only and not has_generic_tag(object.tags) then
+            return
+        end
+        if add_area and hstore_all then
+            output_hstore.area = 'yes'
+        end
+    else
+        output = object.tags
+        if not has_generic_tag(object.tags) then
+            return
+        end
+    end
+
+    local polygon
+    local area_tag = object.tags.area
+    if area_tag == 'yes' or area_tag == '1' or area_tag == 'true' then
+        polygon = true
+    elseif area_tag == 'no' or area_tag == '0' or area_tag == 'false' then
+        polygon = false
+    else
+        polygon = is_polygon(object.tags)
+    end
+
+    if add_area then
+        output.area = 'yes'
+        polygon = true
+    end
+
+    local z_order, roads = get_z_order(object.tags)
+    output.z_order = z_order
+    output = add_generic_tags(object, output)
+
+    output.tags = output_hstore
+
+    if output.highway ~= nil
+    then
+        if output.highway == 'construction'
+        then
+            return
+        end
+        output.highway = highway_class(output)
+        output.ref = highway_refs(output)
+        if output.highway == 'construction' and output.construction == 'motorway'
+        then
+            output.construction = 'trunk'
+        elseif output.highway == 'construction' and output.construction == 'motorway_link'
+        then
+            output.construction = 'trunk_link'
+        end
+
+        -- classify references for for Finland shield rendering
+        if output.ref ~= nil
+        then
+            output.ref_class = classify_road_numbers(output.ref)
+            output.ref_width = ref_widths(output.ref)
+        end
+    end
+
+    if hstore_column then
+        output[hstore_column] = get_hstore_column(object.tags)
+    end
+
+    if polygon and object.is_closed then
+        output.way = { create = 'area' }
+        tables.polygon:add_row(output)
+    else
+        output.way = { create = 'line', split_at = max_length }
+        tables.line:add_row(output)
+        if roads then
+            tables.roads:add_row(output)
+        end
+    end
+end
+
+function osm2pgsql.process_relation(object)
+    if clean_tags(object.tags) then
+        return
+    end
+
+    local type = object.tags.type
+    if (type ~= 'route') and (type ~= 'multipolygon') and (type ~= 'boundary') then
+        return
+    end
+    object.tags.type = nil
+
+    local output
+    local output_hstore = {}
+    if hstore or hstore_all then
+        output, output_hstore = get_non_point_output(object.tags)
+        if not next(output) and not next(output_hstore) then
+            return
+        end
+        if hstore_match_only and not has_generic_tag(object.tags) then
+            return
+        end
+    else
+        output = object.tags
+        if not has_generic_tag(object.tags) then
+            return
+        end
+    end
+
+    if not next(output) and not next(output_hstore) then
+        return
+    end
+
+    if enable_legacy_route_processing and (hstore or hstore_all) and type == 'route' then
+        if not object.tags.route_name then
+            output_hstore.route_name = object.tags.name
+        end
+
+        local state = object.tags.state
+        if state ~= 'alternate' and state ~= 'connection' then
+            state = 'yes'
+        end
+
+        local network = object.tags.network
+        if network == 'lcn' then
+            output_hstore.lcn = output_hstore.lcn or state
+            output_hstore.lcn_ref = output_hstore.lcn_ref or object.tags.ref
+        elseif network == 'rcn' then
+            output_hstore.rcn = output_hstore.rcn or state
+            output_hstore.rcn_ref = output_hstore.rcn_ref or object.tags.ref
+        elseif network == 'ncn' then
+            output_hstore.ncn = output_hstore.ncn or state
+            output_hstore.ncn_ref = output_hstore.ncn_ref or object.tags.ref
+        elseif network == 'lwn' then
+            output_hstore.lwn = output_hstore.lwn or state
+            output_hstore.lwn_ref = output_hstore.lwn_ref or object.tags.ref
+        elseif network == 'rwn' then
+            output_hstore.rwn = output_hstore.rwn or state
+            output_hstore.rwn_ref = output_hstore.rwn_ref or object.tags.ref
+        elseif network == 'nwn' then
+            output_hstore.nwn = output_hstore.nwn or state
+            output_hstore.nwn_ref = output_hstore.nwn_ref or object.tags.ref
+        end
+
+        local pc = object.tags.preferred_color
+        if pc == '0' or pc == '1' or pc == '2' or pc == '3' or pc == '4' then
+            output_hstore.route_pref_color = pc
+        else
+            output_hstore.route_pref_color = '0'
+        end
+    end
+
+    local make_boundary = false
+    local make_polygon = false
+    if type == 'boundary' then
+        make_boundary = true
+    elseif type == 'multipolygon' and object.tags.boundary then
+        make_boundary = true
+    elseif type == 'multipolygon' then
+        make_polygon = true
+    end
+
+    local z_order, roads = get_z_order(object.tags)
+    output.z_order = z_order
+    output = add_generic_tags(object, output)
+
+    output.tags = output_hstore
+
+    if hstore_column then
+        output[hstore_column] = get_hstore_column(object.tags)
+    end
+
+    if not make_polygon then
+        output.way = { create = 'line', split_at = max_length }
+        tables.line:add_row(output)
+        if roads then
+            tables.roads:add_row(output)
+        end
+    end
+
+    if make_boundary or make_polygon then
+        output.way = { create = 'area', multi = multi_geometry }
+        tables.polygon:add_row(output)
+    end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project.mml	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,804 @@
+scale: 1
+metatile: 2
+name: 
+description: A general-purpose OpenStreetMap mapnik style, in CartoCSS
+bounds: &world
+	- -180
+	- -85.05112877980659
+	- 180
+	- 85.05112877980659
+center:
+	- 0
+	- 0
+	- 4
+format: png
+interactivity: false
+minzoom: 0
+maxzoom: 22
+srs: "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"
+
+# Various parts to be included later on
+_parts:
+	# Extents are used for tilemill, and don't actually make it to the generated XML
+	extents: &extents
+		extent: *world
+		srs-name: "900913"
+		srs: "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"
+	osm2pgsql: &osm2pgsql
+		type: "postgis"
+		dbname: "gis"
+		key_field: ""
+		geometry_field: "way"
+		extent: "-20037508,-20037508,20037508,20037508"
+
+Stylesheet:
+	- style/style.mss
+	- style/roads.mss
+	- style/buildings.mss
+	- style/places.mss
+	- style/shapefiles.mss
+	- style/amenity.mss
+	- style/roadref.mss
+Layer:
+	- id: landcover
+		geometry: polygon
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					(CASE WHEN
+						"landuse" IN ('grass', 'meadow', 'recreation_ground')
+						OR ("leisure" IN ('park', 'playground', 'arena', 'stadium', 'sports_centre') AND landuse IS NULL)
+						OR "natural" = 'scrub'
+						THEN 'grass'
+						ELSE CASE WHEN ("landuse" IN ('commercial', 'retail') OR "amenity" IN ('bus_station', 'ferry_terminal'))
+							THEN 'commercial'
+							ELSE CASE WHEN ("natural" = 'wood' OR "landuse" = 'forest')
+								THEN 'forest'
+								ELSE CASE WHEN ("natural" = 'water' OR "landuse" IN ('reservoir'))
+									THEN 'water'
+									ELSE CASE WHEN ("landuse" IN ('religious', 'cemetery') OR "amenity" = 'grave_yard')
+										THEN 'religious'
+										ELSE CASE WHEN ("landuse" = 'railway')
+											THEN 'industrial'
+											ELSE "landuse"
+										END
+									END
+								END
+							END
+						END
+					END) AS feature,
+					way_area/NULLIF(POW(!scale_denominator!*0.001*0.28,2),0) AS way_pixels,
+					way_area
+					FROM planet_osm_polygon
+					WHERE (landuse IN ('forest', 'farmland', 'residential', 'commercial', 'retail', 'industrial', 'meadow', 'grass', 'vineyard', 'orchard', 'religious', 'railway', 'construction', 'cemetery')
+						OR "natural" IN ('wood', 'wetland', 'mud', 'sand', 'scree', 'shingle', 'bare_rock', 'heath', 'grassland', 'scrub', 'water'))
+						OR "leisure" IN ('park', 'playground', 'arena', 'stadium', 'sports_centre')
+						OR "amenity" IN ('bus_station', 'ferry_terminal', 'grave_yard')
+						AND way_area > 0.01*!pixel_width!::real*!pixel_height!::real
+						AND building IS NULL
+					ORDER BY way_area DESC, feature
+				) AS landcover
+		properties:
+			cache-features: true
+			minzoom: 5
+	- id: inland-water
+		geometry: polygon
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way
+					FROM planet_osm_polygon
+					WHERE ("natural" = 'water' OR landuse IN ('reservoir', 'basin') OR waterway = 'riverbank')
+				) AS landcover
+		properties:
+			cache-features: true
+			minzoom: 5
+	- id: ocean-lz
+		geometry: polygon
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+						way
+					FROM simplified_water_polygons
+				) AS ocean_lz
+		properties:
+			maxzoom: 9
+	- id: civic-services
+		geometry: polygon
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way
+					FROM planet_osm_polygon
+					WHERE ("amenity" IN ('hospital', 'community_centre', 'fire_station', 'school', 'university', 'kindergarten', 'childcare', 'social_facility') OR landuse IN ('civic_services', 'civic_admin'))
+				) AS civic_services
+		properties:
+			cache-features: true
+			minzoom: 5
+	- id: aerodrome
+		geometry: polygon
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way
+					FROM planet_osm_polygon
+					WHERE aeroway = 'aerodrome'
+				) AS aerodrome
+		properties:
+			minzoom: 10
+	- id: runway
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					aeroway,
+					ref
+					FROM planet_osm_line
+					WHERE aeroway IN ('runway', 'taxiway')
+				) AS aerodrome
+		properties:
+			minzoom: 10
+	- id: ocean
+		geometry: polygon
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+						way
+					FROM water_polygons
+				) AS ocean
+		properties:
+			minzoom: 10
+	- id: coastline
+		geometry: line
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT way FROM planet_osm_line WHERE "natural" = 'coastline') AS coastlines
+		properties:
+			minzoom: 12
+	- id: buildings
+		geometry: polygon
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					building
+					FROM planet_osm_polygon
+					WHERE building IS NOT NULL
+				) AS landcover
+		properties:
+			cache-features: true
+			minzoom: 14
+	- id: road-casing-low-zoom
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: &road_low_zoom_sql |-
+				(SELECT
+					way,
+					highway
+					FROM planet_osm_roads
+					WHERE "highway" IN ('primary', 'trunk')
+						AND (tags->"access" IS NULL OR tags->"access" NOT IN ('private', 'no'))
+					ORDER BY
+					CASE
+						WHEN highway = 'trunk' THEN 37
+						WHEN highway = 'primary' THEN 36
+					END ASC NULLS LAST
+				) AS road
+		properties:
+			minzoom: 4
+			maxzoom: 9
+	- id: road-low-zoom
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: *road_low_zoom_sql
+		properties:
+			minzoom: 4
+			maxzoom: 9
+	- id: road-casing-layer-n1
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: &road_sql |-
+				(SELECT
+					way,
+					(CASE WHEN "highway" IN ('motorway', 'trunk', 'primary', 'secondary', 'tertiary')
+						THEN 'road_major'
+						ELSE CASE WHEN "highway" IN ('motorway_link', 'trunk_link', 'primary_link', 'secondary_link', 'tertiary_link', 'residential', 'unclassified', 'living_street')
+							THEN 'road_minor'
+							ELSE CASE WHEN "highway" IN ('path', 'footway', 'cycleway', 'track', 'steps', 'pedestrian', 'platform')
+								THEN 'road_path'
+								ELSE 'road_' || "highway"
+							END
+						END
+					END) AS feature,
+					name,
+					minority_name, 
+					highway,
+					COALESCE(layer::integer, 0) AS layer
+					FROM planet_osm_line
+					WHERE "highway" IS NOT NULL
+						AND (tags->"access" IS NULL OR tags->"access" NOT IN ('private', 'no'))
+					ORDER BY
+					CASE
+						WHEN highway = 'motorway' THEN 38
+						WHEN highway = 'trunk' THEN 37
+						WHEN highway = 'primary' THEN 36
+						WHEN highway = 'secondary' THEN 35
+						WHEN highway = 'tertiary' THEN 34
+						
+						WHEN highway = 'motorway_link' THEN 28
+						WHEN highway = 'trunk_link' THEN 27
+						WHEN highway = 'primary_link' THEN 26
+						WHEN highway = 'secondary_link' THEN 25
+						WHEN highway = 'tertiary_link' THEN 24
+						
+						WHEN highway = 'residential' THEN 10
+						WHEN highway = 'unclassified' THEN 10
+						WHEN highway = 'path' THEN 8
+						WHEN highway = 'footway' THEN 8
+						WHEN highway = 'cycleway' THEN 8
+						WHEN highway = 'service' THEN 5
+						
+						WHEN highway = 'runway' THEN 6
+						WHEN highway = 'taxiway' THEN 5
+					END ASC NULLS LAST
+				) AS road
+		properties:
+			minzoom: 10
+	- id: road-layer-n1
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: *road_sql
+		properties:
+			minzoom: 10
+	- id: rail-layer-n1
+		geometry: linestring
+		Datasource:
+			<<: *osm2pgsql
+			table: &rail_sql |-
+				(SELECT
+					way,
+					name,
+					minority_name,
+					service,
+					COALESCE(layer::integer, 0) AS layer,
+					tags->'electrified' AS electrified,
+					tags->'usage' AS usage
+					FROM planet_osm_line
+					WHERE "railway" = 'rail'
+					ORDER BY
+					CASE
+						WHEN service IS NULL THEN 20
+						WHEN service IS NOT NULL THEN 30
+					END DESC NULLS LAST
+				) AS rail
+	- id: road-casing
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: *road_sql
+		properties:
+			minzoom: 12
+	- id: road
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: *road_sql
+		properties:
+			minzoom: 12
+	- id: rail
+		geometry: linestring
+		Datasource:
+			<<: *osm2pgsql
+			table: *rail_sql
+	- id: bridge-area
+		geometry: polygon
+		Datasource:
+			<<: *osm2pgsql
+			table: &bridge_area_sql |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					'0' AS natural
+					FROM planet_osm_polygon
+					WHERE "man_made" = 'bridge'
+				) AS bridge_area
+		properties:
+			minzoom: 12
+	- id: road-casing-layer-1
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: *road_sql
+		properties:
+			minzoom: 12
+	- id: road-layer-1
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: *road_sql
+		properties:
+			minzoom: 12
+	- id: rail-layer-1
+		geometry: linestring
+		Datasource:
+			<<: *osm2pgsql
+			table: *rail_sql
+	- id: place-major
+		geometry: point
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					place
+					FROM planet_osm_point
+					WHERE "place" IN ('city', 'town')
+				) AS place_major
+		properties:
+			minzoom: 6
+			maxzoom: 15
+	- id: train-stations
+		geometry: point
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					railway,
+					tags->'railway:ref' AS ref
+					FROM planet_osm_point
+					WHERE "railway" IN ('station', 'halt')
+				) AS train_stations
+	- id: place-medium
+		geometry: point
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					place
+					FROM planet_osm_point
+					WHERE "place" IN ('suburb', 'borough', 'village')
+				) AS place_medium
+		properties:
+			minzoom: 12
+			maxzoom: 17
+	- id: stations
+		geometry: point
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					COALESCE(
+						'amenity_' || CASE WHEN amenity IN ('bus_station') THEN amenity END
+					) AS feature
+					FROM
+					(
+						SELECT
+						ST_PointOnSurface(way) AS way,
+							name,
+							bilingual_name,
+							amenity
+							FROM planet_osm_polygon
+							WHERE way && !bbox!
+								AND way_area < 768000*POW(!scale_denominator!*0.001*0.28,2)
+						UNION ALL
+						SELECT
+							way,
+							bilingual_name,
+							name,
+							amenity
+							FROM planet_osm_point
+							WHERE way && !bbox!
+					) AS station_subquery
+					WHERE (
+						"amenity" IN ('bus_station')
+					)
+				) AS stations
+		properties:
+			minzoom: 13
+	- id: place-natural
+		geometry: polygon
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					place,
+					way_area/NULLIF(POW(!scale_denominator!*0.001*0.28,2),0) AS way_pixels,
+					way_area
+					FROM planet_osm_polygon
+					WHERE (
+						"place" IN ('island', 'peninsula', 'isthmus', 'islet')
+						OR "natural" IN ('peak', 'hill', 'fell')
+					)
+				) AS place_natural
+		properties:
+			minzoom: 8
+	- id: place-minor
+		geometry: point
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					(CASE WHEN ("place" = 'locality' OR "natural" IN ('peak', 'hill', 'fell')) THEN 1 ELSE 0 END) AS natural
+					FROM planet_osm_point
+					WHERE (
+						"place" IN ('neighbourhood', 'quarter', 'farm', 'hamlet', 'locality')
+						OR "natural" IN ('peak', 'hill', 'fell')
+					)
+				) AS place_medium
+		properties:
+			minzoom: 15
+	- id: train-sites
+		geometry: point
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					railway,
+					tags->'railway:ref' AS ref
+					FROM planet_osm_point
+					WHERE "railway" IN ('site', 'yard', 'crossover', 'junction', 'technical_station', 'service_station')
+				) AS train_stations
+	- id: poi-name
+		geometry: polygon
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					0 as natural
+					FROM
+					(
+						SELECT
+						ST_PointOnSurface(way) AS way,
+							name,
+					bilingual_name,
+							man_made,
+							building,
+							leisure,
+							amenity,
+							historic
+							FROM planet_osm_polygon
+							WHERE way && !bbox!
+								AND way_area < 768000*POW(!scale_denominator!*0.001*0.28,2)
+						UNION ALL
+						SELECT
+							way,
+							name,
+					bilingual_name,
+							building,
+							man_made,
+							leisure,
+							amenity,
+							historic
+							FROM planet_osm_point
+							WHERE way && !bbox!
+					) AS poi_name_subquery
+					WHERE (
+						"man_made" IN ('bridge')
+						OR "amenity" IN ('hospital', 'university', 'exhibition_centre')
+						OR "leisure" IN ('stadium')
+						OR "historic" IN ('castle')
+					)
+				) AS poi_name
+		properties:
+			minzoom: 15
+	- id: poi-name-medium
+		geometry: polygon
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					shop,
+					0 as natural
+					FROM
+					(
+						SELECT
+						ST_PointOnSurface(way) AS way,
+							name,
+							bilingual_name,
+							amenity,
+							shop
+							FROM planet_osm_polygon
+							WHERE way && !bbox!
+								AND way_area < 768000*POW(!scale_denominator!*0.001*0.28,2)
+						UNION ALL
+						SELECT
+							way,
+							name,
+							bilingual_name,
+							shop,
+							amenity
+							FROM planet_osm_point
+							WHERE way && !bbox!
+					) AS poi_name_subquery
+					WHERE (
+						"amenity" IN ('school', 'marketplace', 'fire_station')
+						OR "shop" = 'mall'
+					)
+				) AS poi_name_medium
+		properties:
+			minzoom: 16
+	- id: aerodrome-name
+		geometry: point
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					aeroway,
+					name,
+					bilingual_name,
+					ref
+					FROM
+					(
+						SELECT
+						ST_PointOnSurface(way) AS way,
+							aeroway,
+							name,
+							bilingual_name,
+							COALESCE(tags->'iata', tags->'icao', ref) as ref
+							FROM planet_osm_polygon
+							WHERE way && !bbox!
+								AND way_area < 768000*POW(!scale_denominator!*0.001*0.28,2)
+						UNION ALL
+						SELECT
+							way,
+							aeroway,
+							name,
+							bilingual_name,
+							COALESCE(tags->'iata', tags->'icao', ref) as ref
+							FROM planet_osm_point
+							WHERE way && !bbox!
+					) AS station_subquery
+					WHERE "aeroway" = 'aerodrome'
+				) AS stations
+		properties:
+			minzoom: 9
+	
+	- id: poi-name-minor
+		geometry: polygon
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					name,
+					bilingual_name,
+					0 as natural
+					FROM
+					(
+						SELECT
+						ST_PointOnSurface(way) AS way,
+							name,
+							bilingual_name,
+							highway,
+							area,
+							amenity
+							FROM planet_osm_polygon
+							WHERE way && !bbox!
+								AND way_area < 768000*POW(!scale_denominator!*0.001*0.28,2)
+						UNION ALL
+						SELECT
+							way,
+							name,
+							bilingual_name,
+							highway,
+							NULL as area,
+							amenity
+							FROM planet_osm_point
+							WHERE way && !bbox!
+					) AS poi_name_subquery
+					WHERE (
+						"amenity" IN ('kindergarten', 'social_facility')
+						OR ("highway" IN ('footway', 'pedestrian') AND area = 'yes')
+					)
+				) AS poi_name_medium
+		properties:
+			minzoom: 17
+	- id: train-milestones
+		geometry: point
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					tags->'railway:position' AS position,
+					railway
+					FROM planet_osm_point
+					WHERE "railway" = 'milestone'
+				) AS train_milestones
+	- id: road-text
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: *road_sql
+		properties:
+			minzoom: 14
+	- id: road-text-minority
+		geometry: line
+		Datasource:
+			<<: *osm2pgsql
+			table: *road_sql
+		properties:
+			minzoom: 14
+	- id: roads-text-ref
+		geometry: linestring
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: &road-ref-sql |-
+				(SELECT
+						way,
+						highway,
+						refs,
+						ref_1,
+						ref_2,
+						ref_3,
+						ref_4,
+						ref_5,
+						ref_6,
+						ref_class_1,
+						ref_class_2,
+						ref_class_3,
+						ref_class_4,
+						ref_class_5,
+						ref_class_6,
+						ref_length_1,
+						ref_length_2,
+						ref_length_3,
+						ref_length_4,
+						ref_length_5,
+						ref_length_6
+					FROM (
+						SELECT
+								osm_id,
+								way,
+								highway,
+								array_to_string(refs, E'\n') AS refs,
+								refs[1] as ref_1,
+								refs[2] as ref_2,
+								refs[3] as ref_3,
+								refs[4] as ref_4,
+								refs[5] as ref_5,
+								refs[6] as ref_6,
+								ref_classes[1] as ref_class_1,
+								ref_classes[2] as ref_class_2,
+								ref_classes[3] as ref_class_3,
+								ref_classes[4] as ref_class_4,
+								ref_classes[5] as ref_class_5,
+								ref_classes[6] as ref_class_6,
+								ref_widths[1] as ref_length_1,
+								ref_widths[2] as ref_length_2,
+								ref_widths[3] as ref_length_3,
+								ref_widths[4] as ref_length_4,
+								ref_widths[5] as ref_length_5,
+								ref_widths[6] as ref_length_6
+							FROM (
+								SELECT
+										osm_id,
+										way,
+										highway,
+										string_to_array(ref, ';') AS refs,
+										string_to_array(ref_class, ';') AS ref_classes,
+										string_to_array(ref_width, ';') AS ref_widths
+									FROM planet_osm_line
+									WHERE (highway IN ('motorway', 'trunk', 'primary', 'secondary', 'tertiary'))
+										AND ref IS NOT NULL
+							) AS p) AS q
+					ORDER BY
+						CASE
+							WHEN highway = 'motorway' THEN 38
+							WHEN highway = 'trunk' THEN 37
+							WHEN highway = 'primary' THEN 36
+							WHEN highway = 'secondary' THEN 35
+							WHEN highway = 'tertiary' THEN 34
+							WHEN highway = 'taxiway' THEN 5
+						END DESC NULLS LAST,
+						refs,
+						osm_id
+				) AS roads_text_ref
+		properties:
+			minzoom: 8
+	- id: roads-text-ref2
+		geometry: linestring
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: *road-ref-sql
+		properties:
+			minzoom: 10
+	- id: roads-text-ref3
+		geometry: linestring
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: *road-ref-sql
+		properties:
+			minzoom: 10
+	- id: roads-text-ref4
+		geometry: linestring
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: *road-ref-sql
+		properties:
+			minzoom: 10
+	- id: roads-text-ref5
+		geometry: linestring
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: *road-ref-sql
+		properties:
+			minzoom: 10
+	- id: roads-text-ref6
+		geometry: linestring
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: *road-ref-sql
+		properties:
+			minzoom: 10
+	- id: railway-platform-ref
+		geometry: linestring
+		<<: *extents
+		Datasource:
+			<<: *osm2pgsql
+			table: |-
+				(SELECT
+					way,
+					COALESCE(tags->'local_ref', ref) AS ref
+					FROM planet_osm_line
+					WHERE "railway" = 'platform_edge'
+					ORDER BY ref
+				) AS railway_platform_edge_ref
+		properties:
+			minzoom: 17
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/generate_shields.py	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,122 @@
+#!/usr/bin/env python3
+
+# Generate highway shields as SVG files in symbols/shields.
+
+from __future__ import print_function
+import copy, lxml.etree, math, os
+
+
+def main():
+    namespace = 'http://www.w3.org/2000/svg'
+    svgns = '{' + namespace + '}'
+    svgnsmap = {None: namespace}
+
+    config = {}
+    config['base'] = {}
+
+    # font_height and font_width are determined by trial and error
+    config['base']['rounded_corners'] = 2
+    config['base']['font_height'] = 11
+    config['base']['font_width'] = 0.85
+    config['base']['padding_x'] = 8
+    config['base']['padding_y'] = 2
+    config['base']['stroke_width'] = 1
+
+    # Fall back colours used if no colours are defined in road-colours.yaml for a road type.
+    config['base']['fill'] = '#f1f1f1'
+    config['base']['stroke_fill'] = '#c6c6c6'
+
+    config['global'] = {}
+
+    config['global']['types'] = ['valtatie', 'kantatie', 'seututie', 'yhdystie', 'eurooppatie']
+    config['global']['max_width'] = 48
+    config['global']['output_dir'] = '../symbols/shields/' # specified relative to the script location
+    
+    config['valtatie'] = {'fill': '#ff163c', 'stroke_fill': 'white'}
+    config['kantatie'] = {'fill': '#ffd90f', 'stroke_fill': 'black', 'stroke_width': 0.5}
+    config['seututie'] = {'fill': 'white', 'stroke_fill': 'black', 'stroke_width': 0.5}
+    config['yhdystie'] = {'fill': '#005eb7', 'stroke_fill': 'white'}
+    config['eurooppatie'] = {'fill': '#00997c', 'stroke_fill': 'white'}
+
+    if not os.path.exists(os.path.dirname(config['global']['output_dir'])):
+        os.makedirs(os.path.dirname(config['global']['output_dir']))
+
+    height = 1
+    shield_size = 'base'
+
+    dirpath = os.path.join(os.path.dirname(__file__), config['global']['output_dir'])
+    try:
+        os.makedirs(dirpath)
+    except FileExistsError:
+        pass
+
+    for width in range(1, config['global']['max_width'] + 1):
+        for shield_type in config['global']['types']:
+
+            # merge base config and specific styles
+            vars = copy.deepcopy(config['base'])
+            if shield_type in config:
+                for option in config[shield_type]:
+                    vars[option] = config[shield_type][option]
+
+            shield_width = 2 * vars['padding_x'] + math.ceil(vars['font_width'] * width)
+            shield_height = 2 * vars['padding_y'] + math.ceil(vars['font_height'] * height)
+
+            svg = lxml.etree.Element('svg', nsmap=svgnsmap)
+            svg.set('width', '100%')
+            svg.set('height', '100%')
+            svg.set('viewBox', '0 0 ' + str(shield_width    + vars['stroke_width']) + ' ' + str(shield_height + vars['stroke_width']))
+
+            if vars['stroke_width'] > 0:
+                offset_x = vars['stroke_width'] / 2.0
+                offset_y = vars['stroke_width'] / 2.0
+            else:
+                offset_x = 0
+                offset_y = 0
+
+            background = lxml.etree.Element(svgns + 'rect')
+            background.set('x', str(offset_x))
+            background.set('y', str(offset_y))
+            background.set('width', str(shield_width))
+            background.set('height', str(shield_height))
+            background.set('id', 'shield-background')
+            background.set('style', 'fill:' + vars['fill'])
+            svg.append(background)
+
+            shield = lxml.etree.Element(svgns + 'rect')
+            shield.set('x', str(offset_x + 0.5))
+            shield.set('y', str(offset_y + 0.5))
+            shield.set('width', str(shield_width - 1))
+            shield.set('height', str(shield_height - 1))
+            if vars['rounded_corners'] > 0:
+                shield.set('rx', str(vars['rounded_corners']))
+                shield.set('ry', str(vars['rounded_corners']))
+            shield.set('id', 'shield')
+
+            stroke = ''
+            if vars['stroke_width'] > 0:
+                stroke = 'stroke:' + vars['stroke_fill'] + ';stroke-width:' + str(vars['stroke_width']) + ';'
+
+            shield.set('style', 'fill:' + vars['fill'] + ';' + stroke)
+
+            svg.append(shield)
+
+            filename = shield_type + '_' + str(width) + 'x' + str(height)
+            if shield_size != 'base':
+                filename = filename + '_' + shield_size
+
+            filename = filename + '.svg'
+
+            # save file
+            try:
+                shieldpath = os.path.join(os.path.dirname(__file__), config['global']['output_dir'] + filename)
+                print('Writing', os.path.realpath(shieldpath))
+                shieldfile = open(shieldpath, 'wb')
+                shieldfile.write(lxml.etree.tostring(svg, encoding='utf-8', xml_declaration=True, pretty_print=True))
+                shieldfile.close()
+            except IOError:
+                print('Could not save file ' + filename + '.')
+                continue
+
+if __name__ == "__main__":
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/get-external-data.py	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,258 @@
+#!/usr/bin/env python3
+'''This script is designed to load quasi-static data into a PostGIS database
+for rendering maps. It differs from the usual scripts to do this in that it is
+designed to take its configuration from a file rather than be a series of shell
+commands.
+
+Some implicit assumptions are
+- Time spent querying (rendering) the data is more valuable than the one-time
+    cost of loading it
+- The script will not be running multiple times in parallel. This is not
+    normally likely because the script is likely to be called daily or less,
+    not minutely.
+- Usage patterns will be similar to typical map rendering
+'''
+
+import yaml
+import os
+import re
+import argparse
+import shutil
+
+# modules for getting data
+import zipfile
+import requests
+import io
+
+# modules for converting and postgres loading
+import subprocess
+import psycopg2
+
+import logging
+
+
+def database_setup(conn, temp_schema, schema, metadata_table):
+    with conn.cursor() as cur:
+            cur.execute('''CREATE SCHEMA IF NOT EXISTS {temp_schema};'''
+                        .format(temp_schema=temp_schema))
+            cur.execute(('''CREATE TABLE IF NOT EXISTS "{schema}"."{metadata_table}"'''
+                         ''' (name text primary key, last_modified text);''')
+                        .format(schema=schema, metadata_table=metadata_table))
+    conn.commit()
+
+
+class Table:
+    def __init__(self, name, conn, temp_schema, schema, metadata_table):
+        self._name = name
+        self._conn = conn
+        self._temp_schema = temp_schema
+        self._dst_schema = schema
+        self._metadata_table = metadata_table
+
+    # Clean up the temporary schema in preperation for loading
+    def clean_temp(self):
+        with self._conn.cursor() as cur:
+            cur.execute('''DROP TABLE IF EXISTS "{temp_schema}"."{name}"'''
+                        .format(name=self._name, temp_schema=self._temp_schema))
+        self._conn.commit()
+
+    # get the last modified date from the metadata table
+    def last_modified(self):
+        with self._conn.cursor() as cur:
+            cur.execute('''SELECT last_modified FROM "{schema}"."{metadata_table}" WHERE name = %s'''
+                        .format(schema=self._dst_schema, metadata_table=self._metadata_table), [self._name])
+            results = cur.fetchone()
+            if results is not None:
+                return results[0]
+
+    def index(self):
+        with self._conn.cursor() as cur:
+            # Disable autovacuum while manipulating the table, since it'll get clustered towards the end.
+            cur.execute('''ALTER TABLE "{temp_schema}"."{name}" SET ( autovacuum_enabled = FALSE );'''
+                        .format(name=self._name, temp_schema=self._temp_schema))
+            # ogr creates a ogc_fid column we don't need
+            cur.execute('''ALTER TABLE "{temp_schema}"."{name}" DROP COLUMN ogc_fid;'''
+                        .format(name=self._name, temp_schema=self._temp_schema))
+
+            # Null geometries are useless for rendering
+            cur.execute('''DELETE FROM "{temp_schema}"."{name}" WHERE way IS NULL;'''
+                        .format(name=self._name, temp_schema=self._temp_schema))
+            cur.execute('''ALTER TABLE "{temp_schema}"."{name}" ALTER COLUMN way SET NOT NULL;'''
+                        .format(name=self._name, temp_schema=self._temp_schema))
+            # sorting static tables helps performance and reduces size from the column drop above
+            cur.execute(('''CREATE INDEX "{name}_order" ON "{temp_schema}"."{name}" '''
+                         '''(ST_Envelope(way));'''
+                         '''CLUSTER "{temp_schema}"."{name}" '''
+                         '''USING "{name}_order";'''
+                         '''DROP INDEX "{temp_schema}"."{name}_order";'''
+                         '''CREATE INDEX ON "{temp_schema}"."{name}" '''
+                         '''USING GIST (way) WITH (fillfactor=100);''')
+                        .format(name=self._name, temp_schema=self._temp_schema))
+            # Reset autovacuum. The table is static, so this doesn't really
+            # matter since it'll never need a vacuum.
+            cur.execute('''ALTER TABLE "{temp_schema}"."{name}" RESET ( autovacuum_enabled );'''
+                        .format(name=self._name, temp_schema=self._temp_schema))
+        self._conn.commit()
+
+        # VACUUM can't be run in transaction, so autocommit needs to be turned on
+        old_autocommit = self._conn.autocommit
+        try:
+            self._conn.autocommit = True
+            with self._conn.cursor() as cur:
+                cur.execute('''VACUUM ANALYZE "{temp_schema}"."{name}";'''
+                            .format(name=self._name, temp_schema=self._temp_schema))
+        finally:
+            self._conn.autocommit = old_autocommit
+
+    def replace(self, new_last_modified):
+        with self._conn.cursor() as cur:
+            cur.execute('''BEGIN;''')
+            cur.execute(('''DROP TABLE IF EXISTS "{schema}"."{name}";'''
+                         '''ALTER TABLE "{temp_schema}"."{name}" SET SCHEMA "{schema}";''')
+                        .format(name=self._name, temp_schema=self._temp_schema, schema=self._dst_schema))
+
+            # We checked if the metadata table had this table way up above
+            cur.execute('''SELECT 1 FROM "{schema}"."{metadata_table}" WHERE name = %s'''
+                        .format(schema=self._dst_schema, metadata_table=self._metadata_table),
+                        [self._name])
+            if cur.rowcount == 0:
+                cur.execute(('''INSERT INTO "{schema}"."{metadata_table}" '''
+                            '''(name, last_modified) VALUES (%s, %s)''')
+                            .format(schema=self._dst_schema, metadata_table=self._metadata_table),
+                            [self._name, new_last_modified])
+            else:
+                cur.execute('''UPDATE "{schema}"."{metadata_table}" SET last_modified = %s WHERE name = %s'''
+                            .format(schema=self._dst_schema, metadata_table=self._metadata_table),
+                            [new_last_modified, self._name])
+        self._conn.commit()
+
+
+def main():
+    # parse options
+    parser = argparse.ArgumentParser(description="Load external data into a database")
+
+    parser.add_argument("-f", "--force", action="store_true", help="Download new data, even if not required")
+
+    parser.add_argument("-c", "--config", action="store", default="external-data.yml",
+                        help="Name of configuration file (default external-data.yml)")
+    parser.add_argument("-D", "--data", action="store", help="Override data download directory")
+
+    parser.add_argument("-d", "--database", action="store", help="Override database name to connect to")
+    parser.add_argument("-H", "--host", action="store",
+                        help="Override database server host or socket directory")
+    parser.add_argument("-p", "--port", action="store", help="Override database server port")
+    parser.add_argument("-U", "--username", action="store", help="Override database user name")
+    parser.add_argument("-v", "--verbose", action="store_true", help="Be more verbose. Overrides -q")
+    parser.add_argument("-q", "--quiet", action="store_true", help="Only report serious problems")
+
+    opts = parser.parse_args()
+
+    if opts.verbose:
+        logging.basicConfig(level=logging.DEBUG)
+    elif opts.quiet:
+        logging.basicConfig(level=logging.WARNING)
+    else:
+        logging.basicConfig(level=logging.INFO)
+
+    with open(opts.config) as config_file:
+        config = yaml.safe_load(config_file)
+        data_dir = opts.data or config["settings"]["data_dir"]
+        os.makedirs(data_dir, exist_ok=True)
+
+        # If the DB options are unspecified in both on the command line and in the
+        # config file, libpq will pick what to use with the None
+        database = opts.database or config["settings"].get("database")
+        host = opts.host or config["settings"].get("host")
+        port = opts.port or config["settings"].get("port")
+        user = opts.username or config["settings"].get("username")
+        with requests.Session() as s, \
+            psycopg2.connect(database=database,
+                             host=host, port=port,
+                             user=user) as conn:
+
+            s.headers.update({'User-Agent': 'get-external-data.py/osm-carto'})
+
+            # DB setup
+            database_setup(conn, config["settings"]["temp_schema"],
+                           config["settings"]["schema"],
+                           config["settings"]["metadata_table"])
+
+            for name, source in config["sources"].items():
+                logging.info("Checking table {}".format(name))
+                # Don't attempt to handle strange names
+                # Even if there was code to escape them properly here, you don't want
+                # in a style with all the quoting headaches
+                if not re.match('''^[a-zA-Z0-9_]+$''', name):
+                    raise RuntimeError("Only ASCII alphanumeric table are names supported")
+
+                workingdir = os.path.join(data_dir, name)
+                # Clean up anything left over from an aborted run
+                shutil.rmtree(workingdir, ignore_errors=True)
+
+                os.makedirs(workingdir, exist_ok=True)
+
+                this_table = Table(name, conn,
+                                   config["settings"]["temp_schema"],
+                                   config["settings"]["schema"],
+                                   config["settings"]["metadata_table"])
+                this_table.clean_temp()
+
+                if not opts.force:
+                    headers = {'If-Modified-Since': this_table.last_modified()}
+                else:
+                    headers = {}
+
+                download = s.get(source["url"], headers=headers)
+                download.raise_for_status()
+
+                if (download.status_code == 200):
+                    if "Last-Modified" in download.headers:
+                        new_last_modified = download.headers["Last-Modified"]
+                    else:
+                        new_last_modified = None
+                    if "archive" in source and source["archive"]["format"] == "zip":
+                        zip = zipfile.ZipFile(io.BytesIO(download.content))
+                        for member in source["archive"]["files"]:
+                            zip.extract(member, workingdir)
+
+                    ogrpg = "PG:dbname={}".format(database)
+
+                    if port is not None:
+                        ogrpg = ogrpg + " port={}".format(port)
+                    if user is not None:
+                        ogrpg = ogrpg + " user={}".format(user)
+                    if host is not None:
+                        ogrpg = ogrpg + " host={}".format(host)
+
+                    ogrcommand = ["ogr2ogr",
+                                  '-f', 'PostgreSQL',
+                                  '-lco', 'GEOMETRY_NAME=way',
+                                  '-lco', 'SPATIAL_INDEX=FALSE',
+                                  '-lco', 'EXTRACT_SCHEMA_FROM_LAYER_NAME=YES',
+                                  '-nln', "{}.{}".format(config["settings"]["temp_schema"], name)]
+
+                    if "ogropts" in source:
+                        ogrcommand += source["ogropts"]
+
+                    ogrcommand += [ogrpg, os.path.join(workingdir, source["file"])]
+
+                    logging.debug("running {}".format(subprocess.list2cmdline(ogrcommand)))
+
+                    # ogr2ogr can raise errors here, so they need to be caught
+                    try:
+                        subprocess.check_output(ogrcommand, stderr=subprocess.PIPE, universal_newlines=True)
+                    except subprocess.CalledProcessError as e:
+                        # Add more detail on stdout for the logs
+                        logging.critical("ogr2ogr returned {} with layer {}".format(e.returncode, name))
+                        logging.critical("Command line was {}".format(subprocess.list2cmdline(e.cmd)))
+                        logging.critical("Output was\n{}".format(e.output))
+                        raise RuntimeError("ogr2ogr error when loading table {}".format(name))
+
+                    this_table.index()
+                    this_table.replace(new_last_modified)
+                else:
+                    logging.info("Table {} did not require updating".format(name))
+
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/style/amenity.mss	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,138 @@
+@standard-font-size: 10;
+@standard-wrap-width: 30; // 3 em
+@standard-line-spacing-size: -1.5; // -0.15 em
+@standard-font: @regular-font;
+@traffic-blue: #005eb8;
+@railway-name-color: #644d70;
+@aerodrome-name-color: #463d70;
+
+#stations[zoom >= 15]
+{
+	[feature = 'railway_station'],
+	[feature = 'railway_halt']
+	{
+		marker-file: url('symbols/train-station.svg');
+	}
+	[feature = 'amenity_bus_station']
+	{
+		marker-file: url('symbols/bus-station.svg');
+	}
+	[feature = 'aeroway_aerodrome']
+	{
+		marker-file: url('symbols/aerodrome.svg');
+	}
+	marker-clip: false;
+	text-name: "[bilingual_name]";
+	text-size: @standard-font-size;
+	text-wrap-width: @standard-wrap-width;
+	text-line-spacing: @standard-line-spacing-size;
+	text-fill: @traffic-blue;
+	text-dy: 11;
+	text-face-name: @bold-font;
+	text-halo-radius: @standard-halo-radius;
+	text-halo-fill: @standard-halo-fill;
+}
+
+#train-stations
+{
+	[zoom >= 12]
+	{
+		text-name: "[ref]";
+		[zoom >= 14]
+		{
+			text-name: "[bilingual_name]";
+		}
+		text-size: 10;
+		text-wrap-width: @standard-wrap-width;
+		text-line-spacing: @standard-line-spacing-size;
+		text-fill: white;
+		text-clip: true;
+		text-placement-type: simple;
+		text-placements: E,NE,SE,W,NW,SW;
+		[zoom >= 16] { text-size: 11; }
+		[zoom >= 17] { text-size: 12; }
+		[zoom >= 18] { text-size: 13; }
+		text-face-name: "FreeSans Bold";
+		text-halo-radius: 1.5 * @standard-halo-radius;
+		text-halo-fill: blue;
+		/*
+		[zoom >= 16]
+		{
+			text-transform: uppercase;
+		}
+		*/
+	}
+}
+
+#train-sites
+{
+	[zoom >= 15]
+	{
+		text-name: "[ref]";
+		[zoom >= 16]
+		{
+			text-name: "[bilingual_name]";
+		}
+		text-size: @standard-font-size;
+		text-wrap-width: @standard-wrap-width;
+		text-line-spacing: @standard-line-spacing-size;
+		text-fill: @railway-name-color;
+		text-clip: false;
+		text-placement-type: simple;
+		text-placements: E,NE,SE,W,NW,SW;
+		[zoom >= 16] { text-size: 11; }
+		[zoom >= 17] { text-size: 12; }
+		[zoom >= 18] { text-size: 13; }
+		text-face-name: "FreeSans Bold";
+		text-halo-radius: 0.75 * @standard-halo-radius;
+		text-halo-fill: @standard-halo-fill;
+	}
+}
+
+#train-milestones
+{
+	[zoom >= 16]
+	{
+		text-name: "[position]";
+		text-size: @standard-font-size;
+		text-wrap-width: @standard-wrap-width;
+		text-line-spacing: @standard-line-spacing-size;
+		text-fill: @railway-name-color;
+		text-clip: false;
+		text-placement-type: simple;
+		text-placements: E,NE,SE,W,NW,SW;
+		[zoom >= 17] { text-size: 11; }
+		[zoom >= 18] { text-size: 12; }
+		[zoom >= 19] { text-size: 13; }
+		text-face-name: "FreeSans Bold";
+		text-halo-radius: @standard-halo-radius;
+		text-halo-fill: @standard-halo-fill;
+	}
+}
+
+@aerodrome-color: #dedced;
+#aerodrome
+{
+	polygon-fill: @aerodrome-color;
+	[zoom >= 17]
+	{
+		line-color: saturate(darken(@aerodrome-color, 20%), 20%);
+	}
+}
+
+#aerodrome-name
+{
+	text-name: "[ref]";
+	[zoom >= 12]
+	{
+		text-name: "[bilingual_name]";	
+	}
+	text-size: @standard-font-size;
+	text-wrap-width: @standard-wrap-width;
+	text-line-spacing: @standard-line-spacing-size;
+	text-clip: false;
+	text-fill: @aerodrome-name-color;
+	text-face-name: @bold-font;
+	text-halo-radius: @standard-halo-radius;
+	text-halo-fill: @standard-halo-fill;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/style/buildings.mss	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,11 @@
+@building-color: #bbbab4;
+
+#buildings
+{
+	polygon-fill: @building-color;
+	line-width: 0.5;
+	line-color: darken(@building-color, 20%);
+	[building = 'construction'] {
+		line-dasharray: 4,4;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/style/places.mss	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,112 @@
+@place-halo-fill: rgba(255,255,255,60%);
+@place-halo-radius: 1.5;
+
+@landcover-font-size: 10;
+@landcover-wrap-width-size: 30; // 3 em
+@landcover-line-spacing-size: -1.5; // -0.15 em
+@landcover-font-size-big: 12;
+@landcover-wrap-width-size-big: 36; // 3 em
+@landcover-line-spacing-size-big: -1.8; // -0.15 em
+@landcover-font-size-bigger: 15;
+@landcover-wrap-width-size-bigger: 45; // 3 em
+@landcover-line-spacing-size-bigger: -2.25; // -0.15 em
+@landcover-face-name: @oblique-fonts;
+
+#place-major[zoom >= 10],
+#place-major[place='city'] {
+	text-name: "[bilingual_name]";
+	text-size: 10;
+	[zoom >= 11] { text-size: 11; }
+	[zoom >= 12] { text-size: 12; }
+	[zoom >= 13] { text-size: 13; }
+	[zoom >= 14] { text-size: 14; }
+	[zoom >= 15] { text-size: 15; }
+	text-fill: #000;
+	text-face-name: @place-font;
+	[place='city'][zoom >= 10],
+	[zoom >= 12] {
+		text-face-name: @place-font-bold;
+	}
+	[place='city'][zoom >= 12],
+	[zoom >= 13] {
+		text-transform: uppercase;
+	}
+	text-halo-radius: @place-halo-radius;
+	text-halo-fill: @place-halo-fill;
+	text-clip: false;
+	text-placement-type: simple;
+	text-placements: E,NE,SE,W,NW,SW;
+}
+
+#place-medium {
+	text-name: "[bilingual_name]";
+	text-size: 10;
+	[zoom >= 13] { text-size: 11; }
+	[zoom >= 14] { text-size: 12; }
+	[zoom >= 15] { text-size: 14; }
+	[zoom >= 16] { text-size: 15; }
+	[zoom >= 17] { text-size: 17; }
+	text-fill: #000;
+	text-face-name: @place-font;
+	[zoom >= 13] {
+		text-face-name: @place-font-bold;
+	}
+	text-halo-radius: @place-halo-radius;
+	text-halo-fill: @place-halo-fill;
+	text-clip: false;
+	text-placement-type: simple;
+	text-placements: E,NE,SE,W,NW,SW;
+}
+
+#poi-name,
+#poi-name-medium,
+#poi-name-minor,
+#place-minor
+{
+	text-name: "[bilingual_name]";
+	text-size: 10;
+	[zoom >= 15] { text-size: 11; }
+	[zoom >= 16] { text-size: 12; }
+	[zoom >= 17] { text-size: 13; }
+	[zoom >= 18] { text-size: 14; }
+	text-fill: #000;
+	text-face-name: @place-font;
+	#place-minor[natural = 0][zoom >= 17] {
+		text-face-name: @place-font-bold;
+	}
+	[natural = 1] {
+		text-face-name: @natural-font;
+	}
+	text-halo-radius: @place-halo-radius;
+	text-halo-fill: @place-halo-fill;
+	text-clip: false;
+	text-placement-type: simple;
+	text-placements: E,NE,SE,W,NW,SW;
+}
+
+#place-natural
+{
+	[zoom >= 4][way_pixels > 3000],
+	[zoom >= 16],
+	[zoom >= 11][way_pixels > 3000],
+	[zoom >= 17] {
+		text-name: "[bilingual_name]";
+		text-fill: #000;
+		text-size: 10;
+		text-wrap-width: @landcover-wrap-width-size;
+		text-line-spacing: @landcover-line-spacing-size;
+		[way_pixels > 12000] {
+			text-size: @landcover-font-size-big;
+			text-wrap-width: @landcover-wrap-width-size-big;
+			text-line-spacing: @landcover-line-spacing-size-big;
+		}
+		[way_pixels > 48000] {
+			text-size: @landcover-font-size-bigger;
+			text-wrap-width: @landcover-wrap-width-size-bigger;
+			text-line-spacing: @landcover-line-spacing-size-bigger;
+		}
+		text-face-name: @natural-font;
+		text-halo-radius: @place-halo-radius;
+		text-halo-fill: @place-halo-fill;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/style/roadref.mss	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,232 @@
+// Shield’s line wrap is based on OpenStreetMap data and not on line-wrap-width,
+// but lines are typically rather short, so we use narrow line spacing.
+@shield-size: 10;
+@shield-line-spacing: -2; // -1.50; // -0.15 em
+@shield-size-z16: 11;
+@shield-line-spacing-z16: -2.25; // -1.65; // -0.15 em
+@shield-size-z18: 12;
+@shield-line-spacing-z18: -2.5; // -1.80; // -0.15 em
+@shield-spacing: 760;
+@shield-repeat-distance: 400;
+@shield-margin: 40;
+@shield-font: "Liikenne Regular";
+@shield-clip: false;
+
+#roads-text-ref
+{
+	[highway = 'trunk'][zoom >= 13],
+	[highway = 'primary'][zoom >= 13],
+	[highway = 'secondary'][zoom >= 13],
+	[highway = 'tertiary'][zoom >= 13],
+	[ref_class_1 = 'valtatie'][zoom >= 8],
+	[ref_class_1 = 'eurooppatie'][zoom >= 12],
+	[ref_class_1 = 'kantatie'][zoom >= 10],
+	[ref_class_1 = 'seututie'][zoom >= 12]
+	{
+		[ref_1 != null][ref_class_1 != null][ref_class_1 != 'unknown']
+		{
+			shield-face-name: @shield-font;
+			shield-file: url("symbols/shields/[ref_class_1]_[ref_length_1]x1.svg");
+			[ref_class_1 = 'valtatie'],
+			[ref_class_1 = 'yhdystie'],
+			[ref_class_1 = 'eurooppatie']
+			{
+				shield-fill: white;
+			}
+			[ref_class_1 = 'kantatie'],
+			[ref_class_1 = 'seututie']
+			{
+				shield-fill: black;
+			}
+			shield-name: "[ref_1]";
+			shield-size: 12;
+			shield-placement: line;
+			shield-spacing: @shield-spacing;
+			shield-repeat-distance: @shield-repeat-distance;
+			shield-margin: @shield-margin;
+			shield-clip: @shield-clip;
+		}
+	}
+}
+
+#roads-text-ref2
+{
+	[highway = 'trunk'][zoom >= 13],
+	[highway = 'primary'][zoom >= 13],
+	[highway = 'secondary'][zoom >= 13],
+	[highway = 'tertiary'][zoom >= 13],
+	[ref_class_2 = 'valtatie'][zoom >= 12],
+	[ref_class_2 = 'eurooppatie'][zoom >= 12],
+	[ref_class_2 = 'kantatie'][zoom >= 12],
+	[ref_class_2 = 'seututie'][zoom >= 12]
+	{
+		[ref_2 != null][ref_class_2 != null][ref_class_2 != 'unknown']
+		{
+			shield-face-name: @shield-font;
+			shield-file: url("symbols/shields/[ref_class_2]_[ref_length_2]x1.svg");
+			[ref_class_2 = 'valtatie'],
+			[ref_class_2 = 'yhdystie'],
+			[ref_class_2 = 'eurooppatie']
+			{
+				shield-fill: white;
+			}
+			[ref_class_2 = 'kantatie'],
+			[ref_class_2 = 'seututie']
+			{
+				shield-fill: black;
+			}
+			shield-name: "[ref_2]";
+			shield-size: 12;
+			shield-placement: line;
+			shield-spacing: @shield-spacing;
+			shield-repeat-distance: @shield-repeat-distance;
+			shield-margin: @shield-margin;
+			shield-clip: @shield-clip;
+		}
+	}
+}
+
+#roads-text-ref3
+{
+	[highway = 'trunk'][zoom >= 13],
+	[highway = 'primary'][zoom >= 13],
+	[highway = 'secondary'][zoom >= 13],
+	[highway = 'tertiary'][zoom >= 13],
+	[ref_class_3 = 'valtatie'][zoom >= 12],
+	[ref_class_3 = 'eurooppatie'][zoom >= 12],
+	[ref_class_3 = 'kantatie'][zoom >= 12],
+	[ref_class_3 = 'seututie'][zoom >= 12]
+	{
+		[ref_3 != null][ref_class_3 != null][ref_class_3 != 'unknown']
+		{
+			shield-face-name: @shield-font;
+			shield-file: url("symbols/shields/[ref_class_3]_[ref_length_3]x1.svg");
+			[ref_class_3 = 'valtatie'],
+			[ref_class_3 = 'yhdystie'],
+			[ref_class_3 = 'eurooppatie']
+			{
+				shield-fill: white;
+			}
+			[ref_class_3 = 'kantatie'],
+			[ref_class_3 = 'seututie']
+			{
+				shield-fill: black;
+			}
+			shield-name: "[ref_3]";
+			shield-size: 12;
+			shield-placement: line;
+			shield-spacing: @shield-spacing;
+			shield-repeat-distance: @shield-repeat-distance;
+			shield-margin: @shield-margin;
+			shield-clip: @shield-clip;
+		}
+	}
+}
+#roads-text-ref4
+{
+	[highway = 'trunk'][zoom >= 13],
+	[highway = 'primary'][zoom >= 13],
+	[highway = 'secondary'][zoom >= 13],
+	[highway = 'tertiary'][zoom >= 13],
+	[ref_class_4 = 'valtatie'][zoom >= 10],
+	[ref_class_4 = 'eurooppatie'][zoom >= 11],
+	[ref_class_4 = 'kantatie'][zoom >= 11],
+	[ref_class_4 = 'seututie'][zoom >= 12]
+	{
+		[ref_4 != null][ref_class_4 != null][ref_class_4 != 'unknown']
+		{
+			shield-face-name: @shield-font;
+			shield-file: url("symbols/shields/[ref_class_4]_[ref_length_4]x1.svg");
+			[ref_class_4 = 'valtatie'],
+			[ref_class_4 = 'yhdystie'],
+			[ref_class_4 = 'eurooppatie']
+			{
+				shield-fill: white;
+			}
+			[ref_class_4 = 'kantatie'],
+			[ref_class_4 = 'seututie']
+			{
+				shield-fill: black;
+			}
+			shield-name: "[ref_4]";
+			shield-size: 12;
+			shield-placement: line;
+			shield-spacing: @shield-spacing;
+			shield-repeat-distance: @shield-repeat-distance;
+			shield-margin: @shield-margin;
+			shield-clip: @shield-clip;
+		}
+	}
+}
+#roads-text-ref5
+{
+	[highway = 'trunk'][zoom >= 13],
+	[highway = 'primary'][zoom >= 13],
+	[highway = 'secondary'][zoom >= 13],
+	[highway = 'tertiary'][zoom >= 13],
+	[ref_class_5 = 'valtatie'][zoom >= 12],
+	[ref_class_5 = 'eurooppatie'][zoom >= 12],
+	[ref_class_5 = 'kantatie'][zoom >= 12],
+	[ref_class_5 = 'seututie'][zoom >= 12]
+	{
+		[ref_5 != null][ref_class_5 != null][ref_class_5 != 'unknown']
+		{
+			shield-face-name: @shield-font;
+			shield-file: url("symbols/shields/[ref_class_5]_[ref_length_5]x1.svg");
+			[ref_class_5 = 'valtatie'],
+			[ref_class_5 = 'yhdystie'],
+			[ref_class_5 = 'eurooppatie']
+			{
+				shield-fill: white;
+			}
+			[ref_class_5 = 'kantatie'],
+			[ref_class_5 = 'seututie']
+			{
+				shield-fill: black;
+			}
+			shield-name: "[ref_5]";
+			shield-size: 12;
+			shield-placement: line;
+			shield-spacing: @shield-spacing;
+			shield-repeat-distance: @shield-repeat-distance;
+			shield-margin: @shield-margin;
+			shield-clip: @shield-clip;
+		}
+	}
+}
+#roads-text-ref6
+{
+	[highway = 'trunk'][zoom >= 13],
+	[highway = 'primary'][zoom >= 13],
+	[highway = 'secondary'][zoom >= 13],
+	[highway = 'tertiary'][zoom >= 13],
+	[ref_class_6 = 'valtatie'][zoom >= 10],
+	[ref_class_6 = 'eurooppatie'][zoom >= 12],
+	[ref_class_6 = 'kantatie'][zoom >= 12],
+	[ref_class_6 = 'seututie'][zoom >= 12]
+	{
+		[ref_6 != null][ref_class_6 != null][ref_class_6 != 'unknown']
+		{
+			shield-face-name: @shield-font;
+			shield-file: url("symbols/shields/[ref_class_6]_[ref_length_6]x1.svg");
+			[ref_class_6 = 'valtatie'],
+			[ref_class_6 = 'yhdystie'],
+			[ref_class_6 = 'eurooppatie']
+			{
+				shield-fill: white;
+			}
+			[ref_class_6 = 'kantatie'],
+			[ref_class_6 = 'seututie']
+			{
+				shield-fill: black;
+			}
+			shield-name: "[ref_6]";
+			shield-size: 12;
+			shield-placement: line;
+			shield-spacing: @shield-spacing;
+			shield-repeat-distance: @shield-repeat-distance;
+			shield-margin: @shield-margin;
+			shield-clip: @shield-clip;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/style/roads.mss	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,603 @@
+@highway-trunk-width-z4: 1;
+@highway-trunk-width-z5: 1;
+@highway-trunk-width-z6: 1.5;
+@highway-trunk-width-z7: 1.5;
+@highway-trunk-width-z8: 1.5;
+@highway-trunk-width-z9: 2;
+@highway-trunk-width-z10: 2;
+@highway-trunk-width-z11: 2;
+@highway-trunk-width-z12: 3;
+@highway-trunk-width-z13: 4;
+@highway-trunk-width-z14: 5;
+@highway-trunk-width-z15: 7;
+@highway-trunk-width-z16: 10;
+@highway-trunk-width-z17: 14;
+@highway-trunk-width-z18: 22;
+@highway-trunk-casing-width: @road-major-casing-width;
+
+@highway-primary-width-z10: 1.5;
+@highway-primary-width-z11: 1.5;
+@highway-primary-width-z12: 2;
+@highway-primary-width-z13: 4;
+@highway-primary-width-z14: 5;
+@highway-primary-width-z15: 6;
+@highway-primary-width-z16: 9;
+@highway-primary-width-z17: 14;
+@highway-primary-width-z18: 22;
+@highway-primary-casing-width: @road-major-casing-width;
+
+@highway-secondary-width-z10: 1;
+@highway-secondary-width-z11: 1;
+@highway-secondary-width-z12: 1.5;
+@highway-secondary-width-z13: 2;
+@highway-secondary-width-z14: 4;
+@highway-secondary-width-z15: 5;
+@highway-secondary-width-z16: 6;
+@highway-secondary-width-z17: 14;
+@highway-secondary-width-z18: 22;
+@highway-secondary-casing-width: @road-major-casing-width;
+
+@highway-tertiary-width-z10: 0;
+@highway-tertiary-width-z11: 1;
+@highway-tertiary-width-z12: 1;
+@highway-tertiary-width-z13: 1.5;
+@highway-tertiary-width-z14: 2;
+@highway-tertiary-width-z15: 3;
+@highway-tertiary-width-z16: 6;
+@highway-tertiary-width-z17: 14;
+@highway-tertiary-width-z18: 22;
+@highway-tertiary-casing-width: @road-major-casing-width;
+
+@highway-unclassified-width-z10: 0;
+@highway-unclassified-width-z11: 0;
+@highway-unclassified-width-z12: 0.5;
+@highway-unclassified-width-z13: 1;
+@highway-unclassified-width-z14: 1.5;
+@highway-unclassified-width-z15: 2;
+@highway-unclassified-width-z16: 4;
+@highway-unclassified-width-z17: 8;
+@highway-unclassified-width-z18: 12;
+@highway-unclassified-casing-width: @road-minor-casing-width;
+
+@highway-service-width-z15: 0.5;
+@highway-service-width-z16: 1;
+@highway-service-width-z17: 1.5;
+@highway-service-width-z18: 3;
+@highway-service-width-z19: 4;
+@highway-service-width-z20: 5;
+@highway-service-casing-width: @road-minor-casing-width;
+
+@highway-trunk-link-width-z10: 1;
+@highway-trunk-link-width-z11: 1;
+@highway-trunk-link-width-z12: 1.5;
+@highway-trunk-link-width-z13: 2;
+@highway-trunk-link-width-z14: 3;
+@highway-trunk-link-width-z15: 3;
+@highway-trunk-link-width-z16: 6;
+@highway-trunk-link-width-z17: 14;
+@highway-trunk-link-width-z18: 22;
+@highway-trunk-link-casing-width: @road-major-casing-width;
+
+@highway-path-width-z14: 0.5;
+@highway-path-width-z15: 0.75;
+@highway-path-width-z16: 1;
+@highway-path-width-z17: 2;
+@highway-path-width-z18: 3;
+
+@road-minor-casing-width: 1.5;
+@road-major-casing-width: 2;
+@road-text-scale-factor: 1;
+
+@road-fill: #f4f4ff;
+@road-casing: #bbb;
+@pedestrian-fill: #ccc;
+@living-street-fill: #ddd;
+
+#road-low-zoom
+{
+	[highway = 'trunk']
+	{
+		[zoom >= 4] { line-width: @highway-trunk-width-z4; }
+		[zoom >= 5] { line-width: @highway-trunk-width-z5; }
+		[zoom >= 6] { line-width: @highway-trunk-width-z6; }
+		[zoom >= 7] { line-width: @highway-trunk-width-z7; }
+		[zoom >= 8] { line-width: @highway-trunk-width-z8; }
+		[zoom >= 9] { line-width: @highway-trunk-width-z9; }
+		line-color: #bbb;
+		[zoom >= 9]
+		{
+			line-color: @road-fill;
+		}
+	}
+}
+
+#road-low-zoom-casing
+{
+	[highway = 'trunk'][zoom >= 9]
+	{
+		line-width: @highway-trunk-width-z9 + @highway-trunk-casing-width;
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+}
+
+#road-layer-n1,
+#road[layer = 0],
+#road-layer-1[layer >= 1]
+{
+	[highway = 'trunk']
+	{
+		line-width: @highway-trunk-width-z10;
+		[zoom >= 11] { line-width: @highway-trunk-width-z11; }
+		[zoom >= 12] { line-width: @highway-trunk-width-z12; }
+		[zoom >= 13] { line-width: @highway-trunk-width-z13; }
+		[zoom >= 14] { line-width: @highway-trunk-width-z14; }
+		[zoom >= 15] { line-width: @highway-trunk-width-z15; }
+		[zoom >= 16] { line-width: @highway-trunk-width-z16; }
+		[zoom >= 17] { line-width: @highway-trunk-width-z17; }
+		[zoom >= 18] { line-width: @highway-trunk-width-z18; }
+		line-color: @road-fill;
+		line-join: round;
+		#road-layer-n1 { line-cap: round; }
+	}
+	
+	[highway = 'primary']
+	{
+		line-width: @highway-primary-width-z10;
+		[zoom >= 11] { line-width: @highway-primary-width-z11; }
+		[zoom >= 12] { line-width: @highway-primary-width-z12; }
+		[zoom >= 13] { line-width: @highway-primary-width-z13; }
+		[zoom >= 14] { line-width: @highway-primary-width-z14; }
+		[zoom >= 15] { line-width: @highway-primary-width-z15; }
+		[zoom >= 16] { line-width: @highway-primary-width-z16; }
+		[zoom >= 17] { line-width: @highway-primary-width-z17; }
+		[zoom >= 18] { line-width: @highway-primary-width-z18; }
+		line-color: @road-fill;
+		line-join: round;
+		#road-layer-n1 { line-cap: round; }
+	}
+	
+	[highway = 'secondary']
+	{
+		line-width: @highway-secondary-width-z10;
+		[zoom >= 11] { line-width: @highway-secondary-width-z11; }
+		[zoom >= 12] { line-width: @highway-secondary-width-z12; }
+		[zoom >= 13] { line-width: @highway-secondary-width-z13; }
+		[zoom >= 14] { line-width: @highway-secondary-width-z14; }
+		[zoom >= 15] { line-width: @highway-secondary-width-z15; }
+		[zoom >= 16] { line-width: @highway-secondary-width-z16; }
+		[zoom >= 17] { line-width: @highway-secondary-width-z17; }
+		[zoom >= 18] { line-width: @highway-secondary-width-z18; }
+		line-color: #bbb;
+		[zoom >= 11]
+		{
+			line-color: @road-fill;
+		}
+		line-join: round;
+		#road-layer-n1 { line-cap: round; }
+	}
+
+	[highway = 'tertiary'][zoom >= 11],
+	[highway = 'tertiary_link'][zoom >= 11]
+	{
+		line-width: @highway-tertiary-width-z10;
+		[zoom >= 11] { line-width: @highway-tertiary-width-z11; }
+		[zoom >= 12] { line-width: @highway-tertiary-width-z12; }
+		[zoom >= 13] { line-width: @highway-tertiary-width-z13; }
+		[zoom >= 14] { line-width: @highway-tertiary-width-z14; }
+		[zoom >= 15] { line-width: @highway-tertiary-width-z15; }
+		[zoom >= 16] { line-width: @highway-tertiary-width-z16; }
+		[zoom >= 17] { line-width: @highway-tertiary-width-z17; }
+		[zoom >= 18] { line-width: @highway-tertiary-width-z18; }
+		line-color: #bbb;
+		[zoom >= 12] { line-color: #b2b2b2; }
+		[zoom >= 13] { line-color: @road-fill; }
+		line-join: round;
+		#road-layer-n1 { line-cap: round; }
+	}
+
+	[highway = 'unclassified'][zoom >= 12],
+	[highway = 'residential'][zoom >= 12],
+	[highway = 'living_street'][zoom >= 12],
+	[highway = 'pedestrian'][zoom >= 12]
+	{
+		line-width: @highway-unclassified-width-z10;
+		[zoom >= 11] { line-width: @highway-unclassified-width-z11; }
+		[zoom >= 12] { line-width: @highway-unclassified-width-z12; }
+		[zoom >= 13] { line-width: @highway-unclassified-width-z13; }
+		[zoom >= 14] { line-width: @highway-unclassified-width-z14; }
+		[zoom >= 15] { line-width: @highway-unclassified-width-z15; }
+		[zoom >= 16] { line-width: @highway-unclassified-width-z16; }
+		[zoom >= 17] { line-width: @highway-unclassified-width-z17; }
+		[zoom >= 18] { line-width: @highway-unclassified-width-z18; }
+		line-color: #bbb;
+		[zoom >= 14] { line-color: #b2b2b2; }
+		[zoom >= 15] { line-color: @road-fill; }
+		[zoom >= 15][highway = 'living_street'] { line-color: @living-street-fill; }
+		[zoom >= 15][highway = 'pedestrian'] { line-color: @pedestrian-fill; }
+		line-join: round;
+		#road-layer-n1 { line-cap: round; }
+	}
+	
+	[highway = 'trunk_link'],
+	[highway = 'primary_link']
+	{
+		line-width: @highway-trunk-link-width-z10;
+		[zoom >= 11] { line-width: @highway-trunk-link-width-z11; }
+		[zoom >= 12] { line-width: @highway-trunk-link-width-z12; }
+		[zoom >= 13] { line-width: @highway-trunk-link-width-z13; }
+		[zoom >= 14] { line-width: @highway-trunk-link-width-z14; }
+		[zoom >= 15] { line-width: @highway-trunk-link-width-z15; }
+		[zoom >= 16] { line-width: @highway-trunk-link-width-z16; }
+		[zoom >= 17] { line-width: @highway-trunk-link-width-z17; }
+		[zoom >= 18] { line-width: @highway-trunk-link-width-z18; }
+		line-color: @road-fill;
+		line-join: round;
+		#road-layer-n1 { line-cap: round; }
+	}
+	
+	[highway = 'secondary_link']
+	{
+		line-width: @highway-tertiary-width-z10;
+		[zoom >= 11] { line-width: @highway-tertiary-width-z11; }
+		[zoom >= 12] { line-width: @highway-tertiary-width-z12; }
+		[zoom >= 13] { line-width: @highway-tertiary-width-z13; }
+		[zoom >= 14] { line-width: @highway-tertiary-width-z14; }
+		[zoom >= 15] { line-width: @highway-tertiary-width-z15; }
+		[zoom >= 16] { line-width: @highway-tertiary-width-z16; }
+		[zoom >= 17] { line-width: @highway-tertiary-width-z17; }
+		[zoom >= 18] { line-width: @highway-tertiary-width-z18; }
+		line-color: #bbb;
+		[zoom >= 11]
+		{
+			line-color: @road-fill;
+		}
+		line-join: round;
+		#road-layer-n1 { line-cap: round; }
+	}
+
+	[highway = 'service'][zoom >= 15]
+	{
+		[zoom >= 15] { line-width: @highway-service-width-z15; }
+		[zoom >= 16] { line-width: @highway-service-width-z16; }
+		[zoom >= 17] { line-width: @highway-service-width-z17; }
+		[zoom >= 18] { line-width: @highway-service-width-z18; }
+		[zoom >= 19] { line-width: @highway-service-width-z19; }
+		[zoom >= 20] { line-width: @highway-service-width-z20; }
+		line-color: #bbb;
+		[zoom >= 17]
+		{
+			line-color: @road-fill;
+		}
+		line-join: round;
+		#road-layer-n1 { line-cap: round; }
+	}
+
+	[highway = 'path'][zoom >= 14],
+	[highway = 'footway'][zoom >= 14],
+	[highway = 'track'][zoom >= 14],
+	[highway = 'cycleway'][zoom >= 14]
+	{
+		line-width: @highway-path-width-z14;
+		[zoom >= 15] { line-width: @highway-path-width-z15; }
+		[zoom >= 16] { line-width: @highway-path-width-z16; }
+		[zoom >= 17] { line-width: @highway-path-width-z17; }
+		[zoom >= 18] { line-width: @highway-path-width-z18; }
+		line-color: #aaa;
+		[feature = 'road_path']
+		{
+			line-dasharray: 6, 6;
+		}
+		line-join: round;
+		#road-layer-n1
+		{
+			line-cap: round;
+		}
+	}
+}
+
+#road-casing-layer-n1,
+#road-casing[layer = 0],
+#road-casing-layer-1[layer >= 1]
+{
+	[highway = 'trunk']
+	{
+		line-width: @highway-trunk-width-z10 + @highway-trunk-casing-width;
+		[zoom >= 11] { line-width: @highway-trunk-width-z11 + @highway-trunk-casing-width; }
+		[zoom >= 12] { line-width: @highway-trunk-width-z12 + @highway-trunk-casing-width; }
+		[zoom >= 13] { line-width: @highway-trunk-width-z13 + @highway-trunk-casing-width; }
+		[zoom >= 14] { line-width: @highway-trunk-width-z14 + @highway-trunk-casing-width; }
+		[zoom >= 15] { line-width: @highway-trunk-width-z15 + @highway-trunk-casing-width; }
+		[zoom >= 16] { line-width: @highway-trunk-width-z16 + @highway-trunk-casing-width; }
+		[zoom >= 17] { line-width: @highway-trunk-width-z17 + @highway-trunk-casing-width; }
+		[zoom >= 18] { line-width: @highway-trunk-width-z18 + @highway-trunk-casing-width; }
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+	[highway = 'primary']
+	{
+		line-width: @highway-primary-width-z10 + @highway-primary-casing-width;
+		[zoom >= 11] { line-width: @highway-primary-width-z11 + @highway-primary-casing-width; }
+		[zoom >= 12] { line-width: @highway-primary-width-z12 + @highway-primary-casing-width; }
+		[zoom >= 13] { line-width: @highway-primary-width-z13 + @highway-primary-casing-width; }
+		[zoom >= 14] { line-width: @highway-primary-width-z14 + @highway-primary-casing-width; }
+		[zoom >= 15] { line-width: @highway-primary-width-z15 + @highway-primary-casing-width; }
+		[zoom >= 16] { line-width: @highway-primary-width-z16 + @highway-primary-casing-width; }
+		[zoom >= 17] { line-width: @highway-primary-width-z17 + @highway-primary-casing-width; }
+		[zoom >= 18] { line-width: @highway-primary-width-z18 + @highway-primary-casing-width; }
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+	[highway = 'secondary'][zoom >= 11]
+	{
+		line-width: @highway-secondary-width-z10 + @highway-secondary-casing-width;
+		[zoom >= 11] { line-width: @highway-secondary-width-z11 + @highway-secondary-casing-width; }
+		[zoom >= 12] { line-width: @highway-secondary-width-z12 + @highway-secondary-casing-width; }
+		[zoom >= 13] { line-width: @highway-secondary-width-z13 + @highway-secondary-casing-width; }
+		[zoom >= 14] { line-width: @highway-secondary-width-z14 + @highway-secondary-casing-width; }
+		[zoom >= 15] { line-width: @highway-secondary-width-z15 + @highway-secondary-casing-width; }
+		[zoom >= 16] { line-width: @highway-secondary-width-z16 + @highway-secondary-casing-width; }
+		[zoom >= 17] { line-width: @highway-secondary-width-z17 + @highway-secondary-casing-width; }
+		[zoom >= 18] { line-width: @highway-secondary-width-z18 + @highway-secondary-casing-width; }
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+	[highway = 'tertiary'][zoom >= 13],
+	[highway = 'tertiary_link'][zoom >= 13]
+	{
+		line-width: @highway-tertiary-width-z10 + @highway-tertiary-casing-width;
+		[zoom >= 11] { line-width: @highway-tertiary-width-z11 + @highway-tertiary-casing-width; }
+		[zoom >= 12] { line-width: @highway-tertiary-width-z12 + @highway-tertiary-casing-width; }
+		[zoom >= 13] { line-width: @highway-tertiary-width-z13 + @highway-tertiary-casing-width; }
+		[zoom >= 14] { line-width: @highway-tertiary-width-z14 + @highway-tertiary-casing-width; }
+		[zoom >= 15] { line-width: @highway-tertiary-width-z15 + @highway-tertiary-casing-width; }
+		[zoom >= 16] { line-width: @highway-tertiary-width-z16 + @highway-tertiary-casing-width; }
+		[zoom >= 17] { line-width: @highway-tertiary-width-z17 + @highway-tertiary-casing-width; }
+		[zoom >= 18] { line-width: @highway-tertiary-width-z18 + @highway-tertiary-casing-width; }
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+	[highway = 'unclassified'][zoom >= 15],
+	[highway = 'residential'][zoom >= 15],
+	[highway = 'pedestrian'][zoom >= 15],
+	[highway = 'living_street'][zoom >= 15]
+	{
+		line-width: @highway-unclassified-width-z10 + @highway-unclassified-casing-width;
+		[zoom >= 11] { line-width: @highway-unclassified-width-z11 + @highway-unclassified-casing-width; }
+		[zoom >= 12] { line-width: @highway-unclassified-width-z12 + @highway-unclassified-casing-width; }
+		[zoom >= 13] { line-width: @highway-unclassified-width-z13 + @highway-unclassified-casing-width; }
+		[zoom >= 14] { line-width: @highway-unclassified-width-z14 + @highway-unclassified-casing-width; }
+		[zoom >= 15] { line-width: @highway-unclassified-width-z15 + @highway-unclassified-casing-width; }
+		[zoom >= 16] { line-width: @highway-unclassified-width-z16 + @highway-unclassified-casing-width; }
+		[zoom >= 17] { line-width: @highway-unclassified-width-z17 + @highway-unclassified-casing-width; }
+		[zoom >= 18] { line-width: @highway-unclassified-width-z18 + @highway-unclassified-casing-width; }
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+	[highway = 'trunk_link'],
+	[highway = 'primary_link']
+	{
+		line-width: @highway-trunk-link-width-z10 + @highway-trunk-link-casing-width;
+		[zoom >= 11] { line-width: @highway-trunk-link-width-z11 + @highway-trunk-link-casing-width; }
+		[zoom >= 12] { line-width: @highway-trunk-link-width-z12 + @highway-trunk-link-casing-width; }
+		[zoom >= 13] { line-width: @highway-trunk-link-width-z13 + @highway-trunk-link-casing-width; }
+		[zoom >= 14] { line-width: @highway-trunk-link-width-z14 + @highway-trunk-link-casing-width; }
+		[zoom >= 15] { line-width: @highway-trunk-link-width-z15 + @highway-trunk-link-casing-width; }
+		[zoom >= 16] { line-width: @highway-trunk-link-width-z16 + @highway-trunk-link-casing-width; }
+		[zoom >= 17] { line-width: @highway-trunk-link-width-z17 + @highway-trunk-link-casing-width; }
+		[zoom >= 18] { line-width: @highway-trunk-link-width-z18 + @highway-trunk-link-casing-width; }
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+	[highway = 'secondary_link'][zoom >= 11]
+	{
+		line-width: @highway-tertiary-width-z10 + @highway-tertiary-casing-width;
+		[zoom >= 11] { line-width: @highway-tertiary-width-z11 + @highway-tertiary-casing-width; }
+		[zoom >= 12] { line-width: @highway-tertiary-width-z12 + @highway-tertiary-casing-width; }
+		[zoom >= 13] { line-width: @highway-tertiary-width-z13 + @highway-tertiary-casing-width; }
+		[zoom >= 14] { line-width: @highway-tertiary-width-z14 + @highway-tertiary-casing-width; }
+		[zoom >= 15] { line-width: @highway-tertiary-width-z15 + @highway-tertiary-casing-width; }
+		[zoom >= 16] { line-width: @highway-tertiary-width-z16 + @highway-tertiary-casing-width; }
+		[zoom >= 17] { line-width: @highway-tertiary-width-z17 + @highway-tertiary-casing-width; }
+		[zoom >= 18] { line-width: @highway-tertiary-width-z18 + @highway-tertiary-casing-width; }
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+	[highway = 'service'][zoom >= 17]
+	{
+		[zoom >= 17] { line-width: @highway-service-width-z17 + @highway-service-casing-width; }
+		[zoom >= 18] { line-width: @highway-service-width-z18 + @highway-service-casing-width; }
+		[zoom >= 19] { line-width: @highway-service-width-z19 + @highway-service-casing-width; }
+		[zoom >= 20] { line-width: @highway-service-width-z20 + @highway-service-casing-width; }
+		line-color: @road-casing;
+		line-join: round;
+		#road-casing-layer-n1 { line-cap: round; }
+	}
+	/*
+	[feature = 'road_minor'][zoom >= 15]
+	{
+		line-width: @road-minor-width-z13 + @road-minor-casing-width;
+		[zoom >= 14] { line-width: @road-minor-width-z14 + @road-minor-casing-width; }
+		[zoom >= 15] { line-width: @road-minor-width-z15 + @road-minor-casing-width; }
+		[zoom >= 16] { line-width: @road-minor-width-z16 + @road-minor-casing-width; }
+		[zoom >= 17] { line-width: @road-minor-width-z17 + @road-minor-casing-width; }
+		[zoom >= 18] { line-width: @road-minor-width-z18 + @road-minor-casing-width; }
+		line-color: #ccc;
+		line-join: round;
+		#road-casing-layer-n1
+		{
+			line-cap: round;
+		}
+	}
+	*/
+}
+#road-text,
+#road-text-minority
+{
+	[feature = 'road_major']
+	{
+		text-name: "[name]";
+		#road-text-minority
+		{
+            text-name: "[minority_name]";
+		}
+		text-size: 10;
+		[zoom >= 16] {
+			text-size: 11;
+		}
+		[zoom >= 17] {
+			text-size: 12;
+		}
+		text-fill: #000;
+		text-face-name: "Liberation Sans Regular";
+		text-repeat-distance: 300;
+		[minority_name != null]
+		{
+			text-repeat-distance: 600;
+			text-margin: 25;
+		}
+		text-placement: line;
+		text-halo-radius: 1;
+		text-halo-fill: white;
+		text-clip: false;
+		text-avoid-edges: true;
+		[highway = 'trunk'][zoom >= 14],
+		[highway = 'primary'][zoom >= 14],
+		[zoom >= 15]
+		{
+			text-face-name: "Liberation Sans Bold";
+		}
+	}
+	[feature = 'road_minor'][zoom >= 15],
+	[feature = 'road_path'][zoom >= 15]
+	{
+		text-name: "[name]";
+		#road-text-minority
+		{
+            text-name: "[minority_name]";
+		}
+		text-size: 9;
+		[zoom >= 16] {
+			text-size: 10;
+		}
+		[zoom >= 17] {
+			text-size: 11;
+		}
+		text-fill: #000;
+		text-face-name: "Liberation Sans Regular";
+		text-repeat-distance: 300;
+		[minority_name != null]
+		{
+			text-repeat-distance: 600;
+			[zoom >= 16]
+			{
+				text-margin: 25;
+			}
+		}
+		text-placement: line;
+		text-halo-radius: 1;
+		text-halo-fill: white;
+		text-clip: false;
+		text-avoid-edges: true;
+	}
+}
+
+#rail-layer-n1,
+#rail[layer = 0],
+#rail-layer-1[layer >= 1]
+{
+	[service = null][zoom < 11]
+	{
+		line-width: 0.5;
+		[zoom >= 8] { line-width: 0.75; }
+		[zoom >= 9] { line-width: 1; }
+		line-color: #555;
+	}
+	[zoom >= 14],
+	[service = null][zoom >= 11]
+	{
+		line-color: #444;
+		b/line-color: white;
+		[service != null]
+		{
+			line-color: #888;
+			b/line-color: #ccc;
+		}
+		b/line-dasharray: 8, 8;
+		line-width: 2;
+		b/line-width: 1;
+		[zoom >= 17]
+		{
+			line-width: 3;
+			b/line-width: 1.5;
+		}
+		[zoom >= 18]
+		{
+			line-width: 4;
+			b/line-width: 2;
+		}
+	}
+}
+
+#railway-platform-ref
+{
+	shield-name: "[ref]";
+	shield-size: 12;
+	shield-fill: blue;
+	shield-spacing: 300;
+	shield-clip: false;
+	shield-placement: line;
+	shield-face-name: @railway-fonts-bold;
+	shield-halo-radius: @standard-halo-radius * 2;
+	shield-halo-fill: white;
+	shield-file: url('empty.png');
+	shield-repeat-distance: 10;
+}
+
+#runway[aeroway = 'runway'],
+#runway[aeroway = 'taxiway'][zoom >= 14]
+{
+	line-width: 4;
+	[aeroway = 'taxiway']
+	{
+		line-width: 1.5;
+		[zoom >= 15] { line-width: 3; }
+		[zoom >= 16] { line-width: 4; }
+		[zoom >= 17] { line-width: 6; }
+		[zoom >= 18] { line-width: 8; }
+		[zoom >= 19] { line-width: 12; }
+		[zoom >= 20] { line-width: 25; }
+	}
+	[aeroway = 'runway']
+	{
+		[zoom >= 11] { line-width: 3; }
+		[zoom >= 12] { line-width: 4; }
+		[zoom >= 13] { line-width: 6; }
+		[zoom >= 14] { line-width: 8; }
+		[zoom >= 15] { line-width: 12; }
+		[zoom >= 16] { line-width: 25; }
+		[zoom >= 17] { line-width: 50; }
+		[zoom >= 18] { line-width: 100; }
+		[zoom >= 19] { line-width: 200; }
+		[zoom >= 20] { line-width: 400; }
+	}
+	line-color: #8b8998;
+	text-name: "[ref]";
+	text-fill: black;
+	text-face-name: "Liberation Sans Oblique";
+	text-repeat-distance: 300;
+	text-placement: line;
+	text-halo-radius: 1;
+	text-halo-fill: white;
+	text-clip: false;
+	text-avoid-edges: true;
+	text-size: 12;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/style/shapefiles.mss	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,40 @@
+#necountries {
+  [zoom >= 1][zoom < 4] {
+    line-width: 0.2;
+    [zoom >= 2] {
+      line-width: 0.3;
+    }
+    [zoom >= 3] {
+      line-width: 0.4;
+    }
+    line-color: @admin-boundaries;
+  }
+}
+
+#ocean-lz,
+#ocean {
+  polygon-fill: @water-color;
+}
+
+#icesheet-poly {
+  [zoom >= 5] {
+    polygon-fill: @glacier;
+  }
+}
+
+#icesheet-outlines {
+  [zoom >= 5] {
+    [ice_edge = 'ice_ocean'],
+    [ice_edge = 'ice_land'] {
+      line-width: 0.375;
+      line-color: @glacier-line;
+      [zoom >= 8] {
+        line-width: 0.5;
+      }
+      [zoom >= 10] {
+        line-dasharray: 4,2;
+        line-width: 0.75;
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/style/style.mss	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,121 @@
+/* This is from osm-carto */
+Map {
+  background-color: @land-color;
+}
+
+@regular-font: "Tahoma Regular", "Liberation Sans Regular";
+@bold-font: "Tahoma Bold", "Liberation Sans Bold";
+@natural-font: "Liberation Serif Italic";
+@railway-fonts-bold: "FreeSans Bold";
+@place-font: @regular-font;
+@place-font-bold: @bold-font;
+
+@water-color: #bfdbe8;
+@land-color: #f2efe9;
+
+@standard-halo-radius: 1;
+@standard-halo-fill: rgba(255,255,255,0.6);
+
+@residential-color: #d8d8e2;
+@commercial-color: #ebd0d0;
+@forest-color: #a1c8a7;
+@farmland-color: #e9dfc9;
+@grass-color: #dfebc6;
+@industrial-color: #e3d7e9;
+@religious-color: #c2cdb6;
+@construction-color: #ada9a0;
+@civic-services-color: #f0edcd;
+
+#railway-landuse
+{
+	polygon-fill: @industrial-color;
+	[zoom >= 17] {
+		line-width: 0.5;
+		line-color: saturate(darken(@industrial-color, 20%), 20%);
+	}
+}
+
+#landcover {
+	[feature = 'residential'] {
+		polygon-fill: @residential-color;
+		[zoom >= 17] {
+			line-width: 0.5;
+			line-color: darken(@residential-color, 20%);
+		}
+	}
+	[feature = 'commercial'] {
+		polygon-fill: @commercial-color;
+		[zoom >= 17] {
+			line-width: 0.5;
+			line-color: saturate(darken(@commercial-color, 20%), 20%);
+		}
+	}
+	[feature = 'forest'] {
+		polygon-fill: @forest-color;
+		[zoom >= 17] {
+			line-width: 0.5;
+			line-color: saturate(darken(@forest-color, 20%), 20%);
+		}
+	}
+	[feature = 'farmland'] {
+		polygon-fill: @farmland-color;
+		[zoom >= 17] {
+			line-width: 0.5;
+			line-color: saturate(darken(@farmland-color, 20%), 20%);
+		}
+	}
+	[feature = 'grass'] {
+		polygon-fill: @grass-color;
+		[zoom >= 17] {
+			line-width: 0.5;
+			line-color: saturate(darken(@grass-color, 20%), 20%);
+		}
+	}
+	[feature = 'industrial'] {
+		polygon-fill: @industrial-color;
+		[zoom >= 17] {
+			line-width: 0.5;
+			line-color: saturate(darken(@industrial-color, 20%), 20%);
+		}
+	}
+	[feature = 'religious'] {
+		polygon-fill: @religious-color;
+		[zoom >= 17] {
+			line-width: 0.5;
+			line-color: darken(@religious-color, 20%);
+		}
+	}
+	[feature = 'construction'] {
+		polygon-fill: @construction-color;
+		[zoom >= 17] {
+			line-width: 0.5;
+			line-color: darken(@construction-color, 20%);
+		}
+	}
+}
+
+#civic-services {
+	polygon-fill: @civic-services-color;
+	[zoom >= 17] {
+		line-width: 0.5;
+		line-color: darken(@civic-services-color, 20%);
+	}
+}
+
+#inland-water {
+	polygon-fill: @water-color;
+	[zoom >= 12] {
+		line-width: 0.5;
+		line-color: saturate(darken(@water-color, 20%), 20%);
+	}
+}
+
+#bridge-area {
+	polygon-fill: @land-color;
+}
+
+#coastline
+{
+	line-width: 0.5;
+	line-color: saturate(darken(@water-color, 20%), 20%);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbols/aerodrome.svg	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="18"
+   height="18"
+   viewBox="0 0 18 17.999999"
+   xml:space="preserve"
+   sodipodi:docname="F39_Lentoasema.svg"
+   inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"><metadata
+   id="metadata19"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs17" /><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1920"
+   inkscape:window-height="1021"
+   id="namedview15"
+   showgrid="false"
+   inkscape:zoom="11.313709"
+   inkscape:cx="17.719841"
+   inkscape:cy="9.337293"
+   inkscape:window-x="0"
+   inkscape:window-y="0"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1" />
+
+
+
+<g
+   id="g834"
+   transform="matrix(0.04517294,0,0,0.04517294,-0.62844556,17.81126)"><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_145_">
+	
+		<rect
+   id="rect2"
+   height="396.85599"
+   width="396.85001"
+   style="fill:#005eb8;stroke:#005eb8;stroke-width:0.5;stroke-miterlimit:10"
+   y="14.17"
+   x="14.173" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_143_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path5"
+   d="M 59.527,411.026 H 365.67 c 25.047,0 45.354,-20.309 45.354,-45.355 V 59.527 C 411.024,34.478 390.717,14.17 365.67,14.17 H 59.527 c -25.046,0 -45.354,20.308 -45.354,45.357 v 306.144 c 0,25.047 20.308,45.355 45.354,45.355 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_144_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path8"
+   d="M 59.527,388.345 H 365.67 c 12.521,0 22.68,-10.148 22.68,-22.674 V 59.527 C 388.35,47.003 378.192,36.85 365.67,36.85 H 59.527 C 47.004,36.85 36.85,47.002 36.85,59.527 v 306.144 c 0,12.525 10.154,22.674 22.677,22.674 z"
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_151_">
+	<polygon
+   id="polygon11"
+   points="326.681,209.558 335.808,170.01 320.589,170.01 302.337,206.513 236.933,195.865 236.933,157.841 252.146,87.872 224.767,87.872 168.49,194.347 118.294,194.347 77.229,212.599 118.294,230.856 168.49,230.856 224.767,337.323 252.146,337.323 236.933,267.358 236.933,229.325 302.337,218.685 320.589,255.187 335.808,255.187 326.681,215.636 347.966,212.599 "
+   style="fill:#ffffff" />
+</g></g>
+</svg>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbols/bus-station.svg	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="18"
+   height="18"
+   viewBox="0 0 18 17.999999"
+   xml:space="preserve"
+   sodipodi:docname="bus-station.svg"
+   inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"><metadata
+   id="metadata52"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs50" /><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1920"
+   inkscape:window-height="1021"
+   id="namedview48"
+   showgrid="false"
+   inkscape:zoom="45.254834"
+   inkscape:cx="12.93299"
+   inkscape:cy="10.461887"
+   inkscape:window-x="0"
+   inkscape:window-y="0"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<g
+   id="g892"
+   transform="matrix(0.04535683,0,0,0.04535683,-0.62827696,18.086153)"><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_145_">
+	
+		<rect
+   id="rect2"
+   height="396.85101"
+   width="396.85101"
+   style="fill:#005eb8;stroke:#005eb8;stroke-width:0.5;stroke-miterlimit:10"
+   y="14.173"
+   x="14.173" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_143_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path5"
+   d="M 59.527,411.023 H 365.67 c 25.045,0 45.354,-20.306 45.354,-45.353 V 59.528 c 0,-25.049 -20.309,-45.355 -45.354,-45.355 H 59.527 c -25.047,0 -45.354,20.306 -45.354,45.355 v 306.143 c 0,25.047 20.307,45.352 45.354,45.352 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_144_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path8"
+   d="M 59.527,388.341 H 365.67 c 12.523,0 22.676,-10.147 22.676,-22.67 V 59.528 c 0,-12.526 -10.152,-22.676 -22.676,-22.676 H 59.527 c -12.523,0 -22.677,10.15 -22.677,22.676 v 306.143 c 0,12.522 10.153,22.67 22.677,22.67 z"
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="CIRCLE_14_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path11"
+   d="m 135.825,136.367 c 0,-17.938 -14.54,-32.479 -32.479,-32.479 -17.939,0 -32.479,14.541 -32.479,32.479 0,17.938 14.54,32.48 32.479,32.48 17.939,0 32.479,-14.542 32.479,-32.48 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="CIRCLE_15_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path14"
+   d="m 131.102,136.367 c 0,-15.328 -12.429,-27.756 -27.756,-27.756 -15.332,0 -27.756,12.428 -27.756,27.756 0,15.33 12.424,27.756 27.756,27.756 15.327,0.001 27.756,-12.426 27.756,-27.756 z"
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_171_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path17"
+   d="m 104.738,137.762 8.35,-8.354 c 0.771,-0.767 0.771,-2.015 0,-2.784 -0.764,-0.767 -2.012,-0.767 -2.781,0 l -4.992,4.99 v -14.929 c 0,-1.09 -0.879,-1.97 -1.968,-1.97 -1.089,0 -1.968,0.879 -1.968,1.97 v 19.682 c 0,0.523 0.209,1.022 0.576,1.395 0.77,0.767 2.012,0.767 2.783,0 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="CIRCLE_8_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path20"
+   d="m 148.474,335.139 c 0,-10.6 -8.592,-19.188 -19.191,-19.188 -10.594,0 -19.186,8.588 -19.186,19.188 0,10.598 8.592,19.191 19.186,19.191 10.599,0 19.191,-8.594 19.191,-19.191 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="CIRCLE_9_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path23"
+   d="m 303.962,335.139 c 0,-10.6 -8.593,-19.188 -19.191,-19.188 -10.594,0 -19.187,8.588 -19.187,19.188 0,10.598 8.593,19.191 19.187,19.191 10.599,0 19.191,-8.594 19.191,-19.191 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_160_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path26"
+   d="m 309.173,336.139 h 38.323 c 3.771,0 6.832,-3.062 6.832,-6.839 v -85.881 c 0,-3.775 -3.062,-6.837 -6.832,-6.837 H 92.808 c -3.123,0 -5.85,2.115 -6.625,5.146 l -15.315,59.878 v 34.533 h 34.018 c -0.027,-0.664 -0.027,-1.331 0,-1.996 0.55,-13.473 11.918,-23.952 25.397,-23.402 13.475,0.551 23.953,11.919 23.402,25.398 h 106.688 c -0.027,-0.664 -0.027,-1.331 0,-1.996 0.549,-13.473 11.918,-23.952 25.397,-23.402 13.476,0.55 23.953,11.918 23.403,25.398 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_170_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path29"
+   d="M 354.329,70.866 H 74.018 c -1.743,0 -3.15,1.411 -3.15,3.149 0,1.62 1.227,2.976 2.837,3.135 l 280.624,44.739 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_161_">
+	<polygon
+   id="polygon32"
+   points="79.394,294.655 120.542,294.655 126.782,243.52 92.478,243.52 "
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_162_">
+	<polygon
+   id="polygon35"
+   points="128.584,282.766 175.527,282.766 175.527,243.52 133.374,243.52 "
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_163_">
+	<rect
+   id="rect38"
+   height="39.245998"
+   width="50.152"
+   style="fill:#005eb8"
+   y="243.52"
+   x="182.069" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_164_">
+	<rect
+   id="rect41"
+   height="39.245998"
+   width="50.152"
+   style="fill:#005eb8"
+   y="243.52"
+   x="238.763" />
+</g><g
+     transform="translate(0,-413.19601)"
+     id="LWPOLYLINE_165_">
+	<rect
+   id="rect44"
+   height="39.245998"
+   width="50.146"
+   style="fill:#005eb8"
+   y="243.52"
+   x="295.45801" />
+</g></g>
+</svg>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbols/train-station.svg	Mon Sep 14 22:55:45 2020 +0300
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="18"
+   height="18"
+   viewBox="0 0 18 17.999999"
+   xml:space="preserve"
+   sodipodi:docname="train-station.svg"
+   inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"><metadata
+   id="metadata37"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs35" /><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1920"
+   inkscape:window-height="1021"
+   id="namedview33"
+   showgrid="false"
+   inkscape:zoom="11.313709"
+   inkscape:cx="-16.290539"
+   inkscape:cy="9.790908"
+   inkscape:window-x="0"
+   inkscape:window-y="0"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1" />
+
+
+
+
+
+
+
+
+
+<g
+   id="g864"
+   transform="matrix(0.04523964,0,0,0.04523964,-0.62115711,17.811806)"><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_150_">
+	
+		<rect
+   id="rect2"
+   height="396.85101"
+   width="396.85001"
+   style="fill:#005eb8;stroke:#005eb8;stroke-width:0.5;stroke-miterlimit:10"
+   y="14.173"
+   x="14.173" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_148_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path5"
+   d="m 59.527,411.023 h 306.141 c 25.049,0 45.355,-20.306 45.355,-45.353 V 59.529 c 0,-25.048 -20.307,-45.356 -45.355,-45.356 H 59.527 c -25.046,0 -45.354,20.309 -45.354,45.356 v 306.142 c 0,25.047 20.307,45.352 45.354,45.352 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_149_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path8"
+   d="m 59.527,388.342 h 306.141 c 12.523,0 22.676,-10.148 22.676,-22.671 V 59.529 c 0,-12.525 -10.152,-22.676 -22.676,-22.676 H 59.527 c -12.523,0 -22.676,10.15 -22.676,22.676 v 306.142 c 0,12.522 10.153,22.671 22.676,22.671 z"
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="CIRCLE_14_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path11"
+   d="m 135.824,136.369 c 0,-17.938 -14.54,-32.479 -32.478,-32.479 -17.939,0 -32.479,14.54 -32.479,32.479 0,17.938 14.54,32.48 32.479,32.48 17.938,0.001 32.478,-14.542 32.478,-32.48 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="CIRCLE_15_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path14"
+   d="m 131.102,136.369 c 0,-15.33 -12.429,-27.757 -27.755,-27.757 -15.333,0 -27.756,12.427 -27.756,27.757 0,15.328 12.424,27.756 27.756,27.756 15.326,0 27.755,-12.428 27.755,-27.756 z"
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_156_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path17"
+   d="m 349.968,194.583 v -17.449 h -69.777 v 43.61 h -65.413 v -13.083 c 0,-9.639 -7.813,-17.444 -17.444,-17.444 -9.637,0 -17.443,7.806 -17.443,17.444 v 13.083 h -47.97 v -34.886 h -21.808 v 34.886 H 83.946 v 85.61 h 12.231 c -7.229,12.519 -2.941,28.521 9.577,35.745 0.55,0.318 1.105,0.615 1.677,0.89 H 70.868 v 11.342 h 283.459 v -11.342 h -49.646 c 13.006,-6.299 18.443,-21.944 12.144,-34.951 -0.274,-0.572 -0.573,-1.133 -0.891,-1.684 h 34.034 v -72.525 h -17.443 v 21.803 h -34.892 v -61.049 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_190_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path20"
+   d="m 104.737,137.762 8.35,-8.353 c 0.77,-0.767 0.77,-2.015 0,-2.785 -0.764,-0.768 -2.012,-0.768 -2.781,0 l -4.992,4.992 v -14.932 c 0,-1.088 -0.879,-1.968 -1.967,-1.968 -1.089,0 -1.969,0.88 -1.969,1.968 v 19.685 c 0,0.521 0.209,1.022 0.577,1.393 0.77,0.766 2.012,0.766 2.782,0 z"
+   style="fill:#ffffff" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_157_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path23"
+   d="m 194.509,344.034 h -64.923 c 13.105,-6.351 18.586,-22.122 12.237,-35.233 -0.275,-0.577 -0.578,-1.137 -0.896,-1.693 h 42.236 c -7.285,12.616 -2.963,28.746 9.653,36.031 0.555,0.318 1.116,0.619 1.693,0.895 z"
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_158_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path26"
+   d="M 281.867,342.989 H 217.46 c 13.006,-6.299 18.443,-21.944 12.143,-34.951 -0.274,-0.572 -0.57,-1.133 -0.891,-1.684 h 41.9 c -7.223,12.519 -2.934,28.521 9.578,35.745 0.55,0.319 1.111,0.616 1.677,0.89 z"
+   style="fill:#005eb8" />
+</g><g
+     transform="translate(0,-407.19601)"
+     id="LWPOLYLINE_189_">
+	<path
+   inkscape:connector-curvature="0"
+   id="path29"
+   d="M 354.328,70.868 H 74.018 c -1.743,0 -3.149,1.409 -3.149,3.149 0,1.619 1.226,2.974 2.836,3.133 l 280.623,44.741 z"
+   style="fill:#ffffff" />
+</g></g>
+</svg>
\ No newline at end of file

mercurial