@unmap/themes 0.1.3 → 0.3.0

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
@@ -23,6 +23,22 @@ var ink = {
23
23
  950: "#0E191C",
24
24
  1e3: "#030E10"
25
25
  };
26
+ var paper = {
27
+ 25: "#FBF5F2",
28
+ 50: "#F5EFEC",
29
+ 100: "#ECE6E3",
30
+ 200: "#E1DBD8",
31
+ 300: "#D4CECB",
32
+ 400: "#C3BDBA",
33
+ 500: "#A9A3A0",
34
+ 600: "#8A8582",
35
+ 700: "#696361",
36
+ 800: "#4A4543",
37
+ 850: "#373330",
38
+ 900: "#272220",
39
+ 950: "#1A1614",
40
+ 1e3: "#0E0B09"
41
+ };
26
42
  var wave = {
27
43
  100: "#C7F1F3",
28
44
  200: "#B3E2E4",
@@ -36,6 +52,19 @@ var wave = {
36
52
  950: "#001C1E",
37
53
  980: "#001012"
38
54
  };
55
+ var sky = {
56
+ 100: "#CCEEFF",
57
+ 200: "#A7E2FF",
58
+ 300: "#8ACFF0",
59
+ 400: "#73B7D7",
60
+ 500: "#5A9CBC",
61
+ 600: "#387D9C",
62
+ 700: "#155F7C",
63
+ 800: "#004057",
64
+ 900: "#002837",
65
+ 950: "#001B27",
66
+ 980: "#000F17"
67
+ };
39
68
  var verdant = {
40
69
  100: "#D3F1DA",
41
70
  200: "#C3E3CA",
@@ -68,9 +97,117 @@ var graphite = {
68
97
  900: "#232323",
69
98
  1e3: "#0B0B0B"
70
99
  };
100
+ var mist = {
101
+ 100: "#E7E7E7",
102
+ 200: "#D7D7D7",
103
+ 300: "#C4C4C4",
104
+ 400: "#ACACAC",
105
+ 500: "#929292",
106
+ 600: "#757575",
107
+ 700: "#575757",
108
+ 800: "#3A3A3A",
109
+ 900: "#242424",
110
+ 950: "#171717",
111
+ 980: "#0D0D0D"
112
+ };
113
+ var jade = {
114
+ 25: "#F1F9F4",
115
+ 50: "#E6F4ED",
116
+ 100: "#D7EEE2",
117
+ 200: "#C3E6D4",
118
+ 300: "#ACDDC4",
119
+ 400: "#8BCFAF",
120
+ 500: "#56BB90",
121
+ 600: "#459975",
122
+ 700: "#327357",
123
+ 800: "#21513D",
124
+ 850: "#173C2C",
125
+ 900: "#0E2A1E",
126
+ 950: "#071C13",
127
+ 1e3: "#030F09"
128
+ };
129
+ var cobalt = {
130
+ 25: "#F4F7FB",
131
+ 50: "#ECF0F9",
132
+ 100: "#E1E8F7",
133
+ 200: "#D2DCF5",
134
+ 300: "#C0CFF3",
135
+ 400: "#A8BDF1",
136
+ 500: "#84A2EE",
137
+ 600: "#587EEA",
138
+ 700: "#2C4EE5",
139
+ 800: "#243D93",
140
+ 850: "#1D2F65",
141
+ 900: "#162241",
142
+ 950: "#0F1629",
143
+ 1e3: "#080B15"
144
+ };
145
+ var rose = {
146
+ 25: "#FFF3F3",
147
+ 50: "#FFEBEA",
148
+ 100: "#FFDFDE",
149
+ 200: "#FECFCE",
150
+ 300: "#FCBDBC",
151
+ 400: "#F8A4A4",
152
+ 500: "#E48687",
153
+ 600: "#BA6D6D",
154
+ 700: "#8D5151",
155
+ 800: "#643838",
156
+ 850: "#4B2929",
157
+ 900: "#351B1B",
158
+ 950: "#241111",
159
+ 1e3: "#150808"
160
+ };
161
+ var lilac = {
162
+ 25: "#F8F5FF",
163
+ 50: "#F2EDFF",
164
+ 100: "#EAE4F9",
165
+ 200: "#DFD8EE",
166
+ 300: "#D2CBE1",
167
+ 400: "#C1BACF",
168
+ 500: "#A7A1B5",
169
+ 600: "#888296",
170
+ 700: "#676174",
171
+ 800: "#4A415A",
172
+ 850: "#382E4A",
173
+ 900: "#281C3C",
174
+ 950: "#1C0E30",
175
+ 1e3: "#110225"
176
+ };
177
+ var aqua = {
178
+ 100: "#C7F1F5",
179
+ 200: "#ACE3E9",
180
+ 300: "#89D2DB",
181
+ 400: "#57BEC9",
182
+ 500: "#00A6B3",
183
+ 600: "#00858F",
184
+ 700: "#00636B",
185
+ 800: "#004349",
186
+ 900: "#05292D",
187
+ 950: "#081B1D",
188
+ 980: "#060E0F"
189
+ };
71
190
 
72
191
  // src/recipe.ts
73
- var THEME_BASES = ["base", "muted", "relief", "street", "outdoor"];
192
+ var THEME_BASES = [
193
+ "base",
194
+ "muted",
195
+ "outdoor",
196
+ "decimal",
197
+ "blueprint",
198
+ "blush",
199
+ "orchid",
200
+ "canopy",
201
+ "lagoon"
202
+ ];
203
+ var RETIRED_BASES = {
204
+ relief: "outdoor",
205
+ street: "base"
206
+ };
207
+ function normalizeThemeBase(base) {
208
+ if (THEME_BASES.includes(base)) return base;
209
+ return RETIRED_BASES[base] ?? null;
210
+ }
74
211
  var MODES = ["light", "dark"];
75
212
  function makeFlavor(r) {
76
213
  return {
@@ -158,12 +295,27 @@ function makeFlavor(r) {
158
295
  }
159
296
 
160
297
  // src/recipes.ts
161
- var STOCK_RAMPS = { ink, wave, verdant, sandstone, graphite, ember };
298
+ var STOCK_RAMPS = {
299
+ ink,
300
+ paper,
301
+ wave,
302
+ sky,
303
+ verdant,
304
+ sandstone,
305
+ graphite,
306
+ mist,
307
+ jade,
308
+ cobalt,
309
+ rose,
310
+ lilac,
311
+ aqua,
312
+ ember
313
+ };
162
314
  function buildRecipes(r) {
163
315
  const BASE_LIGHT = {
164
- background: r.ink[200],
165
- earth: r.ink[100],
166
- water: r.wave[300],
316
+ background: r.paper[100],
317
+ earth: r.paper[25],
318
+ water: r.sky[200],
167
319
  parkA: r.verdant[200],
168
320
  parkB: r.verdant[300],
169
321
  woodA: r.verdant[200],
@@ -172,47 +324,47 @@ function buildRecipes(r) {
172
324
  scrubB: r.verdant[300],
173
325
  sand: r.sandstone[200],
174
326
  beach: r.sandstone[200],
175
- glacier: r.ink[25],
176
- institutional: r.ink[50],
177
- pedestrian: r.ink[50],
178
- aerodrome: r.ink[50],
179
- runway: r.ink[200],
180
- pier: r.ink[300],
181
- buildings: r.ink[300],
182
- railway: r.ink[500],
183
- boundaries: r.ink[600],
327
+ glacier: r.paper[25],
328
+ institutional: r.paper[100],
329
+ pedestrian: r.paper[100],
330
+ aerodrome: r.cobalt[200],
331
+ runway: r.cobalt[300],
332
+ pier: r.paper[300],
333
+ buildings: r.paper[200],
334
+ railway: r.graphite[400],
335
+ boundaries: r.cobalt[600],
184
336
  roads: {
185
- other: r.ink[50],
186
- otherCasing: r.ink[300],
187
- minor: r.ink[25],
188
- minorCasing: r.ink[300],
189
- service: r.ink[50],
190
- serviceCasing: r.ink[300],
337
+ other: r.paper[100],
338
+ otherCasing: r.graphite[200],
339
+ minor: "#FFFFFF",
340
+ minorCasing: r.graphite[200],
341
+ service: r.paper[100],
342
+ serviceCasing: r.graphite[200],
191
343
  major: "#FFFFFF",
192
- majorCasing: r.ink[400],
193
- highway: "#FFFFFF",
194
- highwayCasing: r.ink[500],
195
- link: "#FFFFFF",
196
- linkCasing: r.ink[400]
344
+ majorCasing: r.graphite[300],
345
+ highway: r.ember[400],
346
+ highwayCasing: r.ember[600],
347
+ link: r.ember[300],
348
+ linkCasing: r.ember[500]
197
349
  },
198
- tunnelFill: r.ink[200],
199
- tunnelCasing: r.ink[300],
200
- bridgeCasing: r.ink[500],
350
+ tunnelFill: r.paper[200],
351
+ tunnelCasing: r.graphite[200],
352
+ bridgeCasing: r.graphite[400],
201
353
  labels: {
202
- city: r.ink[1e3],
203
- cityHalo: r.ink[25],
204
- state: r.ink[700],
205
- stateHalo: r.ink[25],
206
- country: r.ink[700],
207
- subplace: r.ink[700],
208
- subplaceHalo: r.ink[25],
209
- address: r.ink[700],
210
- addressHalo: r.ink[25],
211
- roadMinor: r.ink[700],
212
- roadMinorHalo: r.ink[25],
213
- roadMajor: r.ink[800],
214
- roadMajorHalo: r.ink[25],
215
- ocean: r.wave[800]
354
+ city: r.paper[1e3],
355
+ cityHalo: r.paper[25],
356
+ state: r.paper[700],
357
+ stateHalo: r.paper[25],
358
+ country: r.paper[700],
359
+ subplace: r.paper[700],
360
+ subplaceHalo: r.paper[25],
361
+ address: r.paper[700],
362
+ addressHalo: r.paper[25],
363
+ roadMinor: r.paper[800],
364
+ roadMinorHalo: r.paper[25],
365
+ roadMajor: r.paper[900],
366
+ roadMajorHalo: r.paper[25],
367
+ ocean: r.sky[800]
216
368
  },
217
369
  pois: {
218
370
  blue: "#2D6E8F",
@@ -220,73 +372,73 @@ function buildRecipes(r) {
220
372
  lapis: "#3F5C93",
221
373
  pink: "#8F4A6B",
222
374
  red: "#9B4340",
223
- slategray: r.ink[700],
375
+ slategray: r.paper[700],
224
376
  tangerine: "#8F5322",
225
- turquoise: r.wave[700]
377
+ turquoise: r.sky[700]
226
378
  },
227
379
  landcover: {
228
380
  grassland: r.verdant[200],
229
381
  barren: r.sandstone[200],
230
- urban_area: r.ink[50],
382
+ urban_area: r.paper[50],
231
383
  farmland: r.verdant[100],
232
- glacier: r.ink[25],
233
- scrub: r.verdant[100],
384
+ glacier: r.paper[25],
385
+ scrub: r.verdant[200],
234
386
  forest: r.verdant[300]
235
387
  }
236
388
  };
237
389
  const BASE_DARK = {
238
- background: r.ink[950],
239
- earth: r.ink[900],
240
- water: r.wave[980],
390
+ background: r.paper[950],
391
+ earth: r.paper[900],
392
+ water: r.sky[980],
241
393
  parkA: r.verdant[800],
242
394
  parkB: r.verdant[700],
243
395
  woodA: r.verdant[800],
244
396
  woodB: r.verdant[700],
245
- scrubA: r.verdant[800],
246
- scrubB: r.verdant[700],
397
+ scrubA: r.verdant[900],
398
+ scrubB: r.verdant[800],
247
399
  sand: r.sandstone[500],
248
400
  beach: r.sandstone[500],
249
- glacier: r.ink[700],
250
- institutional: r.ink[950],
251
- pedestrian: r.ink[950],
252
- aerodrome: r.ink[950],
253
- runway: r.ink[850],
254
- pier: r.ink[850],
255
- buildings: r.ink[850],
256
- railway: r.ink[700],
257
- boundaries: r.ink[600],
401
+ glacier: r.paper[700],
402
+ institutional: r.paper[950],
403
+ pedestrian: r.paper[950],
404
+ aerodrome: r.cobalt[900],
405
+ runway: r.cobalt[850],
406
+ pier: r.paper[850],
407
+ buildings: r.paper[850],
408
+ railway: r.paper[700],
409
+ boundaries: r.cobalt[500],
258
410
  roads: {
259
- other: r.ink[850],
260
- otherCasing: r.ink[1e3],
261
- minor: r.ink[800],
262
- minorCasing: r.ink[1e3],
263
- service: r.ink[850],
264
- serviceCasing: r.ink[1e3],
265
- major: r.ink[700],
266
- majorCasing: r.ink[1e3],
267
- highway: r.ink[600],
268
- highwayCasing: r.ink[1e3],
269
- link: r.ink[700],
270
- linkCasing: r.ink[1e3]
411
+ other: r.paper[850],
412
+ otherCasing: r.paper[1e3],
413
+ minor: r.paper[800],
414
+ minorCasing: r.paper[1e3],
415
+ service: r.paper[850],
416
+ serviceCasing: r.paper[1e3],
417
+ major: r.paper[700],
418
+ majorCasing: r.paper[1e3],
419
+ highway: r.ember[600],
420
+ highwayCasing: r.paper[1e3],
421
+ link: r.ember[700],
422
+ linkCasing: r.paper[1e3]
271
423
  },
272
- tunnelFill: r.ink[900],
273
- tunnelCasing: r.ink[1e3],
274
- bridgeCasing: r.ink[1e3],
424
+ tunnelFill: r.paper[900],
425
+ tunnelCasing: r.paper[1e3],
426
+ bridgeCasing: r.paper[1e3],
275
427
  labels: {
276
- city: r.ink[100],
277
- cityHalo: r.ink[1e3],
278
- state: r.ink[500],
279
- stateHalo: r.ink[1e3],
280
- country: r.ink[500],
281
- subplace: r.ink[500],
282
- subplaceHalo: r.ink[1e3],
283
- address: r.ink[500],
284
- addressHalo: r.ink[1e3],
285
- roadMinor: r.ink[500],
286
- roadMinorHalo: r.ink[1e3],
287
- roadMajor: r.ink[400],
288
- roadMajorHalo: r.ink[1e3],
289
- ocean: r.wave[400]
428
+ city: r.paper[100],
429
+ cityHalo: r.paper[1e3],
430
+ state: r.paper[500],
431
+ stateHalo: r.paper[1e3],
432
+ country: r.paper[500],
433
+ subplace: r.paper[500],
434
+ subplaceHalo: r.paper[1e3],
435
+ address: r.paper[500],
436
+ addressHalo: r.paper[1e3],
437
+ roadMinor: r.paper[500],
438
+ roadMinorHalo: r.paper[1e3],
439
+ roadMajor: r.paper[400],
440
+ roadMajorHalo: r.paper[1e3],
441
+ ocean: r.sky[400]
290
442
  },
291
443
  pois: {
292
444
  blue: "#7FC4E8",
@@ -294,35 +446,35 @@ function buildRecipes(r) {
294
446
  lapis: "#8FB0EA",
295
447
  pink: "#E3A0C0",
296
448
  red: "#EE968F",
297
- slategray: r.ink[500],
449
+ slategray: r.paper[500],
298
450
  tangerine: "#E8AC7C",
299
- turquoise: r.wave[400]
451
+ turquoise: r.sky[400]
300
452
  },
301
453
  landcover: {
302
454
  grassland: r.verdant[800],
303
455
  barren: r.sandstone[500],
304
- urban_area: r.ink[950],
456
+ urban_area: r.paper[950],
305
457
  farmland: r.verdant[900],
306
- glacier: r.ink[700],
458
+ glacier: r.paper[700],
307
459
  scrub: r.verdant[900],
308
460
  forest: r.verdant[700]
309
461
  }
310
462
  };
311
463
  const MUTED_LIGHT = {
312
- background: r.graphite[300],
313
- earth: r.graphite[50],
314
- water: r.graphite[200],
315
- parkA: r.graphite[25],
316
- parkB: r.graphite[50],
317
- woodA: r.graphite[25],
318
- woodB: r.graphite[50],
319
- scrubA: r.graphite[25],
320
- scrubB: r.graphite[50],
464
+ background: r.graphite[100],
465
+ earth: r.graphite[25],
466
+ water: r.mist[200],
467
+ parkA: r.graphite[50],
468
+ parkB: r.graphite[100],
469
+ woodA: r.graphite[50],
470
+ woodB: r.graphite[100],
471
+ scrubA: r.graphite[50],
472
+ scrubB: r.graphite[100],
321
473
  sand: r.graphite[100],
322
474
  beach: r.graphite[100],
323
475
  glacier: r.graphite[25],
324
476
  institutional: r.graphite[100],
325
- pedestrian: r.graphite[25],
477
+ pedestrian: r.graphite[50],
326
478
  aerodrome: r.graphite[100],
327
479
  runway: r.graphite[200],
328
480
  pier: r.graphite[200],
@@ -338,14 +490,14 @@ function buildRecipes(r) {
338
490
  serviceCasing: r.graphite[200],
339
491
  major: "#FFFFFF",
340
492
  majorCasing: r.graphite[300],
341
- highway: "#FFFFFF",
493
+ highway: r.graphite[200],
342
494
  highwayCasing: r.graphite[300],
343
495
  link: "#FFFFFF",
344
496
  linkCasing: r.graphite[300]
345
497
  },
346
498
  tunnelFill: r.graphite[100],
347
499
  tunnelCasing: r.graphite[200],
348
- bridgeCasing: r.graphite[300],
500
+ bridgeCasing: r.graphite[400],
349
501
  labels: {
350
502
  city: r.graphite[1e3],
351
503
  cityHalo: r.graphite[25],
@@ -375,7 +527,7 @@ function buildRecipes(r) {
375
527
  landcover: {
376
528
  grassland: r.graphite[50],
377
529
  barren: r.graphite[100],
378
- urban_area: r.graphite[100],
530
+ urban_area: r.graphite[50],
379
531
  farmland: r.graphite[50],
380
532
  glacier: r.graphite[25],
381
533
  scrub: r.graphite[50],
@@ -385,7 +537,7 @@ function buildRecipes(r) {
385
537
  const MUTED_DARK = {
386
538
  background: r.graphite[1e3],
387
539
  earth: r.graphite[900],
388
- water: r.graphite[1e3],
540
+ water: r.mist[980],
389
541
  parkA: r.graphite[900],
390
542
  parkB: r.graphite[800],
391
543
  woodA: r.graphite[900],
@@ -456,44 +608,45 @@ function buildRecipes(r) {
456
608
  forest: r.graphite[800]
457
609
  }
458
610
  };
459
- const RELIEF_LIGHT = {
611
+ const OUTDOOR_LIGHT = {
460
612
  background: r.ink[200],
461
613
  earth: r.ink[50],
462
614
  water: r.wave[300],
463
- parkA: r.verdant[200],
464
- parkB: r.verdant[300],
465
- woodA: r.verdant[200],
466
- woodB: r.verdant[300],
615
+ parkA: r.verdant[300],
616
+ parkB: r.verdant[400],
617
+ woodA: r.verdant[300],
618
+ woodB: r.verdant[400],
467
619
  scrubA: r.verdant[200],
468
620
  scrubB: r.verdant[300],
469
- sand: r.sandstone[200],
470
- beach: r.sandstone[200],
621
+ sand: r.sandstone[300],
622
+ beach: r.sandstone[300],
471
623
  glacier: r.ink[25],
472
624
  institutional: r.ink[25],
473
625
  pedestrian: r.ink[50],
474
626
  aerodrome: r.ink[50],
475
627
  runway: r.ink[200],
476
628
  pier: r.ink[300],
477
- buildings: r.ink[300],
629
+ // A step lighter than `base`: outdoors, the building footprint is context, not content.
630
+ buildings: r.ink[200],
478
631
  railway: r.ink[500],
479
632
  boundaries: r.ink[600],
480
633
  roads: {
481
634
  other: r.ink[50],
482
- otherCasing: r.ink[300],
635
+ otherCasing: r.ink[200],
483
636
  minor: r.ink[25],
484
- minorCasing: r.ink[300],
637
+ minorCasing: r.ink[200],
485
638
  service: r.ink[50],
486
- serviceCasing: r.ink[300],
639
+ serviceCasing: r.ink[200],
487
640
  major: "#FFFFFF",
488
- majorCasing: r.ink[400],
641
+ majorCasing: r.ink[300],
489
642
  highway: "#FFFFFF",
490
- highwayCasing: r.ink[500],
643
+ highwayCasing: r.ink[400],
491
644
  link: "#FFFFFF",
492
- linkCasing: r.ink[400]
645
+ linkCasing: r.ink[300]
493
646
  },
494
647
  tunnelFill: r.ink[200],
495
648
  tunnelCasing: r.ink[300],
496
- bridgeCasing: r.ink[500],
649
+ bridgeCasing: r.ink[400],
497
650
  labels: {
498
651
  city: r.ink[1e3],
499
652
  cityHalo: r.ink[25],
@@ -512,7 +665,9 @@ function buildRecipes(r) {
512
665
  },
513
666
  pois: {
514
667
  blue: "#2D6E8F",
515
- green: r.verdant[700],
668
+ // Peaks, parks, forests and gardens all come through green. On this flavour they are the
669
+ // POIs worth finding, so it carries a full step more weight than elsewhere.
670
+ green: r.verdant[800],
516
671
  lapis: "#3F5C93",
517
672
  pink: "#8F4A6B",
518
673
  red: "#9B4340",
@@ -522,22 +677,22 @@ function buildRecipes(r) {
522
677
  },
523
678
  landcover: {
524
679
  grassland: r.verdant[200],
525
- barren: r.sandstone[200],
526
- urban_area: r.ink[50],
527
- farmland: r.verdant[100],
680
+ barren: r.sandstone[300],
681
+ urban_area: r.ink[100],
682
+ farmland: r.sandstone[200],
528
683
  glacier: r.ink[25],
529
- scrub: r.verdant[100],
530
- forest: r.verdant[300]
684
+ scrub: r.verdant[300],
685
+ forest: r.verdant[400]
531
686
  }
532
687
  };
533
- const RELIEF_DARK = {
688
+ const OUTDOOR_DARK = {
534
689
  background: r.ink[1e3],
535
690
  earth: r.ink[950],
536
691
  water: r.wave[980],
537
- parkA: r.verdant[800],
538
- parkB: r.verdant[700],
539
- woodA: r.verdant[800],
540
- woodB: r.verdant[700],
692
+ parkA: r.verdant[700],
693
+ parkB: r.verdant[600],
694
+ woodA: r.verdant[700],
695
+ woodB: r.verdant[600],
541
696
  scrubA: r.verdant[800],
542
697
  scrubB: r.verdant[700],
543
698
  sand: r.sandstone[500],
@@ -552,11 +707,13 @@ function buildRecipes(r) {
552
707
  railway: r.ink[700],
553
708
  boundaries: r.ink[600],
554
709
  roads: {
555
- other: r.ink[850],
710
+ // The minor tier recedes toward `earth`; majors and highways hold their contrast,
711
+ // because a road you cannot see is a different failure from a road that is merely quiet.
712
+ other: r.ink[900],
556
713
  otherCasing: r.ink[1e3],
557
- minor: r.ink[800],
714
+ minor: r.ink[850],
558
715
  minorCasing: r.ink[1e3],
559
- service: r.ink[850],
716
+ service: r.ink[900],
560
717
  serviceCasing: r.ink[1e3],
561
718
  major: r.ink[700],
562
719
  majorCasing: r.ink[1e3],
@@ -586,7 +743,7 @@ function buildRecipes(r) {
586
743
  },
587
744
  pois: {
588
745
  blue: "#7FC4E8",
589
- green: r.verdant[400],
746
+ green: r.verdant[300],
590
747
  lapis: "#8FB0EA",
591
748
  pink: "#E3A0C0",
592
749
  red: "#EE968F",
@@ -595,326 +752,928 @@ function buildRecipes(r) {
595
752
  turquoise: r.wave[400]
596
753
  },
597
754
  landcover: {
598
- grassland: r.verdant[800],
755
+ grassland: r.verdant[700],
599
756
  barren: r.sandstone[500],
600
757
  urban_area: r.ink[950],
601
758
  farmland: r.verdant[900],
602
759
  glacier: r.ink[700],
603
- scrub: r.verdant[900],
604
- forest: r.verdant[700]
760
+ scrub: r.verdant[800],
761
+ forest: r.verdant[600]
605
762
  }
606
763
  };
607
- const STREET_LIGHT = {
608
- background: r.ink[300],
609
- earth: r.sandstone[100],
610
- water: r.wave[400],
611
- parkA: r.verdant[200],
764
+ const DECIMAL_LIGHT = {
765
+ background: r.jade[100],
766
+ earth: r.jade[25],
767
+ water: r.jade[200],
768
+ parkA: r.jade[50],
769
+ parkB: r.jade[100],
770
+ woodA: r.jade[50],
771
+ woodB: r.jade[100],
772
+ scrubA: r.jade[50],
773
+ scrubB: r.jade[100],
774
+ sand: r.jade[50],
775
+ beach: r.jade[50],
776
+ glacier: r.jade[25],
777
+ institutional: r.jade[50],
778
+ pedestrian: r.jade[50],
779
+ aerodrome: r.jade[50],
780
+ runway: r.jade[200],
781
+ pier: r.jade[200],
782
+ buildings: r.jade[100],
783
+ railway: r.jade[500],
784
+ boundaries: r.jade[600],
785
+ roads: {
786
+ other: r.jade[200],
787
+ otherCasing: r.jade[25],
788
+ minor: r.jade[300],
789
+ minorCasing: r.jade[25],
790
+ service: r.jade[200],
791
+ serviceCasing: r.jade[25],
792
+ major: r.jade[400],
793
+ majorCasing: r.jade[25],
794
+ highway: r.jade[500],
795
+ highwayCasing: r.jade[25],
796
+ link: r.jade[400],
797
+ linkCasing: r.jade[25]
798
+ },
799
+ tunnelFill: r.jade[100],
800
+ tunnelCasing: r.jade[200],
801
+ bridgeCasing: r.jade[600],
802
+ labels: {
803
+ city: r.jade[1e3],
804
+ cityHalo: r.jade[25],
805
+ state: r.jade[700],
806
+ stateHalo: r.jade[25],
807
+ country: r.jade[700],
808
+ subplace: r.jade[700],
809
+ subplaceHalo: r.jade[25],
810
+ address: r.jade[700],
811
+ addressHalo: r.jade[25],
812
+ roadMinor: r.jade[700],
813
+ roadMinorHalo: r.jade[25],
814
+ roadMajor: r.jade[800],
815
+ roadMajorHalo: r.jade[25],
816
+ ocean: r.jade[800]
817
+ },
818
+ pois: {
819
+ blue: r.jade[700],
820
+ green: r.jade[700],
821
+ lapis: r.jade[700],
822
+ pink: r.jade[700],
823
+ red: r.jade[700],
824
+ slategray: r.jade[700],
825
+ tangerine: r.jade[700],
826
+ turquoise: r.jade[700]
827
+ },
828
+ landcover: {
829
+ grassland: r.jade[50],
830
+ barren: r.jade[50],
831
+ urban_area: r.jade[50],
832
+ farmland: r.jade[50],
833
+ glacier: r.jade[25],
834
+ scrub: r.jade[50],
835
+ forest: r.jade[100]
836
+ }
837
+ };
838
+ const DECIMAL_DARK = {
839
+ background: r.jade[1e3],
840
+ earth: r.jade[1e3],
841
+ water: r.jade[900],
842
+ parkA: r.jade[950],
843
+ parkB: r.jade[900],
844
+ woodA: r.jade[950],
845
+ woodB: r.jade[900],
846
+ scrubA: r.jade[950],
847
+ scrubB: r.jade[900],
848
+ sand: r.jade[950],
849
+ beach: r.jade[950],
850
+ glacier: r.jade[900],
851
+ institutional: r.jade[950],
852
+ pedestrian: r.jade[950],
853
+ aerodrome: r.jade[950],
854
+ runway: r.jade[850],
855
+ pier: r.jade[850],
856
+ buildings: r.jade[900],
857
+ railway: r.jade[800],
858
+ boundaries: r.jade[700],
859
+ roads: {
860
+ other: r.jade[850],
861
+ otherCasing: r.jade[1e3],
862
+ minor: r.jade[800],
863
+ minorCasing: r.jade[1e3],
864
+ service: r.jade[850],
865
+ serviceCasing: r.jade[1e3],
866
+ major: r.jade[700],
867
+ majorCasing: r.jade[1e3],
868
+ highway: r.jade[600],
869
+ highwayCasing: r.jade[1e3],
870
+ link: r.jade[700],
871
+ linkCasing: r.jade[1e3]
872
+ },
873
+ tunnelFill: r.jade[900],
874
+ tunnelCasing: r.jade[1e3],
875
+ bridgeCasing: r.jade[1e3],
876
+ labels: {
877
+ city: r.jade[500],
878
+ cityHalo: r.jade[1e3],
879
+ state: r.jade[600],
880
+ stateHalo: r.jade[1e3],
881
+ country: r.jade[600],
882
+ subplace: r.jade[600],
883
+ subplaceHalo: r.jade[1e3],
884
+ address: r.jade[600],
885
+ addressHalo: r.jade[1e3],
886
+ roadMinor: r.jade[600],
887
+ roadMinorHalo: r.jade[1e3],
888
+ roadMajor: r.jade[500],
889
+ roadMajorHalo: r.jade[1e3],
890
+ ocean: r.jade[500]
891
+ },
892
+ pois: {
893
+ blue: r.jade[600],
894
+ green: r.jade[600],
895
+ lapis: r.jade[600],
896
+ pink: r.jade[600],
897
+ red: r.jade[600],
898
+ slategray: r.jade[600],
899
+ tangerine: r.jade[600],
900
+ turquoise: r.jade[600]
901
+ },
902
+ landcover: {
903
+ grassland: r.jade[950],
904
+ barren: r.jade[950],
905
+ urban_area: r.jade[950],
906
+ farmland: r.jade[950],
907
+ glacier: r.jade[900],
908
+ scrub: r.jade[950],
909
+ forest: r.jade[900]
910
+ }
911
+ };
912
+ const BLUEPRINT_LIGHT = {
913
+ background: r.cobalt[100],
914
+ earth: r.cobalt[25],
915
+ water: r.cobalt[200],
916
+ parkA: r.cobalt[50],
917
+ parkB: r.cobalt[100],
918
+ woodA: r.cobalt[50],
919
+ woodB: r.cobalt[100],
920
+ scrubA: r.cobalt[50],
921
+ scrubB: r.cobalt[100],
922
+ sand: r.cobalt[50],
923
+ beach: r.cobalt[50],
924
+ glacier: r.cobalt[25],
925
+ institutional: r.cobalt[50],
926
+ pedestrian: r.cobalt[50],
927
+ aerodrome: r.cobalt[50],
928
+ runway: r.cobalt[200],
929
+ pier: r.cobalt[200],
930
+ buildings: r.cobalt[100],
931
+ railway: r.cobalt[500],
932
+ boundaries: r.cobalt[600],
933
+ roads: {
934
+ other: r.cobalt[200],
935
+ otherCasing: r.cobalt[25],
936
+ minor: r.cobalt[300],
937
+ minorCasing: r.cobalt[25],
938
+ service: r.cobalt[200],
939
+ serviceCasing: r.cobalt[25],
940
+ major: r.cobalt[400],
941
+ majorCasing: r.cobalt[25],
942
+ highway: r.cobalt[500],
943
+ highwayCasing: r.cobalt[25],
944
+ link: r.cobalt[400],
945
+ linkCasing: r.cobalt[25]
946
+ },
947
+ tunnelFill: r.cobalt[100],
948
+ tunnelCasing: r.cobalt[200],
949
+ bridgeCasing: r.cobalt[600],
950
+ labels: {
951
+ city: r.cobalt[1e3],
952
+ cityHalo: r.cobalt[25],
953
+ state: r.cobalt[700],
954
+ stateHalo: r.cobalt[25],
955
+ country: r.cobalt[700],
956
+ subplace: r.cobalt[700],
957
+ subplaceHalo: r.cobalt[25],
958
+ address: r.cobalt[700],
959
+ addressHalo: r.cobalt[25],
960
+ roadMinor: r.cobalt[700],
961
+ roadMinorHalo: r.cobalt[25],
962
+ roadMajor: r.cobalt[800],
963
+ roadMajorHalo: r.cobalt[25],
964
+ ocean: r.cobalt[800]
965
+ },
966
+ pois: {
967
+ blue: r.cobalt[700],
968
+ green: r.cobalt[700],
969
+ lapis: r.cobalt[700],
970
+ pink: r.cobalt[700],
971
+ red: r.cobalt[700],
972
+ slategray: r.cobalt[700],
973
+ tangerine: r.cobalt[700],
974
+ turquoise: r.cobalt[700]
975
+ },
976
+ landcover: {
977
+ grassland: r.cobalt[50],
978
+ barren: r.cobalt[50],
979
+ urban_area: r.cobalt[50],
980
+ farmland: r.cobalt[50],
981
+ glacier: r.cobalt[25],
982
+ scrub: r.cobalt[50],
983
+ forest: r.cobalt[100]
984
+ }
985
+ };
986
+ const BLUEPRINT_DARK = {
987
+ background: r.cobalt[700],
988
+ earth: r.cobalt[700],
989
+ water: r.cobalt[400],
990
+ parkA: r.cobalt[600],
991
+ parkB: r.cobalt[600],
992
+ woodA: r.cobalt[600],
993
+ woodB: r.cobalt[600],
994
+ scrubA: r.cobalt[600],
995
+ scrubB: r.cobalt[600],
996
+ sand: r.cobalt[600],
997
+ beach: r.cobalt[600],
998
+ glacier: r.cobalt[500],
999
+ institutional: r.cobalt[600],
1000
+ pedestrian: r.cobalt[700],
1001
+ aerodrome: r.cobalt[600],
1002
+ runway: r.cobalt[800],
1003
+ pier: r.cobalt[800],
1004
+ buildings: r.cobalt[600],
1005
+ railway: r.cobalt[400],
1006
+ boundaries: r.cobalt[300],
1007
+ roads: {
1008
+ other: r.cobalt[800],
1009
+ otherCasing: r.cobalt[700],
1010
+ minor: r.cobalt[850],
1011
+ minorCasing: r.cobalt[600],
1012
+ service: r.cobalt[800],
1013
+ serviceCasing: r.cobalt[700],
1014
+ major: r.cobalt[900],
1015
+ majorCasing: r.cobalt[600],
1016
+ highway: r.cobalt[950],
1017
+ highwayCasing: r.cobalt[500],
1018
+ link: r.cobalt[900],
1019
+ linkCasing: r.cobalt[600]
1020
+ },
1021
+ tunnelFill: r.cobalt[800],
1022
+ tunnelCasing: r.cobalt[700],
1023
+ bridgeCasing: r.cobalt[500],
1024
+ labels: {
1025
+ city: r.cobalt[25],
1026
+ cityHalo: r.cobalt[700],
1027
+ state: r.cobalt[200],
1028
+ stateHalo: r.cobalt[700],
1029
+ country: r.cobalt[200],
1030
+ subplace: r.cobalt[300],
1031
+ subplaceHalo: r.cobalt[700],
1032
+ address: r.cobalt[300],
1033
+ addressHalo: r.cobalt[700],
1034
+ roadMinor: r.cobalt[300],
1035
+ roadMinorHalo: r.cobalt[700],
1036
+ roadMajor: r.cobalt[100],
1037
+ roadMajorHalo: r.cobalt[700],
1038
+ ocean: r.cobalt[900]
1039
+ },
1040
+ pois: {
1041
+ blue: r.cobalt[200],
1042
+ green: r.cobalt[200],
1043
+ lapis: r.cobalt[200],
1044
+ pink: r.cobalt[200],
1045
+ red: r.cobalt[200],
1046
+ slategray: r.cobalt[200],
1047
+ tangerine: r.cobalt[200],
1048
+ turquoise: r.cobalt[200]
1049
+ },
1050
+ landcover: {
1051
+ grassland: r.cobalt[600],
1052
+ barren: r.cobalt[600],
1053
+ urban_area: r.cobalt[700],
1054
+ farmland: r.cobalt[600],
1055
+ glacier: r.cobalt[500],
1056
+ scrub: r.cobalt[600],
1057
+ forest: r.cobalt[600]
1058
+ }
1059
+ };
1060
+ const BLUSH_LIGHT = {
1061
+ background: r.ember[200],
1062
+ earth: r.rose[300],
1063
+ water: r.ember[200],
1064
+ parkA: r.verdant[300],
612
1065
  parkB: r.verdant[400],
613
- woodA: r.verdant[200],
1066
+ woodA: r.verdant[300],
614
1067
  woodB: r.verdant[400],
615
- scrubA: r.verdant[200],
616
- scrubB: r.verdant[400],
617
- sand: r.sandstone[300],
618
- beach: r.sandstone[300],
619
- glacier: r.ink[25],
620
- institutional: r.sandstone[200],
621
- pedestrian: r.ink[50],
622
- aerodrome: r.ink[50],
623
- runway: r.ink[200],
624
- pier: r.ink[300],
625
- buildings: r.ink[400],
626
- railway: r.ink[500],
627
- boundaries: r.ink[600],
1068
+ scrubA: r.sandstone[200],
1069
+ scrubB: r.sandstone[300],
1070
+ sand: r.sandstone[200],
1071
+ beach: r.sandstone[100],
1072
+ glacier: r.rose[100],
1073
+ institutional: r.rose[200],
1074
+ pedestrian: r.lilac[200],
1075
+ aerodrome: r.rose[200],
1076
+ runway: r.ember[200],
1077
+ pier: r.sandstone[300],
1078
+ buildings: r.rose[500],
1079
+ railway: r.sandstone[100],
1080
+ boundaries: r.rose[700],
628
1081
  roads: {
629
- other: r.ink[50],
630
- otherCasing: r.ink[300],
631
- minor: r.ink[25],
632
- minorCasing: r.ink[300],
633
- service: r.ink[50],
634
- serviceCasing: r.ink[300],
635
- major: "#FFFFFF",
636
- majorCasing: r.ink[400],
637
- highway: r.ember[400],
638
- highwayCasing: r.ink[500],
639
- link: "#FFFFFF",
640
- linkCasing: r.ink[400]
1082
+ other: r.ember[200],
1083
+ otherCasing: r.rose[300],
1084
+ minor: r.ember[200],
1085
+ minorCasing: r.rose[300],
1086
+ service: r.ember[200],
1087
+ serviceCasing: r.rose[300],
1088
+ major: r.ember[200],
1089
+ majorCasing: r.rose[400],
1090
+ highway: "#FFFFFF",
1091
+ highwayCasing: r.rose[400],
1092
+ link: r.ember[200],
1093
+ linkCasing: r.rose[400]
641
1094
  },
642
- tunnelFill: r.ink[200],
643
- tunnelCasing: r.ink[300],
644
- bridgeCasing: r.ink[500],
1095
+ tunnelFill: r.rose[200],
1096
+ tunnelCasing: r.rose[300],
1097
+ bridgeCasing: r.rose[500],
645
1098
  labels: {
646
- city: r.ink[1e3],
647
- cityHalo: r.ink[25],
648
- state: r.ink[700],
649
- stateHalo: r.ink[25],
650
- country: r.ink[700],
651
- subplace: r.ink[700],
652
- subplaceHalo: r.ink[25],
653
- address: r.ink[700],
654
- addressHalo: r.ink[25],
655
- roadMinor: r.ink[700],
656
- roadMinorHalo: r.ink[25],
657
- roadMajor: r.ink[800],
658
- roadMajorHalo: r.ink[25],
659
- ocean: r.wave[800]
1099
+ city: r.paper[1e3],
1100
+ cityHalo: r.rose[25],
1101
+ state: r.rose[800],
1102
+ stateHalo: r.rose[25],
1103
+ country: r.rose[800],
1104
+ subplace: r.rose[700],
1105
+ subplaceHalo: r.rose[25],
1106
+ address: r.rose[800],
1107
+ addressHalo: r.rose[25],
1108
+ roadMinor: r.rose[800],
1109
+ roadMinorHalo: r.rose[25],
1110
+ roadMajor: r.rose[850],
1111
+ roadMajorHalo: r.rose[25],
1112
+ ocean: r.ember[700]
660
1113
  },
661
1114
  pois: {
662
- blue: "#2D6E8F",
1115
+ blue: r.cobalt[700],
663
1116
  green: r.verdant[700],
664
- lapis: "#3F5C93",
665
- pink: "#8F4A6B",
666
- red: "#9B4340",
667
- slategray: r.ink[700],
668
- tangerine: "#8F5322",
669
- turquoise: r.wave[700]
1117
+ lapis: r.cobalt[700],
1118
+ pink: r.rose[700],
1119
+ red: r.rose[700],
1120
+ slategray: r.rose[700],
1121
+ tangerine: r.ember[700],
1122
+ turquoise: r.sky[700]
670
1123
  },
671
1124
  landcover: {
672
1125
  grassland: r.verdant[300],
673
- barren: r.sandstone[300],
674
- urban_area: r.ink[100],
675
- farmland: r.sandstone[200],
676
- glacier: r.ink[25],
1126
+ barren: r.sandstone[200],
1127
+ urban_area: r.rose[400],
1128
+ farmland: r.verdant[200],
1129
+ glacier: r.rose[100],
677
1130
  scrub: r.verdant[200],
678
1131
  forest: r.verdant[400]
679
1132
  }
680
1133
  };
681
- const STREET_DARK = {
682
- background: r.ink[1e3],
683
- earth: r.ink[900],
684
- water: r.wave[950],
1134
+ const BLUSH_DARK = {
1135
+ background: r.rose[1e3],
1136
+ earth: r.rose[900],
1137
+ water: r.rose[1e3],
685
1138
  parkA: r.verdant[800],
686
1139
  parkB: r.verdant[700],
687
1140
  woodA: r.verdant[800],
688
1141
  woodB: r.verdant[700],
689
- scrubA: r.verdant[800],
690
- scrubB: r.verdant[700],
1142
+ scrubA: r.verdant[900],
1143
+ scrubB: r.verdant[800],
691
1144
  sand: r.sandstone[500],
692
- beach: r.sandstone[500],
693
- glacier: r.ink[700],
694
- institutional: r.ink[850],
695
- pedestrian: r.ink[950],
696
- aerodrome: r.ink[950],
697
- runway: r.ink[850],
698
- pier: r.ink[850],
699
- buildings: r.ink[800],
700
- railway: r.ink[700],
701
- boundaries: r.ink[600],
1145
+ beach: r.sandstone[400],
1146
+ glacier: r.rose[700],
1147
+ institutional: r.rose[850],
1148
+ pedestrian: r.lilac[900],
1149
+ aerodrome: r.rose[850],
1150
+ runway: r.rose[800],
1151
+ pier: r.sandstone[500],
1152
+ buildings: r.rose[700],
1153
+ railway: r.rose[700],
1154
+ boundaries: r.rose[500],
702
1155
  roads: {
703
- other: r.ink[850],
704
- otherCasing: r.ink[1e3],
705
- minor: r.ink[800],
706
- minorCasing: r.ink[1e3],
707
- service: r.ink[850],
708
- serviceCasing: r.ink[1e3],
709
- major: r.ink[700],
710
- majorCasing: r.ink[1e3],
711
- highway: r.ember[600],
712
- highwayCasing: r.ink[1e3],
713
- link: r.ink[700],
714
- linkCasing: r.ink[1e3]
1156
+ other: r.rose[850],
1157
+ otherCasing: r.rose[1e3],
1158
+ minor: r.rose[800],
1159
+ minorCasing: r.rose[1e3],
1160
+ service: r.rose[850],
1161
+ serviceCasing: r.rose[1e3],
1162
+ major: r.rose[700],
1163
+ majorCasing: r.rose[1e3],
1164
+ highway: r.rose[600],
1165
+ highwayCasing: r.rose[1e3],
1166
+ link: r.rose[700],
1167
+ linkCasing: r.rose[1e3]
715
1168
  },
716
- tunnelFill: r.ink[900],
717
- tunnelCasing: r.ink[1e3],
718
- bridgeCasing: r.ink[1e3],
1169
+ tunnelFill: r.rose[900],
1170
+ tunnelCasing: r.rose[1e3],
1171
+ bridgeCasing: r.rose[1e3],
719
1172
  labels: {
720
- city: r.ink[100],
721
- cityHalo: r.ink[1e3],
722
- state: r.ink[500],
723
- stateHalo: r.ink[1e3],
724
- country: r.ink[500],
725
- subplace: r.ink[500],
726
- subplaceHalo: r.ink[1e3],
727
- address: r.ink[500],
728
- addressHalo: r.ink[1e3],
729
- roadMinor: r.ink[500],
730
- roadMinorHalo: r.ink[1e3],
731
- roadMajor: r.ink[400],
732
- roadMajorHalo: r.ink[1e3],
733
- ocean: r.wave[400]
1173
+ city: r.rose[100],
1174
+ cityHalo: r.rose[1e3],
1175
+ state: r.rose[500],
1176
+ stateHalo: r.rose[1e3],
1177
+ country: r.rose[500],
1178
+ subplace: r.rose[500],
1179
+ subplaceHalo: r.rose[1e3],
1180
+ address: r.rose[500],
1181
+ addressHalo: r.rose[1e3],
1182
+ roadMinor: r.rose[500],
1183
+ roadMinorHalo: r.rose[1e3],
1184
+ roadMajor: r.rose[400],
1185
+ roadMajorHalo: r.rose[1e3],
1186
+ ocean: r.ember[400]
734
1187
  },
735
1188
  pois: {
736
- blue: "#7FC4E8",
1189
+ blue: r.cobalt[400],
737
1190
  green: r.verdant[400],
738
- lapis: "#8FB0EA",
739
- pink: "#E3A0C0",
740
- red: "#EE968F",
741
- slategray: r.ink[500],
742
- tangerine: "#E8AC7C",
743
- turquoise: r.wave[400]
1191
+ lapis: r.cobalt[400],
1192
+ pink: r.rose[400],
1193
+ red: r.rose[400],
1194
+ slategray: r.rose[500],
1195
+ tangerine: r.ember[400],
1196
+ turquoise: r.sky[400]
744
1197
  },
745
1198
  landcover: {
746
- grassland: r.verdant[700],
1199
+ grassland: r.verdant[800],
747
1200
  barren: r.sandstone[500],
748
- urban_area: r.ink[850],
749
- farmland: r.verdant[800],
750
- glacier: r.ink[700],
751
- scrub: r.verdant[800],
1201
+ urban_area: r.rose[900],
1202
+ farmland: r.verdant[900],
1203
+ glacier: r.rose[700],
1204
+ scrub: r.verdant[900],
752
1205
  forest: r.verdant[700]
753
1206
  }
754
1207
  };
755
- const OUTDOOR_LIGHT = {
756
- background: r.ink[200],
757
- earth: r.ink[50],
758
- water: r.wave[300],
759
- parkA: r.verdant[300],
760
- parkB: r.verdant[400],
761
- woodA: r.verdant[300],
762
- woodB: r.verdant[400],
763
- scrubA: r.verdant[200],
764
- scrubB: r.verdant[300],
1208
+ const ORCHID_LIGHT = {
1209
+ background: r.lilac[25],
1210
+ earth: r.lilac[200],
1211
+ water: r.sky[300],
1212
+ parkA: r.aqua[300],
1213
+ parkB: r.aqua[400],
1214
+ woodA: r.jade[500],
1215
+ woodB: r.jade[600],
1216
+ scrubA: r.sandstone[300],
1217
+ scrubB: r.sandstone[400],
765
1218
  sand: r.sandstone[300],
766
- beach: r.sandstone[300],
767
- glacier: r.ink[25],
768
- institutional: r.ink[25],
769
- pedestrian: r.ink[50],
770
- aerodrome: r.ink[50],
771
- runway: r.ink[200],
772
- pier: r.ink[300],
773
- // A step lighter than `relief`: outdoors, the building footprint is context, not content.
774
- buildings: r.ink[200],
775
- railway: r.ink[500],
776
- boundaries: r.ink[600],
1219
+ beach: r.sandstone[200],
1220
+ glacier: r.lilac[100],
1221
+ institutional: r.lilac[300],
1222
+ pedestrian: r.lilac[300],
1223
+ aerodrome: r.sandstone[100],
1224
+ runway: r.lilac[25],
1225
+ pier: r.cobalt[500],
1226
+ buildings: r.lilac[300],
1227
+ railway: r.lilac[400],
1228
+ boundaries: r.cobalt[900],
777
1229
  roads: {
778
- other: r.ink[50],
779
- otherCasing: r.ink[200],
780
- minor: r.ink[25],
781
- minorCasing: r.ink[200],
782
- service: r.ink[50],
783
- serviceCasing: r.ink[200],
1230
+ other: "#FFFFFF",
1231
+ otherCasing: r.lilac[200],
1232
+ minor: "#FFFFFF",
1233
+ minorCasing: r.lilac[200],
1234
+ service: "#FFFFFF",
1235
+ serviceCasing: r.lilac[200],
784
1236
  major: "#FFFFFF",
785
- majorCasing: r.ink[300],
1237
+ majorCasing: r.lilac[300],
786
1238
  highway: "#FFFFFF",
787
- highwayCasing: r.ink[400],
1239
+ highwayCasing: r.lilac[400],
788
1240
  link: "#FFFFFF",
789
- linkCasing: r.ink[300]
1241
+ linkCasing: r.lilac[300]
790
1242
  },
791
- tunnelFill: r.ink[200],
792
- tunnelCasing: r.ink[300],
793
- bridgeCasing: r.ink[400],
1243
+ tunnelFill: r.lilac[100],
1244
+ tunnelCasing: r.lilac[200],
1245
+ bridgeCasing: r.lilac[500],
794
1246
  labels: {
795
- city: r.ink[1e3],
796
- cityHalo: r.ink[25],
797
- state: r.ink[700],
798
- stateHalo: r.ink[25],
799
- country: r.ink[700],
800
- subplace: r.ink[700],
801
- subplaceHalo: r.ink[25],
802
- address: r.ink[700],
803
- addressHalo: r.ink[25],
804
- roadMinor: r.ink[700],
805
- roadMinorHalo: r.ink[25],
806
- roadMajor: r.ink[800],
807
- roadMajorHalo: r.ink[25],
808
- ocean: r.wave[800]
1247
+ city: r.cobalt[950],
1248
+ cityHalo: r.lilac[25],
1249
+ state: r.lilac[700],
1250
+ stateHalo: r.lilac[25],
1251
+ country: r.lilac[850],
1252
+ subplace: r.lilac[700],
1253
+ subplaceHalo: r.lilac[25],
1254
+ address: r.lilac[700],
1255
+ addressHalo: r.lilac[25],
1256
+ roadMinor: r.lilac[800],
1257
+ roadMinorHalo: r.lilac[25],
1258
+ roadMajor: r.lilac[850],
1259
+ roadMajorHalo: r.lilac[25],
1260
+ ocean: r.cobalt[800]
809
1261
  },
810
1262
  pois: {
811
- blue: "#2D6E8F",
812
- // Peaks, parks, forests and gardens all come through green. On this flavour they are the
813
- // POIs worth finding, so it carries a full step more weight than elsewhere.
814
- green: r.verdant[800],
815
- lapis: "#3F5C93",
816
- pink: "#8F4A6B",
817
- red: "#9B4340",
818
- slategray: r.ink[700],
819
- tangerine: "#8F5322",
820
- turquoise: r.wave[700]
1263
+ blue: r.cobalt[700],
1264
+ green: r.jade[700],
1265
+ lapis: r.cobalt[700],
1266
+ pink: r.rose[600],
1267
+ red: r.rose[700],
1268
+ slategray: r.lilac[700],
1269
+ tangerine: r.ember[700],
1270
+ turquoise: r.aqua[700]
821
1271
  },
822
1272
  landcover: {
823
- grassland: r.verdant[200],
1273
+ grassland: r.jade[400],
824
1274
  barren: r.sandstone[300],
825
- urban_area: r.ink[100],
826
- farmland: r.sandstone[200],
827
- glacier: r.ink[25],
1275
+ urban_area: r.lilac[200],
1276
+ farmland: r.jade[500],
1277
+ glacier: r.lilac[100],
1278
+ scrub: r.verdant[400],
1279
+ forest: r.jade[500]
1280
+ }
1281
+ };
1282
+ const ORCHID_DARK = {
1283
+ background: r.lilac[1e3],
1284
+ earth: r.lilac[900],
1285
+ water: r.sky[980],
1286
+ parkA: r.aqua[800],
1287
+ parkB: r.aqua[700],
1288
+ woodA: r.jade[800],
1289
+ woodB: r.jade[700],
1290
+ scrubA: r.sandstone[500],
1291
+ scrubB: r.sandstone[500],
1292
+ sand: r.sandstone[500],
1293
+ beach: r.sandstone[400],
1294
+ glacier: r.lilac[700],
1295
+ institutional: r.lilac[850],
1296
+ pedestrian: r.lilac[850],
1297
+ aerodrome: r.lilac[850],
1298
+ runway: r.lilac[800],
1299
+ pier: r.cobalt[600],
1300
+ buildings: r.lilac[800],
1301
+ railway: r.lilac[700],
1302
+ boundaries: r.cobalt[400],
1303
+ roads: {
1304
+ other: r.lilac[850],
1305
+ otherCasing: r.lilac[1e3],
1306
+ minor: r.lilac[800],
1307
+ minorCasing: r.lilac[1e3],
1308
+ service: r.lilac[850],
1309
+ serviceCasing: r.lilac[1e3],
1310
+ major: r.lilac[700],
1311
+ majorCasing: r.lilac[1e3],
1312
+ highway: r.lilac[600],
1313
+ highwayCasing: r.lilac[1e3],
1314
+ link: r.lilac[700],
1315
+ linkCasing: r.lilac[1e3]
1316
+ },
1317
+ tunnelFill: r.lilac[900],
1318
+ tunnelCasing: r.lilac[1e3],
1319
+ bridgeCasing: r.lilac[1e3],
1320
+ labels: {
1321
+ city: r.lilac[100],
1322
+ cityHalo: r.lilac[1e3],
1323
+ state: r.lilac[500],
1324
+ stateHalo: r.lilac[1e3],
1325
+ country: r.lilac[500],
1326
+ subplace: r.lilac[500],
1327
+ subplaceHalo: r.lilac[1e3],
1328
+ address: r.lilac[500],
1329
+ addressHalo: r.lilac[1e3],
1330
+ roadMinor: r.lilac[500],
1331
+ roadMinorHalo: r.lilac[1e3],
1332
+ roadMajor: r.lilac[400],
1333
+ roadMajorHalo: r.lilac[1e3],
1334
+ ocean: r.sky[400]
1335
+ },
1336
+ pois: {
1337
+ blue: r.cobalt[400],
1338
+ green: r.jade[400],
1339
+ lapis: r.cobalt[400],
1340
+ pink: r.rose[400],
1341
+ red: r.rose[400],
1342
+ slategray: r.lilac[500],
1343
+ tangerine: r.ember[400],
1344
+ turquoise: r.aqua[400]
1345
+ },
1346
+ landcover: {
1347
+ grassland: r.jade[800],
1348
+ barren: r.sandstone[500],
1349
+ urban_area: r.lilac[900],
1350
+ farmland: r.jade[900],
1351
+ glacier: r.lilac[700],
1352
+ scrub: r.verdant[800],
1353
+ forest: r.jade[800]
1354
+ }
1355
+ };
1356
+ const CANOPY_LIGHT = {
1357
+ background: r.verdant[100],
1358
+ earth: r.sandstone[200],
1359
+ water: r.cobalt[600],
1360
+ parkA: r.verdant[800],
1361
+ parkB: r.verdant[700],
1362
+ woodA: r.verdant[600],
1363
+ woodB: r.verdant[700],
1364
+ scrubA: r.sandstone[500],
1365
+ scrubB: r.sandstone[400],
1366
+ sand: r.sandstone[200],
1367
+ beach: r.sandstone[100],
1368
+ glacier: r.paper[25],
1369
+ institutional: r.rose[200],
1370
+ pedestrian: r.rose[100],
1371
+ aerodrome: r.lilac[500],
1372
+ runway: r.paper[1e3],
1373
+ pier: r.sky[300],
1374
+ buildings: r.ember[700],
1375
+ railway: r.paper[950],
1376
+ boundaries: r.graphite[300],
1377
+ roads: {
1378
+ other: r.rose[1e3],
1379
+ otherCasing: r.sandstone[200],
1380
+ minor: r.rose[1e3],
1381
+ minorCasing: r.sandstone[200],
1382
+ service: r.rose[1e3],
1383
+ serviceCasing: r.sandstone[200],
1384
+ major: r.rose[1e3],
1385
+ majorCasing: r.sandstone[100],
1386
+ highway: r.rose[1e3],
1387
+ highwayCasing: r.sandstone[100],
1388
+ link: r.rose[1e3],
1389
+ linkCasing: r.sandstone[100]
1390
+ },
1391
+ tunnelFill: r.rose[900],
1392
+ tunnelCasing: r.sandstone[200],
1393
+ bridgeCasing: r.sandstone[100],
1394
+ labels: {
1395
+ city: r.paper[1e3],
1396
+ cityHalo: r.sandstone[100],
1397
+ state: r.paper[800],
1398
+ stateHalo: r.sandstone[100],
1399
+ country: r.paper[800],
1400
+ subplace: r.paper[700],
1401
+ subplaceHalo: r.sandstone[100],
1402
+ address: r.paper[800],
1403
+ addressHalo: r.sandstone[100],
1404
+ roadMinor: r.paper[800],
1405
+ roadMinorHalo: r.sandstone[100],
1406
+ roadMajor: r.paper[900],
1407
+ roadMajorHalo: r.sandstone[100],
1408
+ ocean: r.cobalt[25]
1409
+ },
1410
+ pois: {
1411
+ blue: r.cobalt[700],
1412
+ green: r.verdant[700],
1413
+ lapis: r.cobalt[700],
1414
+ pink: r.rose[600],
1415
+ red: r.rose[700],
1416
+ slategray: r.paper[700],
1417
+ tangerine: r.ember[700],
1418
+ turquoise: r.sky[700]
1419
+ },
1420
+ landcover: {
1421
+ grassland: r.verdant[500],
1422
+ barren: r.sandstone[400],
1423
+ urban_area: r.rose[600],
1424
+ farmland: r.verdant[600],
1425
+ glacier: r.paper[25],
1426
+ scrub: r.sandstone[500],
1427
+ forest: r.verdant[800]
1428
+ }
1429
+ };
1430
+ const CANOPY_DARK = {
1431
+ background: r.paper[950],
1432
+ earth: r.paper[900],
1433
+ water: r.cobalt[950],
1434
+ parkA: r.verdant[900],
1435
+ parkB: r.verdant[800],
1436
+ woodA: r.verdant[800],
1437
+ woodB: r.verdant[800],
1438
+ scrubA: r.paper[850],
1439
+ scrubB: r.paper[850],
1440
+ sand: r.sandstone[500],
1441
+ beach: r.sandstone[400],
1442
+ glacier: r.paper[700],
1443
+ institutional: r.paper[850],
1444
+ pedestrian: r.rose[900],
1445
+ aerodrome: r.lilac[850],
1446
+ runway: r.paper[800],
1447
+ pier: r.sky[700],
1448
+ buildings: r.ember[700],
1449
+ railway: r.paper[700],
1450
+ boundaries: r.graphite[600],
1451
+ roads: {
1452
+ other: r.sandstone[500],
1453
+ otherCasing: r.paper[1e3],
1454
+ minor: r.sandstone[400],
1455
+ minorCasing: r.paper[1e3],
1456
+ service: r.sandstone[500],
1457
+ serviceCasing: r.paper[1e3],
1458
+ major: r.sandstone[300],
1459
+ majorCasing: r.paper[1e3],
1460
+ highway: r.sandstone[200],
1461
+ highwayCasing: r.paper[1e3],
1462
+ link: r.sandstone[300],
1463
+ linkCasing: r.paper[1e3]
1464
+ },
1465
+ tunnelFill: r.paper[900],
1466
+ tunnelCasing: r.paper[1e3],
1467
+ bridgeCasing: r.paper[1e3],
1468
+ labels: {
1469
+ city: r.sandstone[100],
1470
+ cityHalo: r.paper[1e3],
1471
+ state: r.sandstone[300],
1472
+ stateHalo: r.paper[1e3],
1473
+ country: r.sandstone[300],
1474
+ subplace: r.sandstone[300],
1475
+ subplaceHalo: r.paper[1e3],
1476
+ address: r.sandstone[300],
1477
+ addressHalo: r.paper[1e3],
1478
+ roadMinor: r.sandstone[300],
1479
+ roadMinorHalo: r.paper[1e3],
1480
+ roadMajor: r.sandstone[200],
1481
+ roadMajorHalo: r.paper[1e3],
1482
+ ocean: r.cobalt[300]
1483
+ },
1484
+ pois: {
1485
+ blue: r.cobalt[400],
1486
+ green: r.verdant[400],
1487
+ lapis: r.cobalt[400],
1488
+ pink: r.rose[400],
1489
+ red: r.rose[400],
1490
+ slategray: r.sandstone[300],
1491
+ tangerine: r.ember[400],
1492
+ turquoise: r.sky[400]
1493
+ },
1494
+ landcover: {
1495
+ grassland: r.verdant[900],
1496
+ barren: r.sandstone[500],
1497
+ urban_area: r.rose[900],
1498
+ farmland: r.verdant[900],
1499
+ glacier: r.paper[700],
1500
+ scrub: r.paper[850],
1501
+ forest: r.verdant[900]
1502
+ }
1503
+ };
1504
+ const LAGOON_LIGHT = {
1505
+ background: r.verdant[100],
1506
+ earth: r.verdant[100],
1507
+ water: r.wave[200],
1508
+ parkA: r.aqua[300],
1509
+ parkB: r.aqua[400],
1510
+ woodA: r.wave[300],
1511
+ woodB: r.wave[400],
1512
+ scrubA: r.verdant[300],
1513
+ scrubB: r.verdant[400],
1514
+ sand: r.sandstone[200],
1515
+ beach: r.verdant[100],
1516
+ glacier: r.graphite[50],
1517
+ institutional: r.verdant[200],
1518
+ pedestrian: r.wave[100],
1519
+ aerodrome: r.paper[200],
1520
+ runway: r.verdant[100],
1521
+ pier: r.sky[300],
1522
+ buildings: r.graphite[100],
1523
+ railway: r.graphite[25],
1524
+ boundaries: r.graphite[500],
1525
+ roads: {
1526
+ other: "#FFFFFF",
1527
+ otherCasing: r.verdant[200],
1528
+ minor: "#FFFFFF",
1529
+ minorCasing: r.verdant[200],
1530
+ service: "#FFFFFF",
1531
+ serviceCasing: r.verdant[200],
1532
+ major: "#FFFFFF",
1533
+ majorCasing: r.verdant[300],
1534
+ highway: "#FFFFFF",
1535
+ highwayCasing: r.verdant[300],
1536
+ link: "#FFFFFF",
1537
+ linkCasing: r.verdant[300]
1538
+ },
1539
+ tunnelFill: r.graphite[50],
1540
+ tunnelCasing: r.verdant[200],
1541
+ bridgeCasing: r.graphite[400],
1542
+ labels: {
1543
+ city: r.graphite[800],
1544
+ cityHalo: r.verdant[100],
1545
+ state: r.graphite[700],
1546
+ stateHalo: r.verdant[100],
1547
+ country: r.graphite[700],
1548
+ subplace: r.graphite[700],
1549
+ subplaceHalo: r.verdant[100],
1550
+ address: r.graphite[700],
1551
+ addressHalo: r.verdant[100],
1552
+ roadMinor: r.graphite[700],
1553
+ roadMinorHalo: r.verdant[100],
1554
+ roadMajor: r.graphite[800],
1555
+ roadMajorHalo: r.verdant[100],
1556
+ ocean: r.wave[800]
1557
+ },
1558
+ pois: {
1559
+ blue: r.wave[700],
1560
+ green: r.verdant[700],
1561
+ lapis: r.sky[700],
1562
+ pink: r.rose[600],
1563
+ red: r.rose[700],
1564
+ slategray: r.graphite[700],
1565
+ tangerine: r.sandstone[500],
1566
+ turquoise: r.aqua[700]
1567
+ },
1568
+ landcover: {
1569
+ grassland: r.verdant[400],
1570
+ barren: r.sandstone[200],
1571
+ urban_area: r.verdant[100],
1572
+ farmland: r.verdant[300],
1573
+ glacier: r.graphite[50],
828
1574
  scrub: r.verdant[300],
829
- forest: r.verdant[400]
1575
+ forest: r.wave[300]
830
1576
  }
831
1577
  };
832
- const OUTDOOR_DARK = {
833
- background: r.ink[1e3],
834
- earth: r.ink[950],
1578
+ const LAGOON_DARK = {
1579
+ background: r.verdant[900],
1580
+ earth: r.verdant[900],
835
1581
  water: r.wave[980],
836
- parkA: r.verdant[700],
837
- parkB: r.verdant[600],
838
- woodA: r.verdant[700],
839
- woodB: r.verdant[600],
1582
+ parkA: r.aqua[800],
1583
+ parkB: r.aqua[700],
1584
+ woodA: r.wave[800],
1585
+ woodB: r.wave[700],
840
1586
  scrubA: r.verdant[800],
841
- scrubB: r.verdant[700],
1587
+ scrubB: r.verdant[800],
842
1588
  sand: r.sandstone[500],
843
- beach: r.sandstone[500],
844
- glacier: r.ink[700],
845
- institutional: r.ink[1e3],
846
- pedestrian: r.ink[950],
847
- aerodrome: r.ink[950],
848
- runway: r.ink[850],
849
- pier: r.ink[850],
850
- buildings: r.ink[900],
851
- railway: r.ink[700],
852
- boundaries: r.ink[600],
1589
+ beach: r.verdant[800],
1590
+ glacier: r.graphite[700],
1591
+ institutional: r.verdant[800],
1592
+ pedestrian: r.wave[900],
1593
+ aerodrome: r.graphite[800],
1594
+ runway: r.verdant[800],
1595
+ pier: r.sky[600],
1596
+ buildings: r.verdant[800],
1597
+ railway: r.graphite[700],
1598
+ boundaries: r.graphite[600],
853
1599
  roads: {
854
- // The minor tier recedes toward `earth`; majors and highways hold their `relief` values,
855
- // because a road you cannot see is a different failure from a road that is merely quiet.
856
- other: r.ink[900],
857
- otherCasing: r.ink[1e3],
858
- minor: r.ink[850],
859
- minorCasing: r.ink[1e3],
860
- service: r.ink[900],
861
- serviceCasing: r.ink[1e3],
862
- major: r.ink[700],
863
- majorCasing: r.ink[1e3],
864
- highway: r.ink[600],
865
- highwayCasing: r.ink[1e3],
866
- link: r.ink[700],
867
- linkCasing: r.ink[1e3]
1600
+ other: r.verdant[700],
1601
+ otherCasing: r.verdant[900],
1602
+ minor: r.verdant[600],
1603
+ minorCasing: r.verdant[900],
1604
+ service: r.verdant[700],
1605
+ serviceCasing: r.verdant[900],
1606
+ major: r.verdant[500],
1607
+ majorCasing: r.verdant[900],
1608
+ highway: r.verdant[400],
1609
+ highwayCasing: r.verdant[900],
1610
+ link: r.verdant[500],
1611
+ linkCasing: r.verdant[900]
868
1612
  },
869
- tunnelFill: r.ink[900],
870
- tunnelCasing: r.ink[1e3],
871
- bridgeCasing: r.ink[1e3],
1613
+ tunnelFill: r.verdant[800],
1614
+ tunnelCasing: r.verdant[900],
1615
+ bridgeCasing: r.verdant[900],
872
1616
  labels: {
873
- city: r.ink[100],
874
- cityHalo: r.ink[1e3],
875
- state: r.ink[500],
876
- stateHalo: r.ink[1e3],
877
- country: r.ink[500],
878
- subplace: r.ink[500],
879
- subplaceHalo: r.ink[1e3],
880
- address: r.ink[500],
881
- addressHalo: r.ink[1e3],
882
- roadMinor: r.ink[500],
883
- roadMinorHalo: r.ink[1e3],
884
- roadMajor: r.ink[400],
885
- roadMajorHalo: r.ink[1e3],
1617
+ city: r.verdant[100],
1618
+ cityHalo: r.verdant[900],
1619
+ state: r.verdant[300],
1620
+ stateHalo: r.verdant[900],
1621
+ country: r.verdant[300],
1622
+ subplace: r.verdant[300],
1623
+ subplaceHalo: r.verdant[900],
1624
+ address: r.verdant[300],
1625
+ addressHalo: r.verdant[900],
1626
+ roadMinor: r.verdant[300],
1627
+ roadMinorHalo: r.verdant[900],
1628
+ roadMajor: r.verdant[200],
1629
+ roadMajorHalo: r.verdant[900],
886
1630
  ocean: r.wave[400]
887
1631
  },
888
1632
  pois: {
889
- blue: "#7FC4E8",
890
- green: r.verdant[300],
891
- lapis: "#8FB0EA",
892
- pink: "#E3A0C0",
893
- red: "#EE968F",
894
- slategray: r.ink[500],
895
- tangerine: "#E8AC7C",
896
- turquoise: r.wave[400]
1633
+ blue: r.wave[400],
1634
+ green: r.verdant[400],
1635
+ lapis: r.sky[400],
1636
+ pink: r.rose[400],
1637
+ red: r.rose[400],
1638
+ slategray: r.graphite[400],
1639
+ tangerine: r.sandstone[400],
1640
+ turquoise: r.aqua[400]
897
1641
  },
898
1642
  landcover: {
899
- grassland: r.verdant[700],
1643
+ grassland: r.verdant[800],
900
1644
  barren: r.sandstone[500],
901
- urban_area: r.ink[950],
902
- farmland: r.verdant[900],
903
- glacier: r.ink[700],
1645
+ urban_area: r.verdant[900],
1646
+ farmland: r.verdant[800],
1647
+ glacier: r.graphite[700],
904
1648
  scrub: r.verdant[800],
905
- forest: r.verdant[600]
1649
+ forest: r.wave[800]
906
1650
  }
907
1651
  };
908
1652
  return {
909
1653
  base: { light: BASE_LIGHT, dark: BASE_DARK },
910
1654
  muted: { light: MUTED_LIGHT, dark: MUTED_DARK },
911
- relief: { light: RELIEF_LIGHT, dark: RELIEF_DARK },
912
- street: { light: STREET_LIGHT, dark: STREET_DARK },
913
- outdoor: { light: OUTDOOR_LIGHT, dark: OUTDOOR_DARK }
1655
+ outdoor: { light: OUTDOOR_LIGHT, dark: OUTDOOR_DARK },
1656
+ decimal: { light: DECIMAL_LIGHT, dark: DECIMAL_DARK },
1657
+ blueprint: { light: BLUEPRINT_LIGHT, dark: BLUEPRINT_DARK },
1658
+ blush: { light: BLUSH_LIGHT, dark: BLUSH_DARK },
1659
+ orchid: { light: ORCHID_LIGHT, dark: ORCHID_DARK },
1660
+ canopy: { light: CANOPY_LIGHT, dark: CANOPY_DARK },
1661
+ lagoon: { light: LAGOON_LIGHT, dark: LAGOON_DARK }
914
1662
  };
915
1663
  }
916
1664
  var RECIPES = buildRecipes(STOCK_RAMPS);
917
1665
 
1666
+ // src/doc.ts
1667
+ var LAYER_GROUPS = [
1668
+ "land",
1669
+ "water",
1670
+ "buildings",
1671
+ "roads",
1672
+ "boundaries",
1673
+ "buildings3d",
1674
+ "labels"
1675
+ ];
1676
+
918
1677
  // src/validate.ts
919
1678
  var ThemeError = class extends Error {
920
1679
  detail;
@@ -978,7 +1737,42 @@ function walkLeaf(value, colorKeys, bounds, path, errors) {
978
1737
  }
979
1738
  }
980
1739
  var HALF_KEYS = ["basemap", "marker", "route"];
981
- var DOC_KEYS = ["v", "name", "base", "seeds", "light", "dark"];
1740
+ var DOC_KEYS = ["v", "name", "base", "seeds", "layers", "light", "dark"];
1741
+ var LAYERS_KEYS = ["visible", "order"];
1742
+ var isLayerGroup = (v) => typeof v === "string" && LAYER_GROUPS.includes(v);
1743
+ function walkLayers(value, errors) {
1744
+ if (!isRecord(value)) {
1745
+ errors.push("layers: must be an object");
1746
+ return;
1747
+ }
1748
+ for (const key of Object.keys(value)) {
1749
+ if (!LAYERS_KEYS.includes(key)) errors.push(`layers.${key}: unknown field`);
1750
+ }
1751
+ if (value.visible !== void 0) {
1752
+ if (!isRecord(value.visible)) {
1753
+ errors.push("layers.visible: must be an object");
1754
+ } else {
1755
+ for (const [group, v] of Object.entries(value.visible)) {
1756
+ if (!isLayerGroup(group)) errors.push(`layers.visible.${group}: unknown layer group`);
1757
+ else if (typeof v !== "boolean") errors.push(`layers.visible.${group}: must be a boolean`);
1758
+ }
1759
+ }
1760
+ }
1761
+ if (value.order !== void 0) {
1762
+ const order = value.order;
1763
+ if (!Array.isArray(order)) {
1764
+ errors.push("layers.order: must be an array");
1765
+ } else {
1766
+ order.forEach((g, i) => {
1767
+ if (!isLayerGroup(g)) errors.push(`layers.order[${i}]: unknown layer group`);
1768
+ });
1769
+ const known = order.filter(isLayerGroup);
1770
+ if (new Set(known).size !== known.length || known.length !== LAYER_GROUPS.length) {
1771
+ errors.push(`layers.order: must list each of ${LAYER_GROUPS.join(", ")} exactly once`);
1772
+ }
1773
+ }
1774
+ }
1775
+ }
982
1776
  var SEED_COLOR_KEYS = ["land", "water", "nature", "accent"];
983
1777
  var REQUIRED_SEED_KEYS = ["land", "water", "nature"];
984
1778
  function validateTheme(input) {
@@ -990,7 +1784,8 @@ function validateTheme(input) {
990
1784
  if (!DOC_KEYS.includes(key)) errors.push(`${key}: unknown field`);
991
1785
  }
992
1786
  if (input.v !== 1) errors.push("v: must be 1");
993
- if (typeof input.base !== "string" || !THEME_BASES.includes(input.base)) {
1787
+ const base = typeof input.base === "string" ? normalizeThemeBase(input.base) : null;
1788
+ if (!base) {
994
1789
  errors.push(`base: must be one of ${THEME_BASES.join(", ")}`);
995
1790
  }
996
1791
  if (input.name !== void 0) {
@@ -1006,6 +1801,7 @@ function validateTheme(input) {
1006
1801
  }
1007
1802
  }
1008
1803
  }
1804
+ if (input.layers !== void 0) walkLayers(input.layers, errors);
1009
1805
  const reference = RECIPES.base.light;
1010
1806
  for (const mode of ["light", "dark"]) {
1011
1807
  const half = input[mode];
@@ -1028,85 +1824,77 @@ function validateTheme(input) {
1028
1824
  }
1029
1825
  }
1030
1826
  if (errors.length > 0) throw new ThemeError("invalid theme", errors);
1827
+ if (base && base !== input.base) return { ...input, base };
1031
1828
  return input;
1032
1829
  }
1033
1830
 
1034
- // src/codec.ts
1035
- var THEME_CODE_PREFIX = "ut1.";
1036
- var MAX_CODE_LENGTH = 4096;
1037
- var MAX_JSON_BYTES = 16 * 1024;
1038
- async function pump(stream, cap) {
1039
- const reader = stream.getReader();
1040
- const chunks = [];
1041
- let size = 0;
1042
- for (; ; ) {
1043
- const { done, value } = await reader.read();
1044
- if (done) break;
1045
- size += value.byteLength;
1046
- if (size > cap) {
1047
- await reader.cancel().catch(() => {
1048
- });
1049
- throw new ThemeError("invalid theme", ["theme document too large"]);
1050
- }
1051
- chunks.push(value);
1052
- }
1053
- const out = new Uint8Array(size);
1054
- let off = 0;
1055
- for (const c of chunks) {
1056
- out.set(c, off);
1057
- off += c.byteLength;
1058
- }
1059
- return out;
1060
- }
1061
- var toB64url = (b) => {
1062
- let bin = "";
1063
- for (let i = 0; i < b.length; i += 32768) {
1064
- bin += String.fromCharCode(...b.subarray(i, i + 32768));
1065
- }
1066
- return btoa(bin).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
1067
- };
1068
- var fromB64url = (s) => {
1069
- const bin = atob(s.replaceAll("-", "+").replaceAll("_", "/"));
1070
- return Uint8Array.from(bin, (c) => c.charCodeAt(0));
1831
+ // src/presets.ts
1832
+ var STYLE_THEMES = {
1833
+ base: { v: 1, name: "base", base: "base" },
1834
+ muted: { v: 1, name: "muted", base: "muted" },
1835
+ outdoor: { v: 1, name: "outdoor", base: "outdoor" },
1836
+ decimal: { v: 1, name: "decimal", base: "decimal" },
1837
+ blueprint: { v: 1, name: "blueprint", base: "blueprint" },
1838
+ blush: { v: 1, name: "blush", base: "blush" },
1839
+ orchid: { v: 1, name: "orchid", base: "orchid" },
1840
+ canopy: { v: 1, name: "canopy", base: "canopy" },
1841
+ lagoon: { v: 1, name: "lagoon", base: "lagoon" }
1071
1842
  };
1072
- async function through(bytes, transform, cap) {
1073
- const stream = new Blob([bytes]).stream().pipeThrough(transform);
1074
- return pump(stream, cap);
1843
+
1844
+ // src/oklch.ts
1845
+ var srgbToLinear = (v) => v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
1846
+ var linearToSrgb = (v) => v <= 31308e-7 ? 12.92 * v : 1.055 * v ** (1 / 2.4) - 0.055;
1847
+ function hexToRgb(hex) {
1848
+ const h = hex.replace("#", "");
1849
+ return [
1850
+ parseInt(h.slice(0, 2), 16) / 255,
1851
+ parseInt(h.slice(2, 4), 16) / 255,
1852
+ parseInt(h.slice(4, 6), 16) / 255
1853
+ ];
1854
+ }
1855
+ function hexToOklch(hex) {
1856
+ const [r, g, b] = hexToRgb(hex).map(srgbToLinear);
1857
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
1858
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
1859
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
1860
+ const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
1861
+ const a = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
1862
+ const bb = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
1863
+ const c = Math.hypot(a, bb);
1864
+ let h = Math.atan2(bb, a) * 180 / Math.PI;
1865
+ if (h < 0) h += 360;
1866
+ return { l: L, c, h };
1075
1867
  }
1076
- async function encodeTheme(doc) {
1077
- const valid = validateTheme(doc);
1078
- const json = new TextEncoder().encode(JSON.stringify(valid));
1079
- const packed = await through(json, new CompressionStream("deflate"), Number.POSITIVE_INFINITY);
1080
- const code = THEME_CODE_PREFIX + toB64url(packed);
1081
- if (code.length > MAX_CODE_LENGTH) {
1082
- throw new ThemeError("invalid theme", [
1083
- `encoded theme exceeds ${MAX_CODE_LENGTH} characters`
1084
- ]);
1085
- }
1086
- return code;
1868
+ function oklchToLinear({ l: L, c, h }) {
1869
+ const hr = h * Math.PI / 180;
1870
+ const a = c * Math.cos(hr);
1871
+ const bb = c * Math.sin(hr);
1872
+ const l = (L + 0.3963377774 * a + 0.2158037573 * bb) ** 3;
1873
+ const m = (L - 0.1055613458 * a - 0.0638541728 * bb) ** 3;
1874
+ const s = (L - 0.0894841775 * a - 1.291485548 * bb) ** 3;
1875
+ return [
1876
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
1877
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
1878
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
1879
+ ];
1087
1880
  }
1088
- async function decodeTheme(code) {
1089
- if (code.length > MAX_CODE_LENGTH) {
1090
- throw new ThemeError("invalid theme", [`code exceeds ${MAX_CODE_LENGTH} characters`]);
1091
- }
1092
- if (!code.startsWith(THEME_CODE_PREFIX)) {
1093
- throw new ThemeError("invalid theme", [`code must start with "${THEME_CODE_PREFIX}"`]);
1094
- }
1095
- let bytes;
1096
- try {
1097
- const packed = fromB64url(code.slice(THEME_CODE_PREFIX.length));
1098
- bytes = await through(packed, new DecompressionStream("deflate"), MAX_JSON_BYTES);
1099
- } catch (e) {
1100
- if (e instanceof ThemeError) throw e;
1101
- throw new ThemeError("invalid theme", ["code is not valid base64url deflate data"]);
1102
- }
1103
- let parsed;
1104
- try {
1105
- parsed = JSON.parse(new TextDecoder().decode(bytes));
1106
- } catch {
1107
- throw new ThemeError("invalid theme", ["decoded payload is not JSON"]);
1881
+ var inGamut = (rgb) => rgb.every((v) => v >= -1e-6 && v <= 1 + 1e-6);
1882
+ function oklchToHex(color) {
1883
+ let { c } = color;
1884
+ let rgb = oklchToLinear({ ...color, c });
1885
+ if (!inGamut(rgb)) {
1886
+ let lo = 0;
1887
+ let hi = c;
1888
+ for (let i = 0; i < 24; i++) {
1889
+ c = (lo + hi) / 2;
1890
+ rgb = oklchToLinear({ ...color, c });
1891
+ if (inGamut(rgb)) lo = c;
1892
+ else hi = c;
1893
+ }
1894
+ rgb = oklchToLinear({ ...color, c: lo });
1108
1895
  }
1109
- return validateTheme(parsed);
1896
+ const to255 = (v) => Math.round(Math.min(1, Math.max(0, linearToSrgb(v))) * 255);
1897
+ return "#" + rgb.map((v) => to255(v).toString(16).padStart(2, "0")).join("").toUpperCase();
1110
1898
  }
1111
1899
 
1112
1900
  // src/compose.ts
@@ -1206,75 +1994,11 @@ function contrastWarnings(doc) {
1206
1994
  return warnings;
1207
1995
  }
1208
1996
 
1209
- // src/presets.ts
1210
- var PRESET_THEMES = {
1211
- base: { v: 1, name: "ink", base: "base" },
1212
- muted: { v: 1, name: "graphite", base: "muted" },
1213
- relief: { v: 1, name: "relief", base: "relief" },
1214
- street: { v: 1, name: "street", base: "street" },
1215
- outdoor: { v: 1, name: "outdoor", base: "outdoor" }
1216
- };
1217
-
1218
- // src/oklch.ts
1219
- var srgbToLinear = (v) => v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
1220
- var linearToSrgb = (v) => v <= 31308e-7 ? 12.92 * v : 1.055 * v ** (1 / 2.4) - 0.055;
1221
- function hexToRgb(hex) {
1222
- const h = hex.replace("#", "");
1223
- return [
1224
- parseInt(h.slice(0, 2), 16) / 255,
1225
- parseInt(h.slice(2, 4), 16) / 255,
1226
- parseInt(h.slice(4, 6), 16) / 255
1227
- ];
1228
- }
1229
- function hexToOklch(hex) {
1230
- const [r, g, b] = hexToRgb(hex).map(srgbToLinear);
1231
- const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
1232
- const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
1233
- const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
1234
- const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
1235
- const a = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
1236
- const bb = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
1237
- const c = Math.hypot(a, bb);
1238
- let h = Math.atan2(bb, a) * 180 / Math.PI;
1239
- if (h < 0) h += 360;
1240
- return { l: L, c, h };
1241
- }
1242
- function oklchToLinear({ l: L, c, h }) {
1243
- const hr = h * Math.PI / 180;
1244
- const a = c * Math.cos(hr);
1245
- const bb = c * Math.sin(hr);
1246
- const l = (L + 0.3963377774 * a + 0.2158037573 * bb) ** 3;
1247
- const m = (L - 0.1055613458 * a - 0.0638541728 * bb) ** 3;
1248
- const s = (L - 0.0894841775 * a - 1.291485548 * bb) ** 3;
1249
- return [
1250
- 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
1251
- -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
1252
- -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
1253
- ];
1254
- }
1255
- var inGamut = (rgb) => rgb.every((v) => v >= -1e-6 && v <= 1 + 1e-6);
1256
- function oklchToHex(color) {
1257
- let { c } = color;
1258
- let rgb = oklchToLinear({ ...color, c });
1259
- if (!inGamut(rgb)) {
1260
- let lo = 0;
1261
- let hi = c;
1262
- for (let i = 0; i < 24; i++) {
1263
- c = (lo + hi) / 2;
1264
- rgb = oklchToLinear({ ...color, c });
1265
- if (inGamut(rgb)) lo = c;
1266
- else hi = c;
1267
- }
1268
- rgb = oklchToLinear({ ...color, c: lo });
1269
- }
1270
- const to255 = (v) => Math.round(Math.min(1, Math.max(0, linearToSrgb(v))) * 255);
1271
- return "#" + rgb.map((v) => to255(v).toString(16).padStart(2, "0")).join("").toUpperCase();
1272
- }
1273
-
1274
1997
  // src/generate.ts
1275
1998
  var NEUTRAL_CHROMA_CAP = 0.045;
1276
1999
  var MUTED_CHROMA_CAP = 0.012;
1277
2000
  var CHROMA_CAP = 0.32;
2001
+ var NEUTRAL_RAMP_CHROMA = 5e-3;
1278
2002
  var DEFAULT_SEEDS = {
1279
2003
  land: STOCK_RAMPS.ink[500],
1280
2004
  water: STOCK_RAMPS.wave[500],
@@ -1285,14 +2009,15 @@ function reRamp(ref, seedHex, cap) {
1285
2009
  const seed = hexToOklch(seedHex);
1286
2010
  const steps = Object.keys(ref);
1287
2011
  const midStep = steps[Math.floor(steps.length / 2)];
1288
- const midChroma = Math.max(hexToOklch(ref[midStep]).c, 5e-3);
1289
- const factor = Math.min(Math.max(seed.c / midChroma, 0.15), 3);
2012
+ const midChroma = hexToOklch(ref[midStep]).c;
2013
+ const neutral = midChroma < NEUTRAL_RAMP_CHROMA;
2014
+ const factor = Math.min(Math.max(seed.c / Math.max(midChroma, 5e-3), 0.15), 3);
1290
2015
  const out = {};
1291
2016
  for (const step of steps) {
1292
2017
  const refColor = hexToOklch(ref[step]);
1293
2018
  out[step] = oklchToHex({
1294
2019
  l: refColor.l,
1295
- c: Math.min(refColor.c * factor, cap),
2020
+ c: Math.min(neutral ? seed.c : refColor.c * factor, cap),
1296
2021
  h: seed.h
1297
2022
  });
1298
2023
  }
@@ -1308,7 +2033,10 @@ function enforceLabelContrast(recipe) {
1308
2033
  if (contrast(label, bg) >= floor) break;
1309
2034
  const l = hexToOklch(label);
1310
2035
  const direction = hexToOklch(bg).l > l.l ? -1 : 1;
1311
- const nudged = oklchToHex({ ...l, l: Math.min(1, Math.max(0, l.l + direction * 0.015)) });
2036
+ const nudged = oklchToHex({
2037
+ ...l,
2038
+ l: Math.min(1, Math.max(0, l.l + direction * 0.015))
2039
+ });
1312
2040
  setLabelSlot(fixed, labelSlot, nudged);
1313
2041
  }
1314
2042
  }
@@ -1354,8 +2082,16 @@ function generateTheme(base, seeds) {
1354
2082
  const ramps = {
1355
2083
  ...STOCK_RAMPS,
1356
2084
  ink: reRamp(STOCK_RAMPS.ink, seeds.land, NEUTRAL_CHROMA_CAP),
2085
+ paper: reRamp(STOCK_RAMPS.paper, seeds.land, NEUTRAL_CHROMA_CAP),
1357
2086
  graphite: reRamp(STOCK_RAMPS.graphite, seeds.land, MUTED_CHROMA_CAP),
2087
+ jade: reRamp(STOCK_RAMPS.jade, seeds.land, CHROMA_CAP),
2088
+ cobalt: reRamp(STOCK_RAMPS.cobalt, seeds.land, CHROMA_CAP),
2089
+ rose: reRamp(STOCK_RAMPS.rose, seeds.land, CHROMA_CAP),
2090
+ lilac: reRamp(STOCK_RAMPS.lilac, seeds.land, NEUTRAL_CHROMA_CAP),
2091
+ aqua: reRamp(STOCK_RAMPS.aqua, seeds.nature, CHROMA_CAP),
1358
2092
  wave: reRamp(STOCK_RAMPS.wave, seeds.water, CHROMA_CAP),
2093
+ sky: reRamp(STOCK_RAMPS.sky, seeds.water, CHROMA_CAP),
2094
+ mist: reRamp(STOCK_RAMPS.mist, seeds.water, CHROMA_CAP),
1359
2095
  verdant: reRamp(STOCK_RAMPS.verdant, seeds.nature, CHROMA_CAP)
1360
2096
  };
1361
2097
  const generated = buildRecipes(ramps);
@@ -1375,7 +2111,7 @@ function generateTheme(base, seeds) {
1375
2111
  }
1376
2112
 
1377
2113
  // src/palettes.ts
1378
- var SEED_PALETTES = [
2114
+ var THEME_PRESETS = [
1379
2115
  { name: "process ink", seeds: DEFAULT_SEEDS },
1380
2116
  {
1381
2117
  name: "boreal",
@@ -1416,36 +2152,445 @@ function shuffleSeeds(rng = Math.random) {
1416
2152
  accent: oklchToHex({ l: 0.65, c: 0.22 + rng() * 0.08, h: wrap(h + 170 + rng() * 40) })
1417
2153
  };
1418
2154
  }
2155
+
2156
+ // src/preset.ts
2157
+ var PRESET_CODE_PREFIX = "u";
2158
+ var PRESET_CODE_RE = /^u[0-9A-Za-z]{2,24}$/;
2159
+ var BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2160
+ var SEED_KEYS = ["land", "water", "nature", "accent"];
2161
+ var STYLE_ENCODE = {
2162
+ base: 0,
2163
+ muted: 1,
2164
+ outdoor: 4,
2165
+ decimal: 5,
2166
+ blueprint: 6,
2167
+ blush: 8,
2168
+ orchid: 9,
2169
+ canopy: 10,
2170
+ lagoon: 11
2171
+ };
2172
+ var STYLE_DECODE = [
2173
+ "base",
2174
+ "muted",
2175
+ "outdoor",
2176
+ "base",
2177
+ "outdoor",
2178
+ "decimal",
2179
+ "blueprint",
2180
+ void 0,
2181
+ "blush",
2182
+ "orchid",
2183
+ "canopy",
2184
+ "lagoon"
2185
+ ];
2186
+ var PRESET_OFFSET = 8n;
2187
+ var ORIGINAL_SLOTS = 5n;
2188
+ var ORIGINAL_PRESET_LIMIT = 64n;
2189
+ var LATER_OFFSET = PRESET_OFFSET + ORIGINAL_PRESET_LIMIT * ORIGINAL_SLOTS;
2190
+ var LATER_LANES = 3n;
2191
+ var LATER_ROWS = 232n;
2192
+ var WAVE2_BASE = 5;
2193
+ var WAVE3_BASE = 8;
2194
+ var WAVE3_BARE_ROWS = 32n;
2195
+ var WAVE3_STYLE_COLUMNS = 20n;
2196
+ var WAVE3_PRESET_LIMIT = (LATER_ROWS - WAVE3_BARE_ROWS) / WAVE3_STYLE_COLUMNS;
2197
+ var CUSTOM_OFFSET = 1024n;
2198
+ var ESCAPE_SLOT = 7n;
2199
+ var ESCAPE_BITS = 5n;
2200
+ var sameHex = (a, b) => a.toLowerCase() === b.toLowerCase();
2201
+ function isThemePresetCode(code) {
2202
+ return PRESET_CODE_RE.test(code);
2203
+ }
2204
+ function presetId(name) {
2205
+ return name.replace(/\s+([a-zA-Z])/g, (_, c) => c.toUpperCase()).replace(/\s/g, "");
2206
+ }
2207
+ function toBase62(n, min = 2) {
2208
+ if (n === 0n) return "0".repeat(min);
2209
+ let s = "";
2210
+ let x = n;
2211
+ while (x > 0n) {
2212
+ s = BASE62[Number(x % 62n)] + s;
2213
+ x /= 62n;
2214
+ }
2215
+ return s.padStart(min, "0");
2216
+ }
2217
+ function fromBase62(s) {
2218
+ let n = 0n;
2219
+ for (const ch of s) {
2220
+ const i = BASE62.indexOf(ch);
2221
+ if (i < 0) {
2222
+ throw new ThemeError("invalid theme", ["code is not a valid preset"]);
2223
+ }
2224
+ n = n * 62n + BigInt(i);
2225
+ }
2226
+ return n;
2227
+ }
2228
+ function rgb24(hex) {
2229
+ return BigInt(parseInt(hex.replace("#", "").slice(0, 6), 16));
2230
+ }
2231
+ function fromRgb24(n) {
2232
+ return `#${n.toString(16).toUpperCase().padStart(6, "0")}`;
2233
+ }
2234
+ function isBareStyle(doc) {
2235
+ return doc.seeds === void 0 && doc.light === void 0 && doc.dark === void 0;
2236
+ }
2237
+ function deepEqual(a, b) {
2238
+ if (a === b) return true;
2239
+ if (typeof a !== typeof b) return false;
2240
+ if (a && b && typeof a === "object") {
2241
+ const ak = Object.keys(a).sort();
2242
+ const bk = Object.keys(b).sort();
2243
+ return ak.length === bk.length && ak.every((k, i) => k === bk[i] && deepEqual(a[k], b[k]));
2244
+ }
2245
+ return false;
2246
+ }
2247
+ function seedsMatch(a, b) {
2248
+ return SEED_KEYS.every((k) => {
2249
+ const left = a[k];
2250
+ const right = b[k];
2251
+ if (left === void 0 && right === void 0) return true;
2252
+ if (typeof left !== "string" || typeof right !== "string") return left === right;
2253
+ return sameHex(left, right);
2254
+ });
2255
+ }
2256
+ function generatedMatch(doc) {
2257
+ if (!doc.seeds) return false;
2258
+ const generated = generateTheme(doc.base, doc.seeds);
2259
+ return generated.base === doc.base && seedsMatch(generated.seeds, doc.seeds) && deepEqual(generated.light, doc.light) && deepEqual(generated.dark, doc.dark);
2260
+ }
2261
+ function findPresetIndex(seeds) {
2262
+ return THEME_PRESETS.findIndex((p) => seedsMatch(p.seeds, { ...DEFAULT_SEEDS, ...seeds }));
2263
+ }
2264
+ function encodeBits(bits) {
2265
+ return PRESET_CODE_PREFIX + toBase62(bits);
2266
+ }
2267
+ function encodePreset(doc) {
2268
+ const index = STYLE_ENCODE[doc.base];
2269
+ if (index === void 0) return null;
2270
+ const s = BigInt(index);
2271
+ if (isBareStyle(doc)) {
2272
+ if (index < WAVE3_BASE) return encodeBits(s);
2273
+ return encodeBits(LATER_OFFSET + (s - BigInt(WAVE3_BASE)) * LATER_LANES + 2n);
2274
+ }
2275
+ if (!doc.seeds || !generatedMatch(doc)) return null;
2276
+ const presetIndex = findPresetIndex(doc.seeds);
2277
+ if (presetIndex >= 0) {
2278
+ const p = BigInt(presetIndex);
2279
+ if (index < WAVE2_BASE) {
2280
+ if (p < ORIGINAL_PRESET_LIMIT) return encodeBits(PRESET_OFFSET + p * ORIGINAL_SLOTS + s);
2281
+ } else if (index < WAVE3_BASE) {
2282
+ if (p < LATER_ROWS) {
2283
+ return encodeBits(LATER_OFFSET + p * LATER_LANES + (s - BigInt(WAVE2_BASE)));
2284
+ }
2285
+ } else if (p < WAVE3_PRESET_LIMIT && s - BigInt(WAVE3_BASE) < WAVE3_STYLE_COLUMNS) {
2286
+ const row = WAVE3_BARE_ROWS + p * WAVE3_STYLE_COLUMNS + (s - BigInt(WAVE3_BASE));
2287
+ return encodeBits(LATER_OFFSET + row * LATER_LANES + 2n);
2288
+ }
2289
+ }
2290
+ if (!doc.seeds.accent) return null;
2291
+ const filled = { ...DEFAULT_SEEDS, ...doc.seeds };
2292
+ let bits;
2293
+ let shift;
2294
+ if (index < WAVE3_BASE) {
2295
+ bits = CUSTOM_OFFSET + s;
2296
+ shift = 3n;
2297
+ } else {
2298
+ bits = CUSTOM_OFFSET + ESCAPE_SLOT + (s - BigInt(WAVE3_BASE) << 3n);
2299
+ shift = 3n + ESCAPE_BITS;
2300
+ }
2301
+ for (const key of SEED_KEYS) {
2302
+ bits += rgb24(filled[key]) << shift;
2303
+ shift += 24n;
2304
+ }
2305
+ return encodeBits(bits);
2306
+ }
2307
+ function decodePreset(code) {
2308
+ if (!isThemePresetCode(code)) {
2309
+ throw new ThemeError("invalid theme", ["code is not a valid preset"]);
2310
+ }
2311
+ const bits = fromBase62(code.slice(PRESET_CODE_PREFIX.length));
2312
+ const styleAt = (index) => {
2313
+ const base2 = STYLE_DECODE[index];
2314
+ if (!base2) throw new ThemeError("invalid theme", ["preset style is out of range"]);
2315
+ return base2;
2316
+ };
2317
+ const presetAt = (index) => {
2318
+ const preset = THEME_PRESETS[index];
2319
+ if (!preset) throw new ThemeError("invalid theme", ["preset is out of range"]);
2320
+ return preset;
2321
+ };
2322
+ if (bits < PRESET_OFFSET) {
2323
+ return structuredClone(STYLE_THEMES[styleAt(Number(bits))]);
2324
+ }
2325
+ if (bits < LATER_OFFSET) {
2326
+ const n = bits - PRESET_OFFSET;
2327
+ return generateTheme(styleAt(Number(n % ORIGINAL_SLOTS)), presetAt(Number(n / ORIGINAL_SLOTS)).seeds);
2328
+ }
2329
+ if (bits < CUSTOM_OFFSET) {
2330
+ const n = bits - LATER_OFFSET;
2331
+ const lane = Number(n % LATER_LANES);
2332
+ const row = n / LATER_LANES;
2333
+ if (lane < 2) {
2334
+ return generateTheme(styleAt(WAVE2_BASE + lane), presetAt(Number(row)).seeds);
2335
+ }
2336
+ if (row < WAVE3_BARE_ROWS) {
2337
+ return structuredClone(STYLE_THEMES[styleAt(WAVE3_BASE + Number(row))]);
2338
+ }
2339
+ const j = row - WAVE3_BARE_ROWS;
2340
+ const base2 = styleAt(WAVE3_BASE + Number(j % WAVE3_STYLE_COLUMNS));
2341
+ return generateTheme(base2, presetAt(Number(j / WAVE3_STYLE_COLUMNS)).seeds);
2342
+ }
2343
+ const payload = bits - CUSTOM_OFFSET;
2344
+ const slot = payload & 7n;
2345
+ let base;
2346
+ let rest;
2347
+ if (slot === ESCAPE_SLOT) {
2348
+ base = styleAt(WAVE3_BASE + Number(payload >> 3n & (1n << ESCAPE_BITS) - 1n));
2349
+ rest = payload >> 3n + ESCAPE_BITS;
2350
+ } else {
2351
+ base = styleAt(Number(slot));
2352
+ rest = payload >> 3n;
2353
+ }
2354
+ const seeds = { ...DEFAULT_SEEDS };
2355
+ for (const key of SEED_KEYS) {
2356
+ seeds[key] = fromRgb24(rest & 0xffffffn);
2357
+ rest >>= 24n;
2358
+ }
2359
+ if (rest !== 0n) {
2360
+ throw new ThemeError("invalid theme", ["preset payload has unused bits"]);
2361
+ }
2362
+ return generateTheme(base, seeds);
2363
+ }
2364
+ function registryThemeKey(doc) {
2365
+ if (isBareStyle(doc)) return STYLE_THEMES[doc.base]?.name;
2366
+ if (!doc.seeds || doc.base !== "base" || !generatedMatch(doc)) return void 0;
2367
+ const presetIndex = findPresetIndex(doc.seeds);
2368
+ if (presetIndex < 0) return void 0;
2369
+ return presetId(THEME_PRESETS[presetIndex].name);
2370
+ }
2371
+
2372
+ // src/layers.ts
2373
+ var DEFAULT_LAYER_VISIBILITY = {
2374
+ land: true,
2375
+ water: true,
2376
+ buildings: true,
2377
+ roads: true,
2378
+ boundaries: true,
2379
+ buildings3d: false,
2380
+ labels: true
2381
+ };
2382
+ var BUILDINGS_3D_LAYER_ID = "buildings_3d";
2383
+ var LAND_LINES = /* @__PURE__ */ new Set(["roads_runway", "roads_taxiway"]);
2384
+ function layerGroupOf(layer) {
2385
+ const { id, type } = layer;
2386
+ if (type === "symbol") return "labels";
2387
+ if (id === "background") return null;
2388
+ if (id === BUILDINGS_3D_LAYER_ID) return "buildings3d";
2389
+ if (id === "buildings") return "buildings";
2390
+ if (id.startsWith("water")) return "water";
2391
+ if (id.startsWith("boundaries")) return "boundaries";
2392
+ if (LAND_LINES.has(id)) return "land";
2393
+ if (id.startsWith("roads")) return "roads";
2394
+ if (id === "earth" || id === "landcover" || id.startsWith("landuse")) return "land";
2395
+ return null;
2396
+ }
2397
+ function isLayerVisible(layers, group) {
2398
+ return layers?.visible?.[group] ?? DEFAULT_LAYER_VISIBILITY[group];
2399
+ }
2400
+ function effectiveLayerOrder(layers) {
2401
+ return layers?.order ?? LAYER_GROUPS;
2402
+ }
2403
+ function isStockLayerOrder(order) {
2404
+ return !order || order.length === LAYER_GROUPS.length && order.every((g, i) => g === LAYER_GROUPS[i]);
2405
+ }
2406
+ function isStockLayers(layers) {
2407
+ if (!layers) return true;
2408
+ if (!isStockLayerOrder(layers.order)) return false;
2409
+ return LAYER_GROUPS.every((g) => isLayerVisible(layers, g) === DEFAULT_LAYER_VISIBILITY[g]);
2410
+ }
2411
+ function buildings3dLayer(source, color) {
2412
+ return {
2413
+ id: BUILDINGS_3D_LAYER_ID,
2414
+ type: "fill-extrusion",
2415
+ source,
2416
+ "source-layer": "buildings",
2417
+ minzoom: 13,
2418
+ filter: ["in", "kind", "building", "building_part"],
2419
+ paint: {
2420
+ "fill-extrusion-color": color,
2421
+ "fill-extrusion-height": ["coalesce", ["get", "height"], 6],
2422
+ "fill-extrusion-base": ["coalesce", ["get", "min_height"], 0],
2423
+ "fill-extrusion-opacity": 0.85
2424
+ }
2425
+ };
2426
+ }
2427
+ function applyThemeLayers(styleLayers, layers, buildingsColor) {
2428
+ if (isStockLayers(layers)) return styleLayers;
2429
+ const visible = (g) => isLayerVisible(layers, g);
2430
+ const tagged = styleLayers.map((layer) => ({ layer, group: layerGroupOf(layer) }));
2431
+ const source = styleLayers.find((l) => l.id === "buildings")?.source ?? "unmap";
2432
+ const extrusion = visible("buildings3d") ? buildings3dLayer(source, buildingsColor) : null;
2433
+ if (isStockLayerOrder(layers?.order)) {
2434
+ const kept = tagged.filter(({ group }) => group === null || visible(group)).map((t) => t.layer);
2435
+ if (!extrusion) return kept;
2436
+ const firstLabel = kept.findIndex((l) => layerGroupOf(l) === "labels");
2437
+ const at = firstLabel === -1 ? kept.length : firstLabel;
2438
+ return [...kept.slice(0, at), extrusion, ...kept.slice(at)];
2439
+ }
2440
+ const out = tagged.filter(({ group }) => group === null).map((t) => t.layer);
2441
+ for (const group of effectiveLayerOrder(layers)) {
2442
+ if (!visible(group)) continue;
2443
+ if (group === "buildings3d") {
2444
+ if (extrusion) out.push(extrusion);
2445
+ continue;
2446
+ }
2447
+ for (const t of tagged) if (t.group === group) out.push(t.layer);
2448
+ }
2449
+ return out;
2450
+ }
2451
+
2452
+ // src/codec.ts
2453
+ var THEME_CODE_PREFIX = "ut1.";
2454
+ var MAX_CODE_LENGTH = 4096;
2455
+ var MAX_JSON_BYTES = 16 * 1024;
2456
+ async function pump(stream, cap) {
2457
+ const reader = stream.getReader();
2458
+ const chunks = [];
2459
+ let size = 0;
2460
+ for (; ; ) {
2461
+ const { done, value } = await reader.read();
2462
+ if (done) break;
2463
+ size += value.byteLength;
2464
+ if (size > cap) {
2465
+ await reader.cancel().catch(() => {
2466
+ });
2467
+ throw new ThemeError("invalid theme", ["theme document too large"]);
2468
+ }
2469
+ chunks.push(value);
2470
+ }
2471
+ const out = new Uint8Array(size);
2472
+ let off = 0;
2473
+ for (const c of chunks) {
2474
+ out.set(c, off);
2475
+ off += c.byteLength;
2476
+ }
2477
+ return out;
2478
+ }
2479
+ var toB64url = (b) => {
2480
+ let bin = "";
2481
+ for (let i = 0; i < b.length; i += 32768) {
2482
+ bin += String.fromCharCode(...b.subarray(i, i + 32768));
2483
+ }
2484
+ return btoa(bin).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
2485
+ };
2486
+ var fromB64url = (s) => {
2487
+ const bin = atob(s.replaceAll("-", "+").replaceAll("_", "/"));
2488
+ return Uint8Array.from(bin, (c) => c.charCodeAt(0));
2489
+ };
2490
+ async function through(bytes, transform, cap) {
2491
+ const stream = new Blob([bytes]).stream().pipeThrough(transform);
2492
+ return pump(stream, cap);
2493
+ }
2494
+ async function encodeTheme(doc) {
2495
+ const valid = validateTheme(doc);
2496
+ const preset = isStockLayers(valid.layers) ? encodePreset(valid) : null;
2497
+ if (preset) return preset;
2498
+ const json = new TextEncoder().encode(JSON.stringify(valid));
2499
+ const packed = await through(json, new CompressionStream("deflate"), Number.POSITIVE_INFINITY);
2500
+ const code = THEME_CODE_PREFIX + toB64url(packed);
2501
+ if (code.length > MAX_CODE_LENGTH) {
2502
+ throw new ThemeError("invalid theme", [
2503
+ `encoded theme exceeds ${MAX_CODE_LENGTH} characters`
2504
+ ]);
2505
+ }
2506
+ return code;
2507
+ }
2508
+ async function decodeTheme(code) {
2509
+ if (code.length > MAX_CODE_LENGTH) {
2510
+ throw new ThemeError("invalid theme", [`code exceeds ${MAX_CODE_LENGTH} characters`]);
2511
+ }
2512
+ if (code.startsWith(THEME_CODE_PREFIX)) {
2513
+ return decodeDeflate(code);
2514
+ }
2515
+ if (isThemePresetCode(code)) {
2516
+ return validateTheme(decodePreset(code));
2517
+ }
2518
+ throw new ThemeError("invalid theme", [
2519
+ `code must start with "${THEME_CODE_PREFIX}" or be a short preset`
2520
+ ]);
2521
+ }
2522
+ async function decodeDeflate(code) {
2523
+ let bytes;
2524
+ try {
2525
+ const packed = fromB64url(code.slice(THEME_CODE_PREFIX.length));
2526
+ bytes = await through(packed, new DecompressionStream("deflate"), MAX_JSON_BYTES);
2527
+ } catch (e) {
2528
+ if (e instanceof ThemeError) throw e;
2529
+ throw new ThemeError("invalid theme", ["code is not valid base64url deflate data"]);
2530
+ }
2531
+ let parsed;
2532
+ try {
2533
+ parsed = JSON.parse(new TextDecoder().decode(bytes));
2534
+ } catch {
2535
+ throw new ThemeError("invalid theme", ["decoded payload is not JSON"]);
2536
+ }
2537
+ return validateTheme(parsed);
2538
+ }
1419
2539
  export {
2540
+ BUILDINGS_3D_LAYER_ID,
2541
+ DEFAULT_LAYER_VISIBILITY,
1420
2542
  DEFAULT_MARKER,
1421
2543
  DEFAULT_ROUTE,
1422
2544
  DEFAULT_SEEDS,
1423
2545
  LABEL_PAIRS,
2546
+ LAYER_GROUPS,
1424
2547
  MAX_CODE_LENGTH,
1425
2548
  MODES,
1426
- PRESET_THEMES,
2549
+ PRESET_CODE_PREFIX,
2550
+ PRESET_CODE_RE,
1427
2551
  RECIPES,
1428
- SEED_PALETTES,
1429
2552
  STOCK_RAMPS,
2553
+ STYLE_THEMES,
1430
2554
  THEME_BASES,
1431
2555
  THEME_CODE_PREFIX,
2556
+ THEME_PRESETS,
1432
2557
  ThemeError,
2558
+ applyThemeLayers,
2559
+ aqua,
1433
2560
  buildRecipes,
2561
+ cobalt,
1434
2562
  contrast,
1435
2563
  contrastWarnings,
2564
+ decodePreset,
1436
2565
  decodeTheme,
2566
+ effectiveLayerOrder,
1437
2567
  ember,
2568
+ encodePreset,
1438
2569
  encodeTheme,
1439
2570
  generateTheme,
1440
2571
  graphite,
1441
2572
  hexToOklch,
1442
2573
  ink,
2574
+ isLayerVisible,
2575
+ isStockLayerOrder,
2576
+ isStockLayers,
2577
+ isThemePresetCode,
2578
+ jade,
2579
+ layerGroupOf,
2580
+ lilac,
1443
2581
  makeFlavor,
1444
2582
  mergeRecipe,
2583
+ mist,
2584
+ normalizeThemeBase,
1445
2585
  oklchToHex,
2586
+ paper,
2587
+ presetId,
2588
+ registryThemeKey,
1446
2589
  resolveTheme,
2590
+ rose,
1447
2591
  sandstone,
1448
2592
  shuffleSeeds,
2593
+ sky,
1449
2594
  validateTheme,
1450
2595
  verdant,
1451
2596
  wave