@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.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: "#E8D9B0",
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: "#C4B389",
28653
+ stateLine: "#B1A077",
28970
28654
  stateLabel: "#8E8468",
28971
- stateHalo: "#E8D9B0",
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
- "text-color": T.inlandLabel,
29367
- "text-halo-color": T.inlandHalo,
29368
- "text-halo-width": 1.1
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 hsAt = restFinal.findIndex(
30075
- (l) => l.type === "hillshade"
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
- restFinal.forEach((l, i) => {
30079
- if (/-overpair(-|$)/.test(l.id)) lastRepaint = i;
30096
+ assembled.forEach((l, i) => {
30097
+ if (isRepaint(l)) lastRepaint = i;
30080
30098
  });
30081
- if (hsAt !== -1 && lastRepaint > hsAt) {
30082
- const reordered = [...restFinal];
30083
- const [hs] = reordered.splice(hsAt, 1);
30084
- reordered.splice(lastRepaint, 0, hs);
30085
- restFinal = reordered;
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",