@chrtco/sdk 0.10.29 → 0.10.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +382 -354
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +382 -354
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28618,328 +28618,12 @@ function worldMinusBboxPolygon(bbox) {
|
|
|
28618
28618
|
};
|
|
28619
28619
|
}
|
|
28620
28620
|
|
|
28621
|
-
// src/atlas/land-layers.ts
|
|
28622
|
-
var LAND_SURFACE_MINZOOM = BAND_PRIORITY_RANGES["5"].minzoom;
|
|
28623
|
-
var LAND_SURFACE_LAYERS = (id) => id === "chrtland-base" || id === "chrtland-cover" || id === "chrtland-contour" || id === "chrtland-hillshade" || id.startsWith("chrtland-fade-");
|
|
28624
|
-
var FADE_PX = 80;
|
|
28625
|
-
var FADE_BANDS = 16;
|
|
28626
|
-
function fadeAlpha(r) {
|
|
28627
|
-
return Math.max(0, Math.min(1, (FADE_PX / 2 - Math.abs(r)) / FADE_PX));
|
|
28628
|
-
}
|
|
28629
|
-
function landBaseColor(palette) {
|
|
28630
|
-
return (LAND_THEMES[palette] ?? LAND_THEMES.DAY).base;
|
|
28631
|
-
}
|
|
28632
|
-
var LAND_THEMES = {
|
|
28633
|
-
DAY: {
|
|
28634
|
-
base: "#e8d9b0",
|
|
28635
|
-
cover: { wood: "#cfd8b4", wetland: "#c9d3c4", urban: "#dedad2", sand: "#efe4c2" },
|
|
28636
|
-
contour: "#a89878",
|
|
28637
|
-
contourIndex: "#8a7a5c",
|
|
28638
|
-
road: "#d9c9a4",
|
|
28639
|
-
roadMajor: "#d2bd8e",
|
|
28640
|
-
label: "#5b4f3a",
|
|
28641
|
-
halo: "#f2ead6",
|
|
28642
|
-
shadow: "#6b5a3e",
|
|
28643
|
-
highlight: "#fffaf0",
|
|
28644
|
-
fade: "#e8f2f8",
|
|
28645
|
-
// Raised from 0.45 on 2026-08-23. ⚠ Above the ~0.5 that
|
|
28646
|
-
// hillshade-style.mjs warns "starts competing with depth areas" — a
|
|
28647
|
-
// deliberate, sighted choice made against rendered evidence, not a
|
|
28648
|
-
// default. If soundings or DEPARE ever read as fighting the terrain,
|
|
28649
|
-
// this number is the first thing to walk back.
|
|
28650
|
-
exaggeration: 0.8
|
|
28651
|
-
},
|
|
28652
|
-
DUSK: {
|
|
28653
|
-
base: "#4a4433",
|
|
28654
|
-
cover: { wood: "#414a38", wetland: "#3f4740", urban: "#4e4a42", sand: "#544c39" },
|
|
28655
|
-
contour: "#6b6250",
|
|
28656
|
-
contourIndex: "#837961",
|
|
28657
|
-
road: "#565040",
|
|
28658
|
-
roadMajor: "#63594440",
|
|
28659
|
-
label: "#c3b898",
|
|
28660
|
-
halo: "#2b2820",
|
|
28661
|
-
shadow: "#2e2a20",
|
|
28662
|
-
highlight: "#8a8068",
|
|
28663
|
-
fade: "#16202a",
|
|
28664
|
-
// Unchanged. DUSK was not the palette the 0.8 decision was made against.
|
|
28665
|
-
exaggeration: 0.45
|
|
28666
|
-
},
|
|
28667
|
-
NIGHT: {
|
|
28668
|
-
base: "#2a2620",
|
|
28669
|
-
cover: { wood: "#242a20", wetland: "#232823", urban: "#2c2925", sand: "#302b22" },
|
|
28670
|
-
contour: "#413b30",
|
|
28671
|
-
contourIndex: "#524a3b",
|
|
28672
|
-
road: "#332f27",
|
|
28673
|
-
roadMajor: "#3d382d",
|
|
28674
|
-
label: "#7d745e",
|
|
28675
|
-
halo: "#15130f",
|
|
28676
|
-
shadow: "#1a1712",
|
|
28677
|
-
highlight: "#4a4436",
|
|
28678
|
-
fade: "#07090b",
|
|
28679
|
-
// ⚠ DELIBERATELY NOT RAISED. See the type's note: a strong hillshade
|
|
28680
|
-
// under red night vision is a grey haze over exactly the contrast a
|
|
28681
|
-
// skipper is navigating by. Left at the shipped value rather than
|
|
28682
|
-
// lowered, because lowering it is a separate decision from this one.
|
|
28683
|
-
exaggeration: 0.45
|
|
28684
|
-
}
|
|
28685
|
-
};
|
|
28686
|
-
var FITS = ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]];
|
|
28687
|
-
var ANCHOR = ["coalesce", ["get", "anchor"], "top"];
|
|
28688
|
-
var anchorOffset = (em) => [
|
|
28689
|
-
"match",
|
|
28690
|
-
["get", "anchor"],
|
|
28691
|
-
"left",
|
|
28692
|
-
["literal", [0.6, 0]],
|
|
28693
|
-
"right",
|
|
28694
|
-
["literal", [-0.6, 0]],
|
|
28695
|
-
"bottom",
|
|
28696
|
-
["literal", [0, -em]],
|
|
28697
|
-
["literal", [0, em]]
|
|
28698
|
-
];
|
|
28699
|
-
var FONT = ["Open Sans Regular"];
|
|
28700
|
-
var FONT_ITALIC = ["Open Sans Italic"];
|
|
28701
|
-
function landLayers(opts = {}) {
|
|
28702
|
-
const palette = opts.palette ?? "DAY";
|
|
28703
|
-
const T = LAND_THEMES[palette] ?? LAND_THEMES.DAY;
|
|
28704
|
-
const src = opts.sourceId ?? LAND_REGION;
|
|
28705
|
-
const demSrc = opts.reliefSourceId ?? RELIEF_REGION;
|
|
28706
|
-
const L = (o) => o;
|
|
28707
|
-
const layers = [
|
|
28708
|
-
// 1. The land itself — LNDARE ∩ coverage, so it can never outrun the chart.
|
|
28709
|
-
L({
|
|
28710
|
-
id: "chrtland-base",
|
|
28711
|
-
type: "fill",
|
|
28712
|
-
source: src,
|
|
28713
|
-
"source-layer": "land_base",
|
|
28714
|
-
paint: { "fill-color": T.base }
|
|
28715
|
-
})
|
|
28716
|
-
];
|
|
28717
|
-
layers.push(L({
|
|
28718
|
-
id: "chrtland-cover",
|
|
28719
|
-
type: "fill",
|
|
28720
|
-
source: src,
|
|
28721
|
-
"source-layer": "land_cover",
|
|
28722
|
-
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
28723
|
-
paint: {
|
|
28724
|
-
"fill-color": [
|
|
28725
|
-
"match",
|
|
28726
|
-
["get", "class"],
|
|
28727
|
-
"wood",
|
|
28728
|
-
T.cover.wood,
|
|
28729
|
-
"wetland",
|
|
28730
|
-
T.cover.wetland,
|
|
28731
|
-
"urban",
|
|
28732
|
-
T.cover.urban,
|
|
28733
|
-
"sand",
|
|
28734
|
-
T.cover.sand,
|
|
28735
|
-
T.base
|
|
28736
|
-
],
|
|
28737
|
-
"fill-opacity": 0.85
|
|
28738
|
-
}
|
|
28739
|
-
}));
|
|
28740
|
-
if (opts.relief) {
|
|
28741
|
-
layers.push(L({
|
|
28742
|
-
// No minzoom here: LAND_SURFACE_LAYERS floors it with the rest of the
|
|
28743
|
-
// surface, so the two can never drift apart again.
|
|
28744
|
-
id: "chrtland-hillshade",
|
|
28745
|
-
type: "hillshade",
|
|
28746
|
-
source: demSrc,
|
|
28747
|
-
paint: {
|
|
28748
|
-
"hillshade-exaggeration": T.exaggeration,
|
|
28749
|
-
"hillshade-shadow-color": T.shadow,
|
|
28750
|
-
"hillshade-highlight-color": T.highlight,
|
|
28751
|
-
"hillshade-accent-color": T.shadow
|
|
28752
|
-
}
|
|
28753
|
-
}));
|
|
28754
|
-
}
|
|
28755
|
-
const isIndexContour = [
|
|
28756
|
-
"any",
|
|
28757
|
-
["<=", ["coalesce", ["get", "index_z"], 99], ["zoom"]],
|
|
28758
|
-
["==", ["get", "is_index"], 1]
|
|
28759
|
-
];
|
|
28760
|
-
layers.push(L({
|
|
28761
|
-
id: "chrtland-contour",
|
|
28762
|
-
type: "line",
|
|
28763
|
-
source: src,
|
|
28764
|
-
"source-layer": "land_contour",
|
|
28765
|
-
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
28766
|
-
paint: {
|
|
28767
|
-
"line-color": ["case", isIndexContour, T.contourIndex, T.contour],
|
|
28768
|
-
"line-width": ["case", isIndexContour, 0.8, 0.4],
|
|
28769
|
-
"line-opacity": 0.7
|
|
28770
|
-
}
|
|
28771
|
-
}));
|
|
28772
|
-
const d = FADE_PX / 2 / FADE_BANDS;
|
|
28773
|
-
for (let k = 0; k < FADE_BANDS; k++) {
|
|
28774
|
-
const width = k === 0 ? { "line-width": 2 * d } : { "line-width": d, "line-gap-width": 2 * k * d };
|
|
28775
|
-
layers.push(L({
|
|
28776
|
-
id: `chrtland-fade-${k}`,
|
|
28777
|
-
type: "line",
|
|
28778
|
-
source: src,
|
|
28779
|
-
"source-layer": "land_edge",
|
|
28780
|
-
layout: { "line-join": "bevel" },
|
|
28781
|
-
paint: { "line-color": T.fade, "line-blur": 0, "line-opacity": fadeAlpha(k * d + d / 2), ...width }
|
|
28782
|
-
}));
|
|
28783
|
-
}
|
|
28784
|
-
layers.push(L({
|
|
28785
|
-
id: "chrtland-road",
|
|
28786
|
-
type: "line",
|
|
28787
|
-
source: src,
|
|
28788
|
-
"source-layer": "land_road",
|
|
28789
|
-
minzoom: 10,
|
|
28790
|
-
paint: {
|
|
28791
|
-
"line-color": ["match", ["get", "kind"], "highway", T.roadMajor, T.road],
|
|
28792
|
-
"line-width": [
|
|
28793
|
-
"interpolate",
|
|
28794
|
-
["linear"],
|
|
28795
|
-
["zoom"],
|
|
28796
|
-
10,
|
|
28797
|
-
["match", ["get", "kind"], "highway", 0.8, 0.4],
|
|
28798
|
-
14,
|
|
28799
|
-
["match", ["get", "kind"], "highway", 2.4, 1.2]
|
|
28800
|
-
],
|
|
28801
|
-
"line-opacity": 0.8
|
|
28802
|
-
}
|
|
28803
|
-
}));
|
|
28804
|
-
layers.push(L({
|
|
28805
|
-
id: "chrtland-city-major",
|
|
28806
|
-
type: "symbol",
|
|
28807
|
-
source: src,
|
|
28808
|
-
"source-layer": "land_town",
|
|
28809
|
-
minzoom: 6.5,
|
|
28810
|
-
filter: [">=", ["coalesce", ["get", "prank"], 0], 10],
|
|
28811
|
-
layout: {
|
|
28812
|
-
"text-field": [
|
|
28813
|
-
"case",
|
|
28814
|
-
["==", ["get", "upcase"], true],
|
|
28815
|
-
["upcase", ["get", "name"]],
|
|
28816
|
-
["get", "name"]
|
|
28817
|
-
],
|
|
28818
|
-
"text-font": FONT,
|
|
28819
|
-
"text-size": [
|
|
28820
|
-
"interpolate",
|
|
28821
|
-
["linear"],
|
|
28822
|
-
["zoom"],
|
|
28823
|
-
6.5,
|
|
28824
|
-
11.5,
|
|
28825
|
-
9,
|
|
28826
|
-
["+", 10, ["*", 0.4, ["coalesce", ["get", "prank"], 10]]],
|
|
28827
|
-
13,
|
|
28828
|
-
["+", 13, ["*", 0.5, ["coalesce", ["get", "prank"], 10]]]
|
|
28829
|
-
],
|
|
28830
|
-
"text-letter-spacing": ["case", ["==", ["get", "upcase"], true], 0.14, 0.02],
|
|
28831
|
-
"text-offset": anchorOffset(0.75),
|
|
28832
|
-
"text-anchor": ANCHOR,
|
|
28833
|
-
"text-padding": 10,
|
|
28834
|
-
"text-allow-overlap": false,
|
|
28835
|
-
"symbol-sort-key": ["*", -1, ["coalesce", ["get", "pop"], 0]]
|
|
28836
|
-
},
|
|
28837
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.6 }
|
|
28838
|
-
}));
|
|
28839
|
-
layers.push(L({
|
|
28840
|
-
id: "chrtland-town-port",
|
|
28841
|
-
type: "symbol",
|
|
28842
|
-
source: src,
|
|
28843
|
-
"source-layer": "land_town",
|
|
28844
|
-
minzoom: 8.5,
|
|
28845
|
-
filter: [
|
|
28846
|
-
"all",
|
|
28847
|
-
["==", ["get", "enc_dup"], true],
|
|
28848
|
-
["<", ["coalesce", ["get", "prank"], 0], 10]
|
|
28849
|
-
],
|
|
28850
|
-
layout: {
|
|
28851
|
-
"text-field": ["get", "name"],
|
|
28852
|
-
"text-font": FONT,
|
|
28853
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 8.5, 11, 12, 13.5],
|
|
28854
|
-
"text-offset": anchorOffset(0.75),
|
|
28855
|
-
"text-anchor": ANCHOR,
|
|
28856
|
-
"text-padding": 8,
|
|
28857
|
-
"text-allow-overlap": false,
|
|
28858
|
-
// Within the tier, the bigger place wins the space: without this the
|
|
28859
|
-
// tie broke on data order and "West Gloucester" beat Gloucester.
|
|
28860
|
-
"symbol-sort-key": ["*", -1, ["coalesce", ["get", "pop"], 0]]
|
|
28861
|
-
},
|
|
28862
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.4 }
|
|
28863
|
-
}));
|
|
28864
|
-
layers.push(L({
|
|
28865
|
-
id: "chrtland-town",
|
|
28866
|
-
type: "symbol",
|
|
28867
|
-
source: src,
|
|
28868
|
-
"source-layer": "land_town",
|
|
28869
|
-
minzoom: 9,
|
|
28870
|
-
filter: [
|
|
28871
|
-
"all",
|
|
28872
|
-
FITS,
|
|
28873
|
-
["<", ["coalesce", ["get", "prank"], 0], 10],
|
|
28874
|
-
["!=", ["get", "enc_dup"], true]
|
|
28875
|
-
],
|
|
28876
|
-
layout: {
|
|
28877
|
-
"text-field": [
|
|
28878
|
-
"case",
|
|
28879
|
-
["==", ["get", "upcase"], true],
|
|
28880
|
-
["upcase", ["get", "name"]],
|
|
28881
|
-
["get", "name"]
|
|
28882
|
-
],
|
|
28883
|
-
"text-font": FONT,
|
|
28884
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 9, 10, 14, 13.5],
|
|
28885
|
-
"text-letter-spacing": ["case", ["==", ["get", "upcase"], true], 0.14, 0],
|
|
28886
|
-
"text-offset": anchorOffset(0.75),
|
|
28887
|
-
"text-anchor": ANCHOR,
|
|
28888
|
-
"text-padding": 6,
|
|
28889
|
-
"text-allow-overlap": false,
|
|
28890
|
-
"symbol-sort-key": 2
|
|
28891
|
-
},
|
|
28892
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
28893
|
-
}));
|
|
28894
|
-
layers.push(L({
|
|
28895
|
-
id: "chrtland-summit",
|
|
28896
|
-
type: "symbol",
|
|
28897
|
-
source: src,
|
|
28898
|
-
"source-layer": "land_summit",
|
|
28899
|
-
minzoom: 11.5,
|
|
28900
|
-
filter: ["all", FITS, [">=", ["get", "peak_m"], 40]],
|
|
28901
|
-
layout: {
|
|
28902
|
-
"text-field": ["concat", ["get", "name"], "\n", ["to-string", ["get", "peak_m"]], " m"],
|
|
28903
|
-
"text-font": FONT,
|
|
28904
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 11.5, 8.5, 14, 11],
|
|
28905
|
-
"text-offset": anchorOffset(0.8),
|
|
28906
|
-
"text-anchor": ANCHOR,
|
|
28907
|
-
"text-padding": 5,
|
|
28908
|
-
"text-allow-overlap": false,
|
|
28909
|
-
"symbol-sort-key": 3
|
|
28910
|
-
},
|
|
28911
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
28912
|
-
}));
|
|
28913
|
-
layers.push(L({
|
|
28914
|
-
id: "chrtland-poi",
|
|
28915
|
-
type: "symbol",
|
|
28916
|
-
source: src,
|
|
28917
|
-
"source-layer": "land_poi",
|
|
28918
|
-
minzoom: 13,
|
|
28919
|
-
filter: FITS,
|
|
28920
|
-
layout: {
|
|
28921
|
-
"text-field": ["get", "name"],
|
|
28922
|
-
"text-font": FONT_ITALIC,
|
|
28923
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 13, 8, 14, 9.5],
|
|
28924
|
-
"text-offset": anchorOffset(0.7),
|
|
28925
|
-
"text-anchor": ANCHOR,
|
|
28926
|
-
"text-padding": 5,
|
|
28927
|
-
"text-allow-overlap": false,
|
|
28928
|
-
"symbol-sort-key": 5
|
|
28929
|
-
},
|
|
28930
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
28931
|
-
}));
|
|
28932
|
-
for (const layer of layers) {
|
|
28933
|
-
const l = layer;
|
|
28934
|
-
if (!LAND_SURFACE_LAYERS(l.id)) continue;
|
|
28935
|
-
l.minzoom = Math.max(l.minzoom ?? 0, LAND_SURFACE_MINZOOM);
|
|
28936
|
-
}
|
|
28937
|
-
return layers;
|
|
28938
|
-
}
|
|
28939
|
-
|
|
28940
28621
|
// src/atlas/base-layers.ts
|
|
28941
28622
|
var NOCOVERAGE_PATTERN = "chrt:hatch-nocoverage";
|
|
28942
28623
|
var UNCHARTED_PATTERN = "chrt:hatch-uncharted";
|
|
28624
|
+
function inlandWaterColor(palette) {
|
|
28625
|
+
return (BASE_THEMES[palette] ?? BASE_THEMES.DAY).inlandWater;
|
|
28626
|
+
}
|
|
28943
28627
|
var BASE_THEMES = {
|
|
28944
28628
|
DAY: {
|
|
28945
28629
|
// ── `earth` is the jurisdiction tan DIMMED (~0.55), not a blue-grey ──
|
|
@@ -28958,7 +28642,7 @@ var BASE_THEMES = {
|
|
|
28958
28642
|
water: "#1B2328",
|
|
28959
28643
|
river: "#24313A",
|
|
28960
28644
|
boundary: "#4A575E",
|
|
28961
|
-
jurisdiction: "#
|
|
28645
|
+
jurisdiction: "#D4C69D",
|
|
28962
28646
|
// CHRTland's own tan — one land colour
|
|
28963
28647
|
inlandWater: "#B9CFDD",
|
|
28964
28648
|
// muted, unmistakably not a charted blue
|
|
@@ -28966,9 +28650,9 @@ var BASE_THEMES = {
|
|
|
28966
28650
|
// from this table (and its type — the long-standing TS2339 trio), so the
|
|
28967
28651
|
// lines shipped on MapLibre's DEFAULT black. Now deliberate: a hairline
|
|
28968
28652
|
// a shade deeper than the tan, quiet caps, tan halo.
|
|
28969
|
-
stateLine: "#
|
|
28653
|
+
stateLine: "#B1A077",
|
|
28970
28654
|
stateLabel: "#8E8468",
|
|
28971
|
-
stateHalo: "#
|
|
28655
|
+
stateHalo: "#D4C69D",
|
|
28972
28656
|
// Rough-lake furniture (owner ask 2026-08-28: "the lakes need labels,
|
|
28973
28657
|
// and shorelines drawn"): a shoreline a shade deeper than the rough
|
|
28974
28658
|
// water, and a name in the water's own voice, haloed by the water.
|
|
@@ -29346,29 +29030,357 @@ function baseInlandWaterLayers(opts = {}) {
|
|
|
29346
29030
|
id: "chrtbase-inland-label",
|
|
29347
29031
|
type: "symbol",
|
|
29348
29032
|
source: src,
|
|
29349
|
-
"source-layer": "inland_water_label",
|
|
29350
|
-
minzoom: 5,
|
|
29351
|
-
layout: {
|
|
29352
|
-
"text-field": ["get", "name"],
|
|
29353
|
-
"text-font": ["Open Sans Regular"],
|
|
29354
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 5, 9.5, 10, 12],
|
|
29355
|
-
"text-max-width": 7,
|
|
29356
|
-
"text-allow-overlap": false,
|
|
29357
|
-
// Zoom-scaled spacing for the anchor GRID: at z8.9 the 0.08-deg
|
|
29358
|
-
// anchors sit ~54 px apart and a flat padding let six copies of
|
|
29359
|
-
// "Lake Ontario" crowd one screen (owner-reported 2026-08-30).
|
|
29360
|
-
// Wide collision boxes at low zoom thin the grid to the repeat-
|
|
29361
|
-
// by-convention cadence; by z12 the anchors are ~850 px apart and
|
|
29362
|
-
// the padding relaxes to normal.
|
|
29363
|
-
"text-padding": ["interpolate", ["linear"], ["zoom"], 5, 80, 9, 64, 12, 16]
|
|
29364
|
-
},
|
|
29033
|
+
"source-layer": "inland_water_label",
|
|
29034
|
+
minzoom: 5,
|
|
29035
|
+
layout: {
|
|
29036
|
+
"text-field": ["get", "name"],
|
|
29037
|
+
"text-font": ["Open Sans Regular"],
|
|
29038
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 5, 9.5, 10, 12],
|
|
29039
|
+
"text-max-width": 7,
|
|
29040
|
+
"text-allow-overlap": false,
|
|
29041
|
+
// Zoom-scaled spacing for the anchor GRID: at z8.9 the 0.08-deg
|
|
29042
|
+
// anchors sit ~54 px apart and a flat padding let six copies of
|
|
29043
|
+
// "Lake Ontario" crowd one screen (owner-reported 2026-08-30).
|
|
29044
|
+
// Wide collision boxes at low zoom thin the grid to the repeat-
|
|
29045
|
+
// by-convention cadence; by z12 the anchors are ~850 px apart and
|
|
29046
|
+
// the padding relaxes to normal.
|
|
29047
|
+
"text-padding": ["interpolate", ["linear"], ["zoom"], 5, 80, 9, 64, 12, 16]
|
|
29048
|
+
},
|
|
29049
|
+
paint: {
|
|
29050
|
+
"text-color": T.inlandLabel,
|
|
29051
|
+
"text-halo-color": T.inlandHalo,
|
|
29052
|
+
"text-halo-width": 1.1
|
|
29053
|
+
}
|
|
29054
|
+
})
|
|
29055
|
+
];
|
|
29056
|
+
}
|
|
29057
|
+
|
|
29058
|
+
// src/atlas/land-layers.ts
|
|
29059
|
+
var LAND_SURFACE_MINZOOM = BAND_PRIORITY_RANGES["5"].minzoom;
|
|
29060
|
+
var LAND_SURFACE_LAYERS = (id) => id === "chrtland-base" || id === "chrtland-cover" || id === "chrtland-contour" || id === "chrtland-hillshade" || id === "chrtland-water" || id.startsWith("chrtland-fade-");
|
|
29061
|
+
var isLandGroundOverlay = (id) => LAND_SURFACE_LAYERS(id) && id !== "chrtland-base" || id === "chrtland-road";
|
|
29062
|
+
var FADE_PX = 80;
|
|
29063
|
+
var FADE_BANDS = 16;
|
|
29064
|
+
function fadeAlpha(r) {
|
|
29065
|
+
return Math.max(0, Math.min(1, (FADE_PX / 2 - Math.abs(r)) / FADE_PX));
|
|
29066
|
+
}
|
|
29067
|
+
function landBaseColor(palette) {
|
|
29068
|
+
return (LAND_THEMES[palette] ?? LAND_THEMES.DAY).base;
|
|
29069
|
+
}
|
|
29070
|
+
var LAND_THEMES = {
|
|
29071
|
+
DAY: {
|
|
29072
|
+
base: "#d4c69d",
|
|
29073
|
+
cover: { wood: "#bcc5a1", wetland: "#b6c0b1", urban: "#cac6bf", sand: "#dbd0af" },
|
|
29074
|
+
contour: "#958666",
|
|
29075
|
+
contourIndex: "#78694b",
|
|
29076
|
+
road: "#c5b691",
|
|
29077
|
+
roadMajor: "#beaa7c",
|
|
29078
|
+
label: "#5b4f3a",
|
|
29079
|
+
halo: "#ded6c3",
|
|
29080
|
+
shadow: "#6b5a3e",
|
|
29081
|
+
highlight: "#fffaf0",
|
|
29082
|
+
fade: "#e8f2f8",
|
|
29083
|
+
// Raised from 0.45 on 2026-08-23. ⚠ Above the ~0.5 that
|
|
29084
|
+
// hillshade-style.mjs warns "starts competing with depth areas" — a
|
|
29085
|
+
// deliberate, sighted choice made against rendered evidence, not a
|
|
29086
|
+
// default. If soundings or DEPARE ever read as fighting the terrain,
|
|
29087
|
+
// this number is the first thing to walk back.
|
|
29088
|
+
exaggeration: 0.8
|
|
29089
|
+
},
|
|
29090
|
+
DUSK: {
|
|
29091
|
+
base: "#4a4433",
|
|
29092
|
+
cover: { wood: "#414a38", wetland: "#3f4740", urban: "#4e4a42", sand: "#544c39" },
|
|
29093
|
+
contour: "#6b6250",
|
|
29094
|
+
contourIndex: "#837961",
|
|
29095
|
+
road: "#565040",
|
|
29096
|
+
roadMajor: "#63594440",
|
|
29097
|
+
label: "#c3b898",
|
|
29098
|
+
halo: "#2b2820",
|
|
29099
|
+
shadow: "#2e2a20",
|
|
29100
|
+
highlight: "#8a8068",
|
|
29101
|
+
fade: "#16202a",
|
|
29102
|
+
// Unchanged. DUSK was not the palette the 0.8 decision was made against.
|
|
29103
|
+
exaggeration: 0.45
|
|
29104
|
+
},
|
|
29105
|
+
NIGHT: {
|
|
29106
|
+
base: "#2a2620",
|
|
29107
|
+
cover: { wood: "#242a20", wetland: "#232823", urban: "#2c2925", sand: "#302b22" },
|
|
29108
|
+
contour: "#413b30",
|
|
29109
|
+
contourIndex: "#524a3b",
|
|
29110
|
+
road: "#332f27",
|
|
29111
|
+
roadMajor: "#3d382d",
|
|
29112
|
+
label: "#7d745e",
|
|
29113
|
+
halo: "#15130f",
|
|
29114
|
+
shadow: "#1a1712",
|
|
29115
|
+
highlight: "#4a4436",
|
|
29116
|
+
fade: "#07090b",
|
|
29117
|
+
// ⚠ DELIBERATELY NOT RAISED. See the type's note: a strong hillshade
|
|
29118
|
+
// under red night vision is a grey haze over exactly the contrast a
|
|
29119
|
+
// skipper is navigating by. Left at the shipped value rather than
|
|
29120
|
+
// lowered, because lowering it is a separate decision from this one.
|
|
29121
|
+
exaggeration: 0.45
|
|
29122
|
+
}
|
|
29123
|
+
};
|
|
29124
|
+
var FITS = ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]];
|
|
29125
|
+
var ANCHOR = ["coalesce", ["get", "anchor"], "top"];
|
|
29126
|
+
var anchorOffset = (em) => [
|
|
29127
|
+
"match",
|
|
29128
|
+
["get", "anchor"],
|
|
29129
|
+
"left",
|
|
29130
|
+
["literal", [0.6, 0]],
|
|
29131
|
+
"right",
|
|
29132
|
+
["literal", [-0.6, 0]],
|
|
29133
|
+
"bottom",
|
|
29134
|
+
["literal", [0, -em]],
|
|
29135
|
+
["literal", [0, em]]
|
|
29136
|
+
];
|
|
29137
|
+
var FONT = ["Open Sans Regular"];
|
|
29138
|
+
var FONT_ITALIC = ["Open Sans Italic"];
|
|
29139
|
+
function landLayers(opts = {}) {
|
|
29140
|
+
const palette = opts.palette ?? "DAY";
|
|
29141
|
+
const T = LAND_THEMES[palette] ?? LAND_THEMES.DAY;
|
|
29142
|
+
const src = opts.sourceId ?? LAND_REGION;
|
|
29143
|
+
const demSrc = opts.reliefSourceId ?? RELIEF_REGION;
|
|
29144
|
+
const L = (o) => o;
|
|
29145
|
+
const layers = [
|
|
29146
|
+
// 1. The land itself — LNDARE ∩ coverage, so it can never outrun the chart.
|
|
29147
|
+
L({
|
|
29148
|
+
id: "chrtland-base",
|
|
29149
|
+
type: "fill",
|
|
29150
|
+
source: src,
|
|
29151
|
+
"source-layer": "land_base",
|
|
29152
|
+
paint: { "fill-color": T.base }
|
|
29153
|
+
})
|
|
29154
|
+
];
|
|
29155
|
+
layers.push(L({
|
|
29156
|
+
id: "chrtland-cover",
|
|
29157
|
+
type: "fill",
|
|
29158
|
+
source: src,
|
|
29159
|
+
"source-layer": "land_cover",
|
|
29160
|
+
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
29161
|
+
paint: {
|
|
29162
|
+
"fill-color": [
|
|
29163
|
+
"match",
|
|
29164
|
+
["get", "class"],
|
|
29165
|
+
"wood",
|
|
29166
|
+
T.cover.wood,
|
|
29167
|
+
"wetland",
|
|
29168
|
+
T.cover.wetland,
|
|
29169
|
+
"urban",
|
|
29170
|
+
T.cover.urban,
|
|
29171
|
+
"sand",
|
|
29172
|
+
T.cover.sand,
|
|
29173
|
+
T.base
|
|
29174
|
+
],
|
|
29175
|
+
"fill-opacity": 0.85
|
|
29176
|
+
}
|
|
29177
|
+
}));
|
|
29178
|
+
if (opts.relief) {
|
|
29179
|
+
layers.push(L({
|
|
29180
|
+
// No minzoom here: LAND_SURFACE_LAYERS floors it with the rest of the
|
|
29181
|
+
// surface, so the two can never drift apart again.
|
|
29182
|
+
id: "chrtland-hillshade",
|
|
29183
|
+
type: "hillshade",
|
|
29184
|
+
source: demSrc,
|
|
29365
29185
|
paint: {
|
|
29366
|
-
"
|
|
29367
|
-
"
|
|
29368
|
-
"
|
|
29186
|
+
"hillshade-exaggeration": T.exaggeration,
|
|
29187
|
+
"hillshade-shadow-color": T.shadow,
|
|
29188
|
+
"hillshade-highlight-color": T.highlight,
|
|
29189
|
+
"hillshade-accent-color": T.shadow
|
|
29369
29190
|
}
|
|
29370
|
-
})
|
|
29191
|
+
}));
|
|
29192
|
+
}
|
|
29193
|
+
const isIndexContour = [
|
|
29194
|
+
"any",
|
|
29195
|
+
["<=", ["coalesce", ["get", "index_z"], 99], ["zoom"]],
|
|
29196
|
+
["==", ["get", "is_index"], 1]
|
|
29371
29197
|
];
|
|
29198
|
+
layers.push(L({
|
|
29199
|
+
id: "chrtland-contour",
|
|
29200
|
+
type: "line",
|
|
29201
|
+
source: src,
|
|
29202
|
+
"source-layer": "land_contour",
|
|
29203
|
+
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
29204
|
+
paint: {
|
|
29205
|
+
"line-color": ["case", isIndexContour, T.contourIndex, T.contour],
|
|
29206
|
+
"line-width": ["case", isIndexContour, 0.8, 0.4],
|
|
29207
|
+
"line-opacity": 0.7
|
|
29208
|
+
}
|
|
29209
|
+
}));
|
|
29210
|
+
layers.push(L({
|
|
29211
|
+
id: "chrtland-water",
|
|
29212
|
+
type: "fill",
|
|
29213
|
+
source: src,
|
|
29214
|
+
"source-layer": "land_water",
|
|
29215
|
+
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
29216
|
+
paint: { "fill-color": inlandWaterColor(palette) }
|
|
29217
|
+
}));
|
|
29218
|
+
const d = FADE_PX / 2 / FADE_BANDS;
|
|
29219
|
+
for (let k = 0; k < FADE_BANDS; k++) {
|
|
29220
|
+
const width = k === 0 ? { "line-width": 2 * d } : { "line-width": d, "line-gap-width": 2 * k * d };
|
|
29221
|
+
layers.push(L({
|
|
29222
|
+
id: `chrtland-fade-${k}`,
|
|
29223
|
+
type: "line",
|
|
29224
|
+
source: src,
|
|
29225
|
+
"source-layer": "land_edge",
|
|
29226
|
+
layout: { "line-join": "bevel" },
|
|
29227
|
+
paint: { "line-color": T.fade, "line-blur": 0, "line-opacity": fadeAlpha(k * d + d / 2), ...width }
|
|
29228
|
+
}));
|
|
29229
|
+
}
|
|
29230
|
+
layers.push(L({
|
|
29231
|
+
id: "chrtland-road",
|
|
29232
|
+
type: "line",
|
|
29233
|
+
source: src,
|
|
29234
|
+
"source-layer": "land_road",
|
|
29235
|
+
minzoom: 10,
|
|
29236
|
+
paint: {
|
|
29237
|
+
"line-color": ["match", ["get", "kind"], "highway", T.roadMajor, T.road],
|
|
29238
|
+
"line-width": [
|
|
29239
|
+
"interpolate",
|
|
29240
|
+
["linear"],
|
|
29241
|
+
["zoom"],
|
|
29242
|
+
10,
|
|
29243
|
+
["match", ["get", "kind"], "highway", 0.8, 0.4],
|
|
29244
|
+
14,
|
|
29245
|
+
["match", ["get", "kind"], "highway", 2.4, 1.2]
|
|
29246
|
+
],
|
|
29247
|
+
"line-opacity": 0.8
|
|
29248
|
+
}
|
|
29249
|
+
}));
|
|
29250
|
+
layers.push(L({
|
|
29251
|
+
id: "chrtland-city-major",
|
|
29252
|
+
type: "symbol",
|
|
29253
|
+
source: src,
|
|
29254
|
+
"source-layer": "land_town",
|
|
29255
|
+
minzoom: 6.5,
|
|
29256
|
+
filter: [">=", ["coalesce", ["get", "prank"], 0], 10],
|
|
29257
|
+
layout: {
|
|
29258
|
+
"text-field": [
|
|
29259
|
+
"case",
|
|
29260
|
+
["==", ["get", "upcase"], true],
|
|
29261
|
+
["upcase", ["get", "name"]],
|
|
29262
|
+
["get", "name"]
|
|
29263
|
+
],
|
|
29264
|
+
"text-font": FONT,
|
|
29265
|
+
"text-size": [
|
|
29266
|
+
"interpolate",
|
|
29267
|
+
["linear"],
|
|
29268
|
+
["zoom"],
|
|
29269
|
+
6.5,
|
|
29270
|
+
11.5,
|
|
29271
|
+
9,
|
|
29272
|
+
["+", 10, ["*", 0.4, ["coalesce", ["get", "prank"], 10]]],
|
|
29273
|
+
13,
|
|
29274
|
+
["+", 13, ["*", 0.5, ["coalesce", ["get", "prank"], 10]]]
|
|
29275
|
+
],
|
|
29276
|
+
"text-letter-spacing": ["case", ["==", ["get", "upcase"], true], 0.14, 0.02],
|
|
29277
|
+
"text-offset": anchorOffset(0.75),
|
|
29278
|
+
"text-anchor": ANCHOR,
|
|
29279
|
+
"text-padding": 10,
|
|
29280
|
+
"text-allow-overlap": false,
|
|
29281
|
+
"symbol-sort-key": ["*", -1, ["coalesce", ["get", "pop"], 0]]
|
|
29282
|
+
},
|
|
29283
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.6 }
|
|
29284
|
+
}));
|
|
29285
|
+
layers.push(L({
|
|
29286
|
+
id: "chrtland-town-port",
|
|
29287
|
+
type: "symbol",
|
|
29288
|
+
source: src,
|
|
29289
|
+
"source-layer": "land_town",
|
|
29290
|
+
minzoom: 8.5,
|
|
29291
|
+
filter: [
|
|
29292
|
+
"all",
|
|
29293
|
+
["==", ["get", "enc_dup"], true],
|
|
29294
|
+
["<", ["coalesce", ["get", "prank"], 0], 10]
|
|
29295
|
+
],
|
|
29296
|
+
layout: {
|
|
29297
|
+
"text-field": ["get", "name"],
|
|
29298
|
+
"text-font": FONT,
|
|
29299
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 8.5, 11, 12, 13.5],
|
|
29300
|
+
"text-offset": anchorOffset(0.75),
|
|
29301
|
+
"text-anchor": ANCHOR,
|
|
29302
|
+
"text-padding": 8,
|
|
29303
|
+
"text-allow-overlap": false,
|
|
29304
|
+
// Within the tier, the bigger place wins the space: without this the
|
|
29305
|
+
// tie broke on data order and "West Gloucester" beat Gloucester.
|
|
29306
|
+
"symbol-sort-key": ["*", -1, ["coalesce", ["get", "pop"], 0]]
|
|
29307
|
+
},
|
|
29308
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.4 }
|
|
29309
|
+
}));
|
|
29310
|
+
layers.push(L({
|
|
29311
|
+
id: "chrtland-town",
|
|
29312
|
+
type: "symbol",
|
|
29313
|
+
source: src,
|
|
29314
|
+
"source-layer": "land_town",
|
|
29315
|
+
minzoom: 9,
|
|
29316
|
+
filter: [
|
|
29317
|
+
"all",
|
|
29318
|
+
FITS,
|
|
29319
|
+
["<", ["coalesce", ["get", "prank"], 0], 10],
|
|
29320
|
+
["!=", ["get", "enc_dup"], true]
|
|
29321
|
+
],
|
|
29322
|
+
layout: {
|
|
29323
|
+
"text-field": [
|
|
29324
|
+
"case",
|
|
29325
|
+
["==", ["get", "upcase"], true],
|
|
29326
|
+
["upcase", ["get", "name"]],
|
|
29327
|
+
["get", "name"]
|
|
29328
|
+
],
|
|
29329
|
+
"text-font": FONT,
|
|
29330
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 9, 10, 14, 13.5],
|
|
29331
|
+
"text-letter-spacing": ["case", ["==", ["get", "upcase"], true], 0.14, 0],
|
|
29332
|
+
"text-offset": anchorOffset(0.75),
|
|
29333
|
+
"text-anchor": ANCHOR,
|
|
29334
|
+
"text-padding": 6,
|
|
29335
|
+
"text-allow-overlap": false,
|
|
29336
|
+
"symbol-sort-key": 2
|
|
29337
|
+
},
|
|
29338
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29339
|
+
}));
|
|
29340
|
+
layers.push(L({
|
|
29341
|
+
id: "chrtland-summit",
|
|
29342
|
+
type: "symbol",
|
|
29343
|
+
source: src,
|
|
29344
|
+
"source-layer": "land_summit",
|
|
29345
|
+
minzoom: 11.5,
|
|
29346
|
+
filter: ["all", FITS, [">=", ["get", "peak_m"], 40]],
|
|
29347
|
+
layout: {
|
|
29348
|
+
"text-field": ["concat", ["get", "name"], "\n", ["to-string", ["get", "peak_m"]], " m"],
|
|
29349
|
+
"text-font": FONT,
|
|
29350
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 11.5, 8.5, 14, 11],
|
|
29351
|
+
"text-offset": anchorOffset(0.8),
|
|
29352
|
+
"text-anchor": ANCHOR,
|
|
29353
|
+
"text-padding": 5,
|
|
29354
|
+
"text-allow-overlap": false,
|
|
29355
|
+
"symbol-sort-key": 3
|
|
29356
|
+
},
|
|
29357
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29358
|
+
}));
|
|
29359
|
+
layers.push(L({
|
|
29360
|
+
id: "chrtland-poi",
|
|
29361
|
+
type: "symbol",
|
|
29362
|
+
source: src,
|
|
29363
|
+
"source-layer": "land_poi",
|
|
29364
|
+
minzoom: 13,
|
|
29365
|
+
filter: FITS,
|
|
29366
|
+
layout: {
|
|
29367
|
+
"text-field": ["get", "name"],
|
|
29368
|
+
"text-font": FONT_ITALIC,
|
|
29369
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 13, 8, 14, 9.5],
|
|
29370
|
+
"text-offset": anchorOffset(0.7),
|
|
29371
|
+
"text-anchor": ANCHOR,
|
|
29372
|
+
"text-padding": 5,
|
|
29373
|
+
"text-allow-overlap": false,
|
|
29374
|
+
"symbol-sort-key": 5
|
|
29375
|
+
},
|
|
29376
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29377
|
+
}));
|
|
29378
|
+
for (const layer of layers) {
|
|
29379
|
+
const l = layer;
|
|
29380
|
+
if (!LAND_SURFACE_LAYERS(l.id)) continue;
|
|
29381
|
+
l.minzoom = Math.max(l.minzoom ?? 0, LAND_SURFACE_MINZOOM);
|
|
29382
|
+
}
|
|
29383
|
+
return layers;
|
|
29372
29384
|
}
|
|
29373
29385
|
|
|
29374
29386
|
// src/atlas/band-collapse.ts
|
|
@@ -30071,21 +30083,37 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
30071
30083
|
];
|
|
30072
30084
|
}
|
|
30073
30085
|
{
|
|
30074
|
-
const
|
|
30075
|
-
|
|
30076
|
-
|
|
30086
|
+
const assembled = [
|
|
30087
|
+
restFinal[0],
|
|
30088
|
+
...baseBlock,
|
|
30089
|
+
...seaare,
|
|
30090
|
+
...ordered,
|
|
30091
|
+
...restFinal.slice(1)
|
|
30092
|
+
];
|
|
30093
|
+
const idOf = (l) => l.id;
|
|
30094
|
+
const isRepaint = (l) => /-overpair(-|$)/.test(idOf(l));
|
|
30077
30095
|
let lastRepaint = -1;
|
|
30078
|
-
|
|
30079
|
-
if (
|
|
30096
|
+
assembled.forEach((l, i) => {
|
|
30097
|
+
if (isRepaint(l)) lastRepaint = i;
|
|
30080
30098
|
});
|
|
30081
|
-
if (
|
|
30082
|
-
|
|
30083
|
-
|
|
30084
|
-
|
|
30085
|
-
|
|
30086
|
-
|
|
30099
|
+
if (lastRepaint === -1) return assembled;
|
|
30100
|
+
const surface = [];
|
|
30101
|
+
const kept = [];
|
|
30102
|
+
assembled.forEach((l, i) => {
|
|
30103
|
+
if (i < lastRepaint && isLandGroundOverlay(idOf(l))) surface.push(l);
|
|
30104
|
+
else kept.push(l);
|
|
30105
|
+
});
|
|
30106
|
+
if (surface.length === 0) return assembled;
|
|
30107
|
+
let landing = -1;
|
|
30108
|
+
kept.forEach((l, i) => {
|
|
30109
|
+
if (isRepaint(l)) landing = i;
|
|
30110
|
+
});
|
|
30111
|
+
return [
|
|
30112
|
+
...kept.slice(0, landing + 1),
|
|
30113
|
+
...surface,
|
|
30114
|
+
...kept.slice(landing + 1)
|
|
30115
|
+
];
|
|
30087
30116
|
}
|
|
30088
|
-
return [restFinal[0], ...baseBlock, ...seaare, ...ordered, ...restFinal.slice(1)];
|
|
30089
30117
|
})() : layers;
|
|
30090
30118
|
for (const id of [
|
|
30091
30119
|
"chrtbase-country-boundary",
|