diff --git a/pr-preview/pr-68/.nojekyll b/pr-preview/pr-68/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/pr-preview/pr-68/CNAME b/pr-preview/pr-68/CNAME new file mode 100644 index 0000000..18817f6 --- /dev/null +++ b/pr-preview/pr-68/CNAME @@ -0,0 +1 @@ +guide.cloudnativegeo.org diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-details.html b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-details.html new file mode 100644 index 0000000..3835bbf --- /dev/null +++ b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-details.html @@ -0,0 +1,824 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Advanced COG/GeoTIFF Details + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Advanced COG/GeoTIFF Details

+
+ + + +
+ + + + +
+ + +
+ +
+

Advanced COG/GeoTIFF Details

+

The COG Intro page describes what makes a Cloud-Optimized GeoTIFF different from a plain, non-optimized GeoTIFF. The rest of this page details additional useful information (applicable to both COGs and plain GeoTIFF files) that can be relevant for making your files as useful and efficient as possible. Any reference to “GeoTIFF” below applies both to plain GeoTIFF files and to COG files.

+
+

Data Type

+

Recommendation The smallest possible data type that still represents the data appropriately should be used. It is not generally recommended to shift or quantize data from float to integer by multiplying, a space saving technique, as end users then need to undo this step to use the data. Data compression is preferred, see also Compression.

+

The GeoTIFF format supports many data types. The key is that all bands must be of the same data type. Unlike some other formats, you cannot mix and match integer (whole number) and float (decimal number) data types in the same file. If you have this use case consider splitting files by data type and using a catalog like STAC to keep track of them, or look at other formats like Zarr.

+

Scenario: If the COG is intended only for visualization, conversion to 3 band byte will improve performance.

+
+

GDAL supported Data Types list

+
+
+
+

Compression

+

The compression used in a GeoTIFF is the greatest determinator of the file’s size. If storing a large amount of data, the right compression choice can lead to much smaller file sizes on disk, leading to lower costs.

+
+

Internal compression

+

GeoTIFFs have compression internal to the file, meaning that the internal blocks in a GeoTIFF are already compressed. This internal compression is especially useful for COGs, compared to external compression (such as saving a COG inside a ZIP file), since a COG reader can decompress only the specific portion of the file requested, instead of needing to decompress the entire file.

+

The internal compression of a GeoTIFF also means that it does not need additional compression, and indeed that additional compression will decrease performance. Gzip or ZIP compression applied to a GeoTIFF with internal compression will not make the file smaller.

+

It is possible but not recommended to create COGs or GeoTIFFs with no internal compression.

+
+
+

Compression codecs

+

There are a variety of compression codecs supported by GeoTIFF. Compression codecs tend to be split into two camps: lossy compression where the exact original values cannot be recovered or lossless compression which does not lose any information through the compression and decompression process. For most cases, a lossless compression is recommended, but in some cases a lossy compression can be useful and lead to smaller file sizes, such as if the COG is intended to be used only for visualization.

+

Deflate or LZW are both lossless compression codecs and are the recommended algorithms for general use.

+

JPEG is a lossy compression codec useful for true-color GeoTIFFs intended to be used only for visualization. Because it’s lossy, it tends to produce smaller file sizes than deflate or LZW. JPEG should only be used with RGB Byte data.

+

LERC (Limited Error Raster Compression) is a lossy but very efficient compression algorithm for floating point data. This compression rounds values to a precision provided by the user and tends to be useful e.g. for elevation data where the source data is known to not have precision beyond a known value. But note, this compression is not lossless. Additionally, LERC is a relatively new algorithm and may not be supported everywhere. GDAL needs to be compiled with the LERC driver in order to load a GeoTIFF with LERC compression.

+

Some other compression algorithms may be preferred depending on the data type and distribution, and if the goal is maximum compression or not. Codecs that produce the smallest file sizes tend to take longer to read into memory. If the network bandwidth to load the file is slow, then a very efficient compression algorithm may be most efficient, even if it takes longer to decompress when loaded. Alternatively, if the network speed is very fast, or if reading from a local disk, a slightly less efficient compression codec that decompresses faster may be preferred.

+

There are many posts on the internet exploring GeoTIFF compression and performance:

+ +
+
+
+

No Data

+

Setting a no data value makes it clear to users and visualization tools what pixels are not actually data. For visualization this allows these pixels to be easily hidden (transparent). Historically many values have been used, 0, -9999, etc… The key is to make sure the GDAL flag for no data is set. It is also suggested that the smallest negative value be used instead of a random value. For byte and unsigned integers data types this will be 0. For float data, setting NaN as the no data value is suggested. Make sure to use a no data value that does not have meaning in your data; otherwise use a different value (like the max possible value). Having the right nodata flag set is important for overview generation.

+
+
+

Projection

+

Read performance can be greatly impacted by the choice of projection and the particular applications used for dynamic tile serving. Using a known CRS defined in the PROJ database (typically EPSG code) is preferred over custom projections. Load times can be 5-20 times greater when using a custom projection. Whenever applying projections make sure to use WKT2 representation. If using a database of known projections, i.e. EPSG codes, this should be fine, there are known issues around manually setting proj-strings.

+
+
+

Web-Optimized COG

+

Up to this point, we’ve mentioned that a COG has internal tiling, but the exact layout of those internal tiles has been unspecified. A web-optimized COG exploits that internal tiling to enforce the same tiling as used in web maps. Additionally, overviews will also be aligned to the Web Mercator grid. Thus, a web-optimized COG is especially useful for relaying tiled image data to a browser. Because the internal tile layout exactly matches the tiling structure required in web mapping libraries, only one HTTP range request needs to be performed to access any tile.

+

Downsides of web-optimized COGs include the fact that they must be in Web Mercator projection and that the file most likely will not line up exactly with the bounds of the original image data. This means that the COG will have a “collar” of invalid data around the edges of the file.

+

Web-Optimized COGs can be created via GDAL by using the COG driver with the creation option TILING_SCHEME=GoogleMapsCompatible or with rio-cogeo with the --web-optimized flag.

+
+
+

What we don’t know (areas of research)

+
    +
  • The optimum size of data at which splitting across files improves performance as a multi-file dataset instead of a single file.
  • +
  • When to recommend particular internal tile sizes
  • +
  • Compression impacts on http transfer rates.
  • +
  • Support for COG creation in all common geospatial tools varies.
  • +
+
+
+

Additional Resources

+ + + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples.html b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples.html new file mode 100644 index 0000000..94d8506 --- /dev/null +++ b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples.html @@ -0,0 +1,1048 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Examples of Working with COGs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Examples of Working with COGs

+
+ + + +
+ + + + +
+ + +
+ +
+

Environment

+

The packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:

+
conda create -f environment.yml
+

or

+
mamba create -f environment.yml
+

This notebook has been tested to work with the listed Conda environment.

+
+
+

Setup

+

For demonstrating some COG concepts, we will download a regular GeoTIFF, create a Cloud-Optimized GeoTIFF and explore how they are different.

+

First we use the earthaccess library to setup credentials to fetch data from NASA’s EarthData catalog.

+
+
import earthaccess
+import rasterio
+from rasterio.plot import show
+from rio_cogeo import cog_validate, cog_info
+
+
/Users/kyle/local/micromamba/envs/coguide-cog/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
+  from .autonotebook import tqdm as notebook_tqdm
+
+
+
+
earthaccess.login()
+
+
EARTHDATA_USERNAME and EARTHDATA_PASSWORD are not set in the current environment, try setting them or use a different strategy (netrc, interactive)
+You're now authenticated with NASA Earthdata Login
+Using token with expiration date: 10/24/2023
+Using .netrc file for EDL
+
+
+
<earthaccess.auth.Auth at 0x10427d390>
+
+
+
+
+

Download a GeoTIFF from EarthData

+

Note: The whole point of is that we don’t download data. So in future examples, we will demonstrate how to access just subsets of data using COG and compare that with a GeoTIFF.

+
+
# Download data
+short_name = 'VCF5KYR'
+version = '001'
+
+veg_item_results = earthaccess.search_data(
+    short_name=short_name,
+    version=version,
+    count=1
+)
+
+
Granules found: 33
+
+
+
+
test_data_dir = "./test_data"
+veg_files = earthaccess.download(veg_item_results, test_data_dir)
+veg_gtiff_filename = f"{test_data_dir}/{veg_files[0]}"
+
+
 Getting 1 granules, approx download size: 0.07 GB
+File VCF5KYR_1982001_001_2018224204211.tif already downloaded
+
+
+
QUEUEING TASKS | : 100%|██████████| 1/1 [00:00<00:00, 900.84it/s]
+PROCESSING TASKS | : 100%|██████████| 1/1 [00:00<00:00, 15887.52it/s]
+COLLECTING RESULTS | : 100%|██████████| 1/1 [00:00<00:00, 29330.80it/s]
+
+
+
+

To learn more about the example data see the Vegetation Continuous Fields (VCF) information page.

+
+
+
+

Is it a valid COG?

+

We can use rio_cogeo.cog_validate to check. It returns is_valid, errors and warnings.

+
+
cog_validate(veg_gtiff_filename)
+
+
The following warnings were found:
+- The file is greater than 512xH or 512xW, it is recommended to include internal overviews
+
+The following errors were found:
+- The file is greater than 512xH or 512xW, but is not tiled
+
+
+
(False,
+ ['The file is greater than 512xH or 512xW, but is not tiled'],
+ ['The file is greater than 512xH or 512xW, it is recommended to include internal overviews'])
+
+
+

Return values:

+
    +
  1. is_valid is False: this is not a valid COG.
  2. +
  3. errors are 'The file is greater than 512xH or 512xW, but is not tiled'. To be a valid COG, the file should be tiled since it has a height and width both greater than 512.
  4. +
  5. warnings are 'The file is greater than 512xH or 512xW, it is recommended to include internal overviews'. It is recommended to provide overviews.
  6. +
+
+
+

Converting a GeoTIFF to COG

+

We can use rio_cogeo.cog_create to convert a GeoTIFF into a Cloud Optimized GeoTIFF

+
+
veg_cog_filename = veg_gtiff_filename.replace(".tif", "_cog.tif")
+
+!rio cogeo create {veg_gtiff_filename} {veg_cog_filename}
+
+
Reading input: /Users/kyle/ds/cloud-optimized-geospatial-formats-guide/cloud-optimized-geotiffs/test_data/VCF5KYR_1982001_001_2018224204211.tif
+  [####################################]  100%
+Adding overviews...
+Updating dataset tags...
+Writing output to: /Users/kyle/ds/cloud-optimized-geospatial-formats-guide/cloud-optimized-geotiffs/test_data/VCF5KYR_1982001_001_2018224204211_cog.tif
+
+
+
+
cog_validate(veg_cog_filename)
+
+
(True, [], [])
+
+
+

This is a valid COG, so we will use it to compare with our GeoTIFF.

+
+
+

Data Structure

+

Dimensions Dimensions are the number of bands, rows and columns stored in a GeoTIFF. More Info

+

Internal Blocks (aka chunks or internal tiles) Internal blocks are required if the dimensions of data are over 512x512. More Info

+

Let’s check out the dimensions and blocks of our GeoTIFF and Cloud-Optimized GeoTIFF.

+
+
veg_gtiff_rio = rasterio.open(veg_gtiff_filename)
+veg_cog_rio = rasterio.open(veg_cog_filename)
+
+
+
print(veg_gtiff_rio.shape)
+veg_cog_rio.shape
+
+
(3600, 7200)
+
+
+
(3600, 7200)
+
+
+

They have the same dimensions which is what we expect, so that is good!

+

We can also print information about the GeoTIFF’s IFD (Internal File Directory). Only one item is returned because the GeoTIFF doesn’t have overviews. When we print the IFD info for the COG, which has overviews, we see more items returned.

+
+
cog_info(veg_gtiff_filename).IFD
+
+
[IFD(Level=0, Width=7200, Height=3600, Blocksize=(1, 7200), Decimation=0)]
+
+
+
+
cog_info(veg_cog_filename).IFD
+
+
[IFD(Level=0, Width=7200, Height=3600, Blocksize=(512, 512), Decimation=0),
+ IFD(Level=1, Width=3600, Height=1800, Blocksize=(128, 128), Decimation=2),
+ IFD(Level=2, Width=1800, Height=900, Blocksize=(128, 128), Decimation=4),
+ IFD(Level=3, Width=900, Height=450, Blocksize=(128, 128), Decimation=8)]
+
+
+

Note for IFD Level 0, the regular GeoTIFF has a blocksize of (1, 7200) which implies each row of data is a separate block. So whenever reading in data, even if only a few columns are required, the full row must be read.

+
+
+

Overviews

+

Overviews are downsampled (aggregated) data intended for visualization.

+

The smallest size overview should match the tiling components’ fetch size, typically 256x256. Due to aspect ratio variation just aim to have at least one dimension at or slightly less than 256. > The COG driver in GDAL, or rio cogeo tools should do this.

+

There are many resampling algorithms for generating overviews. The best resampling algorithm depends on the range, type, and distribution of the data. When creating overviews several options should be compared before deciding which resampling method to apply.

+

GDAL >= 3.2 allows for the overview resampling method to be set directly.

+ +
+
veg_gtiff_rio.overviews(1)
+
+
[]
+
+
+
+
veg_cog_rio.overviews(1)
+
+
[2, 4, 8]
+
+
+

By displaying each overview, we can see how the dimensions get coarser for each overview level.

+
+
def show_overviews(geotiff):  
+    for overview in geotiff.overviews(1):
+        out_height = int(geotiff.height // overview)
+        out_width = int(geotiff.width // overview)
+        print(f"out height: {out_height}")
+        print(f"out width: {out_width}")    
+        # read first band of file and set shape of new output array
+        window_size_height = round(out_height/8)
+        window_size_width = round(out_width/8)
+        image = veg_cog_rio.read(1, out_shape=(1, out_height, out_width))[
+            window_size_height:(window_size_height*2),
+            window_size_width:(window_size_width*2),
+        ]
+        show(image)
+        
+show_overviews(veg_cog_rio)
+
+
out height: 1800
+out width: 3600
+out height: 900
+out width: 1800
+out height: 450
+out width: 900
+
+
+

+
+
+

+
+
+

+
+
+

We can generate more and different overviews, through different tilesizes and resampling.

+
+
import gen_overviews
+
+
+
tmp_dst = gen_overviews.create_overviews_from_gtiff(veg_gtiff_rio)
+tmp_cog = rasterio.open(tmp_dst)
+cog_info(tmp_dst).IFD
+
+
+
+
+
[IFD(Level=0, Width=7200, Height=3600, Blocksize=(1, 7200), Decimation=0),
+ IFD(Level=1, Width=3600, Height=1800, Blocksize=(128, 128), Decimation=2),
+ IFD(Level=2, Width=1800, Height=900, Blocksize=(128, 128), Decimation=4),
+ IFD(Level=3, Width=900, Height=450, Blocksize=(128, 128), Decimation=8),
+ IFD(Level=4, Width=450, Height=225, Blocksize=(128, 128), Decimation=16)]
+
+
+

Note: Now we have overviews but there are still no tiles on the Level 0 IFD.

+
+
overviews = tmp_cog.overviews(1)
+overviews
+
+
[2, 4, 8, 16]
+
+
+
+
show_overviews(tmp_cog)
+
+
out height: 1800
+out width: 3600
+out height: 900
+out width: 1800
+out height: 450
+out width: 900
+out height: 225
+out width: 450
+
+
+

+
+
+

+
+
+

+
+
+

+
+
+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-2.png b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-2.png new file mode 100644 index 0000000..79bbac4 Binary files /dev/null and b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-2.png differ diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-3.png b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-3.png new file mode 100644 index 0000000..ce9f3b3 Binary files /dev/null and b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-3.png differ diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-4.png b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-4.png new file mode 100644 index 0000000..e0c71be Binary files /dev/null and b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-15-output-4.png differ diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-2.png b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-2.png new file mode 100644 index 0000000..79bbac4 Binary files /dev/null and b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-2.png differ diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-3.png b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-3.png new file mode 100644 index 0000000..ce9f3b3 Binary files /dev/null and b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-3.png differ diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-4.png b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-4.png new file mode 100644 index 0000000..e0c71be Binary files /dev/null and b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-4.png differ diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-5.png b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-5.png new file mode 100644 index 0000000..5df1d99 Binary files /dev/null and b/pr-preview/pr-68/cloud-optimized-geotiffs/cogs-examples_files/figure-html/cell-19-output-5.png differ diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/environment.yml b/pr-preview/pr-68/cloud-optimized-geotiffs/environment.yml new file mode 100644 index 0000000..2af8f00 --- /dev/null +++ b/pr-preview/pr-68/cloud-optimized-geotiffs/environment.yml @@ -0,0 +1,11 @@ +name: coguide-cog +channels: + - conda-forge +dependencies: + - python=3.11 + - earthaccess + - ipykernel + - jupyterlab + - matplotlib + - rasterio + - rio-cogeo diff --git a/pr-preview/pr-68/cloud-optimized-geotiffs/intro.html b/pr-preview/pr-68/cloud-optimized-geotiffs/intro.html new file mode 100644 index 0000000..8b75da5 --- /dev/null +++ b/pr-preview/pr-68/cloud-optimized-geotiffs/intro.html @@ -0,0 +1,781 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Cloud-Optimized GeoTIFFs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Cloud-Optimized GeoTIFFs

+
+ + + +
+ + + + +
+ + +
+ +
+

What is a Cloud-Optimized GeoTIFF?

+

Cloud-Optimized GeoTIFF (COG), a raster format, is a variant of the TIFF image format that specifies a particular layout of internal data in the GeoTIFF specification to allow for optimized (subsetted or aggregated) access over a network for display or data reading. All COG files are valid GeoTIFF files, but not all GeoTIFF files are valid COG files. The key components that differ between GeoTIFF and COG are overviews and internal tiling.

+

For more details see https://www.cogeo.org/

+

COG Diagram

+
+

Dimensions

+

Dimensions are the number of bands, rows and columns stored in a GeoTIFF. There is a tradeoff between storing lots of data in one GeoTIFF and storing less data in many GeoTIFFs. The larger a single file, the larger the GeoTIFF header and the multiple requests may be required just to read the spatial index before data retrieval. The opposite problem occurs if you make too many small files, then it takes many reads to retrieve data, and when rendering a combined visualization can greatly impact load time.

+

If you plan to pan and zoom a large amount of data through a tiling service in a web browser, there is a tradeoff between 1 large file, or many smaller files. The current recommendation is to meet somewhere in the middle, a moderate amount of medium files.

+
+
+

Internal Blocks

+
+

This attribute is also sometimes called chunks or internal tiles.

+
+

Internal blocks are required if the dimensions of data are over 512x512. However you can control the size of the internal blocks. 256x256 or 512x512 are recommended. When displaying data at full resolution, or doing partial reading of data this size will impact the number of reads required. A size of 256 will take less time to read, and read less data outside the desired bounding box, however for reading large parts of a file, it may take more total read requests. Some clients will aggregate neighboring block reads to reduce the total number of requests.

+
+
+

Overviews

+

Overviews are downsampled (aggregated) data intended for visualization. The best resampling algorithm depends on the range, type, and distribution of the data.

+

The smallest size overview should match the tiling components’ fetch size, typically 256x256. Due to aspect ratio variation just aim to have at least one dimension at or slightly less than 256. The COG driver in GDAL, or rio cogeo tools should do this.

+

There are many resampling algorithms for generating overviews. When creating overviews several options should be compared before deciding which resampling method to apply.

+
+
+

See more

+ + + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/cloud-optimized-netcdf4-hdf5/index.html b/pr-preview/pr-68/cloud-optimized-netcdf4-hdf5/index.html new file mode 100644 index 0000000..b0ddc38 --- /dev/null +++ b/pr-preview/pr-68/cloud-optimized-netcdf4-hdf5/index.html @@ -0,0 +1,759 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Cloud-Optimized NetCDF4/HDF5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Cloud-Optimized NetCDF4/HDF5

+
+ + + +
+ + + + +
+ + +
+ +

Cloud-optimized access to NetCDF4/HDF5 files is possible. However, there are no standards for the metadata, chunking and compression for cloud-optimized access for these file types.

+
+
+
+ +
+
+Note +
+
+
+

Note: NetCDF4 are valid HDF5 files, see Reading and Editing NetCDF-4 Files with HDF5.

+
+
+

NetCDF4/HDF5 were designed for disk access and thus moving them to the cloud has borne little fruit. Matt Rocklin describes the issue in HDF in the Cloud: Challenges and Solutions for Scientific Data:

+
+

The HDF format is complex and metadata is strewn throughout the file, so that a complex sequence of reads is required to reach a specific chunk of data. The only pragmatic way to read a chunk of data from an HDF file today is to use the existing HDF C library, which expects to receive a C FILE object, pointing to a normal file system (not a cloud object store) (this is not entirely true, as we’ll see below).

+

So organizations like NASA are dumping large amounts of HDF onto Amazon’s S3 that no one can actually read, except by downloading the entire file to their local hard drive, and then pulling out the particular bits that they need with the HDF library. This is inefficient. It misses out on the potential that cloud-hosted public data can offer to our society.

+
+

To provide cloud-optimized access to these files without an intermediate service like Hyrax or the Highly Scalable Data Service (HSDS), it is recommended to determine if the NetCDF4/HDF5 data you wish to provide can be used with kerchunk. Rich Signell provided some insightful examples and instructions on how to create a kerchunk reference file (aka fsspec.ReferenceFileSystem) for NetCDF4/HDF5 and the things to be aware of in Cloud-Performant NetCDF4/HDF5 with Zarr, Fsspec, and Intake. Note, the post is from 2020, so it’s possible details have changed; however, the approach of using kerchunk for NetCDF4/HDF5 is still recommended.

+

Stay tuned for more information on cloud-optimized NetCDF4/HDF5 in future releases of this guide.

+ + + +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/contributing.html b/pr-preview/pr-68/contributing.html new file mode 100644 index 0000000..09b38f2 --- /dev/null +++ b/pr-preview/pr-68/contributing.html @@ -0,0 +1,882 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Get Involved + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Get Involved

+
+ + + +
+ + + + +
+ + +
+ +
+

Introduction

+

We encourage contributions to this guide. The guide’s goal is to provide documentation on the best practices for the current state-of-the-art cloud-optimized formats. These formats are evolving, and so will the guide.

+
+
+

Pre-requisites

+

If you wish to preview the site locally, install quarto. You will also need to be familiar with quarto markdown.

+
+
+

Communication Channels

+

Discussions can occur in GitHub Discussions and issues can be raised at GitHub Issues.

+
    +
  • GitHub Discussions: Ideal for questions, feature requests, or general conversations about the project. Use this space for collaborative discussions or if you’re unsure where to start.

  • +
  • GitHub Issues: Use this for reporting bugs, suggesting enhancements, or other tasks that require tracking and possibly code changes.

  • +
+
+
+

Core Principles

+
    +
  1. This guide intends to be opinionated but acknowledges no one-size-fits-all solution.
  2. +
  3. This guide should provide the best information and guidance available but acknowledge that experts develop many existing resources. Those resources should be linked as appropriate.
  4. +
+
+
+

Additional Criteria

+ +
+
+

Code of Conduct

+
    +
  • Be inclusive, respectful, and understanding of others’ backgrounds and contexts.
  • +
  • Look for and foster diverse perspectives.
  • +
  • If you experience any harmful behavior, please get in touch with Aimee or Alex.
  • +
+
+
+

Bug Reporting & Feature Requests

+

Before submitting a bug report or a feature request, please start a GitHub Discussion to see if the issue has already been addressed or if it can be resolved through discussion.

+
+

General Steps

+
    +
  1. Fork the repository.
  2. +
  3. Clone your fork locally.
  4. +
  5. Create a new branch for your changes.
  6. +
  7. Make your changes and use quarto preview to make sure they look good.
  8. +
  9. Open a pull request.
  10. +
+

Once the pull request is opened, and the GitHub preview.yml workflow runs (“Deploy PR previews”), you should have a preview available for review at https://developmentseed.org/cloud-optimized-geospatial-formats-guide/pr-preview/pr-<YOUR-PR-NUMBER-HERE>. A bot will comment on your PR when the PR preview is ready.

+
+
+

Specific Contributions

+
+

1. Adding a New Format

+

Follow the steps outlined in the General Steps, then:

+
    +
  1. Create a folder with the format’s name and, within that folder, an intro.qmd.
  2. +
  3. Link to the intro.qmd page in the index.qmd (the Welcome page) file and _quarto.yml table of contents.
  4. +
+
+
+

2. Modify or Add to an Existing Format

+

Feel free to modify or add to existing content if you think it could be improved.

+
+
+

3. Adding a Cookbook

+

Cookbooks should address common questions and present solutions for cloud-optimized access and visualization. To create a cookbook, either add a notebook directly to this repository in the cookbooks directory OR use an external link and add it to cookbooks/index.qmd.

+
+
+

4. (Optional) Update Slides

+

If you have made substantive changes, consider updating the Overview Slides. These slides are generated using Quarto and Reveal.js so can be updated with markdown syntax.

+
+
+

5. Add Yourself to the List of Authors

+

Add yourself to the list of authors on the Welcome page.

+
+
+

6. Final Steps Before Merging

+

Once your PR is approved and all checks have passed, a project maintainer will merge your changes into the main repository.

+
+
+
+
+

Licensing

+

This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. For attribution requirements, please look at the license terms.

+

Preferred citation: Barciauskas, A et al. 2023. Cloud Optimized Geospatial Formats Guide. CC-By-4.0.

+
+
+

Contact

+

For questions on how to contribute, start a discussion in the GitHub Discussions section.

+
+
+

Our Supporters

+
+

Thank you to our supporters

+

This guide has been made possible through the support of:

+
+
+
+
+

NASA Impact Logo

+
+
+
+

 

+
+
+
+

Development Seed Logo

+
+
+
+

 

+
+
+
+

Cloud-Native Geospatial Foundation

+
+
+
+
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/cookbooks/index.html b/pr-preview/pr-68/cookbooks/index.html new file mode 100644 index 0000000..d2abb6b --- /dev/null +++ b/pr-preview/pr-68/cookbooks/index.html @@ -0,0 +1,759 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Cloud-Optimized Cookbooks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Cloud-Optimized Cookbooks

+
+ + + +
+ + + + +
+ + +
+ +

Cookbooks should address common questions and present solutions for cloud-optimized access and visualization.

+

Cookbooks:

+ + + + +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/copc/index.html b/pr-preview/pr-68/copc/index.html new file mode 100644 index 0000000..f5c3b86 --- /dev/null +++ b/pr-preview/pr-68/copc/index.html @@ -0,0 +1,743 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Cloud-Optimized Point Clouds (COPC) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Cloud-Optimized Point Clouds (COPC)

+

An Introduction to Cloud-Optimized Point Clouds (COPC)

+
+ + + +
+ + + + +
+ + +
+ +

The LASER (LAS) file format is designed to store 3-dimensional (x,y,z) point cloud data typically collected from LiDAR. An LAZ file is a compressed LAS file and a Cloud-Optimized Point Cloud (COPC) file is a valid LAZ file.

+

COPC files are similar to COGs for GeoTIFFs: Both are valid versions of the original file format but with additional requirements to support cloud-optimized data access. In the case of COGs, there are additional requirements for tiling and overviews. For COPC, data must be organized into a clustered octree with a variable-length record (VLR) describing the octree structure.

+

Read more at https://copc.io/.

+

Stay tuned for more information on COPC in future releases of this guide.

+ + + +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/flatgeobuf/environment.yml b/pr-preview/pr-68/flatgeobuf/environment.yml new file mode 100644 index 0000000..3d93a58 --- /dev/null +++ b/pr-preview/pr-68/flatgeobuf/environment.yml @@ -0,0 +1,10 @@ +name: coguide-flatgeobuf +channels: + - conda-forge +dependencies: + - python=3.11 + - geopandas==0.13.2 + - pyogrio==0.6.0 + - ipykernel + - jupyterlab + - pyarrow diff --git a/pr-preview/pr-68/flatgeobuf/flatgeobuf-in-js.html b/pr-preview/pr-68/flatgeobuf/flatgeobuf-in-js.html new file mode 100644 index 0000000..6fecfdc --- /dev/null +++ b/pr-preview/pr-68/flatgeobuf/flatgeobuf-in-js.html @@ -0,0 +1,1004 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - FlatGeobuf in JavaScript + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

FlatGeobuf in JavaScript

+

Example of using FlatGeobuf with Leaflet

+
+ + + +
+ + + + +
+ + +
+ +

FlatGeobuf is a cloud-native vector data format because it contains a built-in spatial index that allows reading a specific spatial region from within the file without downloading the entire file’s content.

+

This is very useful for browser-based applications, because it allows them to make use of large files hosted on commodity cloud object storage without maintaining a server.

+

This notebook provides an example of using FlatGeobuf with spatial filtering from JavaScript.

+
+

Downloading vs Streaming vs Range reads

+

FlatGeobuf supports a few different ways of loading data into the browser.

+

Downloading refers to fetching the entire FlatGeobuf file and parsing it after the full file has finished downloading. This has the downside that the user must wait for the entire download to finish before they see any interaction on the web page. This may lead to a user wondering if the web page is broken if it takes a while to download their data.

+

Streaming refers to making use of a file’s contents incrementally as it downloads. This approach still downloads the entire file from beginning to end, but enables e.g. rendering part of the data on a map quickly, before waiting for the full file to finish downloading. This has the benefit of increased responsiveness, but the downside that a large file will be loaded in full. FlatGeobuf supports streaming because the file’s metadata is located at the beginning. A good example of this in action is “Streaming FlatGeobuf” by Björn Harrtell.

+

Range reads refers to fetching only specific parts of the file that are required by the user. In the context of FlatGeobuf, this usually means a spatial query. FlatGeobuf enables this through its spatial index at the beginning of the file. Web clients can read the header, and then make requests only for data in a specific location. This has the benefit that very large files can be used in situations where downloading them in full would be impractical. A downside is that it takes more individual HTTP requests to understand which byte range in the file contains the desired data, leading to a longer latency before data starts to display.

+
+
+

Example

+

This example uses slightly-modified JavaScript syntax used in Observable notebooks.

+

Load the FlatGeobuf JavaScript library:

+
+
flatgeobuf = require("flatgeobuf@3.26.2/dist/flatgeobuf-geojson.min.js")
+
+
+ +
+
+
+

This library has two functions: deserialize to fetch a remote file and parse it to GeoJSON, and serialize, which converts GeoJSON to FlatGeobuf.

+
+
flatgeobuf
+
+
+ +
+
+
+

For this demo, we’ll use the same data source as in the FlatGeobuf leaflet example. This data file represents every census block in the USA.

+
+
url = 'https://flatgeobuf.septima.dk/population_areas.fgb'
+
+
+ +
+
+
+

The above is a really big file at almost 12GB total size, so we don’t want to fetch the entire file. In this demo, we’ll choose a small bounding box representing an area over Manhattan in New York City.

+

Beware: if you make this bounding box too big, FlatGeobuf will try to download a large amount of data into your browser and maybe crash the tab!

+
+
bbox = {
+    return {
+        minX: -74.003802,
+        minY: 40.725756,
+        maxX: -73.981481,
+        maxY: 40.744008,
+    }
+}
+
+
+ +
+
+
+

The above bbox object represents a bounding box in the format required by the FlatGeobuf API, but Leaflet’s API requires an array-formatted bounding box, so we’ll define a function to convert between the two:

+
+
// leaflet uses lat-lon ordering
+bboxObjectToArray = (obj) => [
+  [obj.minY, obj.minX],
+  [obj.maxY, obj.maxX],
+];
+
+
+ +
+
+
+

Next we’ll fetch all the data from the FlatGeobuf file within this bounding box. Notice how we pass the bbox argument into deserialize.

+
+
features = {
+  const iter = flatgeobuf.deserialize(url, bbox);
+  const features = [];
+  for await (const feature of iter) {
+    features.push(feature);
+  }
+  return features;
+}
+
+
+ +
+
+
+

There are 354 individual features that match this query:

+
+
features
+
+
+ +
+
+
+

As in the FlatGeobuf example, we’ll define a color scale based on how many people live in the census block.

+
+
colorScale = (d) => {
+  return d > 750
+    ? "#800026"
+    : d > 500
+    ? "#BD0026"
+    : d > 250
+    ? "#E31A1C"
+    : d > 100
+    ? "#FC4E2A"
+    : d > 50
+    ? "#FD8D3C"
+    : d > 25
+    ? "#FEB24C"
+    : d > 10
+    ? "#FED976"
+    : "#FFEDA0";
+};
+
+
+ +
+
+
+

Next we load the Leaflet JavaScript library and fetch its CSS styling defintions if needed.

+
+
L = {
+  const L = await require("leaflet@1/dist/leaflet.js");
+  if (!L._style) {
+    const href = await require.resolve("leaflet@1/dist/leaflet.css");
+    document.head.appendChild(L._style = html`<link href=${href} rel=stylesheet>`);
+  }
+  return L;
+}
+
+
+ +
+
+
+

Next we instantiate the Leaflet map and include multiple layers:

+
    +
  • An L.tileLayer to show basemap tiles on the map for context.
  • +
  • An L.rectangle to show the bounding box of our FlatGeobuf query.
  • +
  • An L.layerGroup to group all the FlatGeobuf features into a single layer.
  • +
  • An L.geoJSON item for each feature in the FlatGeobuf response.
  • +
+
+
map = {
+  const container = html`<div style="height:600px;"></div>`;
+  yield container;
+  const map = L.map(container).setView([40.7299, -73.9923], 13);
+  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
+    attribution:
+      "&copy; <a href=https://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors",
+  }).addTo(map);
+
+  // Render the bounding box rectangle
+  L.rectangle(bboxObjectToArray(bbox), {
+    interactive: false,
+    color: "blue",
+    fillOpacity: 0.0,
+    opacity: 1.0,
+  }).addTo(map);
+
+  const results = L.layerGroup().addTo(map);
+  for (const feature of features) {
+    // Leaflet styling
+    const defaultStyle = {
+      color: colorScale(feature.properties["population"]),
+      weight: 1,
+      fillOpacity: 0.4,
+    };
+    L.geoJSON(feature, {
+      style: defaultStyle,
+    })
+      .on({
+        mouseover: function (e) {
+          const layer = e.target;
+          layer.setStyle({
+            weight: 4,
+            fillOpacity: 0.8,
+          });
+        },
+        mouseout: function (e) {
+          const layer = e.target;
+          layer.setStyle(defaultStyle);
+        },
+      })
+      .bindPopup(
+        `${feature.properties["population"]} people live in this census block.</h1>`
+      )
+      .addTo(results);
+  }
+}
+
+
+ +
+
+
+

Voilà! We just fetched data directly from a massive FlatGeobuf file, directly from the client, without a server in between.

+
+

References

+

This notebook was created with help from several resources

+ + + +
+
+ +
+ + + + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/flatgeobuf/flatgeobuf.html b/pr-preview/pr-68/flatgeobuf/flatgeobuf.html new file mode 100644 index 0000000..ad8b0f7 --- /dev/null +++ b/pr-preview/pr-68/flatgeobuf/flatgeobuf.html @@ -0,0 +1,1124 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - FlatGeobuf example + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

FlatGeobuf example

+
+ + + +
+ + + + +
+ + +
+ +

This notebook will give an overview of how to read and write FlatGeobuf files with GeoPandas, putting an emphasis on cloud-native operations where possible.

+

The primary way to interact with FlatGeobuf in Python is via bindings to GDAL, as there is no pure-Python implementation of FlatGeobuf.

+

There are two different Python libraries for interacting between Python and GDAL’s vector support: fiona and pyogrio. Both of these are integrated into geopandas.read_file via the engine keyword, but pyogrio is much faster. Set engine="pyogrio" when using read_file or GeoDataFrame.to_file to speed up reading and writing significantly. We also suggest passing use_arrow=True when reading for a slight extra speedup (this is not supported when writing).

+
+
+
+ +
+
+Note +
+
+
+

fiona is the default engine for geopandas.read_file. It provides full-featured bindings to GDAL but does not implement vectorized operations. Vectorization refers to operating on whole arrays of data at once rather than operating on individual values using a Python for loop. fiona’s non-vectorized approach means that each row of the source file is read individually with Python, and a Python for loop. In contrast, pyogrio’s vectorized implementation reads all rows in C before passing the data to Python, allowing it to achieve vast speedups (up to 40x) over fiona.

+

You can opt in to using pyogrio with geopandas.read_file by passing engine="pyogrio".

+

Additionally, if you’re using GDAL version 3.6 or higher (usually the case when using pyogrio), you can pass use_arrow=True to geopandas.read_file to use pyogrio’s support for GDAL’s RFC 86, which speeds up data reading even more.

+
+
+
+

Local vs Remote reading

+

The cloud-native vector ecosystem is young and doesn’t work as seamlessly as the COG and Zarr for subsetted access. We download data here to demonstrate important concepts but look to update these methods once better datasets and tools are available for working with FlatGeobuf without downloading entire files.

+

At the end of the notebook we have an example with reading via a spatial filter. Keep in mind that using a large spatial filter will cause the read to take a long time.

+
+
+

Environment

+

The packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:

+
conda create -f environment.yml
+

or

+
mamba create -f environment.yml
+

Alternatively, you can install the versions of pyogrio and geopandas used in this notebook with pip:

+
pip install pyogrio==0.6.0 geopandas==0.13.2
+
+
+

Imports

+
+
from tempfile import TemporaryDirectory
+from urllib.request import urlretrieve
+
+import geopandas as gpd
+import pyogrio
+
+
+
+

Reading from local disk

+

First we’ll cover reading FlatGeobuf from local disk storage. As a first example, we’ll use the US counties FlatGeobuf data from this example. This file is only 13 MB in size, which we’ll download to cover simple loading from disk.

+
+
# Create a temporary directory in which to save the file
+tmpdir = TemporaryDirectory()
+
+# URL to download
+url = "https://flatgeobuf.org/test/data/UScounties.fgb"
+
+# Download, saving the output path
+local_fgb_path, _ = urlretrieve(url, f"{tmpdir.name}/countries.fgb")
+
+

In each of the cases below, we use geopandas.read_file to read the file into a GeoDataFrame.

+

First we’ll show that reading this file with engine="fiona" (the default) is slower. Taking an extra 500 milliseconds might not seem like a lot, but this file contains only 3,000 rows, so this difference gets magnified with larger files.

+
+
%time gdf = gpd.read_file(local_fgb_path, engine="fiona")
+
+
CPU times: user 565 ms, sys: 16.9 ms, total: 582 ms
+Wall time: 685 ms
+
+
+

Passing engine="pyogrio" speeds up loading by 18x here!

+
+
%time gdf = gpd.read_file(local_fgb_path, engine="pyogrio")
+
+
CPU times: user 25.3 ms, sys: 6.84 ms, total: 32.1 ms
+Wall time: 31.3 ms
+
+
+

Using use_arrow=True often makes loading slightly faster again! We’re now 21x faster than using fiona.

+
+
%time gdf = gpd.read_file(local_fgb_path, engine="pyogrio", use_arrow=True)
+
+
CPU times: user 19.7 ms, sys: 10.1 ms, total: 29.7 ms
+Wall time: 29.1 ms
+
+
+
+
+

Writing to local disk

+

Similarly, we can use GeoDataFrame.to_file to write to a local FlatGeobuf file. As expected, writing can be much faster if you pass engine="pyogrio".

+

By default, this writes a spatial index to the created FlatGeobuf file.

+
+
%time gdf.to_file(f"{tmpdir.name}/out_fiona.fgb")
+
+
CPU times: user 362 ms, sys: 44.4 ms, total: 407 ms
+Wall time: 418 ms
+
+
+
+
%time gdf.to_file(f"{tmpdir.name}/out_pyogrio.fgb", engine="pyogrio")
+
+
CPU times: user 60.8 ms, sys: 23.4 ms, total: 84.2 ms
+Wall time: 83.5 ms
+
+
+
+
+

Reading from the cloud

+

Knowing how to read and write local files is important, but given that FlatGeobuf is a cloud-optimized format, it’s important to be able to read from cloud-hosted files as well.

+

For this example, we’ll use the EuroCrops data hosted on Source Cooperative because it has versions of the same data in both FlatGeobuf and GeoParquet format. Hopefully using the same dataset for both the FlatGeobuf and GeoParquet example notebooks will be helpful.

+
+
url = "https://data.source.coop/cholmes/eurocrops/unprojected/flatgeobuf/FR_2018_EC21.fgb"
+
+

Usually when reading from the cloud, you want to filter on some spatial extent. Pyogrio offers a read_info function to access many pieces of information about the file:

+
+
pyogrio.read_info(url)
+
+
{'crs': 'EPSG:4326',
+ 'encoding': 'UTF-8',
+ 'fields': array(['ID_PARCEL', 'SURF_PARC', 'CODE_CULTU', 'CODE_GROUP', 'CULTURE_D1',
+        'CULTURE_D2', 'EC_org_n', 'EC_trans_n', 'EC_hcat_n', 'EC_hcat_c'],
+       dtype=object),
+ 'dtypes': array(['object', 'float64', 'object', 'object', 'object', 'object',
+        'object', 'object', 'object', 'object'], dtype=object),
+ 'geometry_type': 'MultiPolygon',
+ 'features': 9517874,
+ 'driver': 'FlatGeobuf',
+ 'capabilities': {'random_read': 1,
+  'fast_set_next_by_index': 0,
+  'fast_spatial_filter': 1},
+ 'layer_metadata': None,
+ 'dataset_metadata': None}
+
+
+
+
+
+ +
+
+Note +
+
+
+

Sadly the output of read_info does not yet include the bounding box of the file, even though the FlatGeobuf file contains that information in the header. This may be a reason to consider externalizing metadata using Spatio-Temporal Asset Catalog files (STAC) in the future.

+
+
+

For now we’ll hard-code a region around Valence in the south of France, which we know the be within our dataset.

+
+
# The order of bounds is
+# (min longitude, min latitude, max longitude, max latitude)
+bounds = (4.301042, 44.822783, 4.410535, 44.877149)
+
+

We can fetch a dataframe containing only the records in these bounds by passing a bbox argument to read_file. Note that the Coordinate Reference System of this bounding box must match the CRS of the dataset. Here, we know from the output of read_info that the CRS of the dataset is EPSG:4326, so we can pass a longitude-latitude bounding box.

+
+
%time crops_gdf = gpd.read_file(url, bbox=bounds)
+
+
CPU times: user 144 ms, sys: 21.4 ms, total: 165 ms
+Wall time: 6 s
+
+
+

Passing engine="pyogrio" is only slightly faster, which may mean that most of the time is taken up in network requests, not in parsing the actual data into Python.

+
+
%time crops_gdf = gpd.read_file(url, bbox=bounds, engine="pyogrio")
+
+
CPU times: user 26.9 ms, sys: 2.98 ms, total: 29.9 ms
+Wall time: 490 ms
+
+
+

This gives us a much smaller dataset of only 400 rows (down from 9.5 million rows in the original dataset).

+
+
crops_gdf.head()
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID_PARCELSURF_PARCCODE_CULTUCODE_GROUPCULTURE_D1CULTURE_D2EC_org_nEC_trans_nEC_hcat_nEC_hcat_cgeometry
0948457311.08SPL17NoneNoneSurface pastorale - ressources fourragères lig...Pastoral area - predominant woody fodder resou...other_tree_wood_forest3306990000MULTIPOLYGON (((4.41142 44.85441, 4.41145 44.8...
14872182.53PPH18NoneNonePrairie permanente - herbe prédominante (resso...Permanent pasture - predominantly grass (woody...pasture_meadow_grassland_grass3302000000MULTIPOLYGON (((4.41366 44.85898, 4.41373 44.8...
24872240.89CTG22NoneNoneChâtaigneChestnutsweet_chestnuts3303030500MULTIPOLYGON (((4.41159 44.85891, 4.41034 44.8...
394845421.31CTG22NoneNoneChâtaigneChestnutsweet_chestnuts3303030500MULTIPOLYGON (((4.40904 44.85805, 4.41034 44.8...
44872161.70BOP17NoneNoneBois pâturéGrazed woodother_tree_wood_forest3306990000MULTIPOLYGON (((4.41135 44.85476, 4.41134 44.8...
+ +
+
+
+
+
crops_gdf.shape
+
+
(415, 11)
+
+
+

There are other useful keyword arguments to read_file. Since we’re using the pyogrio engine, we can pass specific column names into read_file, and only those columns will be parsed. In the case of FlatGeobuf, this doesn’t save us much time, because the same amount of data needs to be fetched. (Though if running this cell soon after the previous one, the relevant data will be cached and won’t be downloaded again.)

+
+
column_names = ["ID_PARCEL", "SURF_PARC", "CODE_CULTU", "geometry"]
+%time crops_gdf = gpd.read_file(url, bbox=bounds, columns=column_names, engine="pyogrio")
+
+
CPU times: user 25 ms, sys: 2.47 ms, total: 27.4 ms
+Wall time: 706 ms
+
+
+
+
crops_gdf.head()
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CODE_CULTUID_PARCELSURF_PARCgeometry
0SPL948457311.08MULTIPOLYGON (((4.41142 44.85441, 4.41145 44.8...
1PPH4872182.53MULTIPOLYGON (((4.41366 44.85898, 4.41373 44.8...
2CTG4872240.89MULTIPOLYGON (((4.41159 44.85891, 4.41034 44.8...
3CTG94845421.31MULTIPOLYGON (((4.40904 44.85805, 4.41034 44.8...
4BOP4872161.70MULTIPOLYGON (((4.41135 44.85476, 4.41134 44.8...
+ +
+
+
+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/flatgeobuf/hilbert-r-tree.html b/pr-preview/pr-68/flatgeobuf/hilbert-r-tree.html new file mode 100644 index 0000000..604b909 --- /dev/null +++ b/pr-preview/pr-68/flatgeobuf/hilbert-r-tree.html @@ -0,0 +1,790 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - FlatGeobuf Spatial Index + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

FlatGeobuf Spatial Index

+

Breaking down the Hilbert Packed R-Tree

+
+ + + +
+ + + + +
+ + +
+ +

FlatGeobuf optionally supports including a spatial index that enables random access for each geometry in the file.

+
+

When to use

+

When writing a FlatGeobuf file, one must decide whether to include a spatial index. A spatial index cannot be added to a FlatGeobuf file after the file has been written.

+

A spatial index can enable much more efficient reading from FlatGeobuf, by allowing the reader to skip over portions of the file that fall outside of a qiven spatial query region.

+
+
+

Technical details

+

In this section we’ll get into some gory technical details of how FlatGeobuf’s spatial index works. Understanding the below isn’t necessary for using FlatGeobuf, but it may add context for understanding how to create and work with FlatGeobuf files, and why FlatGeobuf is performant.

+

FlatGeobuf’s spatial index is a static packed Hilbert R-tree index. That’s a mouthful, so let’s break it down:

+
+

R-tree index

+

An R-Tree is a hierarchical collection of bounding boxes. At the lowest level of the tree is a bounding box of every geometry. Then one level above the lowest level exists a collection of bounding boxes, each of which is formed as the union of all child boxes. This means that each box encompasses every child box. There are fewer boxes at this level, because each box contains many child boxes, each of which represents one original geometry. This process continues repeatedly until there’s only one bounding box that indirectly contains the entire dataset.

+

This index allows you to quickly search for features that intersect a given bounding box query. At the top level, compare the bounding box of each node to your query region. If those two don’t intersect, you can discard that node and all of its child nodes from the search, because you know that none of them could possibly fall within your search region.

+

Continuing this process allows you to quickly find only the specific items that are candidates for your search query.

+

+
+

R-Tree diagram from Wikipedia. From top to bottom, the three levels of this tree are the black, blue, and red boxes. The black boxes contain the most items and encompass the largest area, while the red boxes contain the fewest items and encompass a smaller area.

+
+

The Wikipedia article and this Mapbox blog post are great resources for better understanding how R-Trees work.

+
+
+

Hilbert

+

The elements of an R-Tree must be sorted before insertion to make the R-Tree useful. This is because the core benefit of an R-Tree is to exclude elements that aren’t within a spatial filter. If elements of each node are randomly drawn from different geographies, then each node’s bounding box will be so large that no nodes can be excluded.

+

But how do you sort geometries? They encompass two dimensions and a range of shapes. If you sort all geometries first on the x coordinate, then you may pair geometries that are far from each other on the y dimension. Instead, it’s ideal to use a space-filling curve. That’s math jargon, but essentially defines a way to sort elements in n dimensions using 1 dimensional numbers.

+

A Hilbert R-Tree uses a Hilbert Curve, a special type of space-filling curve, to sort the centers of geometries. This ensures that geometries that are nearby on both the x and y dimensions are placed close to each other in the R-Tree. This ensures that the resulting bounding boxes of the R-Tree are as small as possible, which means that the maximum number of elements can be discarded for any given spatial query.

+

This Crunchy Data blog post has helpful examples for why sorting input is important.

+
+
+

Static

+

FlatGeobuf files can’t be modified without rewriting the entire file, so this R-Tree is constructed in such a way that it can’t be modified, which allows for improved tree generation.

+
+
+

Packed

+

An R-Tree has a series of nodes at each level, where each node can contain up to n children. If the R-Tree might be updated, not every node will have a total of n children, because some space needs to be reserved for future elements.

+

Because the index is static and immutable, we can construct a packed index, where every node is completely full. This achieves better space utilization, and is more efficient for queries because there are fewer nodes to traverse.

+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/flatgeobuf/intro.html b/pr-preview/pr-68/flatgeobuf/intro.html new file mode 100644 index 0000000..4adf3fa --- /dev/null +++ b/pr-preview/pr-68/flatgeobuf/intro.html @@ -0,0 +1,870 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - FlatGeobuf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

FlatGeobuf

+

Guidelines for FlatGeobuf

+
+ + + +
+ + + + +
+ + +
+ +
+

FlatGeobuf

+

FlatGeobuf is a binary file format for geographic vector data, such as points, lines, and polygons.

+

Unlike some formats like Cloud-Optimized GeoTIFF, which builds on the previous success of TIFF and GeoTIFF, FlatGeobuf is a new format, designed from the ground up to be faster for geospatial data.

+

FlatGeobuf is widely supported — via its GDAL implementation — in many programming languages as well as applications like QGIS.

+

FlatGeobuf supports any vector geometry type defined in the OGC Simple Features specification. This includes the standard building blocks of Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, and GeometryCollection, but also includes more obscure types such as CircularString, Surface, and TIN (Triangulated irregular network). A best practice is to store only geometries with the same type, as that allows readers to know which geometry type is stored without scanning the entire file.

+

An optional row-based spatial index optimizes for remote reading.

+
+

File layout

+

The internal layout of the file has four sections: magic bytes (aka signature), header, index, and data (aka features).

+

+
+

Image source: Horace Williams, Kicking the Tires: Flatgeobuf

+
+
    +
  1. The file signature is 8 “magic bytes” indicating the file type and specification version, which allows readers to know a file is FlatGeobuf, even if it’s missing a file extension.
  2. +
  3. Next comes the header, which stores the bounding box of the dataset, the geometry type of the features (if known and unique), the attribute schema, the number of features, and coordinate reference system information.
  4. +
  5. After the file header is an optional spatial index. If included, this lets a reader skip reading features that are not within a provided spatial query.
  6. +
  7. Last come the individual features. The rest of the file is a sequence of feature records, placed end to end in a row-wise fashion.
  8. +
+
+
+

Row based

+

Internally, features are laid out in a row-oriented fashion rather than a column-oriented fasion. This means that it’s relatively cheap to select specific records from the file, but relatively expensive to select a specific column. This is ideal for a small spatial query (assuming an index exists in the file) but to load all geometries requires loading all attribute information as well.

+
+
+

No internal compression

+

FlatGeobuf does not support compression while maintaining the ability to seek within the file. In particular, FlatGeobuf’s spatial index describes the byte ranges in the uncompressed file. Those byte ranges will be incorrect if the file is compressed.

+

A compression like gzip can be applied to the FlatGeobuf file in full, but keep in mind that storing the compressed file will eliminate random access support.

+
+
+

No append support

+

FlatGeobuf is a write-only format, and doesn’t support appending, as that would invalidate the spatial index in the file.

+
+
+

Random access supported via spatial index

+

FlatGeobuf optionally supports a spatial index at the beginning of the file, which can speed up reading portions of a file based on a spatial query. For more information on how this spatial index works, refer to the Hilbert R Tree page.

+
+
+
+ +
+
+Note +
+
+
+

Note that because FlatGeobuf has no internal chunking, the spatial index references every single object in the file. This means that for datasets with many small geometries, like points, the spatial index will be very large as a proportion of the file size.

+
+
+ +
+
+

Streaming features is supported

+

FlatGeobuf supports streaming, meaning that you can use part of the file before the entire file has finished downloading. This is different than random access, because you have no ability to skip around in the file.

+

Streaming can be valuable because it makes an application seem more responsive; you can have something happen without having to wait for the full download to complete. A good example of this is this example by FlatGeobuf’s author Björn Harrtell. As the file is downloaded to the browser, portions of the file get rendered progressively in parts.

+

This works even with full-file compression like gzip or deflate because those compression algorithms support streaming decompression.

+
+
+

Broad type system

+

FlatGeobuf supports attributes with a range of types:

+
    +
  • Byte: Signed 8-bit integer
  • +
  • UByte: Unsigned 8-bit integer
  • +
  • Bool: Boolean
  • +
  • Short: Signed 16-bit integer
  • +
  • UShort: Unsigned 16-bit integer
  • +
  • Int: Signed 32-bit integer
  • +
  • UInt: Unsigned 32-bit integer
  • +
  • Long: Signed 64-bit integer
  • +
  • ULong: Unsigned 64-bit integer
  • +
  • Float: Single precision floating point number
  • +
  • Double: Double precision floating point number
  • +
  • String: UTF8 string
  • +
  • Json: General JSON type intended to be application specific
  • +
  • DateTime: ISO 8601 date time
  • +
  • Binary: General binary type intended to be application specific
  • +
+
+
+
+ +
+
+Note +
+
+
+

Note that FlatGeobuf is unable to store nested types without overhead. It doesn’t support a “list” or “dict” type apart from JSON, which has a parsing overhead.

+

In some situations, having strong nested type support can be useful. For example STAC stored as GeoParquet has columns that are nested, such as the assets column that needs to store a dictionary-like mapping from asset names to their information. FlatGeobuf is able to store such data by serializing it to JSON, but it’s not possible to see the nested schema before parsing the full dataset.

+
+
+
+
+

Known table schema

+

FlatGeobuf declares the schema of properties at the beginning of the file. This makes it much easier to read the file — compared to a fully schemaless format like GeoJSON — because the reader knows what data type each attribute has in advance.

+
+
+

References

+ + + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/geoparquet/environment.yml b/pr-preview/pr-68/geoparquet/environment.yml new file mode 100644 index 0000000..5576bb5 --- /dev/null +++ b/pr-preview/pr-68/geoparquet/environment.yml @@ -0,0 +1,18 @@ +name: coguide-geoparquet +channels: + - conda-forge +dependencies: + - python=3.11 + - aiohttp + # TODO: how to define "fsspec[http]", so we don't have to manually install aiohttp + - fsspec + - geopandas==0.13.2 + - ipykernel + - jupyterlab + - libgdal-arrow-parquet + - requests + # This is a hack to install pyarrow via pip because libgdal-arrow-parquet constrains libarrow to + # v10, which constrains pyarrow to v10, which is too old for the `filesystem` parameter at the end + # of the file + - pip: + - pyarrow diff --git a/pr-preview/pr-68/geoparquet/geoparquet-example.html b/pr-preview/pr-68/geoparquet/geoparquet-example.html new file mode 100644 index 0000000..d7f4e4b --- /dev/null +++ b/pr-preview/pr-68/geoparquet/geoparquet-example.html @@ -0,0 +1,1221 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - GeoParquet Example + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

GeoParquet Example

+
+ + + +
+ + + + +
+ + +
+ +

This notebook will give an overview of how to read and write GeoParquet files with GeoPandas, putting an emphasis on cloud-native operations where possible.

+

The easiest way to read and write GeoParquet files is to use GeoPandas’ read_parquet and to_parquet functions.

+
+
+
+ +
+
+Note +
+
+
+

Make sure to use the specific read_parquet and to_parquet functions. These will be much, much faster than using the usual read_file and to_file.

+
+
+
+

Environment

+

The packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:

+
conda create -f environment.yml
+

or

+
mamba create -f environment.yml
+

This notebook has been tested to work with the listed Conda environment. If you don’t want to use Conda or Mamba, install the latest versions of geopandas, fsspec, and pyarrow with pip. Note that you’ll also need the GDAL CLI with Parquet driver. If you’re on MacOS, you can install that via brew install gdal.

+
+
+

Imports

+
+
from urllib.request import urlretrieve
+
+import fsspec
+import geopandas as gpd
+from fsspec.implementations.http import HTTPFileSystem
+
+
+
+

Comparison with FlatGeobuf

+

In order to compare reading GeoParquet with FlatGeobuf, we’ll cover reading and writing GeoParquet files on local disk storage. To be consistent with the FlatGeobuf example, we’ll fetch the same US counties FlatGeobuf file (13 MB) and convert it to GeoParquet using ogr2ogr.

+
+
# URL to download
+url = "https://flatgeobuf.org/test/data/UScounties.fgb"
+
+# Download, saving to the current directory
+local_fgb_path, _ = urlretrieve(url, "countries.fgb")
+
+
+
!ogr2ogr countries.parquet countries.fgb
+
+

Loading this GeoParquet file is really fast! 13% faster than loading the same data via FlatGeobuf (shown in the FlatGeobuf example notebook).

+
+
%time gdf = gpd.read_parquet("countries.parquet")
+
+
CPU times: user 23.8 ms, sys: 11.8 ms, total: 35.6 ms
+Wall time: 34.1 ms
+
+
+
+
gdf
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
STATE_FIPSCOUNTY_FIPFIPSSTATENAMELSADgeometry
02300923009MEHancockCountyMULTIPOLYGON (((-68.53108 44.33278, -68.53348 ...
13300733007NHCoosCountyMULTIPOLYGON (((-71.05975 45.01485, -71.06939 ...
25000950009VTEssexCountyMULTIPOLYGON (((-71.49463 44.90874, -71.49392 ...
35001950019VTOrleansCountyMULTIPOLYGON (((-72.14193 45.00600, -72.16051 ...
42300723007MEFranklinCountyMULTIPOLYGON (((-70.83471 45.27514, -70.77984 ...
........................
32161500315003HIHonoluluCountyMULTIPOLYGON (((-171.73761 25.79210, -171.7513...
32171500715007HIKauaiCountyMULTIPOLYGON (((-160.55535 21.66345, -160.5541...
32181500915009HIMauiCountyMULTIPOLYGON (((-157.06121 20.89150, -157.0611...
32191500115001HIHawaiiCountyMULTIPOLYGON (((-155.08767 19.72887, -155.0909...
32201500515005HIKalawaoCountyMULTIPOLYGON (((-157.01455 21.18550, -157.0145...
+ +

3221 rows × 7 columns

+
+
+
+
+
+

Writing to local disk

+

We can use GeoDataFrame.to_parquet to write out this data to GeoParquet files locally. This is about 3x faster than writing the same dataset to FlatGeobuf, but note that FlatGeobuf’s writing is also calculating a spatial index.

+
+
%time gdf.to_parquet("countries_written.parquet")
+
+
CPU times: user 42.3 ms, sys: 12.6 ms, total: 55 ms
+Wall time: 53.9 ms
+
+
+
+
+

Reading from the cloud

+

As of GeoParquet version 1.0.0-rc.1, spatial indexing has not yet been implemented. Therefore, there is not yet an API in GeoPandas to read data given a specific bounding box.

+

What is already efficient in GeoParquet is reading only specified columns from a dataset.

+
+
url = "https://data.source.coop/cholmes/eurocrops/unprojected/geoparquet/FR_2018_EC21.parquet"
+
+

Note that since we’re fetching this data directly from the cloud, we need to pass in an fsspec filesystem object. Otherwise GeoPandas will attempt to load a local file.

+
+
filesystem = HTTPFileSystem()
+
+

By default, calling read_parquet will fetch the entire file and parse it all into a single GeoDataFrame. Since this is a 3GB file, downloading the file takes a long time:

+
+
# This cell will take a few minutes to run, because it downloads the entire file
+# %time gdf = gpd.read_parquet(url, filesystem=filesystem)
+
+

We can make this faster by only fetching specific columns. Because GeoParquet stores data in a columnar fashion, when selecting only specific columns we can download a lot less data.

+
+
# This cell will take a few minutes to run, because it downloads the entire file for these columns
+# %time gdf = gpd.read_parquet(url, columns=["ID_PARCEL", "geometry"], filesystem=filesystem)
+
+
+
+

Working with GeoParquet row groups (Advanced)

+

As described in the intro document, GeoParquet is a chunked format, which allows you to access one of the chunks of rows very efficiently. This can allow you to stream a dataset — loading and operating on one chunk at a time — if the dataset is larger than your memory.

+

GeoPandas does not yet have built-in support for working with row groups, so this section will use the underlying pyarrow library directly.

+
+
import pyarrow.parquet as pq
+from geopandas.io.arrow import _arrow_to_geopandas
+
+

First, we’ll create a ParquetFile object from the remote URL. All this does is load the metadata from the file, allowing you to inspect the schema and number of columns, rows, and row groups. Because this doesn’t load any actual data, it’s nearly instant to complete.

+
+
parquet_file = pq.ParquetFile(url, filesystem=filesystem)
+
+

We can access the column names in the dataset:

+
+
parquet_file.schema_arrow.names
+
+
['ID_PARCEL',
+ 'SURF_PARC',
+ 'CODE_CULTU',
+ 'CODE_GROUP',
+ 'CULTURE_D1',
+ 'CULTURE_D2',
+ 'EC_org_n',
+ 'EC_trans_n',
+ 'EC_hcat_n',
+ 'EC_hcat_c',
+ 'geometry']
+
+
+

This Parquet file includes 9.5 million rows:

+
+
parquet_file.metadata.num_rows
+
+
9517874
+
+
+

And 146 row groups. Given that each row group is about the same number of rows, each one contains around 65,000 rows.

+
+
parquet_file.num_row_groups
+
+
146
+
+
+

Then to load one of the row groups by numeric index, we can call ParquetFile.read_row_group.

+
+
pyarrow_table = parquet_file.read_row_group(0)
+
+

Note that this returns a pyarrow.Table, not a geopandas.GeoDataFrame. To convert between the two, we can use _arrow_to_geopandas. This conversion is very fast.

+
+
geopandas_gdf = _arrow_to_geopandas(pyarrow_table, parquet_file.metadata.metadata)
+
+

As expected, this row group contains right around 65,000 rows

+
+
geopandas_gdf.shape
+
+
(65536, 11)
+
+
+
+
geopandas_gdf.head()
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID_PARCELSURF_PARCCODE_CULTUCODE_GROUPCULTURE_D1CULTURE_D2EC_org_nEC_trans_nEC_hcat_nEC_hcat_cgeometry
01235636.38CZH5NoneNoneColza d’hiverWinter rapeseedwinter_rapeseed_rape3301060401MULTIPOLYGON (((3.33896 49.84122, 3.33948 49.8...
155270762.30PPH18NoneNonePrairie permanente - herbe prédominante (resso...Permanent pasture - predominantly grass (woody...pasture_meadow_grassland_grass3302000000MULTIPOLYGON (((-1.44483 49.61280, -1.44467 49...
2114792416.33PPH18NoneNonePrairie permanente - herbe prédominante (resso...Permanent pasture - predominantly grass (woody...pasture_meadow_grassland_grass3302000000MULTIPOLYGON (((2.87821 46.53674, 2.87820 46.5...
3129284425.10PPH18NoneNonePrairie permanente - herbe prédominante (resso...Permanent pasture - predominantly grass (woody...pasture_meadow_grassland_grass3302000000MULTIPOLYGON (((-0.19026 48.28723, -0.19025 48...
43183890.92PPH18NoneNonePrairie permanente - herbe prédominante (resso...Permanent pasture - predominantly grass (woody...pasture_meadow_grassland_grass3302000000MULTIPOLYGON (((5.72084 44.03576, 5.72081 44.0...
+ +
+
+
+

As before, we can speed up the data fetching by requesting only specific columns in the read_row_group call.:

+
+
pyarrow_table = parquet_file.read_row_group(0, columns=["ID_PARCEL", "geometry"])
+
+

Then the resulting GeoDataFrame will only have those two columns:

+
+
_arrow_to_geopandas(pyarrow_table, parquet_file.metadata.metadata).head()
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID_PARCELgeometry
0123563MULTIPOLYGON (((3.33896 49.84122, 3.33948 49.8...
15527076MULTIPOLYGON (((-1.44483 49.61280, -1.44467 49...
211479241MULTIPOLYGON (((2.87821 46.53674, 2.87820 46.5...
312928442MULTIPOLYGON (((-0.19026 48.28723, -0.19025 48...
4318389MULTIPOLYGON (((5.72084 44.03576, 5.72081 44.0...
+ +
+
+
+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/geoparquet/index.html b/pr-preview/pr-68/geoparquet/index.html new file mode 100644 index 0000000..f2e0979 --- /dev/null +++ b/pr-preview/pr-68/geoparquet/index.html @@ -0,0 +1,910 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - GeoParquet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

GeoParquet

+

Guidelines for GeoParquet

+
+ + + +
+ + + + +
+ + +
+ +
+

GeoParquet

+

GeoParquet is an encoding for how to store geospatial vector data (point, lines, polygons) in Apache Parquet, a popular columnar storage format for tabular data.

+

Parquet has a wide ecosystem of tools and support; GeoParquet builds on this success by defining how to store geometries in the Parquet format. Because GeoParquet is not a separate format, any program that can read Parquet is able to load GeoParquet as well, even if it can’t make sense of the geometry information. This is very similar to how GeoTIFF layers geospatial information on top of the existing TIFF image standard.

+

The two main things that GeoParquet defines on top of Parquet are how to encode geometries in the geometry column and how to include metadata like the geometries’ Coordinate Reference System (CRS).

+

GeoParquet is a relatively young format, and the specification has not yet reached a 1.0 release (as of August 2023, it’s at 1.0.0-rc.1). However, reading and writing GeoParquet has been supported in GDAL since version 3.5, and thus can be used in programs like GeoPandas and QGIS.

+
+
+
+ +
+
+Warning +
+
+
+

In GeoPandas use read_parquet and to_parquet to read and write GeoParquet, not read_file and to_file as one would use with most other formats. 1

+
+
+

Because GeoParquet stores geometries in standard Well-Known Binary (WKB), it supports any vector geometry type defined in the OGC Simple Features specification. This includes the standard building blocks of Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, and GeometryCollection. A best practice is to store only geometries with the same type, as that allows readers to know which geometry type is stored without scanning the entire file.

+

Some of the sections below will discuss strengths of Parquet in general. Keep in mind that because GeoParquet is built on top of Parquet, GeoParquet inherits all of these strengths.

+
+

File layout

+

Parquet files are laid out differently than other tabular formats like CSV or FlatGeobuf, so it’s helpful to see a diagram:

+
+
+

+
Schematic of Parquet file layout
+
+
+

A Parquet file consists of a sequence of chunks called row groups. These are logical groups of columns with the same number of rows. A row group consists of multiple columns, each of which is called a column chunk. These are sequences of raw column values that are guaranteed to be contiguous in the file. All row groups in the file must have the same schema, meaning that the data type of each column must be the same for every row group.

+

A Parquet file includes metadata describing the internal chunking. This metadata includes the byte range of every column chunk in the dataset. This allows a Parquet reader to fetch any given column chunk once they have the file metadata.

+

The Parquet metadata also includes column statistics (the minimum and maximum value) for each column chunk. This means that if a user is interested in data where column “A” has values greater than 100, the Parquet reader can skip loading and parsing any column chunks where the maximum is known to be less than 100.

+

In Parquet, the metadata is located at the end of the file rather than at the beginning. This makes it much easier to write, as you don’t need to know how many total rows you have at the beginning, but makes it slightly harder to read. In practice, this is not too much more difficult to read: a Parquet reader first reads the end of the file, then makes reads for select columns.

+
+

Column-oriented

+

The bytes of each column are contiguous, instead of each row. This means that it’s easy to filter on columns — fetching all rows of a single column — but not possible to filter on individual rows.

+
+
+

Column filtering

+

Because Parquet is column-oriented, a Parquet reader can fetch only specific columns that the user is interested in.

+
+
+

Row group filtering

+

Because Parquet is internally chunked, Parquet can fetch only specific row groups that meet a specific filtering condition.

+

Note that row group filtering on a specific column tends to only work well if the Parquet file was sorted on that column when saved. Non-sorted columns tend to have random values, and so the column statistics won’t tend to filter out many row groups.

+
+
+
+ +
+
+Note +
+
+
+

In general it’s only possible to optimize filtering row groups by one column. This is the biggest difference between file formats and databases. Databases can have multiple indexes on whatever columns you want, and then when you run a query, and it will use all of the indexes. But that’s why it’s hard to make databases work as cloud-native files, because if you have high latency, you don’t want to make lots of tiny fetches.

+
+
+
+
+

Internal compression by default

+

Parquet is internally compressed by default and Parquet compression is more efficient compared to other formats.

+

Compression algorithms are more effective when nearby bytes are more similar to each other. Data within a column tends to be much more similar than data across a row. Since Parquet is column-oriented, compression algorithms work better and result in smaller file sizes than a comparable row-based format.

+

It’s possible to have random access to one of the internal chunks inside the file at large, even though that chunk is compressed. Note that it isn’t possible to fetch partial data inside one chunk without loading and decompressing the entire chunk.

+
+
+

Geometries encoded as Well-Known Binary

+

For maximum compatibility with existing systems, geometries are stored as ISO-standard WKB. Most geospatial programs are able to read and write WKB.

+
+
+

No spatial index (yet!)

+

GeoParquet is a young specification, and spatial indices are not yet part of the standard. Future revisions of GeoParquet are expected to add support for spatial indexes.

+

One way around this is to store multiple GeoParquet files according to some region identifier, cataloging each file with the SpatioTemporal Asset Catalog (STAC) specification.

+
+
+

Multithreading support but no streaming

+

In a streaming download, you read bytes starting at the beginning of the file, progressing towards the end. In Parquet, this is not helpful because the metadata is in the footer of the file instead of the header.

+

Instead, we can replicate something similar to streaming by first fetching only the metadata region at the end of the file, and then making multiple requests for each internal chunk.

+
+
+

Files are immutable

+

Once written, a Parquet file is immutable. No modification or appending can happen to that Parquet file. Instead, create a new Parquet file.

+
+
+

Multi-file support

+

While at medium data sizes GeoParquet is most easily distributed as a single file, at large data sizes a single dataset is often split into multiple files. Sometimes multiple files can be easier to write, such as if the data is output from a distributed system.

+

A best practice when writing multiple files is to store a top-level metadata file, often named _metadata, with the metadata of all Parquet files in the directory. Without a top-level metadata file, a reader must read the Parquet footer of every individual file in the directory before reading any data. With a metadata file, a Parquet reader can read just that one metadata file, and then read the relevant chunks in the directory. For more information on this, read the “Partitioned Datasets” and “Writing _metadata and _common_metadata files” of the pyarrow documentation. As of August 2023, GeoPandas has no way to write multiple GeoParquet files out of the box, though you may be able to pass a * glob with multiple paths into geopandas.read_parquet.

+

Storing Parquet data in multiple files makes it possible to in effect append to the dataset by adding a new file to the directory, but you must be careful to ensure that the new file has the exact same data schema as the existing files, and if a top-level metadata file exists, it must be rewritten to reflect the new file.

+

Some elements of how to store GeoParquet-specific metadata in a multi-file layout have not yet been standardized.

+
+
+

Extensive type system

+

Parquet supports a very extensive type system, including nested types such as lists and maps (i.e. like a Python dict). This means that you can store a key-value mapping or a multi-dimensional array within an attribute column of a GeoParquet dataset.

+
+
+
+

References

+ + + + +
+
+ + +

Footnotes

+ +
    +
  1. As pointed out by GDAL developer Even Rouault, reading GeoParquet through GDAL is just as fast as reading through the geopandas.read_parquet function if you’re using GDAL’s Arrow API. As of September 2023, this is not the default, so you need to opt into the pyogrio engine and opt into the Arrow API:

    +
    import geopandas as gpd
    +gpd.read_file("file.parquet", engine="pyogrio", use_arrow=True)
    +

    It’s also necessary to note that the Python wheels distributed by pyogrio do not include the Arrow and Parquet drivers by default. In order to use the pyogrio driver for a GeoParquet file, you need to compile from source when installing. You’ll need to have a GDAL installation version 3.6 or later (and built with Arrow and Parquet support, as seen by ogrinfo --formats) on your computer already, and then you can build pyogrio from source with:

    +
    pip install pyogrio --no-binary pyogrio
    +↩︎
  2. +
+
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/glossary.html b/pr-preview/pr-68/glossary.html new file mode 100644 index 0000000..c3cb9df --- /dev/null +++ b/pr-preview/pr-68/glossary.html @@ -0,0 +1,1109 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Glossary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Glossary

+
+ + + +
+ + + + +
+ + +
+ +

This glossary aims to describe all the jargon of geospatial in the cloud! Are we missing something? Create an issue to suggest an improvement.

+
+

Amazon S3 (S3)

+

The object storage service offered by Amazon. Part of Amazon Web Services.

+
+
+

Amazon Web Services (AWS)

+

Cloud computing services offered by Amazon.

+
+
+

Archive format

+

A file format which stores one or more other files, possibly with compression. Examples include ZIP archives and PMTiles.

+
+
+

Array Dimensions

+

The number of variables represented by an array. If an array represents longitude, latitude, time, and temperature, the array has four dimensions.

+
+
+

Asynchronous

+

A manner of scaling computing, to allow more operations to happen at the same time.

+

Think of a glass of water. Synchronous computing is akin to having one straw: when you’ve finished drinking all you wish to drink, you give the straw to your friend for them to drink. Asynchronous computing is akin to sharing the straw between you and your friend. There’s still only one straw, but you can hand off sips. Parallel computing (like multithreading or multiprocessing) is like having two straws, where both you and your friend can drink out of the glass at the same time.

+
+
+

Bandwidth

+

The speed at which data travels over a network. Usually used in reference to downloading or uploading files.

+

See also: latency.

+
+
+

Chunk

+

A grouping of data as part of a file format.

+

In a COG, this refers to a slice of the full array, usually 256 pixels high by 256 pixels wide (256x256), or 512 pixels high by 512 pixels wide (512x512).

+

In a GeoParquet file, this refers to a slice of a group of columns, where the slice has the same number of rows in each column.

+
+
+

Chunk size

+

The size of each chunk in a file format.

+

The chunk size plays a large part in how efficient random access within the file can be. If the chunk size is too small, then the metadata describing the file and the chunk byte ranges will be very large, and many HTTP range requests may have to be made for each small piece desired within the file. On the other hand, if the chunk size is too large, then a reader will have to read a large amount of data even for a very small query.

+
+
+

Cloud

+

Computing services hosted by an external provider, where the provider pays for the upfront cost of buying hardware, earning a profit by selling services. This allows users to scale workloads efficiently because users do not need to pay large upfront costs for computers. These rented services can include compute time or object storage.

+

Usually refers to services hosted by Amazon, Google, or Microsoft.

+
+
+

Cloud-Optimized

+

The property of a file format to be able to read a meaningful part of the file without needing to download all of the file. In particular, this means the file can be used efficiently from cloud storage via HTTP range requests.

+
+
+

Cloud-Optimized GeoTIFF (COG)

+

An extension of GeoTIFF with well-defined internal chunking, designed for efficient random access of the contained raster data.

+
+
+

Cloud-Optimized Point Cloud (COPC)

+

A cloud-optimized file format for point cloud data.

+
+
+

Compression

+

An algorithm that makes data smaller, at the cost of having to encode data into the compressed format before saving and having to decode data out of the compressed format before usage. In most cases, the benefits of smaller file sizes when stored outweigh the time it takes to encode and decode the compressed format.

+

Compression can either be external or internal to a file, and can either be lossless or lossy.

+
+
+

Content Delivery Network (CDN)

+

A globally-distributed network of storage servers designed to cache HTTP requests so that future requests can use the cached copy instead of asking the origin server or storage.

+
+
+

Coordinate Reference System (CRS)

+

Also called a projection

+
+
+

Data Type

+
+
+

Deflate

+

A lossless compression codec used as part of ZIP archives and internally within COG and GeoTIFF files.

+
+
+

Entwine Point Cloud

+

A cloud-optimized file format for point cloud data. Entwine has largely been superseded by COPC because COPC is backwards-compatible with previous point cloud data formats.

+
+
+

EPSG code

+

A projection definition referring to the EPSG database. EPSG codes tend to be four or five digits and tend to be easier to remember and use than longer definitions, such as WKT strings or PROJJSON. The downside of EPSG codes is that the program needs to have the EPSG database available so that it can perform a lookup from the EPSG code to the full projection definition.

+
+
+

External compression

+

Compression that is not part of a file format’s own specification, and which is added on after the main file has been saved. This tends to be used as part of ZIP archives (with file extension .zip) or with standalone gzip compression (file extension .gz).

+

External compression tends to make a file no longer cloud-optimized, as it is usually no longer possible to read part of the file without fetching the entire file, as the entire file is necessary for decompression.

+

This is in contrast to internal compression.

+
+
+

fsspec

+

A Python library for abstracting among several different cloud storage providers. Allows uploading and downloading files to each provider with a consistent API.

+
+
+

GDAL

+

The Geospatial Data Abstraction Library, a widely-used open-source library for converting between different raster data formats, as well as reprojecting between coordinate reference systems.

+

Its common command-line tools include gdalinfo and gdal_translate. It can be used from Python with the rasterio library or from R with the terra library.

+
+
+

GeoDataFrame

+
+
+

GeoJSON

+

A file format for vector data, built on top of JSON. GeoJSON is a common format for transferring vector data to web browsers, because it’s easy for most programming languages to read and write, but tends to have a large size. It’s not cloud-optimized because it can’t be partially parsed; the entire file needs to be downloaded in order to use.

+
+
+

GeoPackage

+

A file format for vector data. GeoPackage supports multiple layers as part of a single file. Because a GeoPackage is internally stored as a SQLite database, it is not cloud-optimized because the entire file must be downloaded in order to read any part of the file.

+
+
+

GeoPandas

+

A Python library for using and managing vector data, organized around GeoDataFrames.

+
+
+

GeoParquet

+

An extension of the Parquet file format to store geospatial vector data. Can be read and written by tools including GDAL and GeoPandas.

+
+
+

GeoTIFF

+

An extension of TIFF to store geospatially-referenced image data. Includes extra information such as the coordinate reference system and geotransform.

+
+
+

Geotransform

+

A set of six numbers that describe where a raster image lies within its coordinate reference system.

+

The geotransform describes the resolution and real-world location of each pixel. The geotransform needs to be used in conjunction with a projection definition for pixels to be located accurately.

+

For more information (in a Python context) read Python affine transforms.

+
+
+

Google Cloud

+

Cloud computing services provided by Google.

+
+
+

gzip

+

A type of lossless compression for general use. Gzip is based on the deflate algorithm and tends to be used standalone for external compression. Files that end with .gz have been encoded with gzip compression.

+
+
+

Hilbert curve

+

A type of space-filling curve used as part of many spatial indexes that ensures that objects near each other in two-dimensional space (e.g. longitude-latitude) are also near each other when ordered in a file.

+
+
+

HTTP Range Request

+

HTTP is the protocol that governs how computers ask for data across a network. HTTP range requests is a part of the HTTP specification that defines how to ask for a specific byte range from a file, instead of the entire file.

+

HTTP range requests is a core part of what makes a file format cloud-optimized, because it means that part of a geospatial data file can be read and used without needing to download the entire file.

+
+
+

Internal compression

+

Compression that is part of a file format’s own specification.

+

File formats such as COG, COPC, and GeoParquet include internal compression. Internal compression is useful for cloud-optimized data formats because it allows internal chunks to be fetched with range requests but still have smaller sizes from compression.

+

For files that have already been internally compressed, adding another layer of external compression, such as ZIP or gzip, will likely not make the file smaller, and only serve to reduce performance by requiring an extra decompression step before the data can be used.

+
+
+

JPEG

+

A lossy compression codec used for visual images. It tends to have a better compression ratio than lossless compression codecs like deflate or LZW.

+
+
+

Latency

+

The time it takes for data to start being retrieved from a server.

+

See also: bandwidth.

+
+
+

LERC

+

LERC (Limited Error Raster Compression) is a lossy but very efficient compression algorithm for floating point raster data. This compression rounds values to a precision provided by the user and tends to be useful e.g. for elevation data where the source data is known to not have precision beyond a known value.

+

LERC is a relatively new algorithm and may not be supported everywhere. For example, GDAL needs to be compiled with the LERC driver in order to load a GeoTIFF with LERC compression.

+
+
+

Lossless compression

+

A type of compression where the exact original values can be recovered after decompression. This means that the compression process does not lose any information. Lossless compression codecs tend to give larger file sizes than lossy compression codecs.

+

Examples include deflate, LZW, gzip, and ZSTD.

+
+
+

Lossy compression

+

A type of compression where the exact original values cannot be recovered after decompression. This means that the compression process will lose information. Lossy compression codecs tend to give smaller file sizes than lossless compression codecs.

+

Examples include LERC and JPEG.

+
+
+

LZW

+

A lossless compression codec for general use. It tends to be slightly slower than deflate.

+
+
+

Mapbox Vector Tile

+

A file format for tiled vector data, usually used for visualization on web maps. PMTiles is a cloud-optimized archive format for storing millions of Mapbox Vector Tile files in an efficient manner, accessible via HTTP range requests.

+
+
+

Metadata

+

Information about the actual data, saved as part of the file format. This allows for recreating the exact data that existed before saving and for cloud-optimized data formats, usually stores the byte ranges of relevant data sections within the file, which allows for using HTTP range requests for efficient random access to that data section.

+
+
+

Microsoft Azure

+

Cloud computing services offered by Microsoft.

+
+
+

Multi-dimensional raster data

+
+
+

Multithreading

+

A manner of scaling computing, to allow more operations to happen at the same time.

+

Think of a glass of water. Synchronous computing is akin to having one straw: when you’ve finished drinking all you wish to drink, you give the straw to your friend for them to drink. Asynchronous computing is akin to sharing the straw between you and your friend. There’s still only one straw, but you can hand off sips. Parallel computing (including multithreading and multiprocessing) is like having two straws, where both you and your friend can drink out of the glass at the same time.

+
+
+

Numpy

+

The foundational Python library for managing n-dimensional array data.

+
+
+

Object storage (Cloud storage)

+

Object storage, or cloud storage, refers to massively scalable cloud storage solutions like Amazon S3. It is relatively cheap, able to hold files small or large, and supports reading data via HTTP range requests. Most open geospatial data is hosted in such cloud storage solutions.

+
+
+

OGR

+

A widely-used open-source library for converting between different vector data formats, as well as reprojecting between coordinate reference systems.

+

Its common command-line tools include ogrinfo and ogr2ogr. It can be used from Python with the pyogrio or fiona libraries or from R with the sf library.

+

OGR is installed as part of GDAL.

+
+
+

Overviews

+

Downsampled (aggregated) data intended for visualization and stored as part of a file format. Overviews are part of the COG specification, and allow reading “zoomed out” data without needing to read and downsample from “full resolution” data.

+
+
+

Parquet

+

A file format for tabular data with internal chunking and internal compression.

+
+
+

PDAL

+

The Point Data Abstraction Library, a widely-used open-source library for converting between different point cloud data formats and managing point cloud data.

+
+
+

PMTiles

+

A type of cloud-optimized archive format for tiled data. It can be used with either vector or raster tiled data, but is most often used with Mapbox Vector Tile files. The individual tiles in a PMTiles file are accessible via HTTP range requests.

+
+
+

Point Cloud Data

+

A type of geospatial data storing three dimensional point locations along with attributes for each point. Point cloud data may come from LIDAR sensors or other photogrammetry, and may represent three-dimensional terrain or buildings.

+
+
+

PROJJSON

+

A projection definition that uses JSON for encoding.

+

The specification is defined as part of the PROJ project and used as part of the GeoParquet vector file format.

+
+
+

Random access

+

The ability to quickly fetch part of a file without reading the entire file.

+

For example, consider videos on YouTube. If you select to watch a video starting from the ten minute mark, YouTube does not need to download the video up to that point. Rather it is able to use the metadata from the video file to know what byte range in the video file corresponds to the ten minute mark, and then use HTTP range requests to download only the part of the video you’ve reqested.

+

The ability to perform efficient random access over a network is a core part of what makes data cloud-optimized.

+
+
+

Raster data

+

A type of geospatial data that stores regularly-gridded data. This often comes from aerial or satellite imagery sensors.

+
+
+

Shapefile

+

A vector data file format. There are many reasons to no longer use Shapefile.

+
+
+

Space-filling curve

+

An algorithm that translates two- or n- dimensional data into one-dimensional data. In practice, this is used as part of spatial indexes to group vector geometries nearby within a file according to their two-dimensional location.

+
+
+

Spatial index

+

A data structure used for searching through spatial data more efficiently.

+

For further reading: A dive into spatial search algorithms.

+
+
+

Tagged Image File Format (TIFF)

+

A file format for image data that supports lossless compression.

+
+
+

Vector data

+

A type of geospatial data to represent points, lines, and polygons.

+
+
+

Web Mercator

+

A coordinate reference system often used with tiled data for web maps.

+
+
+

Well-Known Binary (WKB)

+

A binary encoding for vector geometries that many systems can read and write. For example, GeoParquet uses WKB in its definition of the geometry column.

+
+
+

WKT (Geometry encoding)

+

A text encoding for vector geometries that many systems can read and write. WKT tends to be larger in size and slower to read and write than WKB, so only use WKT if you need to store geometries in a text file, such as a CSV.

+

Note that this is different than WKT (Projection definition).

+
+
+

WKT (Projection definition)

+

An encoding to store coordinate reference system information.

+

There have been multiple versions of WKT; it is suggested to use WKT2 whenever possible.

+
+
+

Zarr

+

A chunked, compressed file format for multi-dimensional raster data.

+
+
+

ZIP Archive

+

A type of archive format that is used to group together existing files. It can also be used to apply external compression onto existing files.

+
+
+

ZSTD

+

A very efficient lossless compression codec. ZSTD tends to give a very good compression ratio at very good performance, but may not be available everywhere. Check that your expected programs have access to ZSTD before using this on your data.

+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/images/2019-points-lines-polygons.png b/pr-preview/pr-68/images/2019-points-lines-polygons.png new file mode 100644 index 0000000..c55fbb6 Binary files /dev/null and b/pr-preview/pr-68/images/2019-points-lines-polygons.png differ diff --git a/pr-preview/pr-68/images/analytical_vs_tiled_geoms.png b/pr-preview/pr-68/images/analytical_vs_tiled_geoms.png new file mode 100644 index 0000000..6e289ea Binary files /dev/null and b/pr-preview/pr-68/images/analytical_vs_tiled_geoms.png differ diff --git a/pr-preview/pr-68/images/cog-diagram-1.png b/pr-preview/pr-68/images/cog-diagram-1.png new file mode 100644 index 0000000..1b1ac72 Binary files /dev/null and b/pr-preview/pr-68/images/cog-diagram-1.png differ diff --git a/pr-preview/pr-68/images/cog-overviews.png b/pr-preview/pr-68/images/cog-overviews.png new file mode 100644 index 0000000..b37e100 Binary files /dev/null and b/pr-preview/pr-68/images/cog-overviews.png differ diff --git a/pr-preview/pr-68/images/cogeo-formats-table.png b/pr-preview/pr-68/images/cogeo-formats-table.png new file mode 100644 index 0000000..07c7fc5 Binary files /dev/null and b/pr-preview/pr-68/images/cogeo-formats-table.png differ diff --git a/pr-preview/pr-68/images/copc-vlr-chunk-table-illustration.png b/pr-preview/pr-68/images/copc-vlr-chunk-table-illustration.png new file mode 100644 index 0000000..6311b0d Binary files /dev/null and b/pr-preview/pr-68/images/copc-vlr-chunk-table-illustration.png differ diff --git a/pr-preview/pr-68/images/fgb_diagram_2.png b/pr-preview/pr-68/images/fgb_diagram_2.png new file mode 100644 index 0000000..8bfd9d8 Binary files /dev/null and b/pr-preview/pr-68/images/fgb_diagram_2.png differ diff --git a/pr-preview/pr-68/images/flatgeobuf_file_layout.png b/pr-preview/pr-68/images/flatgeobuf_file_layout.png new file mode 100644 index 0000000..8bfd9d8 Binary files /dev/null and b/pr-preview/pr-68/images/flatgeobuf_file_layout.png differ diff --git a/pr-preview/pr-68/images/geoparquet_layout.png b/pr-preview/pr-68/images/geoparquet_layout.png new file mode 100644 index 0000000..87e05d2 Binary files /dev/null and b/pr-preview/pr-68/images/geoparquet_layout.png differ diff --git a/pr-preview/pr-68/images/gpq_query_window.png b/pr-preview/pr-68/images/gpq_query_window.png new file mode 100644 index 0000000..e3db5ca Binary files /dev/null and b/pr-preview/pr-68/images/gpq_query_window.png differ diff --git a/pr-preview/pr-68/images/higher-level-libraries.png b/pr-preview/pr-68/images/higher-level-libraries.png new file mode 100644 index 0000000..d2010e7 Binary files /dev/null and b/pr-preview/pr-68/images/higher-level-libraries.png differ diff --git a/pr-preview/pr-68/images/multi_refs.png b/pr-preview/pr-68/images/multi_refs.png new file mode 100644 index 0000000..2582898 Binary files /dev/null and b/pr-preview/pr-68/images/multi_refs.png differ diff --git a/pr-preview/pr-68/images/pmtiles-viewer.png b/pr-preview/pr-68/images/pmtiles-viewer.png new file mode 100644 index 0000000..3d75443 Binary files /dev/null and b/pr-preview/pr-68/images/pmtiles-viewer.png differ diff --git a/pr-preview/pr-68/images/r-tree.svg b/pr-preview/pr-68/images/r-tree.svg new file mode 100644 index 0000000..19b5b42 --- /dev/null +++ b/pr-preview/pr-68/images/r-tree.svg @@ -0,0 +1,1147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + R1 + R3 + R4 + R9 + R11 + R13 + R10 + R12 + R16 + R15 + R14 + R8 + R2 + R6 + R7 + R17 + R18 + R19 + R5 + + R1 + R2 + R3 + R4 + R5 + R6 + R7 + R8 + R9 + R10 + R11 + R12 + R13 + R14 + R15 + R16 + R17 + R18 + R19 + + diff --git a/pr-preview/pr-68/images/thankyous-cng-logo.png b/pr-preview/pr-68/images/thankyous-cng-logo.png new file mode 100644 index 0000000..55a440c Binary files /dev/null and b/pr-preview/pr-68/images/thankyous-cng-logo.png differ diff --git a/pr-preview/pr-68/images/thankyous-devseed-logo.png b/pr-preview/pr-68/images/thankyous-devseed-logo.png new file mode 100644 index 0000000..95b5bf2 Binary files /dev/null and b/pr-preview/pr-68/images/thankyous-devseed-logo.png differ diff --git a/pr-preview/pr-68/images/thankyous-impact-logo.png b/pr-preview/pr-68/images/thankyous-impact-logo.png new file mode 100644 index 0000000..9b88b6e Binary files /dev/null and b/pr-preview/pr-68/images/thankyous-impact-logo.png differ diff --git a/pr-preview/pr-68/images/tile-diagram.png b/pr-preview/pr-68/images/tile-diagram.png new file mode 100644 index 0000000..28d29be Binary files /dev/null and b/pr-preview/pr-68/images/tile-diagram.png differ diff --git a/pr-preview/pr-68/images/type-format-support-matrix.png b/pr-preview/pr-68/images/type-format-support-matrix.png new file mode 100644 index 0000000..b03f378 Binary files /dev/null and b/pr-preview/pr-68/images/type-format-support-matrix.png differ diff --git a/pr-preview/pr-68/images/xarray-datastructure.png b/pr-preview/pr-68/images/xarray-datastructure.png new file mode 100644 index 0000000..b862069 Binary files /dev/null and b/pr-preview/pr-68/images/xarray-datastructure.png differ diff --git a/pr-preview/pr-68/index.html b/pr-preview/pr-68/index.html new file mode 100644 index 0000000..f8171e3 --- /dev/null +++ b/pr-preview/pr-68/index.html @@ -0,0 +1,883 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Cloud-Optimized Geospatial Formats Guide

+

Methods for Generating and Testing Cloud-Optimized Geospatial Formats

+
+ + + +
+ + + + +
+ + +
+ +
+

Why Cloud Optimize?

+

Geospatial data is experiencing exponential growth in both size and complexity. As a result, traditional data access methods, such as file downloads, have become increasingly impractical for achieving scientific objectives. With the limitations of these older methods becoming more apparent, cloud-optimized geospatial formats present a much-needed solution.

+

Cloud optimization enables efficient, on-the-fly access to geospatial data, offering several advantages:

+
    +
  1. Reduced Latency: Subsets of the raw data can be fetched and processed much faster compared to downloading entire files.
  2. +
  3. Scalability: Cloud-optimized formats are usually stored on cloud object storage, which is infinitely scalable. Object storage supports many parallel read requests when combined with metadata about where different data bits are stored, making it easier to work with large datasets.
  4. +
  5. Flexibility: Cloud-optimized formats allow for high levels of customization, enabling users to tailor data access to their specific needs. Additionally, advanced query capabilities provide the freedom to perform complex operations on the data without downloading and processing entire datasets.
  6. +
  7. Cost-Effectiveness: Reduced data transfer and storage needs can lower costs. Many of these formats offer compression options, which reduce storage costs.
  8. +
+

If you want to provide optimized access to geospatial data, this guide is designed to help you understand the best practices and tools available for cloud-optimized geospatial formats.

+
+
+

Built for the Community, by the Community.

+

There is no one-size-fits-all approach to cloud-optimized data. Still, the community has developed many tools for creating and assessing geospatial formats that should be organized and shared.

+

This guide provides the landscape of cloud-optimized geospatial formats and the best-known answers to common questions.

+
+
+

How to Get Involved

+

If you want to contribute or modify content, read the Get Involved page.

+

If you have a question or idea for this guide, please start a Github Discussion.

+
+
+

The Opportunity

+

Storing data in the cloud does not on its own solve geospatial’s data problem. Users cannot reasonably wait to download, store, and work with large files on their machines. Large volumes of data must be available via subsetting methods to access data in memory.

+

While it is possible to provide subsetting as a service, this requires ongoing maintenance of additional servers and as well as extra network latency when accessing data (data has to go to the server where the subsetting service is running and then to the user). With cloud-optimized formats and the appropriate libraries, subsets of data can be accessed directly from an end user’s machine without introducing an additional server.

+

Regardless, users will access data over a network, which must be considered when designing the cloud-optimized format. Traditional geospatial formats are optimized for on-disk access via small internal chunks. A network introduces latency, and the number of requests must be considered.

+

As a community, we have arrived at the following cloud-optimized format pattern:

+
    +
  1. Metadata includes addresses for data blocks.
  2. +
  3. Metadata is stored in a consistent format and location.
  4. +
  5. Metadata can be read once.
  6. +
  7. Metadata can read the underlying file format, which supports subsetted access via addressable chunks, internal tiling, or both.
  8. +
+

These characteristics allow for parallelized and partial reading.

+
+
+

Data Type to Traditional to Cloud-Optimized Geospatial File Format Table

+

The diagram below depicts how some of the cloud-optimized formats discussed in this guide are cloud-optimized formats of traditional geospatial file formats.

+
+
+

+
Cloud-Optimized Geospatial Formats
+
+
+

Notes:

+
    +
  • Some data formats cover multiple data types, specifically: +
      +
    • GeoJSON can be used for vector and point cloud data.
    • +
    • HDF5 can be used for point cloud data or data cubes (or both via groups).
    • +
    • GeoParquet and FlatGeobuf can be used for vector data or point cloud data.
    • +
  • +
  • LAS files are intended for 3D points, not 2D points (since COPC files are compressed LAS files, the same goes for COPC files).
  • +
  • TopoJSON (an extension of GeoJSON that encodes topology) and newline-delimited GeoJSON are types of GeoJSON worth mentioning but have yet to be explicitly represented in the diagram.
  • +
  • GeoTIFF and GeoParquet are geospatial versions of the non-geospatial file formats TIFF and Parquet, respectively. FlatGeobuf builds upon the non-geospatial flatbuffers serialization library (though flatbuffers is not a standalone file format)
  • +
+
+
+

Table of Contents

+
    +
  1. Overview of Formats (slideshow)
  2. +
  3. Formats +
      +
    1. Cloud-Optimized GeoTIFFs
    2. +
    3. Zarr
    4. +
    5. Kerchunk
    6. +
    7. Cloud-Optimized NetCDF4/HDF5
    8. +
    9. GeoParquet
    10. +
    11. FlatGeobuf
    12. +
  4. +
  5. Cookbooks
  6. +
+
+
+

Running Examples

+

Most of the data formats covered in this guide have a Jupyter Notebook example that covers the basics of reading and writing the given format. At the top of each notebook is a link to an environment.yml file describing what libraries need to be installed to run correctly. You can use Conda or Mamba (a successor to Conda with faster package installs) to install the environment needed to run the notebook.

+
+
+

Authors

+
    +
  • Aimee Barciauskas
  • +
  • Alex Mandel
  • +
  • Kyle Barron
  • +
  • Zac Deziel
  • +
  • Overview Slide credits: Vincent Sarago, Chris Holmes, Patrick Quinn, Matt Hanson, Ryan Abernathey
  • +
+
+
+

Questions to Ask When Generating Cloud-Optimized Geospatial Data in Any Format

+
    +
  1. What variable(s) should be included in the new data format?
  2. +
  3. Will you create copies to optimize for different needs?
  4. +
  5. What is the intended use case or usage profile? Will this product be used for visualization, analysis, or both?
  6. +
  7. What is the expected access method?
  8. +
  9. How much of your data is typically rendered or selected at once?
  10. +
+
+
+

Our Supporters

+
+

Thank you to our supporters

+

This guide has been made possible through the support of:

+
+
+
+
+

NASA Impact Logo

+
+
+
+

 

+
+
+
+

Development Seed Logo

+
+
+
+

 

+
+
+
+

Cloud-Native Geospatial Foundation

+
+
+
+
+ + +
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/kerchunk/environment.yml b/pr-preview/pr-68/kerchunk/environment.yml new file mode 100644 index 0000000..5ec2f8a --- /dev/null +++ b/pr-preview/pr-68/kerchunk/environment.yml @@ -0,0 +1,15 @@ +name: coguide-kerchunk +channels: + - conda-forge +dependencies: + - python=3.11 + - cftime + - dask + - fsspec + - h5py + - imagecodecs + - ipykernel + - jupyterlab + - kerchunk + - s3fs + - xarray diff --git a/pr-preview/pr-68/kerchunk/intro.html b/pr-preview/pr-68/kerchunk/intro.html new file mode 100644 index 0000000..25d2f99 --- /dev/null +++ b/pr-preview/pr-68/kerchunk/intro.html @@ -0,0 +1,849 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Kerchunk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Kerchunk

+

References for (optionally) chunked, compressed n-dimensional arrays

+
+ + + +
+ + + + +
+ + +
+ +
+

What is Kerchunk?

+

Kerchunk is a python library for creating reference files (see next paragraph for an explanation) to support cloud-optimized access to traditional geospatial file formats, like NetCDF. Kerchunk negates the need to create and store copies of data for cloud-optimized access. Given the challenge of creating and maintaining copies of data, Kerchunk is a great tool.

+

Reference files can be used to instantiate an fsspec.FileSystemReference instance. Kerchunk reference files are json files with key value pairs for reading the underlying data as a Zarr data store. The keys are Zarr metadata paths or paths to zarr data chunks. The values for each key will either be raw data values or a list of the file URL, starting byte, and byte length where the data can be read.

+

As Kerchunk creates Zarr metadata for non-Zarr data, Kerchunk is compatible with Zarr tools that can use Zarr. Kerchunk enables a unified way to access chunked, compressed n-dimensionsional data across a variety of conventional data formats. The kerchunk library now supports NetCDF/HDF5, GRIB2, TIFF. Check the File format backends section of the kerchunk documentation for updates to supported formats.

+
+
+
+ +
+
+Warning +
+
+
+

A major limitation of kerchunk is the chunking of data will always be constrained to the chunk structure of the underlying data format. Read about zarr chunks on the Zarr page.

+
+
+

Learn more about kerchunk at kerchunk.readthedocs.io.

+
+
+

Why Kerchunk?

+

It is burdensome to create and maintain copies of data. The other pages in this guide introduce data formats which require processing and creating new data products. This process of creating and maintaining new data products, which are essentially copies of existing data, requires time and money. Kerchunk provides a method of providing cloud-optimized access to data that is more traditional archival formats.

+
+
+

How to kerchunk

+

As noted above, kerchunk is a python library you can use to create a reference file from any of the file formats it supports. The reference file is used by the fsspec.ReferenceFileSystem to read data from local or remote storage.

+

Here’s an example:

+
import fsspec
+import json
+from kerchunk.hdf import SingleHdf5ToZarr
+
+local_file = 'some_data.nc'
+out_file = 'some_references.json'
+
+# Instantiate the local file system with fsspec to save kerchunk's reference data as json.
+fs = fsspec.filesystem('')
+in_file = fs.open(local_file)
+
+# The inline threshold adjusts the size below which binary blocks are included directly in the output.
+# A higher inline threshold can result in a larger json file but faster loading time overally, since fewer requests are made.
+h5chunks = SingleHdf5ToZarr(in_file, local_file, inline_threshold=300)
+with fs.open(out_file, 'wb') as f:
+    f.write(json.dumps(h5chunks.translate()).encode())
+
+
+
+ +
+
+Note +
+
+
+

The powerful fsspec library provides a uniform file system interface to many different storage backends and protocols. In addition to abstracting existing protocols, its ReferenceFileSystem class lets you view byte ranges of some other file as a file system. Kerchunk generates these ReferenceFileSystem objects.

+
+
+

Kerchunk generates a “reference set” which is a set of references to data or URLs under a key value store that matches the Zarr spec. For example, a simple reference file for a NetCDF file might look like:

+
{
+  ".zgroup": "{\n    \"zarr_format\": 2\n}",
+  ".zattrs": "{\n    \"Conventions\": \"UGRID-0.9.0\n\"}",
+  "x/.zattrs": "{\n    \"_ARRAY_DIMENSIONS\": [\n        \"node\"\n ...",
+  "x/.zarray": "{\n    \"chunks\": [\n        9228245\n    ],\n    \"compressor\": null,\n    \"dtype\": \"<f8\",\n  ...",
+  "x/0": ["s3://bucket/path/file.nc", 294094376, 73825960]
+}
+

The ["s3://bucket/path/file.nc", 294094376, 73825960] is the key part, which says that to load the first chunk in the x dimension, the Zarr reader needs to fetch a byte range starting at 294094376 with a length of 73825960 bytes. This allows for efficient cloud-native data access without using the standard NetCDF driver.

+

Learn more about how to read and write kerchunk reference files in the Kerchunk in Practice notebook.

+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/kerchunk/kerchunk-in-practice.html b/pr-preview/pr-68/kerchunk/kerchunk-in-practice.html new file mode 100644 index 0000000..46a8310 --- /dev/null +++ b/pr-preview/pr-68/kerchunk/kerchunk-in-practice.html @@ -0,0 +1,3031 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Kerchunk in Practice + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Kerchunk in Practice

+
+ + + +
+ + + + +
+ + +
+ +

In this notebook, we demonstrate how to create a kerchunk reference file for one and then multiple publicly available NetCDF files and how to open a kerchunk store with xarray.

+

Generally, NetCDF should work with kerchunk. Some nested data structures and data types, such as those that can exist in HDF5, won’t work with kerchunk. A future release of this guide will provide further information and/or resources on limitations of kerchunk.

+
+

Environment

+

The packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:

+
conda create -f environment.yml
+

or

+
mamba create -f environment.yml
+

This notebook has been tested to work with the listed Conda environment.

+
+
+

How to create a kerchunk store

+

We can use the publicly available NEX GDDP CMIP6 dataset for this example. This dataset is provided by NASA and publicly available on AWS S3. You can browse that data in the nex-gddp-cmip6 file browser.

+
+
import json
+import os
+from tempfile import TemporaryDirectory
+
+import fsspec
+import imagecodecs.numcodecs
+import xarray as xr
+from kerchunk.combine import MultiZarrToZarr
+from kerchunk.hdf import SingleHdf5ToZarr
+
+imagecodecs.numcodecs.register_codecs() 
+
+
+
# Set variables
+## Since there are a number of CMIP6 models and variables to chose from, we make the model and variable selections variables.
+model = "ACCESS-CM2"
+# `tasmax` is daily-maximum near-surface air temperature, see https://pcmdi.llnl.gov/mips/cmip3/variableList.html.
+variable = "tasmax"
+## Note we are only reading historical data here, but model data is available for SSPs (Shared Socio-economic Pathways) as well.
+## SSPs are scenarios are used to model the future, so SSP files predict environment variables into the future.
+s3_path = f"s3://nex-gddp-cmip6/NEX-GDDP-CMIP6/{model}/historical/r1i1p1*/{variable}/*"
+
+# Initiate fsspec filesystem for reading.
+## We set anon=True because this specific dataset on AWS does not require users to be logged in to access.
+fs_read = fsspec.filesystem("s3", anon=True)
+
+# Retrieve list of available data.
+file_paths = fs_read.glob(s3_path)
+print(f"{len(file_paths)} discovered from {s3_path}")
+
+
65 discovered from s3://nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1*/tasmax/*
+
+
+

To start, we are just going to create a single reference file for a single NetCDF file.

+
+
netcdf_file = file_paths[0]
+netcdf_file
+
+
'nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc'
+
+
+
+
# Define a function to generate the kerchunk file so we can use it again for other files.
+def generate_json_reference(input_file, temp_dir: str):
+    """
+    Use Kerchunk's `SingleHdf5ToZarr` method to create a `Kerchunk` index from a NetCDF file.
+    """
+    with fs_read.open(input_file, **dict(mode="rb")) as infile:
+        print(f"Running kerchunk generation for {input_file}...")
+        # Chunks smaller than `inline_threshold` will be stored directly in the reference file as data (as opposed to a URL and byte range).
+        h5chunks = SingleHdf5ToZarr(infile, input_file, inline_threshold=300)
+        fname = input_file.split("/")[-1].strip(".nc")
+        outf = os.path.join(temp_dir, f"{fname}.json")
+        with open(outf, "wb") as f:
+            f.write(json.dumps(h5chunks.translate()).encode())
+        return outf
+
+
+
# Create a temporary directory to store the .json reference files.
+# Alternately, you could write these to cloud storage.
+td = TemporaryDirectory()
+temp_dir = td.name
+print(f"Writing single file references to {temp_dir}")
+
+
Writing single file references to /var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo
+
+
+
+
single_kerchunk_reference = generate_json_reference(netcdf_file, temp_dir)
+
+
Running kerchunk generation for nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc...
+
+
+

We might also want to inspect what was just created. Below we load just the first few keys and values of the “refs” part of the kerchunk reference file.

+
+
# Read and load the JSON file
+with open(single_kerchunk_reference, 'r') as file:
+    data = json.load(file)
+keys_to_select = ['.zgroup', 'tasmax/.zarray', 'tasmax/0.0.0']
+
+# Pretty print JSON data
+data_to_print = {}
+for key, value in data['refs'].items():
+    if key in keys_to_select:
+        if isinstance(value, str):
+            data_to_print[key] = json.loads(value)
+        else:
+            data_to_print[key] = value
+print(json.dumps(data_to_print, indent=4))
+
+
{
+    ".zgroup": {
+        "zarr_format": 2
+    },
+    "tasmax/.zarray": {
+        "chunks": [
+            1,
+            600,
+            1440
+        ],
+        "compressor": {
+            "id": "zlib",
+            "level": 5
+        },
+        "dtype": "<f4",
+        "fill_value": 1.0000000200408773e+20,
+        "filters": [
+            {
+                "elementsize": 4,
+                "id": "shuffle"
+            }
+        ],
+        "order": "C",
+        "shape": [
+            365,
+            600,
+            1440
+        ],
+        "zarr_format": 2
+    },
+    "tasmax/0.0.0": [
+        "nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc",
+        18097,
+        674483
+    ]
+}
+
+
+

We can also check that our reference file works with xarray.

+
+
# Open dataset as zarr object using fsspec reference file system and Xarray
+fs_single = fsspec.filesystem(
+    "reference", fo=single_kerchunk_reference, remote_protocol="https"
+)
+single_map = fs_single.get_mapper("")
+
+
+
ds_single = xr.open_dataset(single_map, engine="zarr", backend_kwargs=dict(consolidated=False))
+ds_single
+
+ +
+ + + + + + + + + + + + + + +
<xarray.Dataset>
+Dimensions:  (lat: 600, lon: 1440, time: 365)
+Coordinates:
+  * lat      (lat) float64 0.0 1.23e-321 0.0 ... -3.218e+163 -3.218e+163
+  * lon      (lon) float64 0.0 2.164e-314 0.0 ... -2.022e-53 -1.699e+282
+  * time     (time) datetime64[ns] 1950-01-01T12:00:00 ... 1950-12-31T12:00:00
+Data variables:
+    tasmax   (time, lat, lon) float32 ...
+Attributes: (12/22)
+    Conventions:           CF-1.7
+    activity:              NEX-GDDP-CMIP6
+    cmip6_institution_id:  CSIRO-ARCCSS
+    cmip6_license:         CC-BY-SA 4.0
+    cmip6_source_id:       ACCESS-CM2
+    contact:               Dr. Rama Nemani: rama.nemani@nasa.gov, Dr. Bridget...
+    ...                    ...
+    scenario:              historical
+    source:                BCSD
+    title:                 ACCESS-CM2, r1i1p1f1, historical, global downscale...
+    tracking_id:           f85d4c2e-48e4-484f-aad4-6a3f30a04326
+    variant_label:         r1i1p1f1
+    version:               1.0
+
+
+

It worked! But we can do even better. What if you want to open multiple NetCDF files with xarray? Let’s create kerchunk references for 3 files and then combine them.

+
+
subset_files = file_paths[0:3]
+subset_files
+
+
['nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc',
+ 'nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1951.nc',
+ 'nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1952.nc']
+
+
+
+
# Iterate through filelist to generate Kerchunked files. Good use for `dask.bag`, see: https://docs.dask.org/en/stable/bag.html.
+output_files = []
+for single_file in subset_files:
+    out_file = generate_json_reference(single_file, temp_dir)
+    output_files.append(out_file)
+
+
Running kerchunk generation for nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc...
+Running kerchunk generation for nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1951.nc...
+Running kerchunk generation for nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1952.nc...
+
+
+
+
output_files
+
+
['/var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.json',
+ '/var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1951.json',
+ '/var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1952.json']
+
+
+
+
# combine individual references into single consolidated reference
+mzz = MultiZarrToZarr(
+    output_files,
+    remote_protocol='s3',
+    remote_options={'anon': True},
+    concat_dims=['time'],
+    coo_map={'time': 'cf:time'},
+    # inline_threshold=0 means don't story any raw data in the kerchunk reference file.
+    inline_threshold=0
+)
+multi_kerchunk = mzz.translate()
+
+
+
# Write kerchunk .json record
+output_fname = os.path.join(temp_dir, f"combined_CMIP6_daily_{model}_{variable}_kerchunk.json")
+with open(f"{output_fname}", "wb") as f:
+    print(f"Writing combined kerchunk reference file {output_fname}")
+    f.write(json.dumps(multi_kerchunk).encode())
+
+
Writing combined kerchunk reference file /var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo/combined_CMIP6_daily_ACCESS-CM2_tasmax_kerchunk.json
+
+
+
+
# open dataset as zarr object using fsspec reference file system and Xarray
+fs_multi = fsspec.filesystem(
+    "reference",
+    fo=multi_kerchunk,
+    remote_protocol="s3"
+)
+multi_map = fs_multi.get_mapper("")
+
+
+
ds_multi = xr.open_dataset(multi_map, engine="zarr", backend_kwargs=dict(consolidated=False))
+ds_multi
+
+ +
+ + + + + + + + + + + + + + +
<xarray.Dataset>
+Dimensions:  (lat: 600, lon: 1440, time: 1096)
+Coordinates:
+  * lat      (lat) float64 0.0 2.164e-314 0.0 ... 2.961e-314 2.961e-314
+  * lon      (lon) float64 0.0 2.164e-314 0.0 ... -6.915e+193 -4.603e+95
+  * time     (time) datetime64[ns] 1950-01-01T12:00:00 ... 1952-12-31T12:00:00
+Data variables:
+    tasmax   (time, lat, lon) float32 ...
+Attributes: (12/22)
+    Conventions:           CF-1.7
+    activity:              NEX-GDDP-CMIP6
+    cmip6_institution_id:  CSIRO-ARCCSS
+    cmip6_license:         CC-BY-SA 4.0
+    cmip6_source_id:       ACCESS-CM2
+    contact:               Dr. Rama Nemani: rama.nemani@nasa.gov, Dr. Bridget...
+    ...                    ...
+    scenario:              historical
+    source:                BCSD
+    title:                 ACCESS-CM2, r1i1p1f1, historical, global downscale...
+    tracking_id:           f85d4c2e-48e4-484f-aad4-6a3f30a04326
+    variant_label:         r1i1p1f1
+    version:               1.0
+
+
+

Cool! Now we have 1096 days (3 years) of data.

+
+
+

How to read a Kerchunk Store

+

We’ve already demonstrated how to open the datasets with Xarray:

+
fs_multi = fsspec.filesystem(
+    "reference",
+    fo=multi_kerchunk,
+    remote_protocol="s3"
+)
+

Let’s take it line by line to understand what’s happening.

+
    +
  1. fsspec.filesystem is used to open the kerchunk reference. It is not necessary to have kerchunk installed to read data.
  2. +
  3. The first argument to fsspec.filesystem is the protocol. In the case of a kerchunk reference the protocol is the string "reference".
  4. +
  5. The fo argument is the set of reference files used to create a ReferenceFileSystem instance.
  6. +
  7. The remote_protocol argument is the protocol of the filesystem on which the references will be evaluated (unless fs is provided). If not given, will be derived from the first URL that has a protocol in the templates or in the references.
  8. +
+

Notice how the fs_multi object we’ve created is a fsspec.implementations.reference.ReferenceFileSystem.

+
+
type(fs_multi)
+
+
fsspec.implementations.reference.ReferenceFileSystem
+
+
+

Read about all the options for a fsspec.ReferenceFileSystem in the fsspec docs.

+

One other common situation is to load data over HTTP (as opposed to a local filesystem or via the S3 protocol). Here’s an example from the kerchunk case studies that loads a reference file and data files over HTTP:

+
+
zarr_all_url='https://sentinel-1-global-coherence-earthbigdata.s3.us-west-2.amazonaws.com/data/wrappers/zarr-all.json'
+
+mapper = fsspec.get_mapper(
+    'reference://',
+    fo=zarr_all_url,
+    target_protocol='http',
+    remote_protocol='http'
+)
+dataset = xr.open_dataset(
+    mapper, engine='zarr', backend_kwargs={'consolidated': False}
+)
+dataset
+
+ +
+ + + + + + + + + + + + + + +
<xarray.Dataset>
+Dimensions:          (season: 4, polarization: 4, latitude: 193200,
+                      longitude: 432000, coherence: 6, flightdirection: 2,
+                      orbit: 175)
+Coordinates:
+  * coherence        (coherence) float32 6.0 12.0 18.0 24.0 36.0 48.0
+  * flightdirection  (flightdirection) object 'A' 'D'
+  * latitude         (latitude) float32 82.0 82.0 82.0 ... -79.0 -79.0 -79.0
+  * longitude        (longitude) float32 -180.0 -180.0 -180.0 ... 180.0 180.0
+  * orbit            (orbit) float64 1.0 2.0 3.0 4.0 ... 172.0 173.0 174.0 175.0
+  * polarization     (polarization) object 'vv' 'vh' 'hv' 'hh'
+  * season           (season) object 'winter' 'spring' 'summer' 'fall'
+Data variables:
+    AMP              (season, polarization, latitude, longitude) float32 ...
+    COH              (season, polarization, coherence, latitude, longitude) float32 ...
+    inc              (orbit, flightdirection, latitude, longitude) float32 ...
+    lsmap            (orbit, flightdirection, latitude, longitude) float32 ...
+    rho              (season, polarization, latitude, longitude) float32 ...
+    rmse             (season, polarization, latitude, longitude) float32 ...
+    tau              (season, polarization, latitude, longitude) float32 ...
+
+
+

Because xarray uses fsspec to read data, you can also bypass creating a fsspec object explicitly. Here’s an example using of opening a kerchunk reference generated with pangeo-forge for the NOAA 1/4° daily Optimum Interpolation Sea Surface Temperature (or daily OISST) Climate Data Record (CDR).

+
+
url = "https://ncsa.osn.xsede.org/Pangeo/pangeo-forge/pangeo-forge/aws-noaa-oisst-feedstock/aws-noaa-oisst-avhrr-only.zarr/reference.json"
+ds = xr.open_dataset(
+    "reference://",
+    engine='zarr',
+    backend_kwargs={
+        'consolidated': False,
+        'storage_options': {
+            'fo': url,
+            'remote_options': {'anon': True},
+            'remote_protocol': 's3'}},
+    chunks={})
+ds
+
+ +
+ + + + + + + + + + + + + + +
<xarray.Dataset>
+Dimensions:  (time: 15044, zlev: 1, lat: 720, lon: 1440)
+Coordinates:
+  * lat      (lat) float32 -89.88 -89.62 -89.38 -89.12 ... 89.38 89.62 89.88
+  * lon      (lon) float32 0.125 0.375 0.625 0.875 ... 359.1 359.4 359.6 359.9
+  * time     (time) datetime64[ns] 1981-09-01T12:00:00 ... 2022-11-08T12:00:00
+  * zlev     (zlev) float32 0.0
+Data variables:
+    anom     (time, zlev, lat, lon) float32 dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>
+    err      (time, zlev, lat, lon) float32 dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>
+    ice      (time, zlev, lat, lon) float32 dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>
+    sst      (time, zlev, lat, lon) float32 dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>
+Attributes: (12/37)
+    Conventions:                CF-1.6, ACDD-1.3
+    cdm_data_type:              Grid
+    comment:                    Data was converted from NetCDF-3 to NetCDF-4 ...
+    creator_email:              oisst-help@noaa.gov
+    creator_url:                https://www.ncei.noaa.gov/
+    date_created:               2020-05-08T19:05:13Z
+    ...                         ...
+    source:                     ICOADS, NCEP_GTS, GSFC_ICE, NCEP_ICE, Pathfin...
+    standard_name_vocabulary:   CF Standard Name Table (v40, 25 January 2017)
+    summary:                    NOAAs 1/4-degree Daily Optimum Interpolation ...
+    time_coverage_end:          1981-09-01T23:59:59Z
+    time_coverage_start:        1981-09-01T00:00:00Z
+    title:                      NOAA/NCEI 1/4 Degree Daily Optimum Interpolat...
+
+
+
+
+

Other examples of existing kerchunk data

+ +
+
+

Additional resources

+ + + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/overview.html b/pr-preview/pr-68/overview.html new file mode 100644 index 0000000..c47fddc --- /dev/null +++ b/pr-preview/pr-68/overview.html @@ -0,0 +1,1099 @@ + + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - Cloud-Optimized Geospatial Formats Overview + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Cloud-Optimized Geospatial Formats Overview

+

These slides are a summarization of Cloud-Optimized Geospatial Formats Guide to support presentations.

+
+ + + +
+ +
+
Author
+
+

Authors + Credits: Aimee Barciauskas, Alex Mandel, Brianna Pagán, Vincent Sarago, Chris Holmes, Patrick Quinn, Matt Hanson, Ryan Abernathey

+
+
+ + + +
+ + +
+ +
+

These slides were generated with https://quarto.org/docs/presentations/revealjs. Source: https://github.com/cloudnativegeo/cloud-optimized-geospatial-formats-guide.

+
+
+

Cloud-Optimized Geospatial Formats Overview

+

Google Slides version of this content: Cloud-Optimized Geospatial Formats.

+
+
+

What Makes Cloud-Optimized Challenging?

+
    +
  • No one size fits all approach
  • +
  • Earth observation data may be processed into raster, vector and point cloud data types and stored in a long list of data formats and structures.
  • +
  • Optimization depends on the user.
  • +
  • Users must learn new tools and which data is accessed and how may differ depending on the user.
  • +
  • … hopefully only a few new methods and concepts are necessary.
  • +
+
+
+

What Makes Cloud-optimized Challenging?

+

+

image source: ui.josiahparry.com/spatial-analysis.html

+
+
+

What Makes Cloud-optimized Challenging?

+
+
+
+

There is no one-size-fits-all packaging for data, as the optimal packaging is highly use-case dependent.

+
+

Task 51 - Cloud-Optimized Format Study

+

Authors: Chris Durbin, Patrick Quinn, Dana Shum

+
+

+
+
+
+
+

What Does Cloud-Optimized Mean?

+

File formats are read-oriented to support:

+
    +
  • Partial reads
  • +
  • Parallel reads
  • +
+
+

What Does Cloud-Optimized Mean?

+
    +
  • File metadata in one read
  • +
  • When accessing data over the internet, such as when data is in cloud storage, latency is high when compared with local storage so it is preferable to fetch lots of data in fewer reads.
  • +
  • An easy win is metadata in one read, which can be used to read a cloud-native dataset.
  • +
  • A cloud-native dataset is one with small addressable chunks via files, internal tiles, or both.
  • +
+
+
+

What Does Cloud-Optimized Mean?

+
+
+
    +
  • Accessible over HTTP using range requests.
  • +
  • This makes it compatible with object storage (a file storage alternative to local disk) and thus accessible via HTTP, from many compute instances.
  • +
  • Supports lazy access and intelligent subsetting.
  • +
  • Integrates with high-level analysis libraries and distributed frameworks.
  • +
+
+

higher level libraries

+
+
+ +
+

image credit: Ryan Abernathey

+
+
+
+

Formats by Data Type

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatData TypeStandard Status
Cloud-Optimized GeoTIFF (COG)RasterOGC standard for comment
Zarr, KerchunkMulti-dimensional rasterESDIS and OGC standards in development
Cloud-Optimized Point Cloud (COPC), Entwine Point Tiles (EPT)Point Clouds*no known ESDIS or OGC standard
FlatGeobuf, GeoParquet,Vectorno known ESDIS, draft OGC standard
+
+
+

Formats by Adoption

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatAdoptionStandard Status
Cloud-Optimized GeoTIFF (COG)Widely adoptedOGC standard for comment
Zarr, Kerchunk(Less) widely adopted, especially in specific communitiesESDIS and OGC standards in development
Entwine Point Tiles (EPT), Cloud-Optimized Point Cloud (COPC)Less common (PDAL Supported)no known ESDIS or OGC standard
GeoParquet, FlatGeobufLess common (OGR Supported)no known ESDIS, draft OGC standard
+
+
+

What are COGs?

+
+
+
    +
  • COGs are raster data representing a snapshot in time of gridded data, for example digital elevation models (DEMs).
  • +
  • COGs are a de facto standard, with an Open Geospatial Consortium (OGC) standard under review.
  • +
  • The standard specifies conformance to how the GeoTIFF is formatted, with additional requirements of tiling and overviews.
  • +
+
+

+
+
+ +
+

image source: https://www.kitware.com/deciphering-cloud-optimized-geotiffs/

+
+

What are COGs?

+
+
+
    +
  • COGs have internal file directories (IFDs) which are used to tell clients where to find different overview levels and data within the file.
  • +
  • Clients can use this metadata to read only the data they need to visualize or calculate.
  • +
  • This internal organization is friendly for consumption by clients issuing HTTP GET range request (“bytes: start_offset-end_offset” HTTP header)
  • +
+
+

+
+
+ +
+

image source: https://medium.com/devseed/cog-talk-part-1-whats-new-941facbcd3d1

+
+
+
+

What is Zarr?

+
+
+
    +
  • Zarr is used to represent multidimensional raster data or “data cubes”. For example, weather data and climate models.
  • +
  • Chunked, compressed, N-dimensional arrays.
  • +
  • The metadata is stored external to the data files themselves. The data itself is often reorganized and compressed into many files which can be accessed according to which chunks the user is interested in.
  • +
+
+

+
+
+ +
+

image source: https://xarray.dev/

+
+
+

What is Kerchunk?

+
    +
  • Kerchunk is a way to create Zarr metadata for archival formats, so that you can leverage the benefits of partial and parallel reads for archives in NetCDF4, HDF5, GRIB2, TIFF and FITS.
  • +
+

. . .

+

+ +
+

image source: https://fsspec.github.io/kerchunk/detail.html

+
+

Zarr Specs in Development

+
    +
  • V2 and older specs exist, however,
  • +
  • A cross-organization working group has just formed to establish a GeoZarr standards working group, organized by Brianna Pagán (NASA) and includes representatives from many other orgs in the industry.
  • +
  • The GeoZarr spec defines conventions for how geospatial data should be organized in a Zarr store. The spec details how the Zarr DataArray and DataSet metadata, and subsequent organization of data, must be in order to be conformant as GeoZarr archive.
  • +
  • There is a proposal for Zarr v3 which will address challenges in language support, and storage organization to address the issues of high-latency reads and volume of reads for the many objects stored.
  • +
  • There is recent work on a parquet alternative to JSON for indexing.
  • +
+
+
+

COPC (Cloud-Optimized Point Clouds)

+

+ +
+

image source: https://copc.io/

+
    +
  • Point clouds are a set of data points in space, such as gathered from LiDAR measurements.
  • +
  • COPC is a valid LAZ file.
  • +
  • Similar to COGs but for point clouds: COPC is just one file, but data is reorganized into a clustered octree instead of regularly gridded overviews.
  • +
  • 2 key features: +
      +
    • Support for partial decompression via storage of data in a series of chunks
    • +
    • Variable-length records (VLRs) can store application-specific metadata of any kind. VLRs describe the octree structure.
    • +
  • +
  • Limitation: Not all attribute types are compatible.
  • +
+
+
+
+

FlatGeoBuf

+
+
+

+
+
    +
  • Vector data is traditionally stored as rows representing points, lines, or polygons with an attribute table.
  • +
  • FlatGeobuf is a binary encoding format for geographic data. Flatbuffers that hold a collection of Simple Features. Single-File.
  • +
  • A row-based streamable-spatial index optimizes for remote reading.
  • +
  • Developed with OGR compatibility in mind. Works with existing OGR APIs, e.g. python and R.
  • +
  • Works with HTTP range requests, and has CDN compatibility.
  • +
  • Limitation: Not compressed specifically to allow random reads.
  • +
  • Learn more: https://github.com/flatgeobuf/flatgeobuf, Kicking the Tires: Flatgeobuf
  • +
+
+
+ +
+

image source: https://worace.works/2022/02/23/kicking-the-tires-flatgeobuf/

+
+
+

Geoparquet

+
+
+

+
+
    +
  • Vector data is traditionally stored as rows representing points, lines, or polygons with an attribute table
  • +
  • GeoParquet defines how to store vector data in Apache Parquet, which is a columnar storage format (like many cloud data warehouses). “Give me all points with height greater than 10m”.
  • +
  • Highly compressed
  • +
  • Single-file or multi-file
  • +
  • Recent support added to geopandas as a distinct function, R support with geoarrow
  • +
  • Potential for cross language in-memory shared access
  • +
  • Specifications for spatial-indexing, projection handling, etc. are still in discussion
  • +
  • Learn more: https://github.com/opengeospatial/geoparquet
  • +
+
+
+


+ +
+

image source: https://www.wherobots.ai/post/spatial-data-parquet-and-apache-sedona

+
+
+

The End?

+

Return to Cloud-Optimized Geospatial Formats Guide or …

+
+

Not Quite

+
    +
  • These formats and their tooling are in active development
  • +
  • Some formats were not mentioned, such as EPT, geopkg, tiledb, Cloud-Optimized HDF5. This presentation was scoped to those known best by the authors.
  • +
  • This site will continue to be updated with new content.
  • +
+
+
+
+

References

+
+

Prior presentations and studies discussing multiple formats

+ +

Format Homepages and Explainers

+ +
+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/pmtiles/environment.yml b/pr-preview/pr-68/pmtiles/environment.yml new file mode 100644 index 0000000..f4c26f1 --- /dev/null +++ b/pr-preview/pr-68/pmtiles/environment.yml @@ -0,0 +1,11 @@ +name: coguide-pmtiles +channels: + - conda-forge +dependencies: + - python=3.11 + - ipykernel + - jupyterlab + - tippecanoe + - pip: + - pmtiles + - mapbox-vector-tile diff --git a/pr-preview/pr-68/pmtiles/intro.html b/pr-preview/pr-68/pmtiles/intro.html new file mode 100644 index 0000000..55b3991 --- /dev/null +++ b/pr-preview/pr-68/pmtiles/intro.html @@ -0,0 +1,856 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - PMTiles + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

PMTiles

+

Guidelines for PMTiles

+
+ + + +
+ + + + +
+ + +
+ +
+

PMTiles

+

PMTiles is a single-file archive format for tiled data, usually used for visualization.

+

As an “archive format”, PMTiles is similar to a ZIP file: it contains the contents of many individual files inside of one PMTiles file. A single file is often much easier to use and keep track of than many very small files.

+

PMTiles is designed for tiled data. That is, data where one inner file represents a small square somewhere on a map, usually representing the Web Mercator grid. PMTiles can be used for any format of tiled data. PMTiles is used most often with vector data, where each tile data contained within the archive is encoded as a Mapbox Vector Tile (MVT), but can also be used with e.g. raster data or terrain mesh data.

+
+

Analytical vs tiled data formats

+

To understand PMTiles, it’s important to understand the difference between “analytical” data and “tiled” data. Analytical data refers to data in its original form, without any modifications to geometry. Tiled data formats apply a variety of modifications to geometries, including clipping and simplification, to save space and make it faster to visualize.

+

+

Consider the above diagram. In an analytical format, every coordinate of the complex polygon would be included in one single file. In a tiled format, there are predefined tile sets (or grids) and the geometry would be split into one or more files, where each file represents one cell of the grid.

+

The analytical format is more useful for operations like a spatial join, because the entire geometry is available. It’s harder to perform such analyses on tiled data because given any one tile, it’s impossible to know whether the data contained in that tile represents the full geometry or not.

+
    +
  • Know which other tiles contain part of this polygon (This is hard! It requires some other pre-generated attribute other than the geometry itself.)
  • +
  • Fetch each of those neighboring tiles
  • +
  • Assemble the dissected geometries back into a single geometry
  • +
  • Apply the desired operation
  • +
+

The tiled format is more useful for visualization because a user who wants to visualize a small area only needs to download a few tiles. Additionally loading the data is faster because of simplification. It’s slower to visualize analytical data because the entire shape with all coordinates must be loaded, even if visualizing only a small area.

+

Thus analytical and visualization formats strive for different goals.

+
+
+

Cloud-native

+

PMTiles is designed to be a cloud-native file format: used directly from a client over a network via HTTP range requests, without having a server in the middle.

+
+
+

Internal format

+

PMTiles has a file header, one or more metadata regions, and a region of tile data.

+

The header is fixed length, located at the beginning of the file, and includes necessary information to decode the rest of the file accurately.

+

PMTiles includes directories, or regions of bytes with metadata about tiles. It’s important for each directory to remain small, so while there will always be at least one directory, larger PMTiles archives with many tiles may include more than one directory.

+

At the end of the file is the tile data. This includes all data for all the tiles in the archive.

+

The full specification is defined here.

+
+

Hilbert-oriented tiles

+

Interally, tiles are oriented along a Hilbert Curve. This means that tiles that are spatially near each other are also located near each other in the file structure.

+

This is especially appropriate for PMTiles because visualization purposes most often request data within a specific geographic area. Because spatially-nearby tiles are likely to be nearby in the file as well, this allows the PMTiles client to merge multiple requests for tiles into one larger request, rather than needing to fetch a different area of the file for each tile.

+
+
+
+

Multiple resolution

+

PMTiles archives support storing a full XYZ pyramid of tile data. This means that you can store multiple zoom levels of data inside a single file.

+
+
+

Internal compression

+

PMTiles allows tiles to be stored in the file with compression.

+
+
+

Generating PMTiles

+
+

From vector data

+

The easiest way to generate PMTiles for vector data is through the tippecanoe tool. This will generate vector tiles that are ideal for visualization, removing small features at low zoom levels to keep tiles a manageable size.

+
+
+

From existing tiles or MBTiles

+

PMTiles has a command-line program for creating PMTiles if you already have an MBTiles file or a directory of tiles.

+
+
+
+

Using PMTiles

+
+

PMTiles viewer

+

If you have an existing PMTiles archive, either as a local file or hosted on cloud storage, you can use the PMTiles Viewer to inspect the tiles hosted within the file.

+
+
+

JavaScript

+

PMTiles doesn’t have a standalone JavaScript library, but rather is designed to be used in conjunction with a JavaScript map rendering library.

+

See the docs on viewing PMTiles in Leaflet, MapLibre GL JS and OpenLayers.

+
+
+

Python

+

PMTiles has a Python package, which allows reading and writing PMTiles archives from Python.

+
+
+
+

Alternatives

+
+

MBTiles

+

The most common alternative for PMTiles is MBTiles, which was in many ways the precursor to PMTiles. MBTiles stores the included vector tiles in a table in a SQLite database. MBTiles has the benefit of being much easier to use than manually managing millions of tiny, individual files, but MBTiles is not serverless. In general, it’s impossible to read from a SQLite database without fetching the entire file’s content. This means that frontend clients like a web browser couldn’t fetch tiles directly using range requests, but rather a server has to be running to fetch tiles from the MBTiles file.

+
+
+

Saving individual files to cloud storage

+

It’s also possible to upload the bare tiled data directly to cloud storage as individual files.

+

This has significant downsides of needing to manage many millions of tiny individual files. Uploading millions of files to a cloud storage provider such as S3 takes time and money. For example, AWS charges $5 per million files added to an S3 bucket. So a 10 million PMTiles archive would cost $50, compared to 5-millionths of a cent to upload the PMTiles file.

+ + +
+
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/pmtiles/pmtiles-example.html b/pr-preview/pr-68/pmtiles/pmtiles-example.html new file mode 100644 index 0000000..36a44dc --- /dev/null +++ b/pr-preview/pr-68/pmtiles/pmtiles-example.html @@ -0,0 +1,7861 @@ + + + + + + + + + +Cloud-Optimized Geospatial Formats Guide - PMTiles example + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

PMTiles example

+
+ + + +
+ + + + +
+ + +
+ +

This notebook will give an overview of how to create and visualize PMTiles archives.

+
+

Environment

+

The packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:

+
conda create -f environment.yml 
+

or

+
mamba create -f environment.yml 
+

Alternatively, you can install pmtiles and mapbox-vector-tile through pip, and tippecanoe through Homebrew (brew install tippecanoe) if on MacOS.

+
+
+

Creating PMTiles

+

For this example, we’ll use the same file as used in the FlatGeobuf and GeoParquet example notebooks: a 13MB file of US counties.

+

We’ll use Tippecanoe to convert this file into tiles.

+

First we’ll download the file to our local directory:

+
+
!wget https://flatgeobuf.org/test/data/UScounties.fgb
+
+
--2023-08-23 15:54:58--  https://flatgeobuf.org/test/data/UScounties.fgb
+Resolving flatgeobuf.org (flatgeobuf.org)... 185.199.108.153
+Connecting to flatgeobuf.org (flatgeobuf.org)|185.199.108.153|:443... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 14100008 (13M) [application/octet-stream]
+Saving to: ‘UScounties.fgb’
+
+UScounties.fgb      100%[===================>]  13.45M  7.94MB/s    in 1.7s    
+
+2023-08-23 15:55:02 (7.94 MB/s) - ‘UScounties.fgb’ saved [14100008/14100008]
+
+
+
+

Tippecanoe has many options to customize its behavior. Here we’ll use the -zg flag to tell Tippecanoe to deduce appropriate minimum and maximum zoom levels for the dataset. The -o counties.pmtiles flag tells Tippecanoe to save the output with that name.

+

Tippecanoe also works especially well with FlatGeobuf files. When a FlatGeobuf file is used as input, Tippecanoe will reuse the spatial index stored in the FlatGeobuf file instead of creating its own.

+
+
!tippecanoe UScounties.fgb -o counties.pmtiles -zg
+
+
For layer 0, using name "UScountiesfgb"
+detected indexed FlatGeobuf: assigning feature IDs by sequence
+3221 features, 5580299 bytes of geometry, 53296 bytes of string pool
+Choosing a maxzoom of -z1 for features typically 141427 feet (43107 meters) apart, and at least 33249 feet (10135 meters) apart
+Choosing a maxzoom of -z7 for resolution of about 3195 feet (973 meters) within features
+  99.9%  7/36/49   
+  100.0%  7/127/42  
+
+
+

Now we have a file named counties.pmtiles with our data:

+
+
!ls -lh counties.pmtiles
+
+
-rw-r--r--@ 1 kyle  staff   2.8M Aug 25 13:09 counties.pmtiles
+
+
+
+
+

Visualization

+

The easiest way to interpret this data is to load it into the PMTiles Viewer. Drag the counties.pmtiles file into that website, and you’ll be able to hover over areas

+

+
+
+

Reading from Python

+

It’s possible to open and read a PMTiles file from python using the pmtiles and mapbox-vector-tile libraries. The pmtiles library is used to open the archive and fetch a specific tile, while mapbox-vector-tile is used to decode the MVT vector tile data contained within that tile.

+
+
from pmtiles.reader import Reader, MmapSource
+
+

Open the file and create a pmtiles Reader object

+
+
file = open("counties.pmtiles")
+reader = Reader(MmapSource(file))
+
+

Fetch a specific tile. This tile’s coordinates were found from the PMTiles viewer above, and is located over the east coast.

+
+
x, y, z = 37, 48, 7
+tile_data = reader.get(z, x, y)
+
+

tile_data is now a bytes object, representing the data contained in the PMTiles archive for that specific XYZ tile.

+
+
type(tile_data)
+
+
bytes
+
+
+
+
len(tile_data)
+
+
11878
+
+
+

In our case, the PMTiles archive contains MVT data, so we can decode the buffer using mapbox_vector_tile. It’s also possible for the archive to contain raster images (e.g. PNG files), in which case a different decoding process would be necessary.

+
+
import mapbox_vector_tile
+import gzip
+
+

We’ll decode the tile and print the output from mapbox_vector_tile. MVT data are encoded with “quantization”, meaning reduced precision so the data can be compressed better. So the coordinates printed out have a range of 0-4096, where those are the integer steps within the local coordinate reference system within the tile. Refer to the mapbox_vector_tile docs for how to read to GeoJSON.

+
+
mapbox_vector_tile.decode(gzip.decompress(tile_data))
+
+
{'UScountiesfgb': {'extent': 4096,
+  'version': 2,
+  'features': [{'geometry': {'type': 'Polygon',
+     'coordinates': [[[289, 4176],
+       [290, 4168],
+       [299, 4151],
+       [198, 4102],
+       [172, 4100],
+       [163, 4096],
+       [128, 4080],
+       [130, 4070],
+       [0, 4009],
+       [-71, 3976],
+       [-80, 3970],
+       [-80, 4176],
+       [289, 4176]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '079',
+     'FIPS': '42079',
+     'STATE': 'PA',
+     'NAME': 'Luzerne',
+     'LSAD': 'County'},
+    'id': 2224,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1272, 4176],
+       [1256, 4168],
+       [1247, 4167],
+       [1235, 4163],
+       [1226, 4152],
+       [1206, 4143],
+       [1204, 4139],
+       [1180, 4123],
+       [1175, 4118],
+       [1174, 4113],
+       [1174, 4106],
+       [1171, 4096],
+       [1168, 4090],
+       [1168, 4084],
+       [1171, 4079],
+       [1174, 4076],
+       [1177, 4075],
+       [1187, 4077],
+       [1190, 4074],
+       [1177, 4056],
+       [1154, 4041],
+       [1143, 4037],
+       [1119, 4035],
+       [1108, 4030],
+       [1106, 4020],
+       [1092, 4014],
+       [1081, 4012],
+       [1048, 3996],
+       [1042, 3980],
+       [1014, 3960],
+       [1027, 3941],
+       [976, 3908],
+       [967, 3890],
+       [952, 3877],
+       [928, 3864],
+       [898, 3857],
+       [868, 3837],
+       [807, 3809],
+       [758, 3800],
+       [753, 3795],
+       [721, 3785],
+       [675, 3778],
+       [663, 3807],
+       [648, 3835],
+       [529, 4041],
+       [620, 4096],
+       [643, 4110],
+       [590, 4176],
+       [1272, 4176]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '089',
+     'FIPS': '42089',
+     'STATE': 'PA',
+     'NAME': 'Monroe',
+     'LSAD': 'County'},
+    'id': 2227,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[590, 4176],
+       [643, 4110],
+       [620, 4096],
+       [529, 4041],
+       [598, 3923],
+       [655, 3822],
+       [675, 3778],
+       [668, 3775],
+       [625, 3767],
+       [609, 3766],
+       [596, 3762],
+       [577, 3763],
+       [562, 3758],
+       [553, 3752],
+       [524, 3748],
+       [498, 3737],
+       [494, 3730],
+       [488, 3726],
+       [478, 3725],
+       [399, 3706],
+       [363, 3696],
+       [354, 3692],
+       [342, 3677],
+       [304, 3661],
+       [299, 3656],
+       [289, 3642],
+       [282, 3641],
+       [281, 3635],
+       [262, 3625],
+       [75, 3781],
+       [0, 3867],
+       [-80, 3958],
+       [-80, 3970],
+       [0, 4009],
+       [130, 4070],
+       [128, 4080],
+       [163, 4096],
+       [172, 4100],
+       [198, 4102],
+       [299, 4151],
+       [290, 4168],
+       [289, 4176],
+       [590, 4176]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '025',
+     'FIPS': '42025',
+     'STATE': 'PA',
+     'NAME': 'Carbon',
+     'LSAD': 'County'},
+    'id': 2217,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1529, 4176],
+       [1594, 4096],
+       [1703, 3965],
+       [1691, 3952],
+       [1687, 3954],
+       [1681, 3943],
+       [1671, 3935],
+       [1671, 3928],
+       [1668, 3923],
+       [1651, 3914],
+       [1647, 3908],
+       [1648, 3894],
+       [1645, 3883],
+       [1646, 3880],
+       [1654, 3874],
+       [1652, 3869],
+       [1643, 3865],
+       [1642, 3855],
+       [1637, 3849],
+       [1627, 3845],
+       [1625, 3843],
+       [1622, 3833],
+       [1627, 3829],
+       [1630, 3821],
+       [1617, 3812],
+       [1611, 3804],
+       [1613, 3799],
+       [1606, 3792],
+       [1606, 3786],
+       [1598, 3780],
+       [1592, 3771],
+       [1589, 3771],
+       [1588, 3765],
+       [1583, 3757],
+       [1576, 3756],
+       [1569, 3752],
+       [1567, 3756],
+       [1562, 3755],
+       [1558, 3742],
+       [1546, 3737],
+       [1539, 3731],
+       [1535, 3733],
+       [1532, 3732],
+       [1517, 3719],
+       [1505, 3712],
+       [1507, 3706],
+       [1506, 3698],
+       [1507, 3695],
+       [1494, 3686],
+       [1489, 3680],
+       [1489, 3677],
+       [1485, 3672],
+       [1473, 3663],
+       [1470, 3658],
+       [1467, 3656],
+       [1465, 3651],
+       [1452, 3636],
+       [1451, 3631],
+       [1443, 3624],
+       [1435, 3610],
+       [1426, 3606],
+       [1424, 3602],
+       [1419, 3597],
+       [1410, 3577],
+       [1396, 3578],
+       [1393, 3569],
+       [1378, 3563],
+       [1361, 3545],
+       [1356, 3544],
+       [1351, 3547],
+       [1345, 3543],
+       [1341, 3547],
+       [1337, 3542],
+       [1333, 3542],
+       [1315, 3526],
+       [1310, 3526],
+       [1308, 3524],
+       [1303, 3517],
+       [1301, 3516],
+       [1295, 3518],
+       [1288, 3512],
+       [1282, 3510],
+       [1278, 3505],
+       [1275, 3499],
+       [1267, 3497],
+       [1264, 3494],
+       [1254, 3488],
+       [1247, 3476],
+       [1236, 3472],
+       [1235, 3468],
+       [1226, 3458],
+       [1211, 3451],
+       [1207, 3447],
+       [1208, 3442],
+       [1205, 3440],
+       [1180, 3431],
+       [1168, 3424],
+       [1153, 3420],
+       [1150, 3416],
+       [1150, 3408],
+       [1147, 3405],
+       [1141, 3407],
+       [1129, 3399],
+       [1130, 3393],
+       [1128, 3387],
+       [1124, 3385],
+       [1120, 3378],
+       [1114, 3375],
+       [1111, 3363],
+       [1104, 3361],
+       [1102, 3355],
+       [1096, 3351],
+       [1088, 3349],
+       [1085, 3370],
+       [1072, 3393],
+       [1071, 3398],
+       [1077, 3402],
+       [1088, 3404],
+       [1091, 3412],
+       [1085, 3444],
+       [1073, 3455],
+       [1073, 3460],
+       [1087, 3484],
+       [1099, 3492],
+       [1107, 3505],
+       [1108, 3511],
+       [1107, 3514],
+       [1102, 3518],
+       [1097, 3519],
+       [1088, 3518],
+       [1079, 3521],
+       [1073, 3529],
+       [1068, 3541],
+       [1082, 3584],
+       [1089, 3592],
+       [1100, 3618],
+       [1095, 3629],
+       [1081, 3645],
+       [1079, 3656],
+       [1086, 3664],
+       [1099, 3671],
+       [1105, 3676],
+       [1107, 3681],
+       [1110, 3697],
+       [1115, 3707],
+       [1118, 3708],
+       [1127, 3708],
+       [1148, 3701],
+       [1170, 3699],
+       [1174, 3703],
+       [1186, 3724],
+       [1195, 3729],
+       [1203, 3730],
+       [1207, 3732],
+       [1219, 3749],
+       [1219, 3764],
+       [1225, 3773],
+       [1234, 3780],
+       [1243, 3797],
+       [1243, 3803],
+       [1241, 3807],
+       [1224, 3825],
+       [1223, 3832],
+       [1226, 3840],
+       [1233, 3844],
+       [1254, 3845],
+       [1262, 3841],
+       [1269, 3841],
+       [1272, 3842],
+       [1288, 3865],
+       [1291, 3876],
+       [1290, 3885],
+       [1287, 3891],
+       [1280, 3899],
+       [1270, 3914],
+       [1256, 3931],
+       [1255, 3956],
+       [1250, 3969],
+       [1226, 3989],
+       [1212, 4012],
+       [1211, 4018],
+       [1203, 4035],
+       [1194, 4044],
+       [1190, 4065],
+       [1191, 4070],
+       [1190, 4074],
+       [1187, 4077],
+       [1177, 4075],
+       [1174, 4076],
+       [1171, 4079],
+       [1168, 4084],
+       [1168, 4090],
+       [1171, 4096],
+       [1174, 4106],
+       [1174, 4113],
+       [1175, 4118],
+       [1180, 4123],
+       [1204, 4139],
+       [1206, 4143],
+       [1226, 4152],
+       [1235, 4163],
+       [1247, 4167],
+       [1256, 4168],
+       [1272, 4176],
+       [1529, 4176]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '041',
+     'FIPS': '34041',
+     'STATE': 'NJ',
+     'NAME': 'Warren',
+     'LSAD': 'County'},
+    'id': 2207,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[2427, 4176],
+        [2425, 4170],
+        [2437, 4158],
+        [2460, 4120],
+        [2494, 4099],
+        [2518, 4096],
+        [2573, 4090],
+        [2573, 4096],
+        [2574, 4104],
+        [2583, 4096],
+        [2616, 4070],
+        [2606, 4022],
+        [2612, 4020],
+        [2619, 4007],
+        [2615, 3999],
+        [2616, 3992],
+        [2619, 3987],
+        [2630, 3985],
+        [2633, 3981],
+        [2628, 3967],
+        [2630, 3956],
+        [2627, 3941],
+        [2634, 3930],
+        [2632, 3915],
+        [2646, 3904],
+        [2654, 3892],
+        [2656, 3885],
+        [2661, 3874],
+        [2665, 3871],
+        [2665, 3860],
+        [2662, 3856],
+        [2659, 3857],
+        [2656, 3864],
+        [2649, 3864],
+        [2647, 3855],
+        [2648, 3849],
+        [2644, 3833],
+        [2641, 3826],
+        [2645, 3808],
+        [2641, 3793],
+        [2638, 3790],
+        [2632, 3788],
+        [2552, 3846],
+        [2534, 3860],
+        [2536, 3865],
+        [2529, 3868],
+        [2527, 3864],
+        [2472, 3904],
+        [2453, 3906],
+        [2451, 3909],
+        [2443, 3911],
+        [2437, 3917],
+        [2433, 3931],
+        [2425, 3938],
+        [2424, 3942],
+        [2427, 3948],
+        [2424, 3953],
+        [2426, 3956],
+        [2426, 3962],
+        [2430, 3957],
+        [2432, 3957],
+        [2433, 3959],
+        [2426, 3972],
+        [2416, 3973],
+        [2416, 3978],
+        [2408, 3975],
+        [2408, 3980],
+        [2405, 3984],
+        [2407, 3986],
+        [2402, 3989],
+        [2402, 3995],
+        [2401, 3997],
+        [2407, 4002],
+        [2411, 4013],
+        [2415, 4025],
+        [2418, 4047],
+        [2414, 4053],
+        [2415, 4069],
+        [2413, 4071],
+        [2412, 4075],
+        [2413, 4081],
+        [2417, 4079],
+        [2418, 4085],
+        [2412, 4090],
+        [2412, 4096],
+        [2407, 4094],
+        [2399, 4096],
+        [2392, 4094],
+        [2389, 4096],
+        [2389, 4103],
+        [2396, 4111],
+        [2391, 4117],
+        [2391, 4125],
+        [2388, 4128],
+        [2388, 4136],
+        [2387, 4140],
+        [2384, 4140],
+        [2382, 4133],
+        [2370, 4132],
+        [2363, 4139],
+        [2344, 4137],
+        [2341, 4140],
+        [2334, 4142],
+        [2334, 4147],
+        [2329, 4148],
+        [2325, 4146],
+        [2324, 4148],
+        [2318, 4144],
+        [2310, 4144],
+        [2310, 4156],
+        [2306, 4160],
+        [2298, 4162],
+        [2293, 4160],
+        [2292, 4157],
+        [2281, 4157],
+        [2274, 4161],
+        [2265, 4162],
+        [2259, 4157],
+        [2255, 4159],
+        [2251, 4165],
+        [2240, 4168],
+        [2235, 4173],
+        [2234, 4176],
+        [2427, 4176]]],
+      [[[2203, 4176],
+        [2202, 4172],
+        [2196, 4170],
+        [2189, 4174],
+        [2190, 4176],
+        [2203, 4176]]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '031',
+     'FIPS': '34031',
+     'STATE': 'NJ',
+     'NAME': 'Passaic',
+     'LSAD': 'County'},
+    'id': 2230,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2981, 4176],
+       [2977, 4145],
+       [2976, 4129],
+       [2960, 4130],
+       [2885, 4176],
+       [2981, 4176]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '087',
+     'FIPS': '36087',
+     'STATE': 'NY',
+     'NAME': 'Rockland',
+     'LSAD': 'County'},
+    'id': 2226,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[3469, 4176],
+        [3460, 4167],
+        [3451, 4156],
+        [3448, 4138],
+        [3428, 4137],
+        [3426, 4155],
+        [3410, 4166],
+        [3398, 4164],
+        [3341, 4139],
+        [3330, 4126],
+        [3321, 4106],
+        [3317, 4111],
+        [3319, 4122],
+        [3318, 4134],
+        [3325, 4157],
+        [3312, 4176],
+        [3469, 4176]]],
+      [[[3519, 4176],
+        [3517, 4172],
+        [3508, 4166],
+        [3505, 4176],
+        [3519, 4176]]]]},
+    'properties': {'STATE_FIPS': '09',
+     'COUNTY_FIP': '001',
+     'FIPS': '09001',
+     'STATE': 'CT',
+     'NAME': 'Fairfield',
+     'LSAD': 'County'},
+    'id': 1713,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[3156, 3920],
+        [3161, 3917],
+        [3162, 3906],
+        [3161, 3904],
+        [3155, 3902],
+        [3149, 3908],
+        [3149, 3912],
+        [3153, 3912],
+        [3153, 3918],
+        [3156, 3920]]],
+      [[[3312, 4176],
+        [3325, 4157],
+        [3318, 4134],
+        [3319, 4122],
+        [3317, 4111],
+        [3321, 4106],
+        [3323, 4096],
+        [3317, 4074],
+        [3314, 4070],
+        [3310, 4072],
+        [3291, 4063],
+        [3283, 4036],
+        [3278, 4029],
+        [3262, 4018],
+        [3227, 4004],
+        [3212, 3990],
+        [3176, 3966],
+        [3140, 3914],
+        [3137, 3905],
+        [3079, 3925],
+        [3078, 3922],
+        [3057, 3931],
+        [3053, 3950],
+        [3048, 3950],
+        [3048, 3952],
+        [3042, 3955],
+        [3036, 3956],
+        [3039, 3961],
+        [3036, 3961],
+        [3033, 3958],
+        [3034, 3955],
+        [3031, 3954],
+        [3026, 3943],
+        [2941, 3976],
+        [2972, 4096],
+        [2981, 4176],
+        [3312, 4176]]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '119',
+     'FIPS': '36119',
+     'STATE': 'NY',
+     'NAME': 'Westchester',
+     'LSAD': 'County'},
+    'id': 2232,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[-80, 3958],
+       [0, 3867],
+       [75, 3781],
+       [219, 3660],
+       [262, 3625],
+       [250, 3617],
+       [232, 3613],
+       [230, 3605],
+       [205, 3590],
+       [189, 3572],
+       [135, 3544],
+       [120, 3544],
+       [67, 3514],
+       [0, 3481],
+       [-80, 3442],
+       [-80, 3958]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '107',
+     'FIPS': '42107',
+     'STATE': 'PA',
+     'NAME': 'Schuylkill',
+     'LSAD': 'County'},
+    'id': 2216,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[-80, 2134],
+        [-80, 2627],
+        [0, 2560],
+        [93, 2480],
+        [69, 2466],
+        [0, 2431],
+        [-8, 2427],
+        [0, 2380],
+        [2, 2369],
+        [2, 2342],
+        [5, 2310],
+        [3, 2293],
+        [0, 2287],
+        [-72, 2157],
+        [-71, 2150],
+        [-77, 2142],
+        [-80, 2134]]],
+      [[[-80, 2117],
+        [-77, 2115],
+        [-74, 2105],
+        [-65, 2097],
+        [-63, 2093],
+        [-64, 2086],
+        [-69, 2090],
+        [-73, 2086],
+        [-79, 2085],
+        [-78, 2081],
+        [-80, 2080],
+        [-80, 2117]]],
+      [[[-80, 1996],
+        [-74, 1988],
+        [-72, 1979],
+        [-77, 1974],
+        [-79, 1970],
+        [-80, 1971],
+        [-80, 1996]]],
+      [[[-80, 2026],
+        [-73, 2020],
+        [-72, 2015],
+        [-76, 2012],
+        [-78, 2006],
+        [-79, 2001],
+        [-77, 2000],
+        [-80, 1996],
+        [-80, 2026]]],
+      [[[-80, 2123], [-78, 2120], [-80, 2117], [-80, 2123]]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '071',
+     'FIPS': '42071',
+     'STATE': 'PA',
+     'NAME': 'Lancaster',
+     'LSAD': 'County'},
+    'id': 2185,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[223, 1051],
+       [235, 1047],
+       [235, 1044],
+       [240, 1045],
+       [249, 1041],
+       [264, 794],
+       [262, 796],
+       [255, 795],
+       [247, 797],
+       [241, 794],
+       [236, 796],
+       [233, 793],
+       [232, 795],
+       [223, 792],
+       [222, 791],
+       [210, 788],
+       [209, 790],
+       [205, 785],
+       [197, 787],
+       [195, 790],
+       [191, 786],
+       [185, 792],
+       [171, 794],
+       [163, 799],
+       [162, 802],
+       [157, 803],
+       [148, 808],
+       [143, 809],
+       [142, 816],
+       [136, 816],
+       [122, 820],
+       [120, 824],
+       [113, 821],
+       [106, 823],
+       [92, 809],
+       [92, 801],
+       [86, 802],
+       [84, 804],
+       [75, 800],
+       [71, 807],
+       [67, 809],
+       [63, 806],
+       [63, 797],
+       [29, 789],
+       [18, 790],
+       [0, 782],
+       [-5, 780],
+       [-10, 781],
+       [-16, 787],
+       [-21, 788],
+       [-27, 784],
+       [-30, 784],
+       [-37, 786],
+       [-43, 793],
+       [-48, 795],
+       [-58, 792],
+       [-70, 794],
+       [-71, 783],
+       [-75, 781],
+       [-80, 780],
+       [-80, 1037],
+       [-75, 1034],
+       [-64, 1021],
+       [-60, 1021],
+       [-56, 1022],
+       [-48, 1033],
+       [-39, 1036],
+       [-21, 1034],
+       [-17, 1032],
+       [-11, 1025],
+       [-5, 1023],
+       [0, 1025],
+       [8, 1030],
+       [14, 1030],
+       [21, 1022],
+       [49, 1017],
+       [63, 1019],
+       [71, 1012],
+       [76, 1010],
+       [81, 1017],
+       [102, 1023],
+       [107, 1021],
+       [111, 1023],
+       [120, 1017],
+       [130, 1024],
+       [134, 1023],
+       [139, 1029],
+       [155, 1035],
+       [166, 1049],
+       [173, 1050],
+       [176, 1047],
+       [186, 1046],
+       [191, 1038],
+       [193, 1037],
+       [198, 1042],
+       [206, 1041],
+       [209, 1046],
+       [213, 1046],
+       [216, 1048],
+       [222, 1046],
+       [223, 1051]]]},
+    'properties': {'STATE_FIPS': '24',
+     'COUNTY_FIP': '029',
+     'FIPS': '24029',
+     'STATE': 'MD',
+     'NAME': 'Kent',
+     'LSAD': 'County'},
+    'id': 2126,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[120, 824],
+       [122, 820],
+       [136, 816],
+       [142, 816],
+       [143, 809],
+       [148, 808],
+       [157, 803],
+       [162, 802],
+       [163, 799],
+       [171, 794],
+       [185, 792],
+       [191, 786],
+       [195, 790],
+       [197, 787],
+       [205, 785],
+       [209, 790],
+       [210, 788],
+       [222, 791],
+       [223, 792],
+       [232, 795],
+       [233, 793],
+       [236, 796],
+       [241, 794],
+       [247, 797],
+       [255, 795],
+       [262, 796],
+       [264, 794],
+       [276, 601],
+       [262, 592],
+       [236, 584],
+       [213, 581],
+       [209, 575],
+       [202, 573],
+       [197, 566],
+       [186, 558],
+       [167, 548],
+       [153, 536],
+       [149, 535],
+       [143, 520],
+       [137, 502],
+       [133, 500],
+       [130, 495],
+       [132, 473],
+       [129, 466],
+       [116, 452],
+       [112, 447],
+       [108, 443],
+       [99, 440],
+       [96, 432],
+       [89, 422],
+       [86, 421],
+       [86, 418],
+       [88, 417],
+       [89, 414],
+       [87, 405],
+       [84, 404],
+       [82, 396],
+       [79, 393],
+       [79, 389],
+       [78, 387],
+       [80, 384],
+       [73, 382],
+       [71, 377],
+       [68, 374],
+       [68, 366],
+       [57, 359],
+       [49, 364],
+       [47, 361],
+       [49, 354],
+       [49, 352],
+       [42, 352],
+       [42, 348],
+       [39, 340],
+       [35, 339],
+       [33, 335],
+       [26, 332],
+       [23, 322],
+       [11, 315],
+       [13, 311],
+       [7, 307],
+       [4, 299],
+       [4, 295],
+       [0, 292],
+       [-5, 289],
+       [-3, 285],
+       [0, 284],
+       [1, 283],
+       [0, 278],
+       [-8, 270],
+       [-1, 257],
+       [-2, 253],
+       [-4, 254],
+       [-7, 250],
+       [-7, 238],
+       [-10, 234],
+       [-20, 231],
+       [-19, 222],
+       [-14, 222],
+       [-14, 220],
+       [-23, 217],
+       [-21, 214],
+       [-17, 213],
+       [-15, 210],
+       [-16, 204],
+       [-17, 202],
+       [-22, 201],
+       [-22, 200],
+       [-18, 190],
+       [-17, 179],
+       [-45, 186],
+       [-50, 186],
+       [-59, 190],
+       [-80, 194],
+       [-80, 780],
+       [-75, 781],
+       [-71, 783],
+       [-70, 794],
+       [-58, 792],
+       [-48, 795],
+       [-43, 793],
+       [-37, 786],
+       [-30, 784],
+       [-27, 784],
+       [-21, 788],
+       [-16, 787],
+       [-10, 781],
+       [-5, 780],
+       [0, 782],
+       [18, 790],
+       [29, 789],
+       [63, 797],
+       [63, 806],
+       [67, 809],
+       [71, 807],
+       [75, 800],
+       [84, 804],
+       [86, 802],
+       [92, 801],
+       [92, 809],
+       [106, 823],
+       [113, 821],
+       [120, 824]]]},
+    'properties': {'STATE_FIPS': '24',
+     'COUNTY_FIP': '035',
+     'FIPS': '24035',
+     'STATE': 'MD',
+     'NAME': "Queen Anne's",
+     'LSAD': 'County'},
+    'id': 2137,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[-80, 194],
+       [-59, 190],
+       [-50, 186],
+       [-45, 186],
+       [-17, 179],
+       [-10, 176],
+       [-9, 172],
+       [-16, 172],
+       [-16, 167],
+       [-8, 158],
+       [-9, 156],
+       [-15, 153],
+       [-16, 149],
+       [-11, 145],
+       [-10, 140],
+       [-12, 133],
+       [-16, 130],
+       [-16, 129],
+       [-10, 126],
+       [-4, 117],
+       [-6, 115],
+       [-18, 116],
+       [-20, 115],
+       [-20, 108],
+       [-16, 104],
+       [-3, 110],
+       [0, 107],
+       [0, 104],
+       [-2, 101],
+       [-9, 101],
+       [-10, 98],
+       [-6, 85],
+       [-3, 82],
+       [0, 83],
+       [4, 84],
+       [11, 72],
+       [19, 71],
+       [22, 65],
+       [22, 62],
+       [10, 53],
+       [16, 46],
+       [26, 45],
+       [27, 44],
+       [26, 42],
+       [14, 35],
+       [14, 30],
+       [26, 24],
+       [33, 23],
+       [36, 13],
+       [53, 4],
+       [51, 0],
+       [47, -2],
+       [45, -5],
+       [50, -11],
+       [59, -14],
+       [60, -19],
+       [55, -20],
+       [49, -29],
+       [38, -30],
+       [14, -44],
+       [7, -49],
+       [0, -66],
+       [-15, -80],
+       [-80, -80],
+       [-80, 194]]]},
+    'properties': {'STATE_FIPS': '24',
+     'COUNTY_FIP': '041',
+     'FIPS': '24041',
+     'STATE': 'MD',
+     'NAME': 'Talbot',
+     'LSAD': 'County'},
+    'id': 2156,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[478, 3725],
+       [484, 3712],
+       [485, 3703],
+       [482, 3694],
+       [487, 3684],
+       [486, 3666],
+       [489, 3653],
+       [496, 3641],
+       [502, 3627],
+       [509, 3622],
+       [528, 3625],
+       [533, 3621],
+       [538, 3607],
+       [543, 3602],
+       [552, 3597],
+       [558, 3598],
+       [571, 3604],
+       [576, 3611],
+       [578, 3626],
+       [583, 3630],
+       [593, 3627],
+       [598, 3623],
+       [599, 3618],
+       [600, 3595],
+       [605, 3582],
+       [622, 3548],
+       [633, 3537],
+       [640, 3517],
+       [643, 3515],
+       [653, 3511],
+       [659, 3502],
+       [661, 3494],
+       [661, 3481],
+       [664, 3472],
+       [739, 3508],
+       [739, 3497],
+       [783, 3442],
+       [795, 3430],
+       [801, 3429],
+       [800, 3418],
+       [807, 3411],
+       [806, 3404],
+       [808, 3398],
+       [811, 3398],
+       [813, 3394],
+       [799, 3393],
+       [795, 3359],
+       [777, 3330],
+       [777, 3328],
+       [880, 3245],
+       [769, 3151],
+       [660, 3017],
+       [165, 3428],
+       [67, 3514],
+       [120, 3544],
+       [135, 3544],
+       [189, 3572],
+       [205, 3590],
+       [230, 3605],
+       [232, 3613],
+       [250, 3617],
+       [262, 3625],
+       [281, 3635],
+       [282, 3641],
+       [289, 3642],
+       [299, 3656],
+       [304, 3661],
+       [342, 3677],
+       [354, 3692],
+       [380, 3701],
+       [478, 3725]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '077',
+     'FIPS': '42077',
+     'STATE': 'PA',
+     'NAME': 'Lehigh',
+     'LSAD': 'County'},
+    'id': 2212,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[67, 3514],
+       [165, 3428],
+       [594, 3072],
+       [351, 2680],
+       [283, 2632],
+       [93, 2480],
+       [0, 2560],
+       [-25, 2581],
+       [-80, 2627],
+       [-80, 3442],
+       [0, 3481],
+       [67, 3514]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '011',
+     'FIPS': '42011',
+     'STATE': 'PA',
+     'NAME': 'Berks',
+     'LSAD': 'County'},
+    'id': 2193,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[594, 3072],
+       [660, 3017],
+       [745, 2952],
+       [937, 2799],
+       [1053, 2710],
+       [1176, 2612],
+       [1343, 2482],
+       [1335, 2471],
+       [1280, 2421],
+       [1252, 2383],
+       [1245, 2377],
+       [1239, 2369],
+       [1224, 2351],
+       [1238, 2340],
+       [1228, 2327],
+       [1210, 2313],
+       [1206, 2307],
+       [1108, 2381],
+       [1091, 2358],
+       [1040, 2396],
+       [980, 2322],
+       [987, 2313],
+       [1002, 2299],
+       [1007, 2292],
+       [1018, 2281],
+       [1027, 2273],
+       [1048, 2259],
+       [1056, 2249],
+       [1065, 2242],
+       [1063, 2239],
+       [963, 2176],
+       [952, 2195],
+       [912, 2257],
+       [898, 2250],
+       [846, 2340],
+       [841, 2345],
+       [839, 2344],
+       [831, 2357],
+       [794, 2335],
+       [754, 2404],
+       [728, 2390],
+       [723, 2399],
+       [701, 2386],
+       [700, 2400],
+       [691, 2405],
+       [693, 2416],
+       [690, 2416],
+       [682, 2423],
+       [679, 2432],
+       [682, 2441],
+       [692, 2447],
+       [694, 2452],
+       [693, 2457],
+       [677, 2466],
+       [665, 2461],
+       [648, 2460],
+       [629, 2472],
+       [624, 2479],
+       [621, 2488],
+       [625, 2498],
+       [635, 2512],
+       [636, 2519],
+       [633, 2522],
+       [624, 2524],
+       [620, 2522],
+       [614, 2514],
+       [610, 2502],
+       [607, 2500],
+       [602, 2501],
+       [598, 2504],
+       [597, 2511],
+       [598, 2521],
+       [595, 2538],
+       [591, 2544],
+       [580, 2553],
+       [576, 2558],
+       [566, 2580],
+       [555, 2613],
+       [549, 2619],
+       [544, 2618],
+       [543, 2612],
+       [546, 2604],
+       [546, 2596],
+       [539, 2589],
+       [535, 2589],
+       [530, 2591],
+       [522, 2602],
+       [519, 2612],
+       [510, 2627],
+       [496, 2670],
+       [491, 2673],
+       [487, 2673],
+       [483, 2671],
+       [481, 2669],
+       [481, 2664],
+       [487, 2654],
+       [487, 2652],
+       [483, 2648],
+       [474, 2644],
+       [468, 2648],
+       [463, 2658],
+       [428, 2674],
+       [419, 2680],
+       [411, 2679],
+       [406, 2680],
+       [398, 2686],
+       [388, 2685],
+       [381, 2681],
+       [367, 2670],
+       [360, 2670],
+       [351, 2680],
+       [594, 3072]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '091',
+     'FIPS': '42091',
+     'STATE': 'PA',
+     'NAME': 'Montgomery',
+     'LSAD': 'County'},
+    'id': 2198,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[398, 2686],
+        [406, 2680],
+        [411, 2679],
+        [419, 2680],
+        [428, 2674],
+        [463, 2658],
+        [468, 2648],
+        [474, 2644],
+        [483, 2648],
+        [487, 2652],
+        [487, 2654],
+        [481, 2664],
+        [481, 2669],
+        [483, 2671],
+        [487, 2673],
+        [491, 2673],
+        [496, 2670],
+        [510, 2627],
+        [519, 2612],
+        [521, 2604],
+        [525, 2597],
+        [535, 2589],
+        [539, 2589],
+        [546, 2596],
+        [546, 2604],
+        [543, 2612],
+        [544, 2618],
+        [549, 2619],
+        [555, 2613],
+        [566, 2580],
+        [576, 2558],
+        [580, 2553],
+        [591, 2544],
+        [595, 2538],
+        [598, 2521],
+        [597, 2511],
+        [598, 2504],
+        [602, 2501],
+        [607, 2500],
+        [610, 2502],
+        [614, 2514],
+        [620, 2522],
+        [624, 2524],
+        [633, 2522],
+        [636, 2519],
+        [635, 2512],
+        [625, 2498],
+        [621, 2488],
+        [624, 2479],
+        [629, 2472],
+        [648, 2460],
+        [665, 2461],
+        [677, 2466],
+        [693, 2457],
+        [694, 2452],
+        [692, 2447],
+        [682, 2441],
+        [679, 2432],
+        [682, 2423],
+        [690, 2416],
+        [693, 2416],
+        [691, 2405],
+        [700, 2400],
+        [701, 2386],
+        [723, 2399],
+        [728, 2390],
+        [754, 2404],
+        [794, 2335],
+        [831, 2357],
+        [839, 2344],
+        [761, 2299],
+        [776, 2272],
+        [705, 2207],
+        [720, 2208],
+        [724, 2206],
+        [728, 2208],
+        [727, 2204],
+        [731, 2198],
+        [730, 2191],
+        [602, 2113],
+        [609, 2103],
+        [610, 2095],
+        [601, 2090],
+        [599, 2096],
+        [593, 2093],
+        [594, 2091],
+        [593, 2090],
+        [603, 2073],
+        [600, 2071],
+        [598, 2074],
+        [593, 2072],
+        [585, 2086],
+        [575, 2081],
+        [577, 2077],
+        [573, 2074],
+        [573, 2068],
+        [575, 2064],
+        [564, 2058],
+        [570, 2048],
+        [555, 2040],
+        [552, 2046],
+        [548, 2044],
+        [551, 2035],
+        [530, 2023],
+        [532, 2017],
+        [529, 2015],
+        [534, 2007],
+        [520, 1999],
+        [517, 2002],
+        [510, 2000],
+        [514, 1993],
+        [495, 1981],
+        [501, 1972],
+        [502, 1967],
+        [498, 1966],
+        [496, 1962],
+        [497, 1959],
+        [489, 1947],
+        [490, 1945],
+        [493, 1943],
+        [503, 1939],
+        [503, 1937],
+        [500, 1935],
+        [499, 1925],
+        [495, 1918],
+        [495, 1915],
+        [499, 1911],
+        [466, 1904],
+        [431, 1894],
+        [400, 1880],
+        [366, 1861],
+        [344, 1845],
+        [306, 1810],
+        [281, 1779],
+        [258, 1740],
+        [239, 1693],
+        [217, 1692],
+        [0, 1691],
+        [-80, 1691],
+        [-80, 1971],
+        [-79, 1970],
+        [-77, 1974],
+        [-72, 1979],
+        [-72, 1982],
+        [-74, 1988],
+        [-80, 1996],
+        [-77, 2000],
+        [-79, 2001],
+        [-78, 2006],
+        [-76, 2012],
+        [-72, 2015],
+        [-73, 2020],
+        [-80, 2026],
+        [-80, 2080],
+        [-78, 2081],
+        [-79, 2085],
+        [-73, 2086],
+        [-69, 2090],
+        [-64, 2086],
+        [-63, 2093],
+        [-65, 2097],
+        [-74, 2105],
+        [-77, 2115],
+        [-80, 2117],
+        [-78, 2120],
+        [-80, 2123],
+        [-80, 2134],
+        [-77, 2142],
+        [-71, 2150],
+        [-72, 2157],
+        [0, 2287],
+        [3, 2293],
+        [5, 2310],
+        [2, 2342],
+        [2, 2369],
+        [0, 2380],
+        [-8, 2427],
+        [0, 2431],
+        [69, 2466],
+        [93, 2480],
+        [283, 2632],
+        [351, 2680],
+        [360, 2670],
+        [367, 2670],
+        [381, 2681],
+        [388, 2685],
+        [398, 2686]]],
+      [[[512, 1924],
+        [518, 1918],
+        [521, 1913],
+        [502, 1911],
+        [506, 1921],
+        [512, 1924]]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '029',
+     'FIPS': '42029',
+     'STATE': 'PA',
+     'NAME': 'Chester',
+     'LSAD': 'County'},
+    'id': 2187,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[841, 2345],
+       [846, 2340],
+       [898, 2250],
+       [912, 2257],
+       [952, 2195],
+       [963, 2176],
+       [957, 2172],
+       [959, 2167],
+       [964, 2161],
+       [972, 2160],
+       [979, 2153],
+       [986, 2155],
+       [991, 2151],
+       [995, 2154],
+       [1004, 2151],
+       [1004, 2146],
+       [1000, 2142],
+       [1003, 2138],
+       [1002, 2135],
+       [999, 2128],
+       [1001, 2118],
+       [1006, 2112],
+       [1016, 2109],
+       [1016, 2102],
+       [1020, 2102],
+       [1023, 2101],
+       [1020, 2092],
+       [1013, 2093],
+       [1009, 2087],
+       [1011, 2086],
+       [1011, 2082],
+       [1005, 2071],
+       [1006, 2056],
+       [999, 2049],
+       [1001, 2045],
+       [996, 2040],
+       [999, 2038],
+       [993, 2029],
+       [994, 2027],
+       [990, 2021],
+       [992, 2020],
+       [988, 2015],
+       [984, 2014],
+       [983, 2008],
+       [980, 2007],
+       [983, 2002],
+       [980, 2001],
+       [983, 1996],
+       [980, 1996],
+       [983, 1985],
+       [1004, 1985],
+       [1015, 1977],
+       [1023, 1986],
+       [1045, 1983],
+       [1051, 1984],
+       [1051, 1975],
+       [1058, 1964],
+       [1043, 1956],
+       [1023, 1947],
+       [970, 1934],
+       [938, 1932],
+       [914, 1935],
+       [895, 1934],
+       [884, 1933],
+       [868, 1927],
+       [849, 1916],
+       [797, 1869],
+       [761, 1843],
+       [742, 1857],
+       [705, 1878],
+       [664, 1895],
+       [639, 1903],
+       [610, 1909],
+       [580, 1912],
+       [535, 1914],
+       [521, 1913],
+       [518, 1918],
+       [512, 1924],
+       [508, 1922],
+       [502, 1911],
+       [499, 1911],
+       [495, 1915],
+       [495, 1918],
+       [499, 1925],
+       [500, 1935],
+       [503, 1937],
+       [503, 1939],
+       [493, 1943],
+       [490, 1945],
+       [489, 1947],
+       [497, 1959],
+       [496, 1962],
+       [498, 1966],
+       [502, 1967],
+       [501, 1972],
+       [495, 1981],
+       [514, 1993],
+       [510, 2000],
+       [517, 2002],
+       [520, 1999],
+       [534, 2007],
+       [529, 2015],
+       [532, 2017],
+       [530, 2023],
+       [551, 2035],
+       [548, 2044],
+       [552, 2046],
+       [555, 2040],
+       [570, 2048],
+       [564, 2058],
+       [575, 2064],
+       [573, 2068],
+       [573, 2074],
+       [577, 2077],
+       [575, 2081],
+       [585, 2086],
+       [593, 2072],
+       [598, 2074],
+       [600, 2071],
+       [603, 2073],
+       [593, 2090],
+       [594, 2091],
+       [593, 2093],
+       [599, 2096],
+       [601, 2090],
+       [610, 2095],
+       [609, 2103],
+       [602, 2113],
+       [730, 2191],
+       [731, 2198],
+       [727, 2204],
+       [728, 2208],
+       [724, 2206],
+       [720, 2208],
+       [705, 2207],
+       [776, 2272],
+       [761, 2299],
+       [841, 2345]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '045',
+     'FIPS': '42045',
+     'STATE': 'PA',
+     'NAME': 'Delaware',
+     'LSAD': 'County'},
+    'id': 2186,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1190, 4074],
+       [1191, 4070],
+       [1190, 4065],
+       [1194, 4044],
+       [1203, 4035],
+       [1211, 4018],
+       [1212, 4012],
+       [1226, 3989],
+       [1250, 3969],
+       [1255, 3956],
+       [1256, 3931],
+       [1270, 3914],
+       [1280, 3899],
+       [1287, 3891],
+       [1290, 3885],
+       [1291, 3876],
+       [1288, 3865],
+       [1272, 3842],
+       [1269, 3841],
+       [1262, 3841],
+       [1254, 3845],
+       [1233, 3844],
+       [1226, 3840],
+       [1223, 3832],
+       [1224, 3825],
+       [1241, 3807],
+       [1243, 3803],
+       [1243, 3797],
+       [1234, 3780],
+       [1225, 3773],
+       [1219, 3764],
+       [1219, 3749],
+       [1207, 3732],
+       [1203, 3730],
+       [1195, 3729],
+       [1186, 3724],
+       [1174, 3703],
+       [1170, 3699],
+       [1148, 3701],
+       [1127, 3708],
+       [1118, 3708],
+       [1115, 3707],
+       [1110, 3697],
+       [1107, 3681],
+       [1105, 3676],
+       [1099, 3671],
+       [1086, 3664],
+       [1079, 3656],
+       [1081, 3645],
+       [1095, 3629],
+       [1100, 3618],
+       [1089, 3592],
+       [1082, 3584],
+       [1068, 3541],
+       [1073, 3529],
+       [1079, 3521],
+       [1088, 3518],
+       [1097, 3519],
+       [1102, 3518],
+       [1107, 3514],
+       [1108, 3511],
+       [1107, 3505],
+       [1099, 3492],
+       [1087, 3484],
+       [1073, 3460],
+       [1073, 3455],
+       [1085, 3444],
+       [1091, 3412],
+       [1088, 3404],
+       [1077, 3402],
+       [1071, 3398],
+       [1072, 3393],
+       [1079, 3382],
+       [992, 3332],
+       [977, 3322],
+       [938, 3292],
+       [880, 3244],
+       [777, 3328],
+       [777, 3330],
+       [795, 3359],
+       [799, 3393],
+       [813, 3394],
+       [811, 3398],
+       [808, 3398],
+       [806, 3404],
+       [807, 3411],
+       [800, 3418],
+       [801, 3429],
+       [795, 3430],
+       [783, 3442],
+       [739, 3497],
+       [739, 3508],
+       [664, 3472],
+       [661, 3481],
+       [661, 3494],
+       [659, 3502],
+       [653, 3511],
+       [643, 3515],
+       [640, 3517],
+       [633, 3537],
+       [622, 3548],
+       [605, 3582],
+       [600, 3595],
+       [599, 3618],
+       [598, 3623],
+       [593, 3627],
+       [583, 3630],
+       [578, 3626],
+       [576, 3611],
+       [571, 3604],
+       [558, 3598],
+       [552, 3597],
+       [543, 3602],
+       [538, 3607],
+       [533, 3621],
+       [528, 3625],
+       [509, 3622],
+       [502, 3627],
+       [496, 3641],
+       [489, 3653],
+       [486, 3666],
+       [487, 3684],
+       [482, 3694],
+       [485, 3703],
+       [484, 3712],
+       [478, 3725],
+       [488, 3726],
+       [494, 3730],
+       [498, 3737],
+       [524, 3748],
+       [553, 3752],
+       [562, 3758],
+       [577, 3763],
+       [596, 3762],
+       [609, 3766],
+       [625, 3767],
+       [668, 3775],
+       [675, 3778],
+       [721, 3785],
+       [753, 3795],
+       [758, 3800],
+       [807, 3809],
+       [868, 3837],
+       [898, 3857],
+       [928, 3864],
+       [952, 3877],
+       [967, 3890],
+       [976, 3908],
+       [1027, 3941],
+       [1014, 3960],
+       [1042, 3980],
+       [1048, 3996],
+       [1081, 4012],
+       [1092, 4014],
+       [1106, 4020],
+       [1108, 4030],
+       [1119, 4035],
+       [1143, 4037],
+       [1154, 4041],
+       [1177, 4056],
+       [1190, 4074]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '095',
+     'FIPS': '42095',
+     'STATE': 'PA',
+     'NAME': 'Northampton',
+     'LSAD': 'County'},
+    'id': 2208,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1978, 4176],
+       [1938, 4131],
+       [1910, 4096],
+       [1889, 4068],
+       [1888, 4056],
+       [1897, 4040],
+       [1897, 4029],
+       [1889, 4014],
+       [1873, 4001],
+       [1871, 3998],
+       [1870, 3992],
+       [1872, 3987],
+       [1871, 3984],
+       [1855, 3977],
+       [1846, 3969],
+       [1832, 3960],
+       [1827, 3961],
+       [1820, 3959],
+       [1818, 3952],
+       [1814, 3951],
+       [1808, 3954],
+       [1796, 3946],
+       [1792, 3945],
+       [1786, 3940],
+       [1782, 3942],
+       [1785, 3951],
+       [1783, 3958],
+       [1769, 3970],
+       [1761, 3974],
+       [1756, 3982],
+       [1749, 3979],
+       [1734, 3980],
+       [1727, 3976],
+       [1727, 3972],
+       [1722, 3968],
+       [1715, 3968],
+       [1713, 3965],
+       [1711, 3968],
+       [1708, 3965],
+       [1706, 3966],
+       [1703, 3965],
+       [1594, 4096],
+       [1570, 4125],
+       [1529, 4176],
+       [1978, 4176]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '037',
+     'FIPS': '34037',
+     'STATE': 'NJ',
+     'NAME': 'Sussex',
+     'LSAD': 'County'},
+    'id': 2225,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1526, 3726],
+       [1592, 3670],
+       [1594, 3665],
+       [1617, 3642],
+       [1622, 3639],
+       [1633, 3639],
+       [1638, 3638],
+       [1638, 3636],
+       [1644, 3636],
+       [1659, 3638],
+       [1666, 3634],
+       [1704, 3625],
+       [1725, 3617],
+       [1740, 3607],
+       [1740, 3603],
+       [1755, 3595],
+       [1767, 3595],
+       [1768, 3590],
+       [1773, 3586],
+       [1772, 3582],
+       [1774, 3569],
+       [1777, 3567],
+       [1778, 3565],
+       [1776, 3564],
+       [1779, 3558],
+       [1778, 3555],
+       [1772, 3550],
+       [1771, 3541],
+       [1768, 3533],
+       [1776, 3526],
+       [1775, 3519],
+       [1771, 3515],
+       [1769, 3500],
+       [1764, 3494],
+       [1757, 3491],
+       [1762, 3478],
+       [1769, 3474],
+       [1774, 3465],
+       [1768, 3455],
+       [1767, 3450],
+       [1770, 3446],
+       [1769, 3440],
+       [1762, 3434],
+       [1765, 3426],
+       [1774, 3425],
+       [1778, 3426],
+       [1783, 3424],
+       [1786, 3418],
+       [1786, 3413],
+       [1797, 3406],
+       [1786, 3387],
+       [1783, 3389],
+       [1771, 3366],
+       [1775, 3364],
+       [1766, 3344],
+       [1783, 3335],
+       [1766, 3300],
+       [1758, 3295],
+       [1751, 3286],
+       [1740, 3277],
+       [1693, 3182],
+       [1690, 3180],
+       [1685, 3182],
+       [1678, 3190],
+       [1678, 3193],
+       [1674, 3197],
+       [1660, 3203],
+       [1732, 3028],
+       [1644, 3014],
+       [1654, 2953],
+       [1555, 2940],
+       [1575, 2880],
+       [1464, 2866],
+       [1448, 2871],
+       [1447, 2872],
+       [1444, 2901],
+       [1440, 2915],
+       [1433, 2936],
+       [1416, 2977],
+       [1410, 2982],
+       [1390, 2991],
+       [1381, 2999],
+       [1371, 3002],
+       [1360, 2997],
+       [1340, 2991],
+       [1329, 2989],
+       [1324, 2990],
+       [1312, 2995],
+       [1298, 3009],
+       [1284, 3013],
+       [1280, 3017],
+       [1276, 3026],
+       [1274, 3046],
+       [1267, 3075],
+       [1263, 3088],
+       [1267, 3106],
+       [1267, 3122],
+       [1272, 3129],
+       [1275, 3138],
+       [1275, 3147],
+       [1269, 3194],
+       [1271, 3224],
+       [1269, 3244],
+       [1265, 3254],
+       [1251, 3266],
+       [1219, 3304],
+       [1195, 3314],
+       [1166, 3319],
+       [1159, 3318],
+       [1151, 3314],
+       [1135, 3299],
+       [1128, 3296],
+       [1120, 3296],
+       [1110, 3298],
+       [1099, 3303],
+       [1093, 3307],
+       [1083, 3320],
+       [1081, 3326],
+       [1082, 3331],
+       [1087, 3340],
+       [1088, 3349],
+       [1096, 3351],
+       [1102, 3355],
+       [1104, 3361],
+       [1111, 3363],
+       [1114, 3375],
+       [1120, 3378],
+       [1124, 3385],
+       [1128, 3387],
+       [1130, 3393],
+       [1129, 3399],
+       [1141, 3407],
+       [1147, 3405],
+       [1150, 3408],
+       [1150, 3416],
+       [1153, 3420],
+       [1168, 3424],
+       [1180, 3431],
+       [1205, 3440],
+       [1208, 3442],
+       [1207, 3447],
+       [1211, 3451],
+       [1226, 3458],
+       [1235, 3468],
+       [1236, 3472],
+       [1247, 3476],
+       [1254, 3488],
+       [1264, 3494],
+       [1267, 3497],
+       [1275, 3499],
+       [1278, 3505],
+       [1282, 3510],
+       [1288, 3512],
+       [1295, 3518],
+       [1301, 3516],
+       [1303, 3517],
+       [1308, 3524],
+       [1310, 3526],
+       [1315, 3526],
+       [1333, 3542],
+       [1337, 3542],
+       [1341, 3547],
+       [1345, 3543],
+       [1351, 3547],
+       [1356, 3544],
+       [1361, 3545],
+       [1378, 3563],
+       [1393, 3569],
+       [1396, 3578],
+       [1410, 3577],
+       [1419, 3597],
+       [1424, 3602],
+       [1426, 3606],
+       [1435, 3610],
+       [1443, 3624],
+       [1451, 3631],
+       [1452, 3636],
+       [1465, 3651],
+       [1467, 3656],
+       [1470, 3658],
+       [1473, 3663],
+       [1485, 3672],
+       [1489, 3677],
+       [1489, 3680],
+       [1494, 3686],
+       [1507, 3695],
+       [1506, 3698],
+       [1507, 3706],
+       [1505, 3712],
+       [1517, 3719],
+       [1526, 3726]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '019',
+     'FIPS': '34019',
+     'STATE': 'NJ',
+     'NAME': 'Hunterdon',
+     'LSAD': 'County'},
+    'id': 2209,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2012, 3669],
+       [2018, 3663],
+       [2019, 3655],
+       [2017, 3652],
+       [2023, 3646],
+       [2022, 3622],
+       [2026, 3623],
+       [2028, 3621],
+       [2035, 3622],
+       [2043, 3616],
+       [2046, 3617],
+       [2052, 3611],
+       [2048, 3598],
+       [2048, 3595],
+       [2051, 3594],
+       [2052, 3591],
+       [2058, 3587],
+       [2057, 3581],
+       [2054, 3578],
+       [2056, 3575],
+       [2061, 3574],
+       [2068, 3568],
+       [2069, 3561],
+       [2071, 3561],
+       [2073, 3559],
+       [2073, 3547],
+       [2070, 3544],
+       [2067, 3545],
+       [2066, 3541],
+       [2069, 3539],
+       [2069, 3537],
+       [2062, 3535],
+       [2058, 3537],
+       [2055, 3529],
+       [2053, 3527],
+       [2052, 3521],
+       [2056, 3501],
+       [2051, 3498],
+       [2050, 3495],
+       [2043, 3494],
+       [2044, 3491],
+       [2050, 3490],
+       [2051, 3486],
+       [2056, 3482],
+       [2054, 3479],
+       [2056, 3469],
+       [2059, 3469],
+       [2055, 3465],
+       [2060, 3464],
+       [2061, 3461],
+       [2070, 3462],
+       [2071, 3463],
+       [2075, 3460],
+       [2082, 3466],
+       [2086, 3475],
+       [2085, 3477],
+       [2088, 3480],
+       [2091, 3478],
+       [2095, 3479],
+       [2094, 3483],
+       [2100, 3484],
+       [2102, 3482],
+       [2106, 3484],
+       [2106, 3487],
+       [2112, 3488],
+       [2114, 3485],
+       [2117, 3487],
+       [2116, 3491],
+       [2128, 3493],
+       [2133, 3498],
+       [2137, 3496],
+       [2149, 3503],
+       [2150, 3506],
+       [2164, 3469],
+       [2175, 3475],
+       [2185, 3486],
+       [2196, 3491],
+       [2198, 3487],
+       [2202, 3485],
+       [2208, 3477],
+       [2211, 3478],
+       [2214, 3483],
+       [2220, 3485],
+       [2224, 3491],
+       [2231, 3495],
+       [2234, 3493],
+       [2236, 3487],
+       [2235, 3481],
+       [2235, 3473],
+       [2229, 3462],
+       [2229, 3455],
+       [2226, 3447],
+       [2220, 3446],
+       [2219, 3444],
+       [2217, 3429],
+       [2213, 3418],
+       [2206, 3414],
+       [2205, 3405],
+       [2199, 3397],
+       [2193, 3396],
+       [2184, 3385],
+       [2173, 3383],
+       [2169, 3381],
+       [2164, 3373],
+       [2159, 3373],
+       [2152, 3365],
+       [2143, 3362],
+       [2137, 3362],
+       [2126, 3354],
+       [2118, 3345],
+       [2108, 3340],
+       [2104, 3341],
+       [2097, 3338],
+       [2094, 3340],
+       [2091, 3337],
+       [2091, 3334],
+       [2086, 3339],
+       [2076, 3331],
+       [2070, 3329],
+       [2071, 3326],
+       [2063, 3315],
+       [2059, 3307],
+       [2056, 3305],
+       [2057, 3292],
+       [2054, 3288],
+       [2059, 3286],
+       [2065, 3280],
+       [2068, 3273],
+       [2072, 3255],
+       [2083, 3244],
+       [2100, 3230],
+       [2119, 3197],
+       [2122, 3195],
+       [2141, 3190],
+       [2143, 3178],
+       [2151, 3171],
+       [2153, 3166],
+       [2152, 3156],
+       [2140, 3148],
+       [2125, 3143],
+       [2119, 3139],
+       [2102, 3115],
+       [2082, 3099],
+       [2075, 3091],
+       [2064, 3080],
+       [2055, 3068],
+       [2041, 3056],
+       [2013, 3040],
+       [1971, 3018],
+       [1968, 3014],
+       [1969, 2989],
+       [1966, 2981],
+       [1966, 2971],
+       [1960, 2967],
+       [1955, 2956],
+       [1944, 2945],
+       [1928, 2936],
+       [1919, 2933],
+       [1922, 2940],
+       [1921, 2944],
+       [1915, 2952],
+       [1870, 2965],
+       [1839, 2952],
+       [1791, 2943],
+       [1770, 2935],
+       [1660, 3203],
+       [1674, 3197],
+       [1678, 3193],
+       [1678, 3190],
+       [1685, 3182],
+       [1692, 3180],
+       [1740, 3277],
+       [1751, 3286],
+       [1758, 3295],
+       [1766, 3300],
+       [1783, 3335],
+       [1766, 3344],
+       [1775, 3364],
+       [1771, 3366],
+       [1783, 3389],
+       [1786, 3387],
+       [1797, 3406],
+       [1786, 3413],
+       [1786, 3418],
+       [1783, 3424],
+       [1778, 3426],
+       [1774, 3425],
+       [1765, 3426],
+       [1762, 3434],
+       [1769, 3440],
+       [1770, 3446],
+       [1767, 3450],
+       [1768, 3455],
+       [1774, 3465],
+       [1769, 3474],
+       [1762, 3478],
+       [1757, 3491],
+       [1764, 3494],
+       [1769, 3500],
+       [1771, 3515],
+       [1775, 3519],
+       [1776, 3526],
+       [1768, 3533],
+       [1771, 3541],
+       [1772, 3550],
+       [1778, 3555],
+       [1779, 3558],
+       [1776, 3564],
+       [1778, 3565],
+       [1777, 3567],
+       [1774, 3569],
+       [1772, 3582],
+       [1773, 3586],
+       [1768, 3590],
+       [1767, 3595],
+       [1848, 3621],
+       [2012, 3669]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '035',
+     'FIPS': '34035',
+     'STATE': 'NJ',
+     'NAME': 'Somerset',
+     'LSAD': 'County'},
+    'id': 2211,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1079, 3382],
+       [1085, 3370],
+       [1088, 3347],
+       [1087, 3340],
+       [1082, 3331],
+       [1082, 3324],
+       [1085, 3316],
+       [1099, 3303],
+       [1110, 3298],
+       [1128, 3296],
+       [1135, 3299],
+       [1151, 3314],
+       [1159, 3318],
+       [1166, 3319],
+       [1195, 3314],
+       [1219, 3304],
+       [1251, 3266],
+       [1265, 3254],
+       [1269, 3244],
+       [1271, 3224],
+       [1269, 3194],
+       [1275, 3147],
+       [1275, 3138],
+       [1272, 3129],
+       [1267, 3122],
+       [1267, 3106],
+       [1263, 3088],
+       [1267, 3075],
+       [1274, 3046],
+       [1276, 3026],
+       [1280, 3017],
+       [1284, 3013],
+       [1298, 3009],
+       [1312, 2995],
+       [1324, 2990],
+       [1329, 2989],
+       [1340, 2991],
+       [1360, 2997],
+       [1371, 3002],
+       [1381, 2999],
+       [1390, 2991],
+       [1410, 2982],
+       [1416, 2977],
+       [1433, 2936],
+       [1440, 2915],
+       [1444, 2901],
+       [1447, 2872],
+       [1453, 2864],
+       [1499, 2823],
+       [1506, 2821],
+       [1516, 2820],
+       [1523, 2816],
+       [1539, 2802],
+       [1557, 2782],
+       [1569, 2762],
+       [1595, 2697],
+       [1604, 2688],
+       [1622, 2679],
+       [1628, 2674],
+       [1663, 2656],
+       [1698, 2630],
+       [1714, 2598],
+       [1723, 2572],
+       [1727, 2568],
+       [1738, 2564],
+       [1748, 2558],
+       [1770, 2525],
+       [1771, 2512],
+       [1767, 2499],
+       [1743, 2477],
+       [1735, 2475],
+       [1722, 2476],
+       [1716, 2475],
+       [1701, 2465],
+       [1683, 2449],
+       [1673, 2449],
+       [1656, 2453],
+       [1633, 2462],
+       [1624, 2461],
+       [1619, 2455],
+       [1615, 2448],
+       [1609, 2432],
+       [1605, 2417],
+       [1601, 2411],
+       [1593, 2405],
+       [1577, 2397],
+       [1572, 2388],
+       [1570, 2381],
+       [1564, 2376],
+       [1540, 2369],
+       [1529, 2364],
+       [1498, 2353],
+       [1481, 2355],
+       [1474, 2354],
+       [1446, 2340],
+       [1403, 2312],
+       [1394, 2322],
+       [1389, 2323],
+       [1388, 2329],
+       [1394, 2334],
+       [1394, 2345],
+       [1405, 2356],
+       [1408, 2365],
+       [1420, 2368],
+       [1426, 2380],
+       [1426, 2390],
+       [1429, 2397],
+       [1429, 2402],
+       [1421, 2406],
+       [1422, 2416],
+       [1416, 2425],
+       [1418, 2428],
+       [1419, 2438],
+       [1418, 2443],
+       [1414, 2444],
+       [1409, 2442],
+       [1404, 2448],
+       [1395, 2447],
+       [1390, 2450],
+       [1390, 2454],
+       [1384, 2454],
+       [1379, 2460],
+       [1374, 2460],
+       [1377, 2469],
+       [1375, 2471],
+       [1368, 2463],
+       [1184, 2606],
+       [1065, 2701],
+       [937, 2799],
+       [745, 2952],
+       [660, 3017],
+       [769, 3151],
+       [872, 3239],
+       [880, 3244],
+       [938, 3292],
+       [977, 3322],
+       [992, 3332],
+       [1079, 3382]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '017',
+     'FIPS': '42017',
+     'STATE': 'PA',
+     'NAME': 'Bucks',
+     'LSAD': 'County'},
+    'id': 2197,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1343, 2482],
+       [1368, 2463],
+       [1375, 2471],
+       [1377, 2469],
+       [1374, 2460],
+       [1379, 2460],
+       [1384, 2454],
+       [1390, 2454],
+       [1390, 2450],
+       [1395, 2447],
+       [1404, 2448],
+       [1409, 2442],
+       [1414, 2444],
+       [1418, 2443],
+       [1419, 2438],
+       [1418, 2428],
+       [1416, 2425],
+       [1422, 2416],
+       [1421, 2406],
+       [1429, 2402],
+       [1429, 2397],
+       [1426, 2390],
+       [1426, 2380],
+       [1420, 2368],
+       [1408, 2365],
+       [1405, 2356],
+       [1394, 2345],
+       [1394, 2334],
+       [1388, 2329],
+       [1389, 2323],
+       [1394, 2322],
+       [1403, 2312],
+       [1389, 2301],
+       [1349, 2260],
+       [1308, 2244],
+       [1297, 2236],
+       [1291, 2228],
+       [1279, 2205],
+       [1260, 2183],
+       [1236, 2172],
+       [1208, 2163],
+       [1180, 2146],
+       [1171, 2133],
+       [1168, 2119],
+       [1167, 2094],
+       [1169, 2081],
+       [1179, 2052],
+       [1175, 2030],
+       [1158, 2004],
+       [1154, 2000],
+       [1146, 1997],
+       [1099, 1995],
+       [1090, 1993],
+       [1058, 1964],
+       [1051, 1975],
+       [1051, 1984],
+       [1045, 1983],
+       [1023, 1986],
+       [1015, 1977],
+       [1004, 1985],
+       [983, 1985],
+       [980, 1996],
+       [983, 1996],
+       [980, 2001],
+       [983, 2002],
+       [980, 2007],
+       [983, 2008],
+       [984, 2014],
+       [988, 2015],
+       [992, 2020],
+       [990, 2021],
+       [994, 2027],
+       [993, 2029],
+       [999, 2038],
+       [996, 2040],
+       [1001, 2045],
+       [999, 2049],
+       [1006, 2056],
+       [1005, 2071],
+       [1011, 2082],
+       [1011, 2086],
+       [1009, 2087],
+       [1013, 2093],
+       [1020, 2092],
+       [1023, 2101],
+       [1020, 2102],
+       [1016, 2102],
+       [1016, 2109],
+       [1006, 2112],
+       [1001, 2118],
+       [999, 2128],
+       [1002, 2135],
+       [1003, 2138],
+       [1000, 2142],
+       [1004, 2146],
+       [1004, 2151],
+       [995, 2154],
+       [991, 2151],
+       [986, 2155],
+       [979, 2153],
+       [972, 2160],
+       [964, 2161],
+       [957, 2172],
+       [982, 2187],
+       [993, 2196],
+       [1063, 2239],
+       [1065, 2242],
+       [1056, 2249],
+       [1048, 2259],
+       [1027, 2273],
+       [1018, 2281],
+       [1007, 2292],
+       [1002, 2299],
+       [987, 2313],
+       [980, 2322],
+       [1040, 2396],
+       [1091, 2358],
+       [1108, 2381],
+       [1206, 2307],
+       [1210, 2313],
+       [1228, 2327],
+       [1238, 2340],
+       [1224, 2351],
+       [1239, 2369],
+       [1245, 2377],
+       [1252, 2383],
+       [1280, 2421],
+       [1335, 2471],
+       [1343, 2482]]]},
+    'properties': {'STATE_FIPS': '42',
+     'COUNTY_FIP': '101',
+     'FIPS': '42101',
+     'STATE': 'PA',
+     'NAME': 'Philadelphia',
+     'LSAD': 'County'},
+    'id': 2177,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1732, 3028],
+       [1770, 2935],
+       [1791, 2943],
+       [1839, 2952],
+       [1870, 2965],
+       [1915, 2952],
+       [1921, 2944],
+       [1922, 2940],
+       [1916, 2919],
+       [1912, 2916],
+       [1904, 2878],
+       [1904, 2869],
+       [1914, 2857],
+       [1912, 2847],
+       [1915, 2845],
+       [1915, 2840],
+       [1916, 2838],
+       [1925, 2839],
+       [1936, 2833],
+       [1943, 2832],
+       [1947, 2821],
+       [1953, 2819],
+       [1957, 2820],
+       [1969, 2816],
+       [1972, 2803],
+       [1976, 2799],
+       [1983, 2797],
+       [1991, 2790],
+       [1995, 2791],
+       [1999, 2785],
+       [2007, 2783],
+       [2010, 2776],
+       [2016, 2773],
+       [2021, 2773],
+       [2027, 2775],
+       [2028, 2777],
+       [2032, 2775],
+       [2036, 2769],
+       [2040, 2771],
+       [2045, 2776],
+       [2052, 2780],
+       [2061, 2772],
+       [2061, 2765],
+       [2072, 2766],
+       [2077, 2759],
+       [2086, 2754],
+       [2088, 2754],
+       [2091, 2751],
+       [2095, 2754],
+       [2119, 2741],
+       [2116, 2702],
+       [2112, 2702],
+       [2112, 2700],
+       [2119, 2689],
+       [2121, 2683],
+       [2069, 2652],
+       [2031, 2632],
+       [2025, 2624],
+       [2023, 2615],
+       [2011, 2600],
+       [2002, 2581],
+       [1991, 2573],
+       [1985, 2576],
+       [1968, 2569],
+       [1957, 2562],
+       [1954, 2562],
+       [1952, 2574],
+       [1948, 2575],
+       [1927, 2567],
+       [1966, 2483],
+       [1945, 2480],
+       [1937, 2485],
+       [1938, 2487],
+       [1933, 2485],
+       [1926, 2487],
+       [1924, 2489],
+       [1920, 2487],
+       [1916, 2488],
+       [1914, 2490],
+       [1915, 2495],
+       [1914, 2497],
+       [1913, 2503],
+       [1908, 2504],
+       [1908, 2503],
+       [1904, 2503],
+       [1902, 2506],
+       [1899, 2503],
+       [1897, 2508],
+       [1893, 2509],
+       [1892, 2513],
+       [1887, 2515],
+       [1885, 2513],
+       [1880, 2517],
+       [1878, 2516],
+       [1874, 2521],
+       [1868, 2521],
+       [1867, 2524],
+       [1862, 2528],
+       [1859, 2528],
+       [1857, 2534],
+       [1853, 2533],
+       [1852, 2536],
+       [1849, 2537],
+       [1847, 2537],
+       [1846, 2534],
+       [1845, 2537],
+       [1841, 2538],
+       [1838, 2535],
+       [1835, 2536],
+       [1840, 2543],
+       [1838, 2548],
+       [1840, 2550],
+       [1832, 2550],
+       [1831, 2554],
+       [1824, 2559],
+       [1823, 2553],
+       [1822, 2557],
+       [1816, 2556],
+       [1813, 2561],
+       [1808, 2560],
+       [1810, 2567],
+       [1806, 2567],
+       [1799, 2570],
+       [1796, 2566],
+       [1790, 2566],
+       [1786, 2563],
+       [1788, 2560],
+       [1783, 2554],
+       [1786, 2549],
+       [1790, 2547],
+       [1787, 2539],
+       [1788, 2537],
+       [1796, 2541],
+       [1793, 2527],
+       [1783, 2517],
+       [1782, 2510],
+       [1774, 2501],
+       [1767, 2500],
+       [1771, 2512],
+       [1770, 2525],
+       [1748, 2558],
+       [1738, 2564],
+       [1727, 2568],
+       [1723, 2572],
+       [1714, 2598],
+       [1698, 2630],
+       [1663, 2656],
+       [1628, 2674],
+       [1622, 2679],
+       [1604, 2688],
+       [1595, 2697],
+       [1569, 2762],
+       [1557, 2782],
+       [1539, 2802],
+       [1523, 2816],
+       [1516, 2820],
+       [1506, 2821],
+       [1499, 2823],
+       [1486, 2834],
+       [1453, 2864],
+       [1448, 2871],
+       [1464, 2866],
+       [1575, 2880],
+       [1555, 2940],
+       [1654, 2953],
+       [1644, 3014],
+       [1732, 3028]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '021',
+     'FIPS': '34021',
+     'STATE': 'NJ',
+     'NAME': 'Mercer',
+     'LSAD': 'County'},
+    'id': 2196,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1799, 2570],
+       [1806, 2567],
+       [1810, 2567],
+       [1808, 2560],
+       [1813, 2561],
+       [1816, 2556],
+       [1822, 2557],
+       [1823, 2553],
+       [1824, 2559],
+       [1831, 2554],
+       [1832, 2550],
+       [1840, 2550],
+       [1838, 2548],
+       [1840, 2543],
+       [1835, 2536],
+       [1838, 2535],
+       [1841, 2538],
+       [1845, 2537],
+       [1846, 2534],
+       [1847, 2537],
+       [1849, 2537],
+       [1852, 2536],
+       [1853, 2533],
+       [1857, 2534],
+       [1859, 2528],
+       [1862, 2528],
+       [1867, 2524],
+       [1868, 2521],
+       [1874, 2521],
+       [1878, 2516],
+       [1880, 2517],
+       [1885, 2513],
+       [1887, 2515],
+       [1892, 2513],
+       [1893, 2509],
+       [1897, 2508],
+       [1899, 2503],
+       [1902, 2506],
+       [1904, 2503],
+       [1908, 2503],
+       [1908, 2504],
+       [1913, 2503],
+       [1914, 2497],
+       [1915, 2495],
+       [1914, 2490],
+       [1916, 2488],
+       [1920, 2487],
+       [1924, 2489],
+       [1926, 2487],
+       [1933, 2485],
+       [1938, 2487],
+       [1937, 2485],
+       [1945, 2480],
+       [1966, 2483],
+       [2052, 2289],
+       [2084, 2203],
+       [2167, 1994],
+       [2254, 1789],
+       [2253, 1454],
+       [2250, 1450],
+       [2244, 1432],
+       [2242, 1417],
+       [2238, 1409],
+       [2235, 1408],
+       [2232, 1404],
+       [2226, 1404],
+       [2224, 1406],
+       [2221, 1405],
+       [2216, 1405],
+       [2212, 1402],
+       [2214, 1393],
+       [2219, 1390],
+       [2214, 1380],
+       [2209, 1380],
+       [2201, 1373],
+       [2199, 1373],
+       [2191, 1377],
+       [2187, 1376],
+       [2184, 1374],
+       [2184, 1369],
+       [2190, 1359],
+       [2190, 1353],
+       [2188, 1350],
+       [2182, 1350],
+       [2175, 1357],
+       [2172, 1363],
+       [2176, 1378],
+       [2172, 1383],
+       [2169, 1384],
+       [2164, 1382],
+       [2162, 1378],
+       [2162, 1367],
+       [2158, 1361],
+       [2154, 1362],
+       [2152, 1366],
+       [2150, 1376],
+       [2148, 1379],
+       [2144, 1379],
+       [2139, 1377],
+       [2134, 1371],
+       [2130, 1369],
+       [2126, 1372],
+       [2120, 1382],
+       [2113, 1383],
+       [2108, 1379],
+       [2103, 1379],
+       [2101, 1381],
+       [2099, 1391],
+       [2092, 1395],
+       [2088, 1403],
+       [2080, 1402],
+       [2076, 1404],
+       [2072, 1412],
+       [2067, 1411],
+       [2059, 1403],
+       [2054, 1403],
+       [2051, 1405],
+       [2045, 1411],
+       [2037, 1413],
+       [2034, 1417],
+       [2031, 1425],
+       [2033, 1434],
+       [2022, 1442],
+       [2015, 1457],
+       [2000, 1455],
+       [1992, 1459],
+       [1983, 1458],
+       [1975, 1468],
+       [1969, 1471],
+       [1966, 1481],
+       [1964, 1484],
+       [1954, 1488],
+       [1936, 1502],
+       [1929, 1506],
+       [1926, 1505],
+       [1916, 1512],
+       [1914, 1512],
+       [1911, 1509],
+       [1910, 1503],
+       [1906, 1499],
+       [1902, 1501],
+       [1902, 1507],
+       [1900, 1513],
+       [1896, 1513],
+       [1893, 1505],
+       [1890, 1504],
+       [1889, 1505],
+       [1888, 1510],
+       [1878, 1509],
+       [1878, 1514],
+       [1874, 1515],
+       [1871, 1511],
+       [1868, 1512],
+       [1868, 1518],
+       [1866, 1520],
+       [1861, 1521],
+       [1863, 1530],
+       [1861, 1538],
+       [1865, 1546],
+       [1862, 1550],
+       [1863, 1554],
+       [1863, 1559],
+       [1860, 1560],
+       [1862, 1563],
+       [1861, 1566],
+       [1863, 1569],
+       [1860, 1591],
+       [1854, 1601],
+       [1854, 1606],
+       [1851, 1615],
+       [1846, 1623],
+       [1842, 1625],
+       [1837, 1634],
+       [1718, 1733],
+       [1716, 1731],
+       [1713, 1735],
+       [1706, 1738],
+       [1702, 1745],
+       [1696, 1747],
+       [1693, 1758],
+       [1684, 1761],
+       [1680, 1769],
+       [1681, 1771],
+       [1678, 1775],
+       [1676, 1776],
+       [1669, 1787],
+       [1659, 1794],
+       [1646, 1809],
+       [1632, 1813],
+       [1628, 1816],
+       [1603, 1822],
+       [1591, 1821],
+       [1587, 1819],
+       [1584, 1819],
+       [1579, 1815],
+       [1560, 1811],
+       [1545, 1805],
+       [1526, 1806],
+       [1517, 1810],
+       [1513, 1819],
+       [1506, 1823],
+       [1472, 1980],
+       [1464, 2006],
+       [1451, 2015],
+       [1447, 2016],
+       [1443, 2024],
+       [1439, 2027],
+       [1435, 2032],
+       [1435, 2041],
+       [1430, 2055],
+       [1421, 2065],
+       [1418, 2069],
+       [1402, 2070],
+       [1392, 2080],
+       [1389, 2081],
+       [1387, 2086],
+       [1388, 2089],
+       [1393, 2089],
+       [1393, 2094],
+       [1397, 2095],
+       [1402, 2102],
+       [1400, 2105],
+       [1392, 2106],
+       [1385, 2105],
+       [1381, 2107],
+       [1376, 2106],
+       [1368, 2106],
+       [1364, 2109],
+       [1359, 2108],
+       [1352, 2115],
+       [1345, 2116],
+       [1344, 2118],
+       [1342, 2125],
+       [1346, 2132],
+       [1346, 2137],
+       [1340, 2142],
+       [1340, 2149],
+       [1338, 2150],
+       [1337, 2161],
+       [1342, 2163],
+       [1342, 2167],
+       [1340, 2170],
+       [1343, 2172],
+       [1343, 2175],
+       [1351, 2181],
+       [1345, 2182],
+       [1341, 2189],
+       [1344, 2192],
+       [1340, 2191],
+       [1338, 2199],
+       [1336, 2201],
+       [1335, 2198],
+       [1328, 2202],
+       [1325, 2207],
+       [1324, 2204],
+       [1321, 2204],
+       [1314, 2212],
+       [1305, 2210],
+       [1303, 2207],
+       [1300, 2209],
+       [1296, 2208],
+       [1293, 2203],
+       [1278, 2204],
+       [1291, 2228],
+       [1297, 2236],
+       [1308, 2244],
+       [1349, 2260],
+       [1389, 2301],
+       [1402, 2312],
+       [1446, 2340],
+       [1474, 2354],
+       [1481, 2355],
+       [1498, 2353],
+       [1529, 2364],
+       [1540, 2369],
+       [1564, 2376],
+       [1568, 2379],
+       [1574, 2393],
+       [1577, 2397],
+       [1593, 2405],
+       [1601, 2411],
+       [1605, 2417],
+       [1609, 2432],
+       [1615, 2448],
+       [1619, 2455],
+       [1624, 2461],
+       [1633, 2462],
+       [1656, 2453],
+       [1678, 2448],
+       [1683, 2449],
+       [1701, 2465],
+       [1716, 2475],
+       [1722, 2476],
+       [1735, 2475],
+       [1743, 2477],
+       [1767, 2500],
+       [1774, 2501],
+       [1782, 2510],
+       [1783, 2517],
+       [1793, 2527],
+       [1796, 2541],
+       [1788, 2537],
+       [1787, 2539],
+       [1790, 2547],
+       [1786, 2549],
+       [1783, 2554],
+       [1788, 2560],
+       [1786, 2563],
+       [1790, 2566],
+       [1796, 2566],
+       [1799, 2570]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '005',
+     'FIPS': '34005',
+     'STATE': 'NJ',
+     'NAME': 'Burlington',
+     'LSAD': 'County'},
+    'id': 2178,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[217, 1692],
+       [217, 1571],
+       [219, 1532],
+       [249, 1041],
+       [240, 1045],
+       [235, 1044],
+       [235, 1047],
+       [223, 1051],
+       [222, 1046],
+       [216, 1048],
+       [213, 1046],
+       [209, 1046],
+       [206, 1041],
+       [198, 1042],
+       [193, 1037],
+       [191, 1038],
+       [186, 1046],
+       [176, 1047],
+       [173, 1050],
+       [166, 1049],
+       [155, 1035],
+       [139, 1029],
+       [134, 1023],
+       [130, 1024],
+       [120, 1017],
+       [111, 1023],
+       [107, 1021],
+       [102, 1023],
+       [81, 1017],
+       [76, 1010],
+       [71, 1012],
+       [63, 1019],
+       [49, 1017],
+       [21, 1022],
+       [14, 1030],
+       [8, 1030],
+       [0, 1025],
+       [-5, 1023],
+       [-11, 1025],
+       [-17, 1032],
+       [-21, 1034],
+       [-39, 1036],
+       [-48, 1033],
+       [-56, 1022],
+       [-60, 1021],
+       [-64, 1021],
+       [-75, 1034],
+       [-80, 1037],
+       [-80, 1144],
+       [-66, 1150],
+       [-57, 1168],
+       [-57, 1174],
+       [-76, 1194],
+       [-80, 1194],
+       [-80, 1260],
+       [-71, 1292],
+       [-56, 1329],
+       [-43, 1345],
+       [-43, 1367],
+       [-48, 1381],
+       [-80, 1391],
+       [-80, 1691],
+       [0, 1691],
+       [217, 1692]]]},
+    'properties': {'STATE_FIPS': '24',
+     'COUNTY_FIP': '015',
+     'FIPS': '24015',
+     'STATE': 'MD',
+     'NAME': 'Cecil',
+     'LSAD': 'County'},
+    'id': 2129,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1272, 1811],
+       [1283, 1808],
+       [1285, 1809],
+       [1287, 1804],
+       [1294, 1799],
+       [1292, 1795],
+       [1294, 1786],
+       [1300, 1777],
+       [1303, 1772],
+       [1302, 1767],
+       [1308, 1764],
+       [1313, 1759],
+       [1315, 1754],
+       [1333, 1738],
+       [1334, 1735],
+       [1332, 1727],
+       [1335, 1722],
+       [1334, 1714],
+       [1331, 1708],
+       [1373, 1681],
+       [1374, 1670],
+       [1381, 1667],
+       [1384, 1663],
+       [1397, 1657],
+       [1407, 1655],
+       [1413, 1656],
+       [1417, 1655],
+       [1425, 1656],
+       [1434, 1649],
+       [1447, 1647],
+       [1461, 1637],
+       [1463, 1634],
+       [1466, 1633],
+       [1467, 1629],
+       [1472, 1626],
+       [1472, 1621],
+       [1476, 1618],
+       [1480, 1611],
+       [1484, 1611],
+       [1486, 1600],
+       [1498, 1585],
+       [1496, 1582],
+       [1498, 1574],
+       [1497, 1569],
+       [1499, 1567],
+       [1496, 1561],
+       [1498, 1559],
+       [1501, 1539],
+       [1507, 1522],
+       [1522, 1508],
+       [1521, 1502],
+       [1523, 1495],
+       [1536, 1486],
+       [1537, 1482],
+       [1544, 1477],
+       [1387, 1300],
+       [1075, 1588],
+       [1044, 1578],
+       [1039, 1581],
+       [1026, 1578],
+       [1004, 1584],
+       [1000, 1592],
+       [999, 1606],
+       [996, 1610],
+       [991, 1611],
+       [984, 1616],
+       [972, 1617],
+       [963, 1613],
+       [961, 1615],
+       [948, 1612],
+       [938, 1621],
+       [918, 1631],
+       [914, 1630],
+       [912, 1627],
+       [907, 1629],
+       [909, 1632],
+       [907, 1634],
+       [898, 1634],
+       [895, 1631],
+       [890, 1631],
+       [889, 1639],
+       [891, 1643],
+       [884, 1644],
+       [883, 1648],
+       [878, 1651],
+       [876, 1658],
+       [870, 1660],
+       [868, 1659],
+       [859, 1664],
+       [856, 1671],
+       [840, 1675],
+       [839, 1682],
+       [836, 1681],
+       [831, 1684],
+       [832, 1689],
+       [831, 1692],
+       [828, 1692],
+       [823, 1697],
+       [822, 1696],
+       [817, 1700],
+       [817, 1704],
+       [821, 1717],
+       [816, 1725],
+       [819, 1727],
+       [815, 1727],
+       [817, 1729],
+       [815, 1732],
+       [817, 1735],
+       [812, 1742],
+       [803, 1739],
+       [801, 1742],
+       [802, 1747],
+       [800, 1746],
+       [800, 1749],
+       [796, 1749],
+       [796, 1745],
+       [793, 1747],
+       [794, 1749],
+       [789, 1753],
+       [791, 1756],
+       [794, 1754],
+       [797, 1756],
+       [797, 1759],
+       [794, 1760],
+       [798, 1765],
+       [788, 1767],
+       [787, 1762],
+       [785, 1759],
+       [783, 1762],
+       [784, 1766],
+       [778, 1766],
+       [774, 1771],
+       [776, 1782],
+       [779, 1783],
+       [782, 1779],
+       [785, 1781],
+       [790, 1790],
+       [788, 1791],
+       [785, 1788],
+       [783, 1789],
+       [781, 1794],
+       [782, 1799],
+       [779, 1807],
+       [777, 1807],
+       [775, 1803],
+       [771, 1804],
+       [774, 1810],
+       [772, 1816],
+       [769, 1817],
+       [764, 1812],
+       [757, 1813],
+       [748, 1809],
+       [734, 1808],
+       [723, 1803],
+       [728, 1808],
+       [775, 1833],
+       [761, 1843],
+       [797, 1869],
+       [849, 1916],
+       [868, 1927],
+       [884, 1933],
+       [895, 1934],
+       [914, 1935],
+       [938, 1932],
+       [970, 1934],
+       [1011, 1943],
+       [1043, 1956],
+       [1059, 1965],
+       [1090, 1993],
+       [1099, 1995],
+       [1146, 1997],
+       [1154, 2000],
+       [1161, 2008],
+       [1177, 1998],
+       [1180, 1993],
+       [1173, 1989],
+       [1174, 1987],
+       [1190, 1978],
+       [1184, 1976],
+       [1187, 1971],
+       [1188, 1965],
+       [1192, 1959],
+       [1195, 1960],
+       [1193, 1968],
+       [1201, 1959],
+       [1196, 1959],
+       [1201, 1952],
+       [1208, 1953],
+       [1205, 1956],
+       [1209, 1960],
+       [1211, 1960],
+       [1213, 1957],
+       [1211, 1955],
+       [1213, 1943],
+       [1216, 1942],
+       [1215, 1947],
+       [1228, 1938],
+       [1229, 1931],
+       [1235, 1930],
+       [1238, 1924],
+       [1241, 1924],
+       [1244, 1919],
+       [1239, 1912],
+       [1241, 1910],
+       [1242, 1906],
+       [1245, 1903],
+       [1242, 1898],
+       [1245, 1891],
+       [1241, 1887],
+       [1241, 1884],
+       [1237, 1879],
+       [1240, 1870],
+       [1236, 1868],
+       [1238, 1866],
+       [1242, 1865],
+       [1243, 1861],
+       [1248, 1855],
+       [1247, 1853],
+       [1256, 1849],
+       [1259, 1845],
+       [1255, 1839],
+       [1255, 1836],
+       [1257, 1835],
+       [1259, 1827],
+       [1249, 1820],
+       [1246, 1823],
+       [1241, 1813],
+       [1239, 1801],
+       [1252, 1804],
+       [1257, 1790],
+       [1264, 1795],
+       [1261, 1802],
+       [1269, 1806],
+       [1268, 1807],
+       [1272, 1811]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '015',
+     'FIPS': '34015',
+     'STATE': 'NJ',
+     'NAME': 'Gloucester',
+     'LSAD': 'County'},
+    'id': 2180,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[535, 1914],
+        [580, 1912],
+        [610, 1909],
+        [639, 1903],
+        [691, 1885],
+        [742, 1857],
+        [775, 1833],
+        [728, 1808],
+        [712, 1791],
+        [714, 1789],
+        [707, 1781],
+        [696, 1775],
+        [691, 1766],
+        [691, 1761],
+        [682, 1733],
+        [675, 1718],
+        [670, 1697],
+        [670, 1679],
+        [668, 1677],
+        [659, 1680],
+        [654, 1678],
+        [643, 1653],
+        [627, 1645],
+        [624, 1640],
+        [623, 1624],
+        [594, 1636],
+        [547, 1568],
+        [510, 1558],
+        [472, 1501],
+        [470, 1491],
+        [472, 1486],
+        [471, 1473],
+        [474, 1456],
+        [485, 1442],
+        [509, 1425],
+        [511, 1421],
+        [545, 1390],
+        [542, 1383],
+        [536, 1349],
+        [535, 1324],
+        [549, 1311],
+        [540, 1288],
+        [526, 1290],
+        [509, 1265],
+        [502, 1233],
+        [507, 1198],
+        [520, 1180],
+        [522, 1174],
+        [534, 1164],
+        [533, 1157],
+        [556, 1141],
+        [581, 1115],
+        [585, 1101],
+        [603, 1068],
+        [619, 1019],
+        [614, 1017],
+        [613, 1010],
+        [606, 1006],
+        [603, 1008],
+        [597, 1006],
+        [595, 1002],
+        [597, 998],
+        [595, 996],
+        [591, 998],
+        [587, 996],
+        [587, 992],
+        [585, 991],
+        [580, 993],
+        [579, 997],
+        [577, 998],
+        [573, 992],
+        [570, 991],
+        [567, 992],
+        [567, 995],
+        [565, 997],
+        [562, 997],
+        [558, 993],
+        [559, 989],
+        [562, 989],
+        [563, 981],
+        [558, 981],
+        [554, 988],
+        [549, 980],
+        [550, 977],
+        [553, 976],
+        [552, 969],
+        [555, 967],
+        [555, 962],
+        [551, 958],
+        [543, 956],
+        [537, 950],
+        [535, 945],
+        [537, 940],
+        [528, 921],
+        [519, 916],
+        [514, 912],
+        [510, 914],
+        [510, 916],
+        [504, 917],
+        [500, 911],
+        [496, 914],
+        [489, 911],
+        [486, 916],
+        [482, 911],
+        [474, 912],
+        [471, 911],
+        [468, 914],
+        [463, 914],
+        [458, 911],
+        [454, 903],
+        [451, 904],
+        [445, 898],
+        [430, 897],
+        [430, 894],
+        [422, 888],
+        [417, 880],
+        [403, 880],
+        [396, 878],
+        [391, 879],
+        [383, 878],
+        [375, 881],
+        [368, 890],
+        [324, 894],
+        [258, 889],
+        [219, 1532],
+        [217, 1571],
+        [217, 1692],
+        [239, 1693],
+        [250, 1722],
+        [269, 1760],
+        [293, 1794],
+        [321, 1825],
+        [344, 1845],
+        [366, 1861],
+        [400, 1880],
+        [431, 1894],
+        [466, 1904],
+        [501, 1911],
+        [535, 1914]]],
+      [[[551, 1518],
+        [550, 1507],
+        [554, 1484],
+        [553, 1479],
+        [556, 1472],
+        [547, 1471],
+        [539, 1487],
+        [533, 1506],
+        [534, 1512],
+        [551, 1518]]],
+      [[[521, 1459],
+        [541, 1443],
+        [543, 1430],
+        [526, 1439],
+        [523, 1445],
+        [521, 1459]]]]},
+    'properties': {'STATE_FIPS': '10',
+     'COUNTY_FIP': '003',
+     'FIPS': '10003',
+     'STATE': 'DE',
+     'NAME': 'New Castle',
+     'LSAD': 'County'},
+    'id': 2130,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[276, 601],
+       [314, 0],
+       [314, -1],
+       [319, -80],
+       [-15, -80],
+       [0, -66],
+       [7, -49],
+       [14, -44],
+       [38, -30],
+       [49, -29],
+       [55, -20],
+       [60, -19],
+       [59, -14],
+       [50, -11],
+       [45, -5],
+       [47, -2],
+       [51, 0],
+       [53, 4],
+       [36, 13],
+       [33, 23],
+       [26, 24],
+       [14, 30],
+       [14, 35],
+       [26, 42],
+       [27, 44],
+       [26, 45],
+       [16, 46],
+       [10, 53],
+       [22, 62],
+       [22, 65],
+       [19, 71],
+       [11, 72],
+       [4, 84],
+       [0, 83],
+       [-3, 82],
+       [-6, 85],
+       [-10, 98],
+       [-9, 101],
+       [-2, 101],
+       [0, 104],
+       [0, 107],
+       [-3, 110],
+       [-16, 104],
+       [-20, 108],
+       [-20, 115],
+       [-18, 116],
+       [-6, 115],
+       [-4, 117],
+       [-10, 126],
+       [-16, 129],
+       [-16, 130],
+       [-12, 133],
+       [-10, 140],
+       [-11, 145],
+       [-16, 149],
+       [-15, 153],
+       [-9, 156],
+       [-8, 158],
+       [-16, 167],
+       [-16, 172],
+       [-9, 172],
+       [-10, 176],
+       [-17, 179],
+       [-18, 190],
+       [-22, 200],
+       [-22, 201],
+       [-17, 202],
+       [-16, 204],
+       [-15, 210],
+       [-17, 213],
+       [-21, 214],
+       [-23, 217],
+       [-14, 220],
+       [-14, 222],
+       [-19, 222],
+       [-20, 231],
+       [-10, 234],
+       [-7, 238],
+       [-7, 250],
+       [-4, 254],
+       [-2, 253],
+       [-1, 257],
+       [-8, 270],
+       [0, 278],
+       [1, 283],
+       [0, 284],
+       [-3, 285],
+       [-5, 289],
+       [0, 292],
+       [4, 295],
+       [4, 299],
+       [7, 307],
+       [13, 311],
+       [11, 315],
+       [23, 322],
+       [26, 332],
+       [33, 335],
+       [35, 339],
+       [39, 340],
+       [42, 348],
+       [42, 352],
+       [49, 352],
+       [49, 354],
+       [47, 361],
+       [49, 364],
+       [57, 359],
+       [68, 366],
+       [68, 374],
+       [71, 377],
+       [73, 382],
+       [80, 384],
+       [78, 387],
+       [79, 389],
+       [79, 393],
+       [82, 396],
+       [84, 404],
+       [87, 405],
+       [89, 414],
+       [88, 417],
+       [86, 418],
+       [86, 421],
+       [89, 422],
+       [96, 432],
+       [99, 440],
+       [108, 443],
+       [112, 447],
+       [116, 452],
+       [129, 466],
+       [132, 473],
+       [130, 495],
+       [133, 500],
+       [137, 502],
+       [143, 520],
+       [149, 535],
+       [153, 536],
+       [167, 548],
+       [186, 558],
+       [197, 566],
+       [202, 573],
+       [209, 575],
+       [213, 581],
+       [236, 584],
+       [262, 592],
+       [276, 601]]]},
+    'properties': {'STATE_FIPS': '24',
+     'COUNTY_FIP': '011',
+     'FIPS': '24011',
+     'STATE': 'MD',
+     'NAME': 'Caroline',
+     'LSAD': 'County'},
+    'id': 2136,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[619, 1019],
+       [629, 1007],
+       [646, 998],
+       [649, 993],
+       [646, 983],
+       [651, 976],
+       [682, 953],
+       [695, 949],
+       [726, 921],
+       [729, 913],
+       [731, 889],
+       [742, 867],
+       [771, 829],
+       [778, 810],
+       [774, 789],
+       [774, 752],
+       [787, 738],
+       [793, 716],
+       [790, 685],
+       [783, 682],
+       [771, 660],
+       [767, 625],
+       [781, 498],
+       [780, 457],
+       [789, 443],
+       [788, 441],
+       [800, 428],
+       [812, 424],
+       [862, 379],
+       [869, 369],
+       [902, 310],
+       [907, 296],
+       [912, 271],
+       [910, 240],
+       [911, 231],
+       [908, 233],
+       [909, 239],
+       [904, 244],
+       [900, 245],
+       [897, 245],
+       [893, 238],
+       [887, 237],
+       [884, 239],
+       [881, 240],
+       [877, 233],
+       [872, 231],
+       [865, 234],
+       [867, 241],
+       [864, 248],
+       [863, 248],
+       [855, 234],
+       [852, 234],
+       [841, 253],
+       [832, 246],
+       [829, 253],
+       [830, 256],
+       [823, 260],
+       [817, 258],
+       [810, 260],
+       [808, 249],
+       [799, 247],
+       [796, 251],
+       [793, 250],
+       [792, 244],
+       [785, 238],
+       [781, 233],
+       [785, 221],
+       [783, 218],
+       [779, 215],
+       [783, 211],
+       [786, 213],
+       [781, 200],
+       [784, 195],
+       [783, 193],
+       [780, 192],
+       [778, 187],
+       [781, 180],
+       [779, 178],
+       [776, 177],
+       [775, 181],
+       [770, 182],
+       [770, 176],
+       [759, 179],
+       [757, 171],
+       [753, 174],
+       [751, 171],
+       [741, 169],
+       [732, 165],
+       [724, 169],
+       [716, 169],
+       [695, 162],
+       [688, 166],
+       [670, 156],
+       [659, 152],
+       [654, 143],
+       [655, 131],
+       [651, 125],
+       [645, 122],
+       [642, 113],
+       [640, 111],
+       [635, 109],
+       [632, 110],
+       [625, 105],
+       [607, 62],
+       [584, 51],
+       [585, 47],
+       [580, 39],
+       [577, 38],
+       [573, 39],
+       [566, 35],
+       [557, 24],
+       [313, 14],
+       [258, 889],
+       [324, 894],
+       [368, 890],
+       [375, 881],
+       [383, 878],
+       [391, 879],
+       [396, 878],
+       [403, 880],
+       [417, 880],
+       [422, 888],
+       [430, 894],
+       [430, 897],
+       [445, 898],
+       [451, 904],
+       [454, 903],
+       [458, 911],
+       [463, 914],
+       [468, 914],
+       [471, 911],
+       [474, 912],
+       [482, 911],
+       [486, 916],
+       [489, 911],
+       [496, 914],
+       [500, 911],
+       [504, 917],
+       [510, 916],
+       [510, 914],
+       [514, 912],
+       [519, 916],
+       [528, 921],
+       [537, 940],
+       [535, 945],
+       [537, 950],
+       [543, 956],
+       [551, 958],
+       [555, 962],
+       [555, 967],
+       [552, 969],
+       [553, 976],
+       [550, 977],
+       [549, 980],
+       [554, 988],
+       [558, 981],
+       [563, 981],
+       [562, 989],
+       [559, 989],
+       [558, 993],
+       [562, 997],
+       [565, 997],
+       [567, 995],
+       [567, 992],
+       [570, 991],
+       [573, 992],
+       [577, 998],
+       [579, 997],
+       [580, 993],
+       [585, 991],
+       [587, 992],
+       [587, 996],
+       [591, 998],
+       [595, 996],
+       [597, 998],
+       [595, 1002],
+       [597, 1006],
+       [603, 1008],
+       [606, 1006],
+       [613, 1010],
+       [614, 1017],
+       [619, 1019]]]},
+    'properties': {'STATE_FIPS': '10',
+     'COUNTY_FIP': '001',
+     'FIPS': '10001',
+     'STATE': 'DE',
+     'NAME': 'Kent',
+     'LSAD': 'County'},
+    'id': 2138,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1272, 1811],
+       [1268, 1807],
+       [1269, 1806],
+       [1261, 1802],
+       [1264, 1795],
+       [1257, 1790],
+       [1252, 1804],
+       [1239, 1801],
+       [1241, 1813],
+       [1246, 1823],
+       [1249, 1820],
+       [1259, 1827],
+       [1257, 1835],
+       [1255, 1836],
+       [1255, 1839],
+       [1259, 1845],
+       [1256, 1849],
+       [1247, 1853],
+       [1248, 1855],
+       [1243, 1861],
+       [1242, 1865],
+       [1238, 1866],
+       [1236, 1868],
+       [1240, 1870],
+       [1237, 1879],
+       [1241, 1884],
+       [1241, 1887],
+       [1245, 1891],
+       [1242, 1898],
+       [1245, 1903],
+       [1242, 1906],
+       [1241, 1910],
+       [1239, 1912],
+       [1244, 1919],
+       [1241, 1924],
+       [1238, 1924],
+       [1235, 1930],
+       [1229, 1931],
+       [1228, 1938],
+       [1215, 1947],
+       [1216, 1942],
+       [1213, 1943],
+       [1211, 1955],
+       [1213, 1957],
+       [1211, 1960],
+       [1209, 1960],
+       [1205, 1956],
+       [1208, 1953],
+       [1201, 1952],
+       [1196, 1959],
+       [1201, 1959],
+       [1193, 1968],
+       [1195, 1960],
+       [1192, 1959],
+       [1188, 1965],
+       [1187, 1971],
+       [1184, 1976],
+       [1190, 1978],
+       [1174, 1987],
+       [1173, 1989],
+       [1180, 1993],
+       [1177, 1998],
+       [1161, 2008],
+       [1175, 2030],
+       [1179, 2052],
+       [1169, 2081],
+       [1167, 2094],
+       [1168, 2119],
+       [1171, 2133],
+       [1180, 2146],
+       [1208, 2163],
+       [1236, 2172],
+       [1260, 2183],
+       [1278, 2204],
+       [1293, 2203],
+       [1296, 2208],
+       [1300, 2209],
+       [1303, 2207],
+       [1305, 2210],
+       [1314, 2212],
+       [1321, 2204],
+       [1324, 2204],
+       [1325, 2207],
+       [1328, 2202],
+       [1335, 2198],
+       [1336, 2201],
+       [1338, 2199],
+       [1340, 2191],
+       [1344, 2192],
+       [1341, 2189],
+       [1345, 2182],
+       [1351, 2181],
+       [1343, 2175],
+       [1343, 2172],
+       [1340, 2170],
+       [1342, 2167],
+       [1342, 2163],
+       [1337, 2161],
+       [1338, 2150],
+       [1340, 2149],
+       [1340, 2142],
+       [1346, 2137],
+       [1346, 2132],
+       [1342, 2125],
+       [1344, 2118],
+       [1345, 2116],
+       [1352, 2115],
+       [1359, 2108],
+       [1364, 2109],
+       [1368, 2106],
+       [1376, 2106],
+       [1381, 2107],
+       [1385, 2105],
+       [1392, 2106],
+       [1400, 2105],
+       [1402, 2102],
+       [1397, 2095],
+       [1393, 2094],
+       [1393, 2089],
+       [1388, 2089],
+       [1387, 2086],
+       [1389, 2081],
+       [1392, 2080],
+       [1402, 2070],
+       [1418, 2069],
+       [1421, 2065],
+       [1430, 2055],
+       [1435, 2041],
+       [1435, 2032],
+       [1439, 2027],
+       [1443, 2024],
+       [1447, 2016],
+       [1451, 2015],
+       [1464, 2006],
+       [1472, 1980],
+       [1506, 1823],
+       [1513, 1819],
+       [1517, 1810],
+       [1526, 1806],
+       [1545, 1805],
+       [1560, 1811],
+       [1579, 1815],
+       [1584, 1819],
+       [1587, 1819],
+       [1591, 1821],
+       [1603, 1822],
+       [1628, 1816],
+       [1632, 1813],
+       [1646, 1809],
+       [1659, 1794],
+       [1669, 1787],
+       [1676, 1776],
+       [1678, 1775],
+       [1681, 1771],
+       [1680, 1769],
+       [1684, 1761],
+       [1693, 1758],
+       [1696, 1747],
+       [1702, 1745],
+       [1706, 1738],
+       [1713, 1735],
+       [1716, 1731],
+       [1718, 1733],
+       [1749, 1707],
+       [1544, 1477],
+       [1537, 1482],
+       [1536, 1486],
+       [1523, 1495],
+       [1521, 1502],
+       [1522, 1508],
+       [1507, 1522],
+       [1501, 1539],
+       [1498, 1559],
+       [1496, 1561],
+       [1499, 1567],
+       [1497, 1569],
+       [1498, 1574],
+       [1496, 1582],
+       [1498, 1585],
+       [1486, 1600],
+       [1484, 1611],
+       [1480, 1611],
+       [1476, 1618],
+       [1472, 1621],
+       [1472, 1626],
+       [1467, 1629],
+       [1466, 1633],
+       [1463, 1634],
+       [1461, 1637],
+       [1447, 1647],
+       [1434, 1649],
+       [1425, 1656],
+       [1417, 1655],
+       [1413, 1656],
+       [1407, 1655],
+       [1397, 1657],
+       [1384, 1663],
+       [1381, 1667],
+       [1374, 1670],
+       [1373, 1681],
+       [1331, 1708],
+       [1334, 1714],
+       [1335, 1722],
+       [1332, 1727],
+       [1334, 1735],
+       [1333, 1738],
+       [1315, 1754],
+       [1313, 1759],
+       [1308, 1764],
+       [1302, 1767],
+       [1303, 1772],
+       [1300, 1777],
+       [1294, 1786],
+       [1292, 1795],
+       [1294, 1799],
+       [1287, 1804],
+       [1285, 1809],
+       [1283, 1808],
+       [1272, 1811]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '007',
+     'FIPS': '34007',
+     'STATE': 'NJ',
+     'NAME': 'Camden',
+     'LSAD': 'County'},
+    'id': 2179,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[763, 1054],
+        [751, 1058],
+        [736, 1068],
+        [721, 1088],
+        [688, 1157],
+        [672, 1156],
+        [661, 1161],
+        [629, 1184],
+        [625, 1195],
+        [584, 1198],
+        [575, 1217],
+        [573, 1234],
+        [575, 1266],
+        [596, 1269],
+        [598, 1273],
+        [594, 1275],
+        [593, 1283],
+        [593, 1293],
+        [598, 1323],
+        [598, 1332],
+        [597, 1339],
+        [591, 1342],
+        [588, 1349],
+        [590, 1354],
+        [609, 1377],
+        [616, 1391],
+        [620, 1400],
+        [619, 1420],
+        [615, 1425],
+        [609, 1430],
+        [600, 1431],
+        [583, 1448],
+        [571, 1455],
+        [559, 1465],
+        [553, 1479],
+        [554, 1484],
+        [550, 1507],
+        [551, 1518],
+        [555, 1527],
+        [568, 1538],
+        [576, 1548],
+        [586, 1551],
+        [616, 1591],
+        [620, 1602],
+        [624, 1623],
+        [624, 1640],
+        [627, 1645],
+        [643, 1653],
+        [654, 1678],
+        [659, 1680],
+        [668, 1677],
+        [670, 1679],
+        [670, 1697],
+        [675, 1718],
+        [682, 1733],
+        [691, 1761],
+        [691, 1766],
+        [696, 1775],
+        [707, 1781],
+        [714, 1789],
+        [712, 1791],
+        [723, 1803],
+        [734, 1808],
+        [748, 1809],
+        [757, 1813],
+        [764, 1812],
+        [769, 1817],
+        [772, 1816],
+        [774, 1810],
+        [771, 1804],
+        [775, 1803],
+        [777, 1807],
+        [779, 1807],
+        [782, 1799],
+        [781, 1794],
+        [783, 1789],
+        [785, 1788],
+        [788, 1791],
+        [790, 1790],
+        [785, 1781],
+        [782, 1779],
+        [779, 1783],
+        [776, 1782],
+        [774, 1771],
+        [778, 1766],
+        [784, 1766],
+        [783, 1762],
+        [785, 1759],
+        [787, 1762],
+        [788, 1767],
+        [798, 1765],
+        [794, 1760],
+        [797, 1759],
+        [797, 1756],
+        [794, 1754],
+        [791, 1756],
+        [789, 1753],
+        [794, 1749],
+        [793, 1747],
+        [796, 1745],
+        [796, 1749],
+        [800, 1749],
+        [800, 1746],
+        [802, 1747],
+        [801, 1742],
+        [803, 1739],
+        [812, 1742],
+        [817, 1735],
+        [815, 1732],
+        [817, 1729],
+        [815, 1727],
+        [819, 1727],
+        [816, 1725],
+        [821, 1717],
+        [817, 1704],
+        [817, 1700],
+        [822, 1696],
+        [823, 1697],
+        [828, 1692],
+        [831, 1692],
+        [832, 1689],
+        [831, 1684],
+        [836, 1681],
+        [839, 1682],
+        [840, 1675],
+        [856, 1671],
+        [859, 1664],
+        [868, 1659],
+        [870, 1660],
+        [876, 1658],
+        [878, 1651],
+        [883, 1648],
+        [884, 1644],
+        [891, 1643],
+        [889, 1639],
+        [890, 1631],
+        [895, 1631],
+        [898, 1634],
+        [907, 1634],
+        [909, 1632],
+        [907, 1629],
+        [912, 1627],
+        [914, 1630],
+        [918, 1631],
+        [938, 1621],
+        [948, 1612],
+        [961, 1615],
+        [963, 1613],
+        [972, 1617],
+        [984, 1616],
+        [991, 1611],
+        [996, 1610],
+        [999, 1606],
+        [1000, 1592],
+        [1004, 1584],
+        [1026, 1578],
+        [1039, 1581],
+        [1044, 1578],
+        [1075, 1588],
+        [1275, 1402],
+        [1269, 1387],
+        [1268, 1378],
+        [1264, 1373],
+        [1257, 1357],
+        [1262, 1348],
+        [1260, 1340],
+        [1260, 1334],
+        [1262, 1334],
+        [1258, 1324],
+        [1260, 1318],
+        [1256, 1309],
+        [1256, 1303],
+        [1253, 1299],
+        [1252, 1291],
+        [1253, 1289],
+        [1252, 1283],
+        [1253, 1282],
+        [1249, 1275],
+        [1251, 1267],
+        [1254, 1264],
+        [1257, 1257],
+        [1256, 1251],
+        [1259, 1245],
+        [1257, 1239],
+        [1254, 1237],
+        [1253, 1229],
+        [1251, 1229],
+        [1252, 1227],
+        [1250, 1224],
+        [1251, 1222],
+        [1248, 1219],
+        [1247, 1215],
+        [1249, 1212],
+        [1247, 1211],
+        [1246, 1206],
+        [1248, 1202],
+        [1243, 1192],
+        [1178, 1249],
+        [1016, 1384],
+        [1003, 1367],
+        [902, 1257],
+        [891, 1251],
+        [867, 1255],
+        [855, 1230],
+        [854, 1219],
+        [851, 1216],
+        [845, 1216],
+        [844, 1212],
+        [836, 1205],
+        [836, 1201],
+        [829, 1191],
+        [820, 1188],
+        [813, 1192],
+        [813, 1194],
+        [802, 1193],
+        [783, 1201],
+        [771, 1194],
+        [761, 1182],
+        [762, 1179],
+        [768, 1178],
+        [766, 1169],
+        [769, 1165],
+        [765, 1159],
+        [760, 1160],
+        [759, 1156],
+        [762, 1153],
+        [768, 1157],
+        [769, 1153],
+        [766, 1147],
+        [764, 1147],
+        [760, 1149],
+        [755, 1145],
+        [757, 1140],
+        [762, 1138],
+        [765, 1142],
+        [768, 1141],
+        [768, 1135],
+        [771, 1131],
+        [770, 1129],
+        [766, 1128],
+        [765, 1126],
+        [766, 1122],
+        [761, 1121],
+        [762, 1114],
+        [756, 1113],
+        [755, 1105],
+        [760, 1100],
+        [762, 1093],
+        [764, 1092],
+        [766, 1094],
+        [767, 1100],
+        [775, 1098],
+        [775, 1094],
+        [773, 1091],
+        [767, 1086],
+        [767, 1084],
+        [772, 1080],
+        [772, 1076],
+        [769, 1074],
+        [763, 1074],
+        [758, 1076],
+        [757, 1071],
+        [761, 1066],
+        [758, 1062],
+        [758, 1060],
+        [763, 1054]]],
+      [[[763, 1054],
+        [765, 1055],
+        [767, 1060],
+        [770, 1060],
+        [772, 1050],
+        [763, 1054]]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '033',
+     'FIPS': '34033',
+     'STATE': 'NJ',
+     'NAME': 'Salem',
+     'LSAD': 'County'},
+    'id': 2131,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1275, 1402],
+       [1575, 1130],
+       [1573, 1127],
+       [1574, 1123],
+       [1579, 1112],
+       [1580, 1106],
+       [1577, 1095],
+       [1572, 1086],
+       [1573, 1080],
+       [1572, 1075],
+       [1580, 1055],
+       [1581, 1041],
+       [1579, 1031],
+       [1569, 1012],
+       [1570, 1000],
+       [1564, 981],
+       [1564, 974],
+       [1562, 968],
+       [1563, 948],
+       [1568, 940],
+       [1563, 941],
+       [1557, 929],
+       [1549, 919],
+       [1537, 911],
+       [1515, 773],
+       [1490, 757],
+       [1479, 754],
+       [1476, 743],
+       [1474, 742],
+       [1476, 740],
+       [1474, 739],
+       [1473, 735],
+       [1475, 732],
+       [1474, 730],
+       [1476, 727],
+       [1473, 727],
+       [1473, 724],
+       [1477, 722],
+       [1476, 719],
+       [1479, 717],
+       [1474, 710],
+       [1473, 701],
+       [1475, 698],
+       [1483, 700],
+       [1484, 697],
+       [1478, 691],
+       [1478, 686],
+       [1480, 685],
+       [1481, 687],
+       [1491, 685],
+       [1488, 679],
+       [1490, 673],
+       [1493, 672],
+       [1492, 669],
+       [1493, 667],
+       [1489, 665],
+       [1420, 689],
+       [1400, 693],
+       [1368, 691],
+       [1327, 695],
+       [1323, 697],
+       [1325, 706],
+       [1331, 712],
+       [1331, 716],
+       [1327, 726],
+       [1313, 736],
+       [1305, 737],
+       [1296, 729],
+       [1289, 733],
+       [1274, 733],
+       [1240, 723],
+       [1218, 729],
+       [1209, 729],
+       [1198, 722],
+       [1180, 688],
+       [1166, 669],
+       [1163, 670],
+       [1124, 711],
+       [1125, 739],
+       [1117, 772],
+       [1107, 788],
+       [1099, 795],
+       [1086, 793],
+       [1079, 813],
+       [1066, 825],
+       [1056, 825],
+       [1013, 847],
+       [1010, 853],
+       [1012, 859],
+       [1009, 869],
+       [999, 895],
+       [970, 903],
+       [954, 894],
+       [950, 881],
+       [945, 876],
+       [920, 899],
+       [906, 915],
+       [889, 957],
+       [888, 969],
+       [879, 981],
+       [867, 987],
+       [848, 985],
+       [834, 973],
+       [797, 1005],
+       [791, 1015],
+       [790, 1030],
+       [784, 1045],
+       [772, 1050],
+       [770, 1060],
+       [767, 1060],
+       [765, 1055],
+       [763, 1054],
+       [758, 1060],
+       [758, 1062],
+       [761, 1066],
+       [757, 1071],
+       [757, 1075],
+       [758, 1076],
+       [763, 1074],
+       [769, 1074],
+       [772, 1076],
+       [772, 1080],
+       [767, 1084],
+       [767, 1086],
+       [773, 1091],
+       [775, 1094],
+       [775, 1098],
+       [767, 1100],
+       [766, 1094],
+       [764, 1092],
+       [762, 1093],
+       [760, 1100],
+       [755, 1103],
+       [754, 1109],
+       [756, 1113],
+       [762, 1114],
+       [761, 1121],
+       [766, 1122],
+       [765, 1126],
+       [766, 1128],
+       [770, 1129],
+       [771, 1131],
+       [768, 1135],
+       [768, 1141],
+       [765, 1142],
+       [762, 1138],
+       [757, 1140],
+       [755, 1145],
+       [760, 1149],
+       [764, 1147],
+       [766, 1147],
+       [769, 1153],
+       [768, 1157],
+       [762, 1153],
+       [759, 1156],
+       [760, 1160],
+       [765, 1159],
+       [769, 1165],
+       [766, 1169],
+       [768, 1178],
+       [762, 1179],
+       [761, 1182],
+       [771, 1194],
+       [783, 1201],
+       [802, 1193],
+       [813, 1194],
+       [813, 1192],
+       [820, 1188],
+       [829, 1191],
+       [836, 1201],
+       [836, 1205],
+       [844, 1212],
+       [845, 1216],
+       [851, 1216],
+       [854, 1219],
+       [855, 1230],
+       [867, 1255],
+       [891, 1251],
+       [902, 1257],
+       [1003, 1367],
+       [1016, 1384],
+       [1178, 1249],
+       [1243, 1192],
+       [1248, 1202],
+       [1246, 1206],
+       [1247, 1211],
+       [1249, 1212],
+       [1247, 1215],
+       [1248, 1219],
+       [1251, 1222],
+       [1250, 1224],
+       [1252, 1227],
+       [1251, 1229],
+       [1253, 1229],
+       [1254, 1237],
+       [1257, 1239],
+       [1259, 1245],
+       [1256, 1251],
+       [1257, 1257],
+       [1254, 1264],
+       [1251, 1267],
+       [1249, 1275],
+       [1253, 1282],
+       [1252, 1283],
+       [1253, 1289],
+       [1252, 1291],
+       [1253, 1299],
+       [1256, 1303],
+       [1256, 1309],
+       [1260, 1318],
+       [1258, 1324],
+       [1262, 1334],
+       [1260, 1334],
+       [1260, 1340],
+       [1262, 1348],
+       [1257, 1357],
+       [1264, 1373],
+       [1268, 1378],
+       [1269, 1387],
+       [1275, 1402]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '011',
+     'FIPS': '34011',
+     'STATE': 'NJ',
+     'NAME': 'Cumberland',
+     'LSAD': 'County'},
+    'id': 2133,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1563, 941],
+       [1568, 940],
+       [1568, 932],
+       [1576, 930],
+       [1582, 926],
+       [1602, 924],
+       [1611, 916],
+       [1620, 905],
+       [1627, 909],
+       [1629, 907],
+       [1643, 907],
+       [1646, 904],
+       [1651, 909],
+       [1656, 911],
+       [1659, 908],
+       [1664, 908],
+       [1666, 905],
+       [1671, 909],
+       [1676, 908],
+       [1679, 909],
+       [1689, 902],
+       [1687, 894],
+       [1688, 894],
+       [1696, 897],
+       [1699, 894],
+       [1706, 893],
+       [1709, 889],
+       [1720, 894],
+       [1725, 891],
+       [1726, 886],
+       [1735, 885],
+       [1744, 888],
+       [1748, 893],
+       [1758, 892],
+       [1764, 888],
+       [1773, 893],
+       [1775, 892],
+       [1773, 886],
+       [1778, 881],
+       [1782, 880],
+       [1785, 886],
+       [1788, 886],
+       [1789, 880],
+       [1791, 878],
+       [1794, 884],
+       [1798, 885],
+       [1802, 878],
+       [1805, 875],
+       [1810, 879],
+       [1816, 878],
+       [1820, 883],
+       [1824, 885],
+       [1828, 883],
+       [1831, 884],
+       [1835, 890],
+       [1837, 890],
+       [1840, 887],
+       [1840, 883],
+       [1838, 877],
+       [1840, 875],
+       [1843, 876],
+       [1845, 881],
+       [1845, 889],
+       [1849, 891],
+       [1864, 890],
+       [1862, 879],
+       [1863, 877],
+       [1870, 874],
+       [1875, 875],
+       [1879, 882],
+       [1885, 887],
+       [1889, 888],
+       [1900, 886],
+       [1913, 881],
+       [1918, 882],
+       [1960, 913],
+       [1967, 914],
+       [1994, 894],
+       [2011, 893],
+       [2023, 900],
+       [2031, 899],
+       [2033, 896],
+       [2019, 883],
+       [2016, 871],
+       [2005, 855],
+       [1976, 841],
+       [1951, 818],
+       [1927, 791],
+       [1895, 747],
+       [1880, 730],
+       [1873, 705],
+       [1844, 669],
+       [1781, 557],
+       [1780, 551],
+       [1782, 547],
+       [1796, 534],
+       [1794, 525],
+       [1746, 472],
+       [1688, 375],
+       [1676, 332],
+       [1667, 317],
+       [1645, 306],
+       [1628, 293],
+       [1583, 247],
+       [1563, 220],
+       [1562, 222],
+       [1554, 226],
+       [1537, 223],
+       [1501, 205],
+       [1481, 199],
+       [1462, 198],
+       [1419, 203],
+       [1413, 207],
+       [1406, 220],
+       [1430, 334],
+       [1439, 361],
+       [1455, 398],
+       [1506, 496],
+       [1514, 517],
+       [1522, 544],
+       [1531, 601],
+       [1530, 630],
+       [1503, 660],
+       [1489, 665],
+       [1493, 667],
+       [1492, 669],
+       [1493, 672],
+       [1490, 673],
+       [1488, 679],
+       [1491, 685],
+       [1481, 687],
+       [1480, 685],
+       [1478, 686],
+       [1478, 691],
+       [1484, 697],
+       [1482, 701],
+       [1475, 698],
+       [1473, 701],
+       [1474, 710],
+       [1479, 717],
+       [1476, 719],
+       [1477, 722],
+       [1473, 724],
+       [1473, 727],
+       [1476, 727],
+       [1474, 730],
+       [1475, 732],
+       [1473, 735],
+       [1474, 739],
+       [1476, 740],
+       [1474, 742],
+       [1476, 743],
+       [1479, 754],
+       [1490, 757],
+       [1515, 773],
+       [1537, 911],
+       [1549, 919],
+       [1557, 929],
+       [1563, 941]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '009',
+     'FIPS': '34009',
+     'STATE': 'NJ',
+     'NAME': 'Cape May',
+     'LSAD': 'County'},
+    'id': 2134,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2885, 4176],
+       [2960, 4130],
+       [2976, 4129],
+       [2972, 4096],
+       [2941, 3976],
+       [2925, 3922],
+       [2889, 3842],
+       [2875, 3801],
+       [2844, 3745],
+       [2831, 3752],
+       [2832, 3760],
+       [2803, 3780],
+       [2803, 3784],
+       [2806, 3789],
+       [2802, 3794],
+       [2797, 3795],
+       [2792, 3789],
+       [2792, 3785],
+       [2788, 3785],
+       [2787, 3781],
+       [2785, 3780],
+       [2786, 3778],
+       [2781, 3781],
+       [2780, 3774],
+       [2775, 3774],
+       [2769, 3765],
+       [2742, 3763],
+       [2733, 3760],
+       [2727, 3755],
+       [2722, 3747],
+       [2718, 3744],
+       [2710, 3742],
+       [2708, 3736],
+       [2692, 3711],
+       [2690, 3703],
+       [2693, 3687],
+       [2690, 3677],
+       [2686, 3679],
+       [2683, 3677],
+       [2677, 3687],
+       [2679, 3692],
+       [2675, 3703],
+       [2672, 3702],
+       [2669, 3705],
+       [2662, 3706],
+       [2657, 3703],
+       [2653, 3694],
+       [2650, 3692],
+       [2640, 3696],
+       [2636, 3695],
+       [2633, 3699],
+       [2632, 3707],
+       [2607, 3723],
+       [2619, 3744],
+       [2620, 3749],
+       [2618, 3760],
+       [2623, 3784],
+       [2638, 3790],
+       [2641, 3793],
+       [2643, 3799],
+       [2645, 3808],
+       [2641, 3826],
+       [2644, 3833],
+       [2648, 3849],
+       [2647, 3855],
+       [2649, 3864],
+       [2656, 3864],
+       [2659, 3857],
+       [2661, 3856],
+       [2665, 3860],
+       [2666, 3864],
+       [2665, 3871],
+       [2661, 3874],
+       [2656, 3885],
+       [2654, 3892],
+       [2646, 3904],
+       [2632, 3915],
+       [2634, 3930],
+       [2627, 3941],
+       [2630, 3956],
+       [2628, 3967],
+       [2633, 3981],
+       [2630, 3985],
+       [2619, 3987],
+       [2616, 3992],
+       [2615, 3999],
+       [2619, 4007],
+       [2612, 4020],
+       [2606, 4022],
+       [2616, 4070],
+       [2583, 4096],
+       [2574, 4104],
+       [2573, 4096],
+       [2573, 4090],
+       [2518, 4096],
+       [2494, 4099],
+       [2460, 4120],
+       [2437, 4158],
+       [2425, 4170],
+       [2427, 4176],
+       [2885, 4176]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '003',
+     'FIPS': '34003',
+     'STATE': 'NJ',
+     'NAME': 'Bergen',
+     'LSAD': 'County'},
+    'id': 2229,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2234, 4176],
+       [2235, 4173],
+       [2240, 4168],
+       [2251, 4165],
+       [2255, 4159],
+       [2259, 4157],
+       [2265, 4162],
+       [2274, 4161],
+       [2281, 4157],
+       [2292, 4157],
+       [2293, 4160],
+       [2298, 4162],
+       [2306, 4160],
+       [2310, 4156],
+       [2310, 4144],
+       [2318, 4144],
+       [2324, 4148],
+       [2325, 4146],
+       [2329, 4148],
+       [2334, 4147],
+       [2334, 4142],
+       [2341, 4140],
+       [2344, 4137],
+       [2363, 4139],
+       [2370, 4132],
+       [2382, 4133],
+       [2384, 4140],
+       [2387, 4140],
+       [2388, 4136],
+       [2388, 4128],
+       [2391, 4125],
+       [2391, 4117],
+       [2396, 4111],
+       [2389, 4103],
+       [2389, 4096],
+       [2392, 4094],
+       [2399, 4096],
+       [2407, 4094],
+       [2412, 4096],
+       [2412, 4090],
+       [2418, 4085],
+       [2417, 4079],
+       [2413, 4081],
+       [2412, 4075],
+       [2413, 4071],
+       [2415, 4069],
+       [2414, 4053],
+       [2418, 4047],
+       [2415, 4025],
+       [2407, 4002],
+       [2401, 3997],
+       [2402, 3995],
+       [2402, 3989],
+       [2407, 3986],
+       [2405, 3984],
+       [2408, 3980],
+       [2408, 3975],
+       [2416, 3978],
+       [2416, 3973],
+       [2426, 3972],
+       [2433, 3959],
+       [2432, 3957],
+       [2430, 3957],
+       [2426, 3962],
+       [2426, 3956],
+       [2424, 3953],
+       [2427, 3948],
+       [2424, 3942],
+       [2425, 3938],
+       [2427, 3936],
+       [2413, 3937],
+       [2411, 3934],
+       [2407, 3933],
+       [2408, 3938],
+       [2404, 3940],
+       [2411, 3942],
+       [2411, 3944],
+       [2406, 3945],
+       [2400, 3941],
+       [2397, 3942],
+       [2396, 3944],
+       [2397, 3945],
+       [2396, 3948],
+       [2397, 3953],
+       [2390, 3954],
+       [2380, 3950],
+       [2381, 3956],
+       [2376, 3952],
+       [2370, 3951],
+       [2367, 3952],
+       [2364, 3949],
+       [2358, 3948],
+       [2358, 3957],
+       [2355, 3957],
+       [2353, 3955],
+       [2351, 3956],
+       [2352, 3959],
+       [2347, 3958],
+       [2345, 3956],
+       [2348, 3956],
+       [2348, 3953],
+       [2344, 3953],
+       [2342, 3959],
+       [2340, 3955],
+       [2335, 3952],
+       [2330, 3939],
+       [2335, 3937],
+       [2335, 3935],
+       [2331, 3935],
+       [2328, 3931],
+       [2333, 3929],
+       [2328, 3927],
+       [2327, 3923],
+       [2329, 3918],
+       [2326, 3902],
+       [2330, 3902],
+       [2330, 3900],
+       [2334, 3898],
+       [2330, 3894],
+       [2335, 3891],
+       [2330, 3888],
+       [2332, 3885],
+       [2329, 3884],
+       [2331, 3878],
+       [2337, 3883],
+       [2339, 3878],
+       [2347, 3877],
+       [2353, 3873],
+       [2356, 3876],
+       [2359, 3874],
+       [2358, 3871],
+       [2354, 3869],
+       [2357, 3861],
+       [2349, 3861],
+       [2347, 3858],
+       [2348, 3854],
+       [2346, 3851],
+       [2345, 3847],
+       [2341, 3844],
+       [2343, 3835],
+       [2347, 3834],
+       [2345, 3830],
+       [2342, 3829],
+       [2341, 3816],
+       [2343, 3811],
+       [2334, 3803],
+       [2338, 3792],
+       [2335, 3785],
+       [2327, 3774],
+       [2320, 3776],
+       [2313, 3774],
+       [2311, 3763],
+       [2303, 3757],
+       [2298, 3749],
+       [2291, 3748],
+       [2291, 3742],
+       [2288, 3739],
+       [2287, 3711],
+       [2279, 3701],
+       [2282, 3700],
+       [2284, 3694],
+       [2280, 3687],
+       [2283, 3686],
+       [2282, 3680],
+       [2278, 3678],
+       [2274, 3678],
+       [2272, 3675],
+       [2275, 3674],
+       [2277, 3669],
+       [2287, 3675],
+       [2286, 3669],
+       [2291, 3668],
+       [2295, 3665],
+       [2301, 3665],
+       [2301, 3662],
+       [2298, 3655],
+       [2287, 3652],
+       [2286, 3650],
+       [2291, 3646],
+       [2288, 3642],
+       [2279, 3637],
+       [2282, 3626],
+       [2280, 3622],
+       [2276, 3622],
+       [2272, 3623],
+       [2268, 3621],
+       [2272, 3615],
+       [2262, 3604],
+       [2258, 3607],
+       [2253, 3606],
+       [2253, 3592],
+       [2246, 3590],
+       [2236, 3592],
+       [2228, 3583],
+       [2227, 3577],
+       [2222, 3577],
+       [2217, 3568],
+       [2200, 3560],
+       [2197, 3555],
+       [2194, 3545],
+       [2189, 3545],
+       [2184, 3542],
+       [2181, 3537],
+       [2169, 3529],
+       [2164, 3529],
+       [2162, 3524],
+       [2164, 3518],
+       [2162, 3514],
+       [2163, 3512],
+       [2160, 3507],
+       [2154, 3508],
+       [2150, 3506],
+       [2149, 3503],
+       [2137, 3496],
+       [2133, 3498],
+       [2128, 3493],
+       [2116, 3491],
+       [2117, 3487],
+       [2114, 3485],
+       [2112, 3488],
+       [2106, 3487],
+       [2106, 3484],
+       [2102, 3482],
+       [2100, 3484],
+       [2094, 3483],
+       [2095, 3479],
+       [2091, 3478],
+       [2088, 3480],
+       [2085, 3477],
+       [2086, 3475],
+       [2082, 3466],
+       [2075, 3460],
+       [2071, 3463],
+       [2070, 3462],
+       [2061, 3461],
+       [2060, 3464],
+       [2055, 3465],
+       [2059, 3469],
+       [2056, 3469],
+       [2054, 3479],
+       [2056, 3482],
+       [2051, 3486],
+       [2050, 3490],
+       [2044, 3491],
+       [2043, 3494],
+       [2050, 3495],
+       [2051, 3498],
+       [2056, 3501],
+       [2052, 3521],
+       [2053, 3527],
+       [2055, 3529],
+       [2058, 3537],
+       [2062, 3535],
+       [2069, 3537],
+       [2069, 3539],
+       [2066, 3541],
+       [2067, 3545],
+       [2070, 3544],
+       [2073, 3547],
+       [2073, 3559],
+       [2071, 3561],
+       [2069, 3561],
+       [2068, 3568],
+       [2061, 3574],
+       [2056, 3575],
+       [2054, 3578],
+       [2057, 3581],
+       [2058, 3587],
+       [2052, 3591],
+       [2051, 3594],
+       [2048, 3595],
+       [2048, 3598],
+       [2052, 3611],
+       [2046, 3617],
+       [2043, 3616],
+       [2035, 3622],
+       [2028, 3621],
+       [2026, 3623],
+       [2022, 3622],
+       [2023, 3646],
+       [2017, 3652],
+       [2019, 3655],
+       [2018, 3663],
+       [2012, 3669],
+       [1848, 3621],
+       [1765, 3594],
+       [1755, 3595],
+       [1740, 3603],
+       [1740, 3607],
+       [1725, 3617],
+       [1704, 3625],
+       [1666, 3634],
+       [1659, 3638],
+       [1644, 3636],
+       [1638, 3636],
+       [1638, 3638],
+       [1633, 3639],
+       [1622, 3639],
+       [1617, 3642],
+       [1594, 3665],
+       [1592, 3670],
+       [1526, 3726],
+       [1532, 3732],
+       [1535, 3733],
+       [1539, 3731],
+       [1546, 3737],
+       [1558, 3742],
+       [1562, 3755],
+       [1567, 3756],
+       [1569, 3752],
+       [1576, 3756],
+       [1583, 3757],
+       [1588, 3765],
+       [1589, 3771],
+       [1592, 3771],
+       [1598, 3780],
+       [1606, 3786],
+       [1606, 3792],
+       [1613, 3799],
+       [1611, 3804],
+       [1617, 3812],
+       [1630, 3821],
+       [1627, 3829],
+       [1622, 3833],
+       [1625, 3843],
+       [1627, 3845],
+       [1637, 3849],
+       [1642, 3855],
+       [1643, 3865],
+       [1652, 3869],
+       [1654, 3874],
+       [1646, 3880],
+       [1645, 3883],
+       [1648, 3894],
+       [1647, 3908],
+       [1651, 3914],
+       [1668, 3923],
+       [1671, 3928],
+       [1671, 3935],
+       [1681, 3943],
+       [1687, 3954],
+       [1691, 3952],
+       [1706, 3966],
+       [1708, 3965],
+       [1711, 3968],
+       [1713, 3965],
+       [1715, 3968],
+       [1722, 3968],
+       [1727, 3972],
+       [1727, 3976],
+       [1734, 3980],
+       [1749, 3979],
+       [1756, 3982],
+       [1761, 3974],
+       [1769, 3970],
+       [1783, 3958],
+       [1785, 3951],
+       [1782, 3942],
+       [1786, 3940],
+       [1792, 3945],
+       [1796, 3946],
+       [1808, 3954],
+       [1814, 3951],
+       [1818, 3952],
+       [1820, 3959],
+       [1827, 3961],
+       [1832, 3960],
+       [1846, 3969],
+       [1855, 3977],
+       [1871, 3984],
+       [1872, 3987],
+       [1870, 3992],
+       [1871, 3998],
+       [1873, 4001],
+       [1889, 4014],
+       [1897, 4029],
+       [1897, 4040],
+       [1888, 4056],
+       [1889, 4068],
+       [1910, 4096],
+       [1938, 4131],
+       [1978, 4176],
+       [2190, 4176],
+       [2189, 4174],
+       [2196, 4170],
+       [2202, 4172],
+       [2203, 4176],
+       [2234, 4176]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '027',
+     'FIPS': '34027',
+     'STATE': 'NJ',
+     'NAME': 'Morris',
+     'LSAD': 'County'},
+    'id': 2228,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2352, 3959],
+       [2351, 3956],
+       [2353, 3955],
+       [2355, 3957],
+       [2358, 3957],
+       [2358, 3948],
+       [2364, 3949],
+       [2367, 3952],
+       [2370, 3951],
+       [2376, 3952],
+       [2381, 3956],
+       [2380, 3950],
+       [2390, 3954],
+       [2397, 3953],
+       [2396, 3948],
+       [2397, 3945],
+       [2396, 3944],
+       [2397, 3942],
+       [2400, 3941],
+       [2406, 3945],
+       [2411, 3944],
+       [2411, 3942],
+       [2404, 3940],
+       [2408, 3938],
+       [2407, 3933],
+       [2411, 3934],
+       [2413, 3937],
+       [2427, 3936],
+       [2433, 3931],
+       [2437, 3917],
+       [2443, 3911],
+       [2451, 3909],
+       [2453, 3906],
+       [2472, 3904],
+       [2527, 3864],
+       [2529, 3868],
+       [2536, 3865],
+       [2534, 3860],
+       [2632, 3788],
+       [2623, 3784],
+       [2618, 3760],
+       [2620, 3749],
+       [2619, 3744],
+       [2607, 3723],
+       [2606, 3710],
+       [2596, 3695],
+       [2592, 3684],
+       [2584, 3671],
+       [2580, 3648],
+       [2586, 3626],
+       [2589, 3623],
+       [2596, 3622],
+       [2606, 3623],
+       [2610, 3626],
+       [2614, 3633],
+       [2621, 3637],
+       [2643, 3638],
+       [2650, 3633],
+       [2651, 3629],
+       [2645, 3598],
+       [2647, 3588],
+       [2657, 3563],
+       [2623, 3508],
+       [2620, 3507],
+       [2588, 3532],
+       [2587, 3536],
+       [2585, 3537],
+       [2577, 3538],
+       [2575, 3535],
+       [2528, 3532],
+       [2516, 3540],
+       [2511, 3558],
+       [2498, 3571],
+       [2448, 3583],
+       [2406, 3600],
+       [2398, 3598],
+       [2393, 3595],
+       [2392, 3591],
+       [2386, 3584],
+       [2382, 3583],
+       [2368, 3587],
+       [2361, 3594],
+       [2354, 3594],
+       [2348, 3590],
+       [2323, 3606],
+       [2304, 3624],
+       [2280, 3633],
+       [2279, 3637],
+       [2288, 3642],
+       [2291, 3646],
+       [2286, 3650],
+       [2287, 3652],
+       [2298, 3655],
+       [2301, 3662],
+       [2301, 3665],
+       [2295, 3665],
+       [2291, 3668],
+       [2286, 3669],
+       [2287, 3675],
+       [2277, 3669],
+       [2275, 3674],
+       [2272, 3675],
+       [2274, 3678],
+       [2278, 3678],
+       [2282, 3680],
+       [2283, 3686],
+       [2280, 3687],
+       [2284, 3694],
+       [2282, 3700],
+       [2279, 3701],
+       [2287, 3711],
+       [2288, 3739],
+       [2291, 3742],
+       [2291, 3748],
+       [2298, 3749],
+       [2303, 3757],
+       [2311, 3763],
+       [2313, 3774],
+       [2320, 3776],
+       [2327, 3774],
+       [2335, 3785],
+       [2338, 3792],
+       [2334, 3803],
+       [2343, 3811],
+       [2341, 3816],
+       [2342, 3829],
+       [2345, 3830],
+       [2347, 3834],
+       [2343, 3835],
+       [2341, 3844],
+       [2345, 3847],
+       [2346, 3851],
+       [2348, 3854],
+       [2347, 3858],
+       [2349, 3861],
+       [2357, 3861],
+       [2354, 3869],
+       [2358, 3871],
+       [2359, 3874],
+       [2356, 3876],
+       [2353, 3873],
+       [2347, 3877],
+       [2339, 3878],
+       [2337, 3883],
+       [2331, 3878],
+       [2329, 3884],
+       [2332, 3885],
+       [2330, 3888],
+       [2335, 3891],
+       [2330, 3894],
+       [2334, 3898],
+       [2330, 3900],
+       [2330, 3902],
+       [2326, 3902],
+       [2329, 3918],
+       [2327, 3923],
+       [2328, 3927],
+       [2333, 3929],
+       [2328, 3931],
+       [2331, 3935],
+       [2335, 3935],
+       [2335, 3937],
+       [2330, 3939],
+       [2331, 3942],
+       [2335, 3952],
+       [2340, 3955],
+       [2342, 3959],
+       [2344, 3953],
+       [2348, 3953],
+       [2348, 3956],
+       [2345, 3956],
+       [2347, 3958],
+       [2352, 3959]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '013',
+     'FIPS': '34013',
+     'STATE': 'NJ',
+     'NAME': 'Essex',
+     'LSAD': 'County'},
+    'id': 2206,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2380, 3382],
+       [2380, 3379],
+       [2378, 3378],
+       [2380, 3376],
+       [2377, 3366],
+       [2385, 3361],
+       [2397, 3350],
+       [2443, 3360],
+       [2446, 3370],
+       [2467, 3365],
+       [2478, 3370],
+       [2484, 3363],
+       [2498, 3366],
+       [2504, 3368],
+       [2508, 3373],
+       [2512, 3369],
+       [2513, 3362],
+       [2521, 3355],
+       [2517, 3320],
+       [2509, 3290],
+       [2504, 3283],
+       [2484, 3287],
+       [2460, 3269],
+       [2456, 3255],
+       [2463, 3214],
+       [2431, 3172],
+       [2425, 3151],
+       [2432, 3120],
+       [2440, 3106],
+       [2477, 3093],
+       [2494, 3084],
+       [2494, 3083],
+       [2497, 3080],
+       [2490, 3067],
+       [2483, 3068],
+       [2481, 3065],
+       [2479, 3067],
+       [2461, 3042],
+       [2461, 3006],
+       [2458, 3003],
+       [2460, 2996],
+       [2455, 2990],
+       [2271, 2799],
+       [2248, 2769],
+       [2249, 2752],
+       [2150, 2698],
+       [2146, 2700],
+       [2116, 2702],
+       [2119, 2741],
+       [2095, 2754],
+       [2091, 2751],
+       [2088, 2754],
+       [2086, 2754],
+       [2077, 2759],
+       [2072, 2766],
+       [2061, 2765],
+       [2061, 2772],
+       [2052, 2780],
+       [2045, 2776],
+       [2040, 2771],
+       [2036, 2769],
+       [2032, 2775],
+       [2028, 2777],
+       [2027, 2775],
+       [2021, 2773],
+       [2016, 2773],
+       [2010, 2776],
+       [2007, 2783],
+       [1999, 2785],
+       [1995, 2791],
+       [1991, 2790],
+       [1983, 2797],
+       [1976, 2799],
+       [1972, 2803],
+       [1969, 2816],
+       [1957, 2820],
+       [1953, 2819],
+       [1947, 2821],
+       [1943, 2832],
+       [1936, 2833],
+       [1925, 2839],
+       [1916, 2838],
+       [1915, 2840],
+       [1915, 2845],
+       [1912, 2847],
+       [1914, 2857],
+       [1904, 2869],
+       [1904, 2878],
+       [1912, 2916],
+       [1916, 2919],
+       [1919, 2933],
+       [1928, 2936],
+       [1944, 2945],
+       [1955, 2956],
+       [1960, 2967],
+       [1966, 2971],
+       [1966, 2981],
+       [1969, 2989],
+       [1969, 3016],
+       [1983, 3025],
+       [2013, 3040],
+       [2041, 3056],
+       [2055, 3068],
+       [2064, 3080],
+       [2075, 3091],
+       [2082, 3099],
+       [2102, 3115],
+       [2119, 3139],
+       [2125, 3143],
+       [2140, 3148],
+       [2152, 3156],
+       [2153, 3166],
+       [2151, 3171],
+       [2143, 3178],
+       [2141, 3190],
+       [2122, 3195],
+       [2119, 3197],
+       [2100, 3230],
+       [2083, 3244],
+       [2072, 3255],
+       [2068, 3273],
+       [2065, 3280],
+       [2059, 3286],
+       [2054, 3288],
+       [2057, 3292],
+       [2056, 3305],
+       [2059, 3307],
+       [2063, 3315],
+       [2071, 3326],
+       [2070, 3329],
+       [2076, 3331],
+       [2086, 3339],
+       [2091, 3334],
+       [2091, 3337],
+       [2094, 3340],
+       [2097, 3338],
+       [2104, 3341],
+       [2108, 3340],
+       [2118, 3345],
+       [2126, 3354],
+       [2137, 3362],
+       [2143, 3362],
+       [2147, 3364],
+       [2154, 3355],
+       [2156, 3357],
+       [2203, 3362],
+       [2279, 3370],
+       [2380, 3382]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '023',
+     'FIPS': '34023',
+     'STATE': 'NJ',
+     'NAME': 'Middlesex',
+     'LSAD': 'County'},
+    'id': 2194,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2280, 3633],
+       [2304, 3624],
+       [2323, 3606],
+       [2348, 3590],
+       [2354, 3594],
+       [2361, 3594],
+       [2368, 3587],
+       [2382, 3583],
+       [2386, 3584],
+       [2392, 3591],
+       [2393, 3595],
+       [2398, 3598],
+       [2406, 3600],
+       [2448, 3583],
+       [2498, 3571],
+       [2511, 3558],
+       [2516, 3540],
+       [2528, 3532],
+       [2575, 3535],
+       [2577, 3538],
+       [2585, 3537],
+       [2587, 3536],
+       [2588, 3532],
+       [2620, 3507],
+       [2623, 3508],
+       [2587, 3450],
+       [2558, 3454],
+       [2551, 3454],
+       [2527, 3425],
+       [2521, 3355],
+       [2513, 3362],
+       [2512, 3369],
+       [2508, 3373],
+       [2504, 3368],
+       [2498, 3366],
+       [2484, 3363],
+       [2478, 3370],
+       [2467, 3365],
+       [2446, 3370],
+       [2443, 3360],
+       [2397, 3350],
+       [2385, 3361],
+       [2377, 3366],
+       [2380, 3376],
+       [2378, 3378],
+       [2380, 3379],
+       [2380, 3382],
+       [2279, 3370],
+       [2203, 3362],
+       [2156, 3357],
+       [2154, 3355],
+       [2147, 3364],
+       [2152, 3365],
+       [2159, 3373],
+       [2164, 3373],
+       [2169, 3381],
+       [2173, 3383],
+       [2184, 3385],
+       [2193, 3396],
+       [2199, 3397],
+       [2203, 3402],
+       [2206, 3414],
+       [2213, 3418],
+       [2217, 3429],
+       [2219, 3444],
+       [2220, 3446],
+       [2226, 3447],
+       [2229, 3455],
+       [2229, 3462],
+       [2235, 3473],
+       [2235, 3481],
+       [2236, 3487],
+       [2234, 3493],
+       [2231, 3495],
+       [2224, 3491],
+       [2220, 3485],
+       [2214, 3483],
+       [2211, 3478],
+       [2208, 3477],
+       [2202, 3485],
+       [2198, 3487],
+       [2196, 3491],
+       [2185, 3486],
+       [2175, 3475],
+       [2164, 3469],
+       [2150, 3506],
+       [2154, 3508],
+       [2160, 3507],
+       [2163, 3512],
+       [2162, 3514],
+       [2164, 3518],
+       [2162, 3524],
+       [2164, 3529],
+       [2169, 3529],
+       [2181, 3537],
+       [2184, 3542],
+       [2189, 3545],
+       [2194, 3545],
+       [2197, 3555],
+       [2200, 3560],
+       [2217, 3568],
+       [2222, 3577],
+       [2227, 3577],
+       [2228, 3583],
+       [2236, 3592],
+       [2246, 3590],
+       [2253, 3592],
+       [2253, 3606],
+       [2258, 3607],
+       [2262, 3604],
+       [2272, 3615],
+       [2268, 3621],
+       [2272, 3623],
+       [2276, 3622],
+       [2280, 3622],
+       [2282, 3626],
+       [2280, 3633]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '039',
+     'FIPS': '34039',
+     'STATE': 'NJ',
+     'NAME': 'Union',
+     'LSAD': 'County'},
+    'id': 2204,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[2941, 3976],
+        [3026, 3943],
+        [3031, 3954],
+        [3034, 3955],
+        [3033, 3958],
+        [3036, 3961],
+        [3039, 3961],
+        [3036, 3956],
+        [3042, 3955],
+        [3048, 3952],
+        [3048, 3950],
+        [3053, 3950],
+        [3057, 3931],
+        [3078, 3922],
+        [3079, 3925],
+        [3137, 3905],
+        [3135, 3901],
+        [3134, 3882],
+        [3129, 3862],
+        [3130, 3854],
+        [3135, 3849],
+        [3139, 3841],
+        [3140, 3824],
+        [3136, 3820],
+        [3130, 3830],
+        [3126, 3839],
+        [3128, 3848],
+        [3124, 3857],
+        [3122, 3856],
+        [3117, 3850],
+        [3114, 3842],
+        [3103, 3845],
+        [3094, 3839],
+        [3090, 3817],
+        [3091, 3809],
+        [3096, 3798],
+        [3106, 3785],
+        [3117, 3779],
+        [3133, 3751],
+        [3131, 3749],
+        [3122, 3749],
+        [3097, 3759],
+        [3088, 3760],
+        [3074, 3755],
+        [3038, 3749],
+        [3022, 3744],
+        [3011, 3732],
+        [3010, 3724],
+        [2998, 3722],
+        [2982, 3725],
+        [2981, 3730],
+        [2949, 3742],
+        [2940, 3748],
+        [2935, 3754],
+        [2928, 3754],
+        [2921, 3765],
+        [2920, 3772],
+        [2919, 3818],
+        [2926, 3837],
+        [2938, 3859],
+        [2952, 3877],
+        [2957, 3891],
+        [2957, 3896],
+        [2953, 3901],
+        [2946, 3897],
+        [2945, 3895],
+        [2938, 3897],
+        [2936, 3900],
+        [2919, 3907],
+        [2925, 3922],
+        [2941, 3976]]],
+      [[[3156, 3866],
+        [3162, 3860],
+        [3164, 3854],
+        [3162, 3836],
+        [3157, 3835],
+        [3152, 3842],
+        [3152, 3864],
+        [3156, 3866]]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '005',
+     'FIPS': '36005',
+     'STATE': 'NY',
+     'NAME': 'Bronx',
+     'LSAD': 'County'},
+    'id': 2199,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2797, 3795],
+       [2802, 3794],
+       [2806, 3789],
+       [2803, 3784],
+       [2803, 3780],
+       [2832, 3760],
+       [2831, 3752],
+       [2844, 3745],
+       [2802, 3666],
+       [2786, 3575],
+       [2766, 3578],
+       [2747, 3549],
+       [2722, 3481],
+       [2694, 3468],
+       [2685, 3461],
+       [2613, 3446],
+       [2587, 3450],
+       [2657, 3563],
+       [2647, 3588],
+       [2645, 3598],
+       [2651, 3629],
+       [2650, 3633],
+       [2643, 3638],
+       [2621, 3637],
+       [2614, 3633],
+       [2610, 3626],
+       [2606, 3623],
+       [2596, 3622],
+       [2589, 3623],
+       [2583, 3633],
+       [2580, 3648],
+       [2582, 3665],
+       [2586, 3675],
+       [2592, 3684],
+       [2596, 3695],
+       [2606, 3710],
+       [2607, 3723],
+       [2632, 3707],
+       [2633, 3699],
+       [2636, 3695],
+       [2640, 3696],
+       [2650, 3692],
+       [2653, 3694],
+       [2657, 3703],
+       [2662, 3706],
+       [2669, 3705],
+       [2672, 3702],
+       [2675, 3703],
+       [2679, 3692],
+       [2677, 3687],
+       [2683, 3677],
+       [2686, 3679],
+       [2690, 3677],
+       [2693, 3687],
+       [2690, 3703],
+       [2692, 3711],
+       [2708, 3736],
+       [2710, 3742],
+       [2718, 3744],
+       [2722, 3747],
+       [2727, 3755],
+       [2733, 3760],
+       [2742, 3763],
+       [2769, 3765],
+       [2775, 3774],
+       [2780, 3774],
+       [2781, 3781],
+       [2786, 3778],
+       [2785, 3780],
+       [2787, 3781],
+       [2788, 3785],
+       [2792, 3785],
+       [2792, 3789],
+       [2797, 3795]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '017',
+     'FIPS': '34017',
+     'STATE': 'NJ',
+     'NAME': 'Hudson',
+     'LSAD': 'County'},
+    'id': 2205,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2711, 3458],
+       [2720, 3444],
+       [2723, 3411],
+       [2734, 3388],
+       [2744, 3372],
+       [2735, 3353],
+       [2722, 3335],
+       [2689, 3301],
+       [2659, 3263],
+       [2658, 3265],
+       [2644, 3255],
+       [2622, 3231],
+       [2617, 3238],
+       [2611, 3241],
+       [2605, 3240],
+       [2587, 3225],
+       [2562, 3211],
+       [2556, 3213],
+       [2531, 3196],
+       [2515, 3192],
+       [2502, 3179],
+       [2482, 3176],
+       [2462, 3166],
+       [2457, 3167],
+       [2451, 3178],
+       [2449, 3189],
+       [2454, 3200],
+       [2468, 3214],
+       [2470, 3233],
+       [2461, 3257],
+       [2488, 3279],
+       [2506, 3279],
+       [2515, 3290],
+       [2525, 3345],
+       [2535, 3360],
+       [2537, 3369],
+       [2536, 3396],
+       [2529, 3398],
+       [2528, 3403],
+       [2530, 3426],
+       [2546, 3446],
+       [2559, 3453],
+       [2568, 3452],
+       [2574, 3446],
+       [2599, 3440],
+       [2647, 3446],
+       [2696, 3458],
+       [2711, 3458]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '085',
+     'FIPS': '36085',
+     'STATE': 'NY',
+     'NAME': 'Richmond',
+     'LSAD': 'County'},
+    'id': 2210,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2891, 3633],
+       [2906, 3626],
+       [2913, 3615],
+       [2925, 3611],
+       [2933, 3596],
+       [2934, 3590],
+       [2932, 3587],
+       [2937, 3577],
+       [2936, 3574],
+       [2950, 3564],
+       [2949, 3562],
+       [2952, 3559],
+       [2950, 3557],
+       [2961, 3549],
+       [2959, 3546],
+       [2966, 3541],
+       [2966, 3533],
+       [2972, 3523],
+       [2976, 3529],
+       [2978, 3525],
+       [2982, 3528],
+       [2983, 3527],
+       [3005, 3546],
+       [3013, 3548],
+       [3017, 3522],
+       [3020, 3523],
+       [3025, 3502],
+       [3029, 3503],
+       [3032, 3488],
+       [3028, 3487],
+       [3029, 3480],
+       [3021, 3477],
+       [3031, 3460],
+       [3033, 3447],
+       [3043, 3449],
+       [3064, 3420],
+       [3063, 3379],
+       [3040, 3344],
+       [2998, 3317],
+       [2911, 3300],
+       [2902, 3305],
+       [2894, 3314],
+       [2834, 3308],
+       [2819, 3309],
+       [2804, 3316],
+       [2803, 3323],
+       [2819, 3347],
+       [2817, 3357],
+       [2806, 3367],
+       [2774, 3374],
+       [2764, 3390],
+       [2760, 3413],
+       [2766, 3436],
+       [2775, 3454],
+       [2795, 3478],
+       [2792, 3516],
+       [2788, 3521],
+       [2793, 3518],
+       [2798, 3520],
+       [2799, 3522],
+       [2816, 3536],
+       [2825, 3557],
+       [2831, 3566],
+       [2852, 3568],
+       [2862, 3574],
+       [2866, 3570],
+       [2866, 3575],
+       [2869, 3589],
+       [2878, 3603],
+       [2876, 3630],
+       [2878, 3628],
+       [2889, 3633],
+       [2891, 3633]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '047',
+     'FIPS': '36047',
+     'STATE': 'NY',
+     'NAME': 'Kings',
+     'LSAD': 'County'},
+    'id': 2203,
+    'type': 'Feature'},
+   {'geometry': {'type': 'MultiPolygon',
+     'coordinates': [[[[2919, 3907],
+        [2936, 3900],
+        [2938, 3897],
+        [2945, 3895],
+        [2946, 3897],
+        [2953, 3901],
+        [2957, 3896],
+        [2957, 3891],
+        [2952, 3877],
+        [2938, 3859],
+        [2926, 3837],
+        [2919, 3813],
+        [2921, 3765],
+        [2928, 3754],
+        [2935, 3754],
+        [2940, 3748],
+        [2949, 3742],
+        [2952, 3732],
+        [2945, 3727],
+        [2941, 3721],
+        [2927, 3705],
+        [2921, 3708],
+        [2918, 3706],
+        [2916, 3709],
+        [2915, 3705],
+        [2911, 3701],
+        [2912, 3697],
+        [2916, 3695],
+        [2915, 3693],
+        [2903, 3681],
+        [2887, 3656],
+        [2882, 3645],
+        [2878, 3640],
+        [2876, 3630],
+        [2878, 3603],
+        [2869, 3589],
+        [2866, 3575],
+        [2866, 3570],
+        [2862, 3574],
+        [2852, 3568],
+        [2830, 3565],
+        [2816, 3536],
+        [2799, 3522],
+        [2798, 3520],
+        [2793, 3518],
+        [2787, 3523],
+        [2786, 3532],
+        [2790, 3545],
+        [2795, 3548],
+        [2797, 3561],
+        [2793, 3571],
+        [2786, 3575],
+        [2802, 3666],
+        [2875, 3801],
+        [2889, 3842],
+        [2919, 3907]]],
+      [[[2763, 3558],
+        [2766, 3555],
+        [2757, 3535],
+        [2753, 3539],
+        [2763, 3558]]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '061',
+     'FIPS': '36061',
+     'STATE': 'NY',
+     'NAME': 'New York',
+     'LSAD': 'County'},
+    'id': 2200,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[3088, 3760],
+       [3097, 3759],
+       [3122, 3749],
+       [3131, 3749],
+       [3133, 3751],
+       [3140, 3740],
+       [3148, 3740],
+       [3159, 3751],
+       [3190, 3709],
+       [3190, 3712],
+       [3228, 3682],
+       [3255, 3660],
+       [3257, 3655],
+       [3258, 3633],
+       [3247, 3611],
+       [3228, 3606],
+       [3214, 3600],
+       [3219, 3578],
+       [3222, 3558],
+       [3220, 3551],
+       [3221, 3519],
+       [3217, 3493],
+       [3222, 3468],
+       [3217, 3463],
+       [3199, 3457],
+       [3198, 3446],
+       [3201, 3434],
+       [3197, 3432],
+       [3198, 3437],
+       [3198, 3438],
+       [3194, 3438],
+       [3193, 3431],
+       [3162, 3415],
+       [3163, 3394],
+       [3171, 3387],
+       [3178, 3386],
+       [3178, 3384],
+       [3189, 3389],
+       [3190, 3387],
+       [3192, 3388],
+       [3203, 3370],
+       [3203, 3354],
+       [3204, 3352],
+       [3195, 3352],
+       [3189, 3349],
+       [3179, 3339],
+       [3181, 3347],
+       [3149, 3348],
+       [3103, 3336],
+       [3063, 3322],
+       [2998, 3290],
+       [2908, 3256],
+       [2909, 3278],
+       [2920, 3289],
+       [2915, 3298],
+       [2911, 3300],
+       [2998, 3317],
+       [3040, 3344],
+       [3063, 3379],
+       [3064, 3420],
+       [3043, 3449],
+       [3033, 3447],
+       [3031, 3460],
+       [3021, 3477],
+       [3029, 3480],
+       [3028, 3487],
+       [3032, 3488],
+       [3029, 3503],
+       [3025, 3502],
+       [3020, 3523],
+       [3017, 3522],
+       [3013, 3548],
+       [3005, 3546],
+       [2983, 3527],
+       [2982, 3528],
+       [2978, 3525],
+       [2976, 3529],
+       [2972, 3523],
+       [2966, 3533],
+       [2966, 3541],
+       [2959, 3546],
+       [2961, 3549],
+       [2950, 3557],
+       [2952, 3559],
+       [2949, 3562],
+       [2950, 3564],
+       [2936, 3574],
+       [2937, 3577],
+       [2932, 3587],
+       [2934, 3590],
+       [2933, 3596],
+       [2925, 3611],
+       [2913, 3615],
+       [2906, 3626],
+       [2891, 3633],
+       [2889, 3633],
+       [2878, 3628],
+       [2876, 3630],
+       [2878, 3640],
+       [2882, 3645],
+       [2887, 3656],
+       [2903, 3681],
+       [2915, 3693],
+       [2916, 3695],
+       [2912, 3697],
+       [2911, 3701],
+       [2915, 3705],
+       [2916, 3709],
+       [2918, 3706],
+       [2921, 3708],
+       [2927, 3705],
+       [2941, 3721],
+       [2945, 3727],
+       [2952, 3732],
+       [2949, 3742],
+       [2981, 3730],
+       [2982, 3725],
+       [2998, 3722],
+       [3010, 3724],
+       [3011, 3732],
+       [3022, 3744],
+       [3038, 3749],
+       [3074, 3755],
+       [3088, 3760]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '081',
+     'FIPS': '36081',
+     'STATE': 'NY',
+     'NAME': 'Queens',
+     'LSAD': 'County'},
+    'id': 2202,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2801, 3129],
+       [2811, 3126],
+       [2828, 3114],
+       [2853, 3059],
+       [2855, 2998],
+       [2863, 2928],
+       [2863, 2883],
+       [2855, 2790],
+       [2848, 2752],
+       [2831, 2672],
+       [2778, 2453],
+       [2772, 2416],
+       [2775, 2412],
+       [2765, 2418],
+       [2763, 2417],
+       [2757, 2420],
+       [2749, 2418],
+       [2740, 2412],
+       [2738, 2405],
+       [2733, 2403],
+       [2718, 2389],
+       [2700, 2402],
+       [2684, 2424],
+       [2685, 2431],
+       [2683, 2435],
+       [2685, 2438],
+       [2681, 2448],
+       [2682, 2464],
+       [2680, 2465],
+       [2677, 2463],
+       [2670, 2472],
+       [2671, 2475],
+       [2665, 2480],
+       [2603, 2407],
+       [2597, 2409],
+       [2596, 2413],
+       [2592, 2416],
+       [2591, 2419],
+       [2588, 2423],
+       [2571, 2424],
+       [2561, 2430],
+       [2556, 2429],
+       [2551, 2431],
+       [2546, 2430],
+       [2539, 2433],
+       [2533, 2432],
+       [2525, 2434],
+       [2513, 2429],
+       [2503, 2429],
+       [2495, 2427],
+       [2483, 2429],
+       [2480, 2432],
+       [2473, 2433],
+       [2465, 2445],
+       [2467, 2453],
+       [2469, 2454],
+       [2470, 2466],
+       [2458, 2494],
+       [2453, 2500],
+       [2447, 2503],
+       [2443, 2503],
+       [2445, 2509],
+       [2443, 2518],
+       [2446, 2524],
+       [2442, 2535],
+       [2438, 2540],
+       [2229, 2548],
+       [2138, 2464],
+       [2054, 2391],
+       [2016, 2370],
+       [1927, 2567],
+       [1948, 2575],
+       [1952, 2574],
+       [1954, 2562],
+       [1957, 2562],
+       [1968, 2569],
+       [1985, 2576],
+       [1991, 2573],
+       [2002, 2581],
+       [2011, 2600],
+       [2023, 2615],
+       [2025, 2624],
+       [2031, 2632],
+       [2069, 2652],
+       [2120, 2682],
+       [2119, 2689],
+       [2114, 2695],
+       [2112, 2702],
+       [2146, 2700],
+       [2150, 2698],
+       [2249, 2752],
+       [2248, 2769],
+       [2271, 2799],
+       [2460, 2996],
+       [2458, 3003],
+       [2461, 3006],
+       [2461, 3042],
+       [2479, 3067],
+       [2481, 3065],
+       [2483, 3068],
+       [2490, 3067],
+       [2497, 3080],
+       [2494, 3083],
+       [2494, 3084],
+       [2516, 3073],
+       [2521, 3060],
+       [2521, 3056],
+       [2518, 3054],
+       [2520, 3050],
+       [2527, 3057],
+       [2539, 3061],
+       [2548, 3073],
+       [2567, 3089],
+       [2567, 3076],
+       [2564, 3074],
+       [2566, 3071],
+       [2574, 3079],
+       [2578, 3075],
+       [2580, 3072],
+       [2584, 3075],
+       [2592, 3071],
+       [2599, 3073],
+       [2614, 3079],
+       [2620, 3086],
+       [2624, 3088],
+       [2651, 3070],
+       [2693, 3056],
+       [2711, 3047],
+       [2736, 3026],
+       [2752, 3018],
+       [2812, 3003],
+       [2824, 3003],
+       [2828, 3019],
+       [2834, 3064],
+       [2813, 3106],
+       [2796, 3120],
+       [2796, 3124],
+       [2801, 3129]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '025',
+     'FIPS': '34025',
+     'STATE': 'NJ',
+     'NAME': 'Monmouth',
+     'LSAD': 'County'},
+    'id': 2195,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[2229, 2548],
+       [2438, 2540],
+       [2442, 2535],
+       [2446, 2524],
+       [2443, 2518],
+       [2445, 2509],
+       [2443, 2503],
+       [2447, 2503],
+       [2453, 2500],
+       [2458, 2494],
+       [2470, 2466],
+       [2469, 2454],
+       [2467, 2453],
+       [2465, 2445],
+       [2473, 2433],
+       [2480, 2432],
+       [2483, 2429],
+       [2495, 2427],
+       [2503, 2429],
+       [2513, 2429],
+       [2525, 2434],
+       [2533, 2432],
+       [2539, 2433],
+       [2546, 2430],
+       [2551, 2431],
+       [2556, 2429],
+       [2561, 2430],
+       [2571, 2424],
+       [2588, 2423],
+       [2591, 2419],
+       [2592, 2416],
+       [2596, 2413],
+       [2597, 2409],
+       [2603, 2407],
+       [2665, 2480],
+       [2671, 2475],
+       [2670, 2472],
+       [2677, 2463],
+       [2680, 2465],
+       [2682, 2464],
+       [2681, 2448],
+       [2685, 2438],
+       [2683, 2435],
+       [2685, 2431],
+       [2684, 2424],
+       [2700, 2402],
+       [2718, 2389],
+       [2733, 2403],
+       [2738, 2405],
+       [2740, 2412],
+       [2749, 2418],
+       [2757, 2420],
+       [2763, 2417],
+       [2765, 2418],
+       [2776, 2411],
+       [2773, 2409],
+       [2764, 2374],
+       [2728, 2180],
+       [2709, 2050],
+       [2689, 1840],
+       [2680, 1779],
+       [2681, 1770],
+       [2678, 1763],
+       [2656, 1727],
+       [2615, 1630],
+       [2544, 1509],
+       [2471, 1376],
+       [2459, 1363],
+       [2418, 1299],
+       [2396, 1277],
+       [2381, 1273],
+       [2378, 1286],
+       [2369, 1285],
+       [2367, 1272],
+       [2353, 1282],
+       [2346, 1284],
+       [2330, 1285],
+       [2306, 1283],
+       [2296, 1276],
+       [2267, 1270],
+       [2234, 1349],
+       [2224, 1363],
+       [2216, 1366],
+       [2215, 1368],
+       [2216, 1378],
+       [2214, 1380],
+       [2219, 1390],
+       [2214, 1393],
+       [2212, 1402],
+       [2216, 1405],
+       [2221, 1405],
+       [2224, 1406],
+       [2226, 1404],
+       [2232, 1404],
+       [2235, 1408],
+       [2238, 1409],
+       [2242, 1417],
+       [2244, 1432],
+       [2250, 1450],
+       [2253, 1454],
+       [2254, 1789],
+       [2167, 1994],
+       [2084, 2203],
+       [2052, 2289],
+       [2016, 2370],
+       [2054, 2391],
+       [2138, 2464],
+       [2229, 2548]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '029',
+     'FIPS': '34029',
+     'STATE': 'NJ',
+     'NAME': 'Ocean',
+     'LSAD': 'County'},
+    'id': 2176,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[3554, 3986],
+       [3563, 3979],
+       [3567, 3971],
+       [3568, 3972],
+       [3574, 3953],
+       [3579, 3944],
+       [3583, 3941],
+       [3585, 3898],
+       [3597, 3881],
+       [3604, 3879],
+       [3602, 3864],
+       [3612, 3843],
+       [3615, 3828],
+       [3661, 3502],
+       [3660, 3492],
+       [3660, 3476],
+       [3661, 3473],
+       [3658, 3473],
+       [3661, 3384],
+       [3622, 3372],
+       [3572, 3360],
+       [3440, 3315],
+       [3442, 3337],
+       [3428, 3340],
+       [3388, 3342],
+       [3336, 3332],
+       [3179, 3335],
+       [3179, 3339],
+       [3189, 3349],
+       [3195, 3352],
+       [3204, 3352],
+       [3203, 3354],
+       [3203, 3370],
+       [3192, 3388],
+       [3190, 3387],
+       [3189, 3389],
+       [3178, 3384],
+       [3178, 3386],
+       [3171, 3387],
+       [3163, 3394],
+       [3162, 3415],
+       [3193, 3431],
+       [3194, 3438],
+       [3198, 3438],
+       [3198, 3437],
+       [3197, 3432],
+       [3201, 3434],
+       [3198, 3446],
+       [3199, 3457],
+       [3217, 3463],
+       [3222, 3468],
+       [3217, 3493],
+       [3221, 3519],
+       [3220, 3551],
+       [3222, 3558],
+       [3219, 3578],
+       [3214, 3600],
+       [3228, 3606],
+       [3247, 3611],
+       [3258, 3633],
+       [3256, 3658],
+       [3190, 3712],
+       [3190, 3709],
+       [3159, 3751],
+       [3180, 3790],
+       [3179, 3801],
+       [3217, 3851],
+       [3220, 3859],
+       [3214, 3875],
+       [3216, 3877],
+       [3239, 3884],
+       [3294, 3859],
+       [3323, 3872],
+       [3325, 3900],
+       [3344, 3928],
+       [3355, 3938],
+       [3365, 3941],
+       [3379, 3938],
+       [3402, 3947],
+       [3411, 3956],
+       [3448, 3972],
+       [3454, 3972],
+       [3480, 3959],
+       [3522, 3970],
+       [3528, 3967],
+       [3550, 3977],
+       [3554, 3986]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '059',
+     'FIPS': '36059',
+     'STATE': 'NY',
+     'NAME': 'Nassau',
+     'LSAD': 'County'},
+    'id': 2201,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[1749, 1707],
+       [1837, 1634],
+       [1842, 1625],
+       [1846, 1623],
+       [1851, 1615],
+       [1854, 1606],
+       [1854, 1601],
+       [1860, 1591],
+       [1863, 1569],
+       [1861, 1566],
+       [1862, 1563],
+       [1860, 1560],
+       [1863, 1559],
+       [1863, 1554],
+       [1862, 1550],
+       [1865, 1546],
+       [1861, 1538],
+       [1863, 1530],
+       [1861, 1521],
+       [1866, 1520],
+       [1868, 1518],
+       [1868, 1512],
+       [1871, 1511],
+       [1874, 1515],
+       [1878, 1514],
+       [1878, 1509],
+       [1888, 1510],
+       [1889, 1505],
+       [1890, 1504],
+       [1893, 1505],
+       [1896, 1513],
+       [1900, 1513],
+       [1902, 1507],
+       [1902, 1501],
+       [1906, 1499],
+       [1910, 1503],
+       [1911, 1509],
+       [1914, 1512],
+       [1916, 1512],
+       [1926, 1505],
+       [1929, 1506],
+       [1936, 1502],
+       [1954, 1488],
+       [1964, 1484],
+       [1966, 1481],
+       [1969, 1471],
+       [1975, 1468],
+       [1983, 1458],
+       [1992, 1459],
+       [2000, 1455],
+       [2015, 1457],
+       [2022, 1442],
+       [2033, 1434],
+       [2031, 1425],
+       [2034, 1417],
+       [2037, 1413],
+       [2045, 1411],
+       [2051, 1405],
+       [2054, 1403],
+       [2059, 1403],
+       [2067, 1411],
+       [2072, 1412],
+       [2076, 1404],
+       [2080, 1402],
+       [2088, 1403],
+       [2092, 1395],
+       [2099, 1391],
+       [2101, 1381],
+       [2103, 1379],
+       [2108, 1379],
+       [2113, 1383],
+       [2120, 1382],
+       [2126, 1372],
+       [2130, 1369],
+       [2134, 1371],
+       [2139, 1377],
+       [2144, 1379],
+       [2148, 1379],
+       [2150, 1376],
+       [2152, 1366],
+       [2154, 1362],
+       [2158, 1361],
+       [2162, 1367],
+       [2162, 1378],
+       [2164, 1382],
+       [2169, 1384],
+       [2172, 1383],
+       [2176, 1378],
+       [2172, 1363],
+       [2178, 1354],
+       [2182, 1350],
+       [2185, 1349],
+       [2190, 1353],
+       [2190, 1359],
+       [2184, 1369],
+       [2184, 1374],
+       [2187, 1376],
+       [2191, 1377],
+       [2199, 1373],
+       [2201, 1373],
+       [2209, 1380],
+       [2214, 1380],
+       [2216, 1378],
+       [2215, 1368],
+       [2216, 1366],
+       [2224, 1363],
+       [2234, 1349],
+       [2267, 1270],
+       [2296, 1276],
+       [2306, 1283],
+       [2330, 1285],
+       [2346, 1284],
+       [2353, 1282],
+       [2367, 1272],
+       [2365, 1261],
+       [2373, 1242],
+       [2378, 1240],
+       [2382, 1233],
+       [2378, 1218],
+       [2334, 1144],
+       [2287, 1088],
+       [2229, 1041],
+       [2227, 1018],
+       [2221, 1010],
+       [2152, 980],
+       [2062, 921],
+       [2033, 896],
+       [2029, 900],
+       [2023, 900],
+       [2011, 893],
+       [1994, 894],
+       [1967, 914],
+       [1960, 913],
+       [1918, 882],
+       [1913, 881],
+       [1900, 886],
+       [1889, 888],
+       [1885, 887],
+       [1879, 882],
+       [1875, 875],
+       [1870, 874],
+       [1863, 877],
+       [1862, 879],
+       [1864, 890],
+       [1849, 891],
+       [1845, 889],
+       [1845, 881],
+       [1843, 876],
+       [1840, 875],
+       [1838, 877],
+       [1840, 883],
+       [1840, 887],
+       [1837, 890],
+       [1835, 890],
+       [1831, 884],
+       [1828, 883],
+       [1824, 885],
+       [1820, 883],
+       [1816, 878],
+       [1810, 879],
+       [1805, 875],
+       [1802, 878],
+       [1798, 885],
+       [1794, 884],
+       [1791, 878],
+       [1789, 880],
+       [1788, 886],
+       [1785, 886],
+       [1782, 880],
+       [1778, 881],
+       [1773, 886],
+       [1775, 892],
+       [1773, 893],
+       [1764, 888],
+       [1758, 892],
+       [1748, 893],
+       [1744, 888],
+       [1735, 885],
+       [1726, 886],
+       [1725, 891],
+       [1720, 894],
+       [1709, 889],
+       [1706, 893],
+       [1699, 894],
+       [1696, 897],
+       [1688, 894],
+       [1687, 894],
+       [1689, 902],
+       [1679, 909],
+       [1676, 908],
+       [1671, 909],
+       [1666, 905],
+       [1664, 908],
+       [1659, 908],
+       [1656, 911],
+       [1651, 909],
+       [1646, 904],
+       [1643, 907],
+       [1629, 907],
+       [1627, 909],
+       [1620, 905],
+       [1611, 916],
+       [1602, 924],
+       [1582, 926],
+       [1576, 930],
+       [1568, 932],
+       [1568, 940],
+       [1563, 948],
+       [1562, 968],
+       [1564, 974],
+       [1564, 981],
+       [1570, 1000],
+       [1569, 1012],
+       [1579, 1031],
+       [1581, 1041],
+       [1580, 1055],
+       [1572, 1075],
+       [1573, 1080],
+       [1572, 1086],
+       [1577, 1095],
+       [1580, 1106],
+       [1579, 1112],
+       [1574, 1123],
+       [1573, 1127],
+       [1575, 1130],
+       [1387, 1300],
+       [1749, 1707]]]},
+    'properties': {'STATE_FIPS': '34',
+     'COUNTY_FIP': '001',
+     'FIPS': '34001',
+     'STATE': 'NJ',
+     'NAME': 'Atlantic',
+     'LSAD': 'County'},
+    'id': 2132,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[812, 261],
+       [817, 258],
+       [823, 260],
+       [830, 256],
+       [829, 253],
+       [832, 246],
+       [841, 253],
+       [852, 234],
+       [855, 234],
+       [863, 248],
+       [865, 247],
+       [867, 241],
+       [865, 234],
+       [872, 231],
+       [877, 233],
+       [881, 240],
+       [884, 239],
+       [887, 237],
+       [893, 238],
+       [897, 245],
+       [904, 244],
+       [909, 239],
+       [908, 233],
+       [925, 218],
+       [911, 191],
+       [922, 169],
+       [982, 102],
+       [1027, 41],
+       [1067, 0],
+       [1088, -29],
+       [1134, -61],
+       [1170, -75],
+       [1200, -74],
+       [1224, -63],
+       [1229, -53],
+       [1224, -36],
+       [1229, -35],
+       [1235, -47],
+       [1242, -80],
+       [319, -80],
+       [314, 0],
+       [313, 14],
+       [557, 24],
+       [566, 35],
+       [573, 39],
+       [577, 38],
+       [580, 39],
+       [585, 47],
+       [584, 51],
+       [607, 62],
+       [625, 105],
+       [632, 110],
+       [635, 109],
+       [640, 111],
+       [642, 113],
+       [645, 122],
+       [651, 125],
+       [655, 131],
+       [654, 143],
+       [659, 152],
+       [670, 156],
+       [688, 166],
+       [695, 162],
+       [716, 169],
+       [724, 169],
+       [732, 165],
+       [741, 169],
+       [751, 171],
+       [753, 174],
+       [757, 171],
+       [759, 179],
+       [770, 176],
+       [770, 182],
+       [775, 181],
+       [776, 177],
+       [779, 178],
+       [781, 180],
+       [778, 187],
+       [780, 192],
+       [783, 193],
+       [784, 195],
+       [781, 200],
+       [786, 213],
+       [783, 211],
+       [779, 215],
+       [783, 218],
+       [785, 221],
+       [781, 233],
+       [785, 238],
+       [792, 244],
+       [793, 250],
+       [796, 251],
+       [799, 247],
+       [808, 249],
+       [810, 260],
+       [812, 261]]]},
+    'properties': {'STATE_FIPS': '10',
+     'COUNTY_FIP': '005',
+     'FIPS': '10005',
+     'STATE': 'DE',
+     'NAME': 'Sussex',
+     'LSAD': 'County'},
+    'id': 2175,
+    'type': 'Feature'},
+   {'geometry': {'type': 'Polygon',
+     'coordinates': [[[4106, 4092],
+       [4117, 4081],
+       [4159, 4083],
+       [4176, 4076],
+       [4176, 3486],
+       [4096, 3462],
+       [3974, 3424],
+       [3896, 3406],
+       [3832, 3405],
+       [3827, 3408],
+       [3813, 3434],
+       [3766, 3424],
+       [3707, 3399],
+       [3661, 3384],
+       [3658, 3473],
+       [3661, 3473],
+       [3660, 3476],
+       [3660, 3492],
+       [3661, 3502],
+       [3615, 3828],
+       [3612, 3843],
+       [3602, 3864],
+       [3604, 3879],
+       [3597, 3881],
+       [3585, 3898],
+       [3583, 3941],
+       [3579, 3944],
+       [3574, 3953],
+       [3568, 3972],
+       [3567, 3971],
+       [3563, 3979],
+       [3554, 3986],
+       [3562, 4023],
+       [3571, 4031],
+       [3581, 4023],
+       [3603, 4015],
+       [3642, 4009],
+       [3652, 3999],
+       [3654, 3983],
+       [3687, 3981],
+       [3691, 3990],
+       [3690, 4023],
+       [3694, 4046],
+       [3696, 4048],
+       [3706, 4049],
+       [3733, 4014],
+       [3745, 4003],
+       [3764, 3993],
+       [3775, 3991],
+       [3777, 3995],
+       [3795, 3999],
+       [3848, 3989],
+       [3944, 3952],
+       [4061, 3998],
+       [4065, 4010],
+       [4067, 4050],
+       [4053, 4061],
+       [4046, 4074],
+       [4078, 4071],
+       [4096, 4085],
+       [4106, 4092]]]},
+    'properties': {'STATE_FIPS': '36',
+     'COUNTY_FIP': '103',
+     'FIPS': '36103',
+     'STATE': 'NY',
+     'NAME': 'Suffolk',
+     'LSAD': 'County'},
+    'id': 2231,
+    'type': 'Feature'}],
+  'type': 'FeatureCollection'}}
+
+
+ + +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/pr-preview/pr-68/search.json b/pr-preview/pr-68/search.json new file mode 100644 index 0000000..090d767 --- /dev/null +++ b/pr-preview/pr-68/search.json @@ -0,0 +1,835 @@ +[ + { + "objectID": "contributing.html", + "href": "contributing.html", + "title": "Get Involved", + "section": "", + "text": "We encourage contributions to this guide. The guide’s goal is to provide documentation on the best practices for the current state-of-the-art cloud-optimized formats. These formats are evolving, and so will the guide." + }, + { + "objectID": "contributing.html#introduction", + "href": "contributing.html#introduction", + "title": "Get Involved", + "section": "", + "text": "We encourage contributions to this guide. The guide’s goal is to provide documentation on the best practices for the current state-of-the-art cloud-optimized formats. These formats are evolving, and so will the guide." + }, + { + "objectID": "contributing.html#pre-requisites", + "href": "contributing.html#pre-requisites", + "title": "Get Involved", + "section": "Pre-requisites", + "text": "Pre-requisites\nIf you wish to preview the site locally, install quarto. You will also need to be familiar with quarto markdown." + }, + { + "objectID": "contributing.html#communication-channels", + "href": "contributing.html#communication-channels", + "title": "Get Involved", + "section": "Communication Channels", + "text": "Communication Channels\nDiscussions can occur in GitHub Discussions and issues can be raised at GitHub Issues.\n\nGitHub Discussions: Ideal for questions, feature requests, or general conversations about the project. Use this space for collaborative discussions or if you’re unsure where to start.\nGitHub Issues: Use this for reporting bugs, suggesting enhancements, or other tasks that require tracking and possibly code changes." + }, + { + "objectID": "contributing.html#core-principles", + "href": "contributing.html#core-principles", + "title": "Get Involved", + "section": "Core Principles", + "text": "Core Principles\n\nThis guide intends to be opinionated but acknowledges no one-size-fits-all solution.\nThis guide should provide the best information and guidance available but acknowledge that experts develop many existing resources. Those resources should be linked as appropriate." + }, + { + "objectID": "contributing.html#additional-criteria", + "href": "contributing.html#additional-criteria", + "title": "Get Involved", + "section": "Additional Criteria", + "text": "Additional Criteria\n\nAll examples should use open data. If an example uses data from NASA Earthdata, it must include an example of providing credentials (Earthdata registration is available to anyone).\nLanding pages with no code should use quarto markdown (.qmd).\nPages with executable code should be Jupyter Notebooks (.ipynb)." + }, + { + "objectID": "contributing.html#code-of-conduct", + "href": "contributing.html#code-of-conduct", + "title": "Get Involved", + "section": "Code of Conduct", + "text": "Code of Conduct\n\nBe inclusive, respectful, and understanding of others’ backgrounds and contexts.\nLook for and foster diverse perspectives.\nIf you experience any harmful behavior, please get in touch with Aimee or Alex." + }, + { + "objectID": "contributing.html#bug-reporting-feature-requests", + "href": "contributing.html#bug-reporting-feature-requests", + "title": "Get Involved", + "section": "Bug Reporting & Feature Requests", + "text": "Bug Reporting & Feature Requests\nBefore submitting a bug report or a feature request, please start a GitHub Discussion to see if the issue has already been addressed or if it can be resolved through discussion.\n\nGeneral Steps\n\nFork the repository.\nClone your fork locally.\nCreate a new branch for your changes.\nMake your changes and use quarto preview to make sure they look good.\nOpen a pull request.\n\nOnce the pull request is opened, and the GitHub preview.yml workflow runs (“Deploy PR previews”), you should have a preview available for review at https://developmentseed.org/cloud-optimized-geospatial-formats-guide/pr-preview/pr-<YOUR-PR-NUMBER-HERE>. A bot will comment on your PR when the PR preview is ready.\n\n\nSpecific Contributions\n\n1. Adding a New Format\nFollow the steps outlined in the General Steps, then:\n\nCreate a folder with the format’s name and, within that folder, an intro.qmd.\nLink to the intro.qmd page in the index.qmd (the Welcome page) file and _quarto.yml table of contents.\n\n\n\n2. Modify or Add to an Existing Format\nFeel free to modify or add to existing content if you think it could be improved.\n\n\n3. Adding a Cookbook\nCookbooks should address common questions and present solutions for cloud-optimized access and visualization. To create a cookbook, either add a notebook directly to this repository in the cookbooks directory OR use an external link and add it to cookbooks/index.qmd.\n\n\n4. (Optional) Update Slides\nIf you have made substantive changes, consider updating the Overview Slides. These slides are generated using Quarto and Reveal.js so can be updated with markdown syntax.\n\n\n5. Add Yourself to the List of Authors\nAdd yourself to the list of authors on the Welcome page.\n\n\n6. Final Steps Before Merging\nOnce your PR is approved and all checks have passed, a project maintainer will merge your changes into the main repository." + }, + { + "objectID": "contributing.html#licensing", + "href": "contributing.html#licensing", + "title": "Get Involved", + "section": "Licensing", + "text": "Licensing\nThis work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. For attribution requirements, please look at the license terms.\nPreferred citation: Barciauskas, A et al. 2023. Cloud Optimized Geospatial Formats Guide. CC-By-4.0." + }, + { + "objectID": "contributing.html#contact", + "href": "contributing.html#contact", + "title": "Get Involved", + "section": "Contact", + "text": "Contact\nFor questions on how to contribute, start a discussion in the GitHub Discussions section." + }, + { + "objectID": "contributing.html#thank-you-to-our-supporters", + "href": "contributing.html#thank-you-to-our-supporters", + "title": "Get Involved", + "section": "Thank you to our supporters", + "text": "Thank you to our supporters\nThis guide has been made possible through the support of:" + }, + { + "objectID": "pmtiles/pmtiles-example.html", + "href": "pmtiles/pmtiles-example.html", + "title": "PMTiles example", + "section": "", + "text": "This notebook will give an overview of how to create and visualize PMTiles archives." + }, + { + "objectID": "pmtiles/pmtiles-example.html#environment", + "href": "pmtiles/pmtiles-example.html#environment", + "title": "PMTiles example", + "section": "Environment", + "text": "Environment\nThe packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:\nconda create -f environment.yml \nor\nmamba create -f environment.yml \nAlternatively, you can install pmtiles and mapbox-vector-tile through pip, and tippecanoe through Homebrew (brew install tippecanoe) if on MacOS." + }, + { + "objectID": "pmtiles/pmtiles-example.html#creating-pmtiles", + "href": "pmtiles/pmtiles-example.html#creating-pmtiles", + "title": "PMTiles example", + "section": "Creating PMTiles", + "text": "Creating PMTiles\nFor this example, we’ll use the same file as used in the FlatGeobuf and GeoParquet example notebooks: a 13MB file of US counties.\nWe’ll use Tippecanoe to convert this file into tiles.\nFirst we’ll download the file to our local directory:\n\n!wget https://flatgeobuf.org/test/data/UScounties.fgb\n\n--2023-08-23 15:54:58-- https://flatgeobuf.org/test/data/UScounties.fgb\nResolving flatgeobuf.org (flatgeobuf.org)... 185.199.108.153\nConnecting to flatgeobuf.org (flatgeobuf.org)|185.199.108.153|:443... connected.\nHTTP request sent, awaiting response... 200 OK\nLength: 14100008 (13M) [application/octet-stream]\nSaving to: ‘UScounties.fgb’\n\nUScounties.fgb 100%[===================>] 13.45M 7.94MB/s in 1.7s \n\n2023-08-23 15:55:02 (7.94 MB/s) - ‘UScounties.fgb’ saved [14100008/14100008]\n\n\n\nTippecanoe has many options to customize its behavior. Here we’ll use the -zg flag to tell Tippecanoe to deduce appropriate minimum and maximum zoom levels for the dataset. The -o counties.pmtiles flag tells Tippecanoe to save the output with that name.\nTippecanoe also works especially well with FlatGeobuf files. When a FlatGeobuf file is used as input, Tippecanoe will reuse the spatial index stored in the FlatGeobuf file instead of creating its own.\n\n!tippecanoe UScounties.fgb -o counties.pmtiles -zg\n\nFor layer 0, using name \"UScountiesfgb\"\ndetected indexed FlatGeobuf: assigning feature IDs by sequence\n3221 features, 5580299 bytes of geometry, 53296 bytes of string pool\nChoosing a maxzoom of -z1 for features typically 141427 feet (43107 meters) apart, and at least 33249 feet (10135 meters) apart\nChoosing a maxzoom of -z7 for resolution of about 3195 feet (973 meters) within features\n 99.9% 7/36/49 \n 100.0% 7/127/42 \n\n\nNow we have a file named counties.pmtiles with our data:\n\n!ls -lh counties.pmtiles\n\n-rw-r--r--@ 1 kyle staff 2.8M Aug 25 13:09 counties.pmtiles" + }, + { + "objectID": "pmtiles/pmtiles-example.html#visualization", + "href": "pmtiles/pmtiles-example.html#visualization", + "title": "PMTiles example", + "section": "Visualization", + "text": "Visualization\nThe easiest way to interpret this data is to load it into the PMTiles Viewer. Drag the counties.pmtiles file into that website, and you’ll be able to hover over areas" + }, + { + "objectID": "pmtiles/pmtiles-example.html#reading-from-python", + "href": "pmtiles/pmtiles-example.html#reading-from-python", + "title": "PMTiles example", + "section": "Reading from Python", + "text": "Reading from Python\nIt’s possible to open and read a PMTiles file from python using the pmtiles and mapbox-vector-tile libraries. The pmtiles library is used to open the archive and fetch a specific tile, while mapbox-vector-tile is used to decode the MVT vector tile data contained within that tile.\n\nfrom pmtiles.reader import Reader, MmapSource\n\nOpen the file and create a pmtiles Reader object\n\nfile = open(\"counties.pmtiles\")\nreader = Reader(MmapSource(file))\n\nFetch a specific tile. This tile’s coordinates were found from the PMTiles viewer above, and is located over the east coast.\n\nx, y, z = 37, 48, 7\ntile_data = reader.get(z, x, y)\n\ntile_data is now a bytes object, representing the data contained in the PMTiles archive for that specific XYZ tile.\n\ntype(tile_data)\n\nbytes\n\n\n\nlen(tile_data)\n\n11878\n\n\nIn our case, the PMTiles archive contains MVT data, so we can decode the buffer using mapbox_vector_tile. It’s also possible for the archive to contain raster images (e.g. PNG files), in which case a different decoding process would be necessary.\n\nimport mapbox_vector_tile\nimport gzip\n\nWe’ll decode the tile and print the output from mapbox_vector_tile. MVT data are encoded with “quantization”, meaning reduced precision so the data can be compressed better. So the coordinates printed out have a range of 0-4096, where those are the integer steps within the local coordinate reference system within the tile. Refer to the mapbox_vector_tile docs for how to read to GeoJSON.\n\nmapbox_vector_tile.decode(gzip.decompress(tile_data))\n\n{'UScountiesfgb': {'extent': 4096,\n 'version': 2,\n 'features': [{'geometry': {'type': 'Polygon',\n 'coordinates': [[[289, 4176],\n [290, 4168],\n [299, 4151],\n [198, 4102],\n [172, 4100],\n [163, 4096],\n [128, 4080],\n [130, 4070],\n [0, 4009],\n [-71, 3976],\n [-80, 3970],\n [-80, 4176],\n [289, 4176]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '079',\n 'FIPS': '42079',\n 'STATE': 'PA',\n 'NAME': 'Luzerne',\n 'LSAD': 'County'},\n 'id': 2224,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1272, 4176],\n [1256, 4168],\n [1247, 4167],\n [1235, 4163],\n [1226, 4152],\n [1206, 4143],\n [1204, 4139],\n [1180, 4123],\n [1175, 4118],\n [1174, 4113],\n [1174, 4106],\n [1171, 4096],\n [1168, 4090],\n [1168, 4084],\n [1171, 4079],\n [1174, 4076],\n [1177, 4075],\n [1187, 4077],\n [1190, 4074],\n [1177, 4056],\n [1154, 4041],\n [1143, 4037],\n [1119, 4035],\n [1108, 4030],\n [1106, 4020],\n [1092, 4014],\n [1081, 4012],\n [1048, 3996],\n [1042, 3980],\n [1014, 3960],\n [1027, 3941],\n [976, 3908],\n [967, 3890],\n [952, 3877],\n [928, 3864],\n [898, 3857],\n [868, 3837],\n [807, 3809],\n [758, 3800],\n [753, 3795],\n [721, 3785],\n [675, 3778],\n [663, 3807],\n [648, 3835],\n [529, 4041],\n [620, 4096],\n [643, 4110],\n [590, 4176],\n [1272, 4176]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '089',\n 'FIPS': '42089',\n 'STATE': 'PA',\n 'NAME': 'Monroe',\n 'LSAD': 'County'},\n 'id': 2227,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[590, 4176],\n [643, 4110],\n [620, 4096],\n [529, 4041],\n [598, 3923],\n [655, 3822],\n [675, 3778],\n [668, 3775],\n [625, 3767],\n [609, 3766],\n [596, 3762],\n [577, 3763],\n [562, 3758],\n [553, 3752],\n [524, 3748],\n [498, 3737],\n [494, 3730],\n [488, 3726],\n [478, 3725],\n [399, 3706],\n [363, 3696],\n [354, 3692],\n [342, 3677],\n [304, 3661],\n [299, 3656],\n [289, 3642],\n [282, 3641],\n [281, 3635],\n [262, 3625],\n [75, 3781],\n [0, 3867],\n [-80, 3958],\n [-80, 3970],\n [0, 4009],\n [130, 4070],\n [128, 4080],\n [163, 4096],\n [172, 4100],\n [198, 4102],\n [299, 4151],\n [290, 4168],\n [289, 4176],\n [590, 4176]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '025',\n 'FIPS': '42025',\n 'STATE': 'PA',\n 'NAME': 'Carbon',\n 'LSAD': 'County'},\n 'id': 2217,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1529, 4176],\n [1594, 4096],\n [1703, 3965],\n [1691, 3952],\n [1687, 3954],\n [1681, 3943],\n [1671, 3935],\n [1671, 3928],\n [1668, 3923],\n [1651, 3914],\n [1647, 3908],\n [1648, 3894],\n [1645, 3883],\n [1646, 3880],\n [1654, 3874],\n [1652, 3869],\n [1643, 3865],\n [1642, 3855],\n [1637, 3849],\n [1627, 3845],\n [1625, 3843],\n [1622, 3833],\n [1627, 3829],\n [1630, 3821],\n [1617, 3812],\n [1611, 3804],\n [1613, 3799],\n [1606, 3792],\n [1606, 3786],\n [1598, 3780],\n [1592, 3771],\n [1589, 3771],\n [1588, 3765],\n [1583, 3757],\n [1576, 3756],\n [1569, 3752],\n [1567, 3756],\n [1562, 3755],\n [1558, 3742],\n [1546, 3737],\n [1539, 3731],\n [1535, 3733],\n [1532, 3732],\n [1517, 3719],\n [1505, 3712],\n [1507, 3706],\n [1506, 3698],\n [1507, 3695],\n [1494, 3686],\n [1489, 3680],\n [1489, 3677],\n [1485, 3672],\n [1473, 3663],\n [1470, 3658],\n [1467, 3656],\n [1465, 3651],\n [1452, 3636],\n [1451, 3631],\n [1443, 3624],\n [1435, 3610],\n [1426, 3606],\n [1424, 3602],\n [1419, 3597],\n [1410, 3577],\n [1396, 3578],\n [1393, 3569],\n [1378, 3563],\n [1361, 3545],\n [1356, 3544],\n [1351, 3547],\n [1345, 3543],\n [1341, 3547],\n [1337, 3542],\n [1333, 3542],\n [1315, 3526],\n [1310, 3526],\n [1308, 3524],\n [1303, 3517],\n [1301, 3516],\n [1295, 3518],\n [1288, 3512],\n [1282, 3510],\n [1278, 3505],\n [1275, 3499],\n [1267, 3497],\n [1264, 3494],\n [1254, 3488],\n [1247, 3476],\n [1236, 3472],\n [1235, 3468],\n [1226, 3458],\n [1211, 3451],\n [1207, 3447],\n [1208, 3442],\n [1205, 3440],\n [1180, 3431],\n [1168, 3424],\n [1153, 3420],\n [1150, 3416],\n [1150, 3408],\n [1147, 3405],\n [1141, 3407],\n [1129, 3399],\n [1130, 3393],\n [1128, 3387],\n [1124, 3385],\n [1120, 3378],\n [1114, 3375],\n [1111, 3363],\n [1104, 3361],\n [1102, 3355],\n [1096, 3351],\n [1088, 3349],\n [1085, 3370],\n [1072, 3393],\n [1071, 3398],\n [1077, 3402],\n [1088, 3404],\n [1091, 3412],\n [1085, 3444],\n [1073, 3455],\n [1073, 3460],\n [1087, 3484],\n [1099, 3492],\n [1107, 3505],\n [1108, 3511],\n [1107, 3514],\n [1102, 3518],\n [1097, 3519],\n [1088, 3518],\n [1079, 3521],\n [1073, 3529],\n [1068, 3541],\n [1082, 3584],\n [1089, 3592],\n [1100, 3618],\n [1095, 3629],\n [1081, 3645],\n [1079, 3656],\n [1086, 3664],\n [1099, 3671],\n [1105, 3676],\n [1107, 3681],\n [1110, 3697],\n [1115, 3707],\n [1118, 3708],\n [1127, 3708],\n [1148, 3701],\n [1170, 3699],\n [1174, 3703],\n [1186, 3724],\n [1195, 3729],\n [1203, 3730],\n [1207, 3732],\n [1219, 3749],\n [1219, 3764],\n [1225, 3773],\n [1234, 3780],\n [1243, 3797],\n [1243, 3803],\n [1241, 3807],\n [1224, 3825],\n [1223, 3832],\n [1226, 3840],\n [1233, 3844],\n [1254, 3845],\n [1262, 3841],\n [1269, 3841],\n [1272, 3842],\n [1288, 3865],\n [1291, 3876],\n [1290, 3885],\n [1287, 3891],\n [1280, 3899],\n [1270, 3914],\n [1256, 3931],\n [1255, 3956],\n [1250, 3969],\n [1226, 3989],\n [1212, 4012],\n [1211, 4018],\n [1203, 4035],\n [1194, 4044],\n [1190, 4065],\n [1191, 4070],\n [1190, 4074],\n [1187, 4077],\n [1177, 4075],\n [1174, 4076],\n [1171, 4079],\n [1168, 4084],\n [1168, 4090],\n [1171, 4096],\n [1174, 4106],\n [1174, 4113],\n [1175, 4118],\n [1180, 4123],\n [1204, 4139],\n [1206, 4143],\n [1226, 4152],\n [1235, 4163],\n [1247, 4167],\n [1256, 4168],\n [1272, 4176],\n [1529, 4176]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '041',\n 'FIPS': '34041',\n 'STATE': 'NJ',\n 'NAME': 'Warren',\n 'LSAD': 'County'},\n 'id': 2207,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[2427, 4176],\n [2425, 4170],\n [2437, 4158],\n [2460, 4120],\n [2494, 4099],\n [2518, 4096],\n [2573, 4090],\n [2573, 4096],\n [2574, 4104],\n [2583, 4096],\n [2616, 4070],\n [2606, 4022],\n [2612, 4020],\n [2619, 4007],\n [2615, 3999],\n [2616, 3992],\n [2619, 3987],\n [2630, 3985],\n [2633, 3981],\n [2628, 3967],\n [2630, 3956],\n [2627, 3941],\n [2634, 3930],\n [2632, 3915],\n [2646, 3904],\n [2654, 3892],\n [2656, 3885],\n [2661, 3874],\n [2665, 3871],\n [2665, 3860],\n [2662, 3856],\n [2659, 3857],\n [2656, 3864],\n [2649, 3864],\n [2647, 3855],\n [2648, 3849],\n [2644, 3833],\n [2641, 3826],\n [2645, 3808],\n [2641, 3793],\n [2638, 3790],\n [2632, 3788],\n [2552, 3846],\n [2534, 3860],\n [2536, 3865],\n [2529, 3868],\n [2527, 3864],\n [2472, 3904],\n [2453, 3906],\n [2451, 3909],\n [2443, 3911],\n [2437, 3917],\n [2433, 3931],\n [2425, 3938],\n [2424, 3942],\n [2427, 3948],\n [2424, 3953],\n [2426, 3956],\n [2426, 3962],\n [2430, 3957],\n [2432, 3957],\n [2433, 3959],\n [2426, 3972],\n [2416, 3973],\n [2416, 3978],\n [2408, 3975],\n [2408, 3980],\n [2405, 3984],\n [2407, 3986],\n [2402, 3989],\n [2402, 3995],\n [2401, 3997],\n [2407, 4002],\n [2411, 4013],\n [2415, 4025],\n [2418, 4047],\n [2414, 4053],\n [2415, 4069],\n [2413, 4071],\n [2412, 4075],\n [2413, 4081],\n [2417, 4079],\n [2418, 4085],\n [2412, 4090],\n [2412, 4096],\n [2407, 4094],\n [2399, 4096],\n [2392, 4094],\n [2389, 4096],\n [2389, 4103],\n [2396, 4111],\n [2391, 4117],\n [2391, 4125],\n [2388, 4128],\n [2388, 4136],\n [2387, 4140],\n [2384, 4140],\n [2382, 4133],\n [2370, 4132],\n [2363, 4139],\n [2344, 4137],\n [2341, 4140],\n [2334, 4142],\n [2334, 4147],\n [2329, 4148],\n [2325, 4146],\n [2324, 4148],\n [2318, 4144],\n [2310, 4144],\n [2310, 4156],\n [2306, 4160],\n [2298, 4162],\n [2293, 4160],\n [2292, 4157],\n [2281, 4157],\n [2274, 4161],\n [2265, 4162],\n [2259, 4157],\n [2255, 4159],\n [2251, 4165],\n [2240, 4168],\n [2235, 4173],\n [2234, 4176],\n [2427, 4176]]],\n [[[2203, 4176],\n [2202, 4172],\n [2196, 4170],\n [2189, 4174],\n [2190, 4176],\n [2203, 4176]]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '031',\n 'FIPS': '34031',\n 'STATE': 'NJ',\n 'NAME': 'Passaic',\n 'LSAD': 'County'},\n 'id': 2230,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2981, 4176],\n [2977, 4145],\n [2976, 4129],\n [2960, 4130],\n [2885, 4176],\n [2981, 4176]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '087',\n 'FIPS': '36087',\n 'STATE': 'NY',\n 'NAME': 'Rockland',\n 'LSAD': 'County'},\n 'id': 2226,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[3469, 4176],\n [3460, 4167],\n [3451, 4156],\n [3448, 4138],\n [3428, 4137],\n [3426, 4155],\n [3410, 4166],\n [3398, 4164],\n [3341, 4139],\n [3330, 4126],\n [3321, 4106],\n [3317, 4111],\n [3319, 4122],\n [3318, 4134],\n [3325, 4157],\n [3312, 4176],\n [3469, 4176]]],\n [[[3519, 4176],\n [3517, 4172],\n [3508, 4166],\n [3505, 4176],\n [3519, 4176]]]]},\n 'properties': {'STATE_FIPS': '09',\n 'COUNTY_FIP': '001',\n 'FIPS': '09001',\n 'STATE': 'CT',\n 'NAME': 'Fairfield',\n 'LSAD': 'County'},\n 'id': 1713,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[3156, 3920],\n [3161, 3917],\n [3162, 3906],\n [3161, 3904],\n [3155, 3902],\n [3149, 3908],\n [3149, 3912],\n [3153, 3912],\n [3153, 3918],\n [3156, 3920]]],\n [[[3312, 4176],\n [3325, 4157],\n [3318, 4134],\n [3319, 4122],\n [3317, 4111],\n [3321, 4106],\n [3323, 4096],\n [3317, 4074],\n [3314, 4070],\n [3310, 4072],\n [3291, 4063],\n [3283, 4036],\n [3278, 4029],\n [3262, 4018],\n [3227, 4004],\n [3212, 3990],\n [3176, 3966],\n [3140, 3914],\n [3137, 3905],\n [3079, 3925],\n [3078, 3922],\n [3057, 3931],\n [3053, 3950],\n [3048, 3950],\n [3048, 3952],\n [3042, 3955],\n [3036, 3956],\n [3039, 3961],\n [3036, 3961],\n [3033, 3958],\n [3034, 3955],\n [3031, 3954],\n [3026, 3943],\n [2941, 3976],\n [2972, 4096],\n [2981, 4176],\n [3312, 4176]]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '119',\n 'FIPS': '36119',\n 'STATE': 'NY',\n 'NAME': 'Westchester',\n 'LSAD': 'County'},\n 'id': 2232,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[-80, 3958],\n [0, 3867],\n [75, 3781],\n [219, 3660],\n [262, 3625],\n [250, 3617],\n [232, 3613],\n [230, 3605],\n [205, 3590],\n [189, 3572],\n [135, 3544],\n [120, 3544],\n [67, 3514],\n [0, 3481],\n [-80, 3442],\n [-80, 3958]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '107',\n 'FIPS': '42107',\n 'STATE': 'PA',\n 'NAME': 'Schuylkill',\n 'LSAD': 'County'},\n 'id': 2216,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[-80, 2134],\n [-80, 2627],\n [0, 2560],\n [93, 2480],\n [69, 2466],\n [0, 2431],\n [-8, 2427],\n [0, 2380],\n [2, 2369],\n [2, 2342],\n [5, 2310],\n [3, 2293],\n [0, 2287],\n [-72, 2157],\n [-71, 2150],\n [-77, 2142],\n [-80, 2134]]],\n [[[-80, 2117],\n [-77, 2115],\n [-74, 2105],\n [-65, 2097],\n [-63, 2093],\n [-64, 2086],\n [-69, 2090],\n [-73, 2086],\n [-79, 2085],\n [-78, 2081],\n [-80, 2080],\n [-80, 2117]]],\n [[[-80, 1996],\n [-74, 1988],\n [-72, 1979],\n [-77, 1974],\n [-79, 1970],\n [-80, 1971],\n [-80, 1996]]],\n [[[-80, 2026],\n [-73, 2020],\n [-72, 2015],\n [-76, 2012],\n [-78, 2006],\n [-79, 2001],\n [-77, 2000],\n [-80, 1996],\n [-80, 2026]]],\n [[[-80, 2123], [-78, 2120], [-80, 2117], [-80, 2123]]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '071',\n 'FIPS': '42071',\n 'STATE': 'PA',\n 'NAME': 'Lancaster',\n 'LSAD': 'County'},\n 'id': 2185,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[223, 1051],\n [235, 1047],\n [235, 1044],\n [240, 1045],\n [249, 1041],\n [264, 794],\n [262, 796],\n [255, 795],\n [247, 797],\n [241, 794],\n [236, 796],\n [233, 793],\n [232, 795],\n [223, 792],\n [222, 791],\n [210, 788],\n [209, 790],\n [205, 785],\n [197, 787],\n [195, 790],\n [191, 786],\n [185, 792],\n [171, 794],\n [163, 799],\n [162, 802],\n [157, 803],\n [148, 808],\n [143, 809],\n [142, 816],\n [136, 816],\n [122, 820],\n [120, 824],\n [113, 821],\n [106, 823],\n [92, 809],\n [92, 801],\n [86, 802],\n [84, 804],\n [75, 800],\n [71, 807],\n [67, 809],\n [63, 806],\n [63, 797],\n [29, 789],\n [18, 790],\n [0, 782],\n [-5, 780],\n [-10, 781],\n [-16, 787],\n [-21, 788],\n [-27, 784],\n [-30, 784],\n [-37, 786],\n [-43, 793],\n [-48, 795],\n [-58, 792],\n [-70, 794],\n [-71, 783],\n [-75, 781],\n [-80, 780],\n [-80, 1037],\n [-75, 1034],\n [-64, 1021],\n [-60, 1021],\n [-56, 1022],\n [-48, 1033],\n [-39, 1036],\n [-21, 1034],\n [-17, 1032],\n [-11, 1025],\n [-5, 1023],\n [0, 1025],\n [8, 1030],\n [14, 1030],\n [21, 1022],\n [49, 1017],\n [63, 1019],\n [71, 1012],\n [76, 1010],\n [81, 1017],\n [102, 1023],\n [107, 1021],\n [111, 1023],\n [120, 1017],\n [130, 1024],\n [134, 1023],\n [139, 1029],\n [155, 1035],\n [166, 1049],\n [173, 1050],\n [176, 1047],\n [186, 1046],\n [191, 1038],\n [193, 1037],\n [198, 1042],\n [206, 1041],\n [209, 1046],\n [213, 1046],\n [216, 1048],\n [222, 1046],\n [223, 1051]]]},\n 'properties': {'STATE_FIPS': '24',\n 'COUNTY_FIP': '029',\n 'FIPS': '24029',\n 'STATE': 'MD',\n 'NAME': 'Kent',\n 'LSAD': 'County'},\n 'id': 2126,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[120, 824],\n [122, 820],\n [136, 816],\n [142, 816],\n [143, 809],\n [148, 808],\n [157, 803],\n [162, 802],\n [163, 799],\n [171, 794],\n [185, 792],\n [191, 786],\n [195, 790],\n [197, 787],\n [205, 785],\n [209, 790],\n [210, 788],\n [222, 791],\n [223, 792],\n [232, 795],\n [233, 793],\n [236, 796],\n [241, 794],\n [247, 797],\n [255, 795],\n [262, 796],\n [264, 794],\n [276, 601],\n [262, 592],\n [236, 584],\n [213, 581],\n [209, 575],\n [202, 573],\n [197, 566],\n [186, 558],\n [167, 548],\n [153, 536],\n [149, 535],\n [143, 520],\n [137, 502],\n [133, 500],\n [130, 495],\n [132, 473],\n [129, 466],\n [116, 452],\n [112, 447],\n [108, 443],\n [99, 440],\n [96, 432],\n [89, 422],\n [86, 421],\n [86, 418],\n [88, 417],\n [89, 414],\n [87, 405],\n [84, 404],\n [82, 396],\n [79, 393],\n [79, 389],\n [78, 387],\n [80, 384],\n [73, 382],\n [71, 377],\n [68, 374],\n [68, 366],\n [57, 359],\n [49, 364],\n [47, 361],\n [49, 354],\n [49, 352],\n [42, 352],\n [42, 348],\n [39, 340],\n [35, 339],\n [33, 335],\n [26, 332],\n [23, 322],\n [11, 315],\n [13, 311],\n [7, 307],\n [4, 299],\n [4, 295],\n [0, 292],\n [-5, 289],\n [-3, 285],\n [0, 284],\n [1, 283],\n [0, 278],\n [-8, 270],\n [-1, 257],\n [-2, 253],\n [-4, 254],\n [-7, 250],\n [-7, 238],\n [-10, 234],\n [-20, 231],\n [-19, 222],\n [-14, 222],\n [-14, 220],\n [-23, 217],\n [-21, 214],\n [-17, 213],\n [-15, 210],\n [-16, 204],\n [-17, 202],\n [-22, 201],\n [-22, 200],\n [-18, 190],\n [-17, 179],\n [-45, 186],\n [-50, 186],\n [-59, 190],\n [-80, 194],\n [-80, 780],\n [-75, 781],\n [-71, 783],\n [-70, 794],\n [-58, 792],\n [-48, 795],\n [-43, 793],\n [-37, 786],\n [-30, 784],\n [-27, 784],\n [-21, 788],\n [-16, 787],\n [-10, 781],\n [-5, 780],\n [0, 782],\n [18, 790],\n [29, 789],\n [63, 797],\n [63, 806],\n [67, 809],\n [71, 807],\n [75, 800],\n [84, 804],\n [86, 802],\n [92, 801],\n [92, 809],\n [106, 823],\n [113, 821],\n [120, 824]]]},\n 'properties': {'STATE_FIPS': '24',\n 'COUNTY_FIP': '035',\n 'FIPS': '24035',\n 'STATE': 'MD',\n 'NAME': \"Queen Anne's\",\n 'LSAD': 'County'},\n 'id': 2137,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[-80, 194],\n [-59, 190],\n [-50, 186],\n [-45, 186],\n [-17, 179],\n [-10, 176],\n [-9, 172],\n [-16, 172],\n [-16, 167],\n [-8, 158],\n [-9, 156],\n [-15, 153],\n [-16, 149],\n [-11, 145],\n [-10, 140],\n [-12, 133],\n [-16, 130],\n [-16, 129],\n [-10, 126],\n [-4, 117],\n [-6, 115],\n [-18, 116],\n [-20, 115],\n [-20, 108],\n [-16, 104],\n [-3, 110],\n [0, 107],\n [0, 104],\n [-2, 101],\n [-9, 101],\n [-10, 98],\n [-6, 85],\n [-3, 82],\n [0, 83],\n [4, 84],\n [11, 72],\n [19, 71],\n [22, 65],\n [22, 62],\n [10, 53],\n [16, 46],\n [26, 45],\n [27, 44],\n [26, 42],\n [14, 35],\n [14, 30],\n [26, 24],\n [33, 23],\n [36, 13],\n [53, 4],\n [51, 0],\n [47, -2],\n [45, -5],\n [50, -11],\n [59, -14],\n [60, -19],\n [55, -20],\n [49, -29],\n [38, -30],\n [14, -44],\n [7, -49],\n [0, -66],\n [-15, -80],\n [-80, -80],\n [-80, 194]]]},\n 'properties': {'STATE_FIPS': '24',\n 'COUNTY_FIP': '041',\n 'FIPS': '24041',\n 'STATE': 'MD',\n 'NAME': 'Talbot',\n 'LSAD': 'County'},\n 'id': 2156,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[478, 3725],\n [484, 3712],\n [485, 3703],\n [482, 3694],\n [487, 3684],\n [486, 3666],\n [489, 3653],\n [496, 3641],\n [502, 3627],\n [509, 3622],\n [528, 3625],\n [533, 3621],\n [538, 3607],\n [543, 3602],\n [552, 3597],\n [558, 3598],\n [571, 3604],\n [576, 3611],\n [578, 3626],\n [583, 3630],\n [593, 3627],\n [598, 3623],\n [599, 3618],\n [600, 3595],\n [605, 3582],\n [622, 3548],\n [633, 3537],\n [640, 3517],\n [643, 3515],\n [653, 3511],\n [659, 3502],\n [661, 3494],\n [661, 3481],\n [664, 3472],\n [739, 3508],\n [739, 3497],\n [783, 3442],\n [795, 3430],\n [801, 3429],\n [800, 3418],\n [807, 3411],\n [806, 3404],\n [808, 3398],\n [811, 3398],\n [813, 3394],\n [799, 3393],\n [795, 3359],\n [777, 3330],\n [777, 3328],\n [880, 3245],\n [769, 3151],\n [660, 3017],\n [165, 3428],\n [67, 3514],\n [120, 3544],\n [135, 3544],\n [189, 3572],\n [205, 3590],\n [230, 3605],\n [232, 3613],\n [250, 3617],\n [262, 3625],\n [281, 3635],\n [282, 3641],\n [289, 3642],\n [299, 3656],\n [304, 3661],\n [342, 3677],\n [354, 3692],\n [380, 3701],\n [478, 3725]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '077',\n 'FIPS': '42077',\n 'STATE': 'PA',\n 'NAME': 'Lehigh',\n 'LSAD': 'County'},\n 'id': 2212,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[67, 3514],\n [165, 3428],\n [594, 3072],\n [351, 2680],\n [283, 2632],\n [93, 2480],\n [0, 2560],\n [-25, 2581],\n [-80, 2627],\n [-80, 3442],\n [0, 3481],\n [67, 3514]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '011',\n 'FIPS': '42011',\n 'STATE': 'PA',\n 'NAME': 'Berks',\n 'LSAD': 'County'},\n 'id': 2193,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[594, 3072],\n [660, 3017],\n [745, 2952],\n [937, 2799],\n [1053, 2710],\n [1176, 2612],\n [1343, 2482],\n [1335, 2471],\n [1280, 2421],\n [1252, 2383],\n [1245, 2377],\n [1239, 2369],\n [1224, 2351],\n [1238, 2340],\n [1228, 2327],\n [1210, 2313],\n [1206, 2307],\n [1108, 2381],\n [1091, 2358],\n [1040, 2396],\n [980, 2322],\n [987, 2313],\n [1002, 2299],\n [1007, 2292],\n [1018, 2281],\n [1027, 2273],\n [1048, 2259],\n [1056, 2249],\n [1065, 2242],\n [1063, 2239],\n [963, 2176],\n [952, 2195],\n [912, 2257],\n [898, 2250],\n [846, 2340],\n [841, 2345],\n [839, 2344],\n [831, 2357],\n [794, 2335],\n [754, 2404],\n [728, 2390],\n [723, 2399],\n [701, 2386],\n [700, 2400],\n [691, 2405],\n [693, 2416],\n [690, 2416],\n [682, 2423],\n [679, 2432],\n [682, 2441],\n [692, 2447],\n [694, 2452],\n [693, 2457],\n [677, 2466],\n [665, 2461],\n [648, 2460],\n [629, 2472],\n [624, 2479],\n [621, 2488],\n [625, 2498],\n [635, 2512],\n [636, 2519],\n [633, 2522],\n [624, 2524],\n [620, 2522],\n [614, 2514],\n [610, 2502],\n [607, 2500],\n [602, 2501],\n [598, 2504],\n [597, 2511],\n [598, 2521],\n [595, 2538],\n [591, 2544],\n [580, 2553],\n [576, 2558],\n [566, 2580],\n [555, 2613],\n [549, 2619],\n [544, 2618],\n [543, 2612],\n [546, 2604],\n [546, 2596],\n [539, 2589],\n [535, 2589],\n [530, 2591],\n [522, 2602],\n [519, 2612],\n [510, 2627],\n [496, 2670],\n [491, 2673],\n [487, 2673],\n [483, 2671],\n [481, 2669],\n [481, 2664],\n [487, 2654],\n [487, 2652],\n [483, 2648],\n [474, 2644],\n [468, 2648],\n [463, 2658],\n [428, 2674],\n [419, 2680],\n [411, 2679],\n [406, 2680],\n [398, 2686],\n [388, 2685],\n [381, 2681],\n [367, 2670],\n [360, 2670],\n [351, 2680],\n [594, 3072]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '091',\n 'FIPS': '42091',\n 'STATE': 'PA',\n 'NAME': 'Montgomery',\n 'LSAD': 'County'},\n 'id': 2198,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[398, 2686],\n [406, 2680],\n [411, 2679],\n [419, 2680],\n [428, 2674],\n [463, 2658],\n [468, 2648],\n [474, 2644],\n [483, 2648],\n [487, 2652],\n [487, 2654],\n [481, 2664],\n [481, 2669],\n [483, 2671],\n [487, 2673],\n [491, 2673],\n [496, 2670],\n [510, 2627],\n [519, 2612],\n [521, 2604],\n [525, 2597],\n [535, 2589],\n [539, 2589],\n [546, 2596],\n [546, 2604],\n [543, 2612],\n [544, 2618],\n [549, 2619],\n [555, 2613],\n [566, 2580],\n [576, 2558],\n [580, 2553],\n [591, 2544],\n [595, 2538],\n [598, 2521],\n [597, 2511],\n [598, 2504],\n [602, 2501],\n [607, 2500],\n [610, 2502],\n [614, 2514],\n [620, 2522],\n [624, 2524],\n [633, 2522],\n [636, 2519],\n [635, 2512],\n [625, 2498],\n [621, 2488],\n [624, 2479],\n [629, 2472],\n [648, 2460],\n [665, 2461],\n [677, 2466],\n [693, 2457],\n [694, 2452],\n [692, 2447],\n [682, 2441],\n [679, 2432],\n [682, 2423],\n [690, 2416],\n [693, 2416],\n [691, 2405],\n [700, 2400],\n [701, 2386],\n [723, 2399],\n [728, 2390],\n [754, 2404],\n [794, 2335],\n [831, 2357],\n [839, 2344],\n [761, 2299],\n [776, 2272],\n [705, 2207],\n [720, 2208],\n [724, 2206],\n [728, 2208],\n [727, 2204],\n [731, 2198],\n [730, 2191],\n [602, 2113],\n [609, 2103],\n [610, 2095],\n [601, 2090],\n [599, 2096],\n [593, 2093],\n [594, 2091],\n [593, 2090],\n [603, 2073],\n [600, 2071],\n [598, 2074],\n [593, 2072],\n [585, 2086],\n [575, 2081],\n [577, 2077],\n [573, 2074],\n [573, 2068],\n [575, 2064],\n [564, 2058],\n [570, 2048],\n [555, 2040],\n [552, 2046],\n [548, 2044],\n [551, 2035],\n [530, 2023],\n [532, 2017],\n [529, 2015],\n [534, 2007],\n [520, 1999],\n [517, 2002],\n [510, 2000],\n [514, 1993],\n [495, 1981],\n [501, 1972],\n [502, 1967],\n [498, 1966],\n [496, 1962],\n [497, 1959],\n [489, 1947],\n [490, 1945],\n [493, 1943],\n [503, 1939],\n [503, 1937],\n [500, 1935],\n [499, 1925],\n [495, 1918],\n [495, 1915],\n [499, 1911],\n [466, 1904],\n [431, 1894],\n [400, 1880],\n [366, 1861],\n [344, 1845],\n [306, 1810],\n [281, 1779],\n [258, 1740],\n [239, 1693],\n [217, 1692],\n [0, 1691],\n [-80, 1691],\n [-80, 1971],\n [-79, 1970],\n [-77, 1974],\n [-72, 1979],\n [-72, 1982],\n [-74, 1988],\n [-80, 1996],\n [-77, 2000],\n [-79, 2001],\n [-78, 2006],\n [-76, 2012],\n [-72, 2015],\n [-73, 2020],\n [-80, 2026],\n [-80, 2080],\n [-78, 2081],\n [-79, 2085],\n [-73, 2086],\n [-69, 2090],\n [-64, 2086],\n [-63, 2093],\n [-65, 2097],\n [-74, 2105],\n [-77, 2115],\n [-80, 2117],\n [-78, 2120],\n [-80, 2123],\n [-80, 2134],\n [-77, 2142],\n [-71, 2150],\n [-72, 2157],\n [0, 2287],\n [3, 2293],\n [5, 2310],\n [2, 2342],\n [2, 2369],\n [0, 2380],\n [-8, 2427],\n [0, 2431],\n [69, 2466],\n [93, 2480],\n [283, 2632],\n [351, 2680],\n [360, 2670],\n [367, 2670],\n [381, 2681],\n [388, 2685],\n [398, 2686]]],\n [[[512, 1924],\n [518, 1918],\n [521, 1913],\n [502, 1911],\n [506, 1921],\n [512, 1924]]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '029',\n 'FIPS': '42029',\n 'STATE': 'PA',\n 'NAME': 'Chester',\n 'LSAD': 'County'},\n 'id': 2187,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[841, 2345],\n [846, 2340],\n [898, 2250],\n [912, 2257],\n [952, 2195],\n [963, 2176],\n [957, 2172],\n [959, 2167],\n [964, 2161],\n [972, 2160],\n [979, 2153],\n [986, 2155],\n [991, 2151],\n [995, 2154],\n [1004, 2151],\n [1004, 2146],\n [1000, 2142],\n [1003, 2138],\n [1002, 2135],\n [999, 2128],\n [1001, 2118],\n [1006, 2112],\n [1016, 2109],\n [1016, 2102],\n [1020, 2102],\n [1023, 2101],\n [1020, 2092],\n [1013, 2093],\n [1009, 2087],\n [1011, 2086],\n [1011, 2082],\n [1005, 2071],\n [1006, 2056],\n [999, 2049],\n [1001, 2045],\n [996, 2040],\n [999, 2038],\n [993, 2029],\n [994, 2027],\n [990, 2021],\n [992, 2020],\n [988, 2015],\n [984, 2014],\n [983, 2008],\n [980, 2007],\n [983, 2002],\n [980, 2001],\n [983, 1996],\n [980, 1996],\n [983, 1985],\n [1004, 1985],\n [1015, 1977],\n [1023, 1986],\n [1045, 1983],\n [1051, 1984],\n [1051, 1975],\n [1058, 1964],\n [1043, 1956],\n [1023, 1947],\n [970, 1934],\n [938, 1932],\n [914, 1935],\n [895, 1934],\n [884, 1933],\n [868, 1927],\n [849, 1916],\n [797, 1869],\n [761, 1843],\n [742, 1857],\n [705, 1878],\n [664, 1895],\n [639, 1903],\n [610, 1909],\n [580, 1912],\n [535, 1914],\n [521, 1913],\n [518, 1918],\n [512, 1924],\n [508, 1922],\n [502, 1911],\n [499, 1911],\n [495, 1915],\n [495, 1918],\n [499, 1925],\n [500, 1935],\n [503, 1937],\n [503, 1939],\n [493, 1943],\n [490, 1945],\n [489, 1947],\n [497, 1959],\n [496, 1962],\n [498, 1966],\n [502, 1967],\n [501, 1972],\n [495, 1981],\n [514, 1993],\n [510, 2000],\n [517, 2002],\n [520, 1999],\n [534, 2007],\n [529, 2015],\n [532, 2017],\n [530, 2023],\n [551, 2035],\n [548, 2044],\n [552, 2046],\n [555, 2040],\n [570, 2048],\n [564, 2058],\n [575, 2064],\n [573, 2068],\n [573, 2074],\n [577, 2077],\n [575, 2081],\n [585, 2086],\n [593, 2072],\n [598, 2074],\n [600, 2071],\n [603, 2073],\n [593, 2090],\n [594, 2091],\n [593, 2093],\n [599, 2096],\n [601, 2090],\n [610, 2095],\n [609, 2103],\n [602, 2113],\n [730, 2191],\n [731, 2198],\n [727, 2204],\n [728, 2208],\n [724, 2206],\n [720, 2208],\n [705, 2207],\n [776, 2272],\n [761, 2299],\n [841, 2345]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '045',\n 'FIPS': '42045',\n 'STATE': 'PA',\n 'NAME': 'Delaware',\n 'LSAD': 'County'},\n 'id': 2186,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1190, 4074],\n [1191, 4070],\n [1190, 4065],\n [1194, 4044],\n [1203, 4035],\n [1211, 4018],\n [1212, 4012],\n [1226, 3989],\n [1250, 3969],\n [1255, 3956],\n [1256, 3931],\n [1270, 3914],\n [1280, 3899],\n [1287, 3891],\n [1290, 3885],\n [1291, 3876],\n [1288, 3865],\n [1272, 3842],\n [1269, 3841],\n [1262, 3841],\n [1254, 3845],\n [1233, 3844],\n [1226, 3840],\n [1223, 3832],\n [1224, 3825],\n [1241, 3807],\n [1243, 3803],\n [1243, 3797],\n [1234, 3780],\n [1225, 3773],\n [1219, 3764],\n [1219, 3749],\n [1207, 3732],\n [1203, 3730],\n [1195, 3729],\n [1186, 3724],\n [1174, 3703],\n [1170, 3699],\n [1148, 3701],\n [1127, 3708],\n [1118, 3708],\n [1115, 3707],\n [1110, 3697],\n [1107, 3681],\n [1105, 3676],\n [1099, 3671],\n [1086, 3664],\n [1079, 3656],\n [1081, 3645],\n [1095, 3629],\n [1100, 3618],\n [1089, 3592],\n [1082, 3584],\n [1068, 3541],\n [1073, 3529],\n [1079, 3521],\n [1088, 3518],\n [1097, 3519],\n [1102, 3518],\n [1107, 3514],\n [1108, 3511],\n [1107, 3505],\n [1099, 3492],\n [1087, 3484],\n [1073, 3460],\n [1073, 3455],\n [1085, 3444],\n [1091, 3412],\n [1088, 3404],\n [1077, 3402],\n [1071, 3398],\n [1072, 3393],\n [1079, 3382],\n [992, 3332],\n [977, 3322],\n [938, 3292],\n [880, 3244],\n [777, 3328],\n [777, 3330],\n [795, 3359],\n [799, 3393],\n [813, 3394],\n [811, 3398],\n [808, 3398],\n [806, 3404],\n [807, 3411],\n [800, 3418],\n [801, 3429],\n [795, 3430],\n [783, 3442],\n [739, 3497],\n [739, 3508],\n [664, 3472],\n [661, 3481],\n [661, 3494],\n [659, 3502],\n [653, 3511],\n [643, 3515],\n [640, 3517],\n [633, 3537],\n [622, 3548],\n [605, 3582],\n [600, 3595],\n [599, 3618],\n [598, 3623],\n [593, 3627],\n [583, 3630],\n [578, 3626],\n [576, 3611],\n [571, 3604],\n [558, 3598],\n [552, 3597],\n [543, 3602],\n [538, 3607],\n [533, 3621],\n [528, 3625],\n [509, 3622],\n [502, 3627],\n [496, 3641],\n [489, 3653],\n [486, 3666],\n [487, 3684],\n [482, 3694],\n [485, 3703],\n [484, 3712],\n [478, 3725],\n [488, 3726],\n [494, 3730],\n [498, 3737],\n [524, 3748],\n [553, 3752],\n [562, 3758],\n [577, 3763],\n [596, 3762],\n [609, 3766],\n [625, 3767],\n [668, 3775],\n [675, 3778],\n [721, 3785],\n [753, 3795],\n [758, 3800],\n [807, 3809],\n [868, 3837],\n [898, 3857],\n [928, 3864],\n [952, 3877],\n [967, 3890],\n [976, 3908],\n [1027, 3941],\n [1014, 3960],\n [1042, 3980],\n [1048, 3996],\n [1081, 4012],\n [1092, 4014],\n [1106, 4020],\n [1108, 4030],\n [1119, 4035],\n [1143, 4037],\n [1154, 4041],\n [1177, 4056],\n [1190, 4074]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '095',\n 'FIPS': '42095',\n 'STATE': 'PA',\n 'NAME': 'Northampton',\n 'LSAD': 'County'},\n 'id': 2208,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1978, 4176],\n [1938, 4131],\n [1910, 4096],\n [1889, 4068],\n [1888, 4056],\n [1897, 4040],\n [1897, 4029],\n [1889, 4014],\n [1873, 4001],\n [1871, 3998],\n [1870, 3992],\n [1872, 3987],\n [1871, 3984],\n [1855, 3977],\n [1846, 3969],\n [1832, 3960],\n [1827, 3961],\n [1820, 3959],\n [1818, 3952],\n [1814, 3951],\n [1808, 3954],\n [1796, 3946],\n [1792, 3945],\n [1786, 3940],\n [1782, 3942],\n [1785, 3951],\n [1783, 3958],\n [1769, 3970],\n [1761, 3974],\n [1756, 3982],\n [1749, 3979],\n [1734, 3980],\n [1727, 3976],\n [1727, 3972],\n [1722, 3968],\n [1715, 3968],\n [1713, 3965],\n [1711, 3968],\n [1708, 3965],\n [1706, 3966],\n [1703, 3965],\n [1594, 4096],\n [1570, 4125],\n [1529, 4176],\n [1978, 4176]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '037',\n 'FIPS': '34037',\n 'STATE': 'NJ',\n 'NAME': 'Sussex',\n 'LSAD': 'County'},\n 'id': 2225,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1526, 3726],\n [1592, 3670],\n [1594, 3665],\n [1617, 3642],\n [1622, 3639],\n [1633, 3639],\n [1638, 3638],\n [1638, 3636],\n [1644, 3636],\n [1659, 3638],\n [1666, 3634],\n [1704, 3625],\n [1725, 3617],\n [1740, 3607],\n [1740, 3603],\n [1755, 3595],\n [1767, 3595],\n [1768, 3590],\n [1773, 3586],\n [1772, 3582],\n [1774, 3569],\n [1777, 3567],\n [1778, 3565],\n [1776, 3564],\n [1779, 3558],\n [1778, 3555],\n [1772, 3550],\n [1771, 3541],\n [1768, 3533],\n [1776, 3526],\n [1775, 3519],\n [1771, 3515],\n [1769, 3500],\n [1764, 3494],\n [1757, 3491],\n [1762, 3478],\n [1769, 3474],\n [1774, 3465],\n [1768, 3455],\n [1767, 3450],\n [1770, 3446],\n [1769, 3440],\n [1762, 3434],\n [1765, 3426],\n [1774, 3425],\n [1778, 3426],\n [1783, 3424],\n [1786, 3418],\n [1786, 3413],\n [1797, 3406],\n [1786, 3387],\n [1783, 3389],\n [1771, 3366],\n [1775, 3364],\n [1766, 3344],\n [1783, 3335],\n [1766, 3300],\n [1758, 3295],\n [1751, 3286],\n [1740, 3277],\n [1693, 3182],\n [1690, 3180],\n [1685, 3182],\n [1678, 3190],\n [1678, 3193],\n [1674, 3197],\n [1660, 3203],\n [1732, 3028],\n [1644, 3014],\n [1654, 2953],\n [1555, 2940],\n [1575, 2880],\n [1464, 2866],\n [1448, 2871],\n [1447, 2872],\n [1444, 2901],\n [1440, 2915],\n [1433, 2936],\n [1416, 2977],\n [1410, 2982],\n [1390, 2991],\n [1381, 2999],\n [1371, 3002],\n [1360, 2997],\n [1340, 2991],\n [1329, 2989],\n [1324, 2990],\n [1312, 2995],\n [1298, 3009],\n [1284, 3013],\n [1280, 3017],\n [1276, 3026],\n [1274, 3046],\n [1267, 3075],\n [1263, 3088],\n [1267, 3106],\n [1267, 3122],\n [1272, 3129],\n [1275, 3138],\n [1275, 3147],\n [1269, 3194],\n [1271, 3224],\n [1269, 3244],\n [1265, 3254],\n [1251, 3266],\n [1219, 3304],\n [1195, 3314],\n [1166, 3319],\n [1159, 3318],\n [1151, 3314],\n [1135, 3299],\n [1128, 3296],\n [1120, 3296],\n [1110, 3298],\n [1099, 3303],\n [1093, 3307],\n [1083, 3320],\n [1081, 3326],\n [1082, 3331],\n [1087, 3340],\n [1088, 3349],\n [1096, 3351],\n [1102, 3355],\n [1104, 3361],\n [1111, 3363],\n [1114, 3375],\n [1120, 3378],\n [1124, 3385],\n [1128, 3387],\n [1130, 3393],\n [1129, 3399],\n [1141, 3407],\n [1147, 3405],\n [1150, 3408],\n [1150, 3416],\n [1153, 3420],\n [1168, 3424],\n [1180, 3431],\n [1205, 3440],\n [1208, 3442],\n [1207, 3447],\n [1211, 3451],\n [1226, 3458],\n [1235, 3468],\n [1236, 3472],\n [1247, 3476],\n [1254, 3488],\n [1264, 3494],\n [1267, 3497],\n [1275, 3499],\n [1278, 3505],\n [1282, 3510],\n [1288, 3512],\n [1295, 3518],\n [1301, 3516],\n [1303, 3517],\n [1308, 3524],\n [1310, 3526],\n [1315, 3526],\n [1333, 3542],\n [1337, 3542],\n [1341, 3547],\n [1345, 3543],\n [1351, 3547],\n [1356, 3544],\n [1361, 3545],\n [1378, 3563],\n [1393, 3569],\n [1396, 3578],\n [1410, 3577],\n [1419, 3597],\n [1424, 3602],\n [1426, 3606],\n [1435, 3610],\n [1443, 3624],\n [1451, 3631],\n [1452, 3636],\n [1465, 3651],\n [1467, 3656],\n [1470, 3658],\n [1473, 3663],\n [1485, 3672],\n [1489, 3677],\n [1489, 3680],\n [1494, 3686],\n [1507, 3695],\n [1506, 3698],\n [1507, 3706],\n [1505, 3712],\n [1517, 3719],\n [1526, 3726]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '019',\n 'FIPS': '34019',\n 'STATE': 'NJ',\n 'NAME': 'Hunterdon',\n 'LSAD': 'County'},\n 'id': 2209,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2012, 3669],\n [2018, 3663],\n [2019, 3655],\n [2017, 3652],\n [2023, 3646],\n [2022, 3622],\n [2026, 3623],\n [2028, 3621],\n [2035, 3622],\n [2043, 3616],\n [2046, 3617],\n [2052, 3611],\n [2048, 3598],\n [2048, 3595],\n [2051, 3594],\n [2052, 3591],\n [2058, 3587],\n [2057, 3581],\n [2054, 3578],\n [2056, 3575],\n [2061, 3574],\n [2068, 3568],\n [2069, 3561],\n [2071, 3561],\n [2073, 3559],\n [2073, 3547],\n [2070, 3544],\n [2067, 3545],\n [2066, 3541],\n [2069, 3539],\n [2069, 3537],\n [2062, 3535],\n [2058, 3537],\n [2055, 3529],\n [2053, 3527],\n [2052, 3521],\n [2056, 3501],\n [2051, 3498],\n [2050, 3495],\n [2043, 3494],\n [2044, 3491],\n [2050, 3490],\n [2051, 3486],\n [2056, 3482],\n [2054, 3479],\n [2056, 3469],\n [2059, 3469],\n [2055, 3465],\n [2060, 3464],\n [2061, 3461],\n [2070, 3462],\n [2071, 3463],\n [2075, 3460],\n [2082, 3466],\n [2086, 3475],\n [2085, 3477],\n [2088, 3480],\n [2091, 3478],\n [2095, 3479],\n [2094, 3483],\n [2100, 3484],\n [2102, 3482],\n [2106, 3484],\n [2106, 3487],\n [2112, 3488],\n [2114, 3485],\n [2117, 3487],\n [2116, 3491],\n [2128, 3493],\n [2133, 3498],\n [2137, 3496],\n [2149, 3503],\n [2150, 3506],\n [2164, 3469],\n [2175, 3475],\n [2185, 3486],\n [2196, 3491],\n [2198, 3487],\n [2202, 3485],\n [2208, 3477],\n [2211, 3478],\n [2214, 3483],\n [2220, 3485],\n [2224, 3491],\n [2231, 3495],\n [2234, 3493],\n [2236, 3487],\n [2235, 3481],\n [2235, 3473],\n [2229, 3462],\n [2229, 3455],\n [2226, 3447],\n [2220, 3446],\n [2219, 3444],\n [2217, 3429],\n [2213, 3418],\n [2206, 3414],\n [2205, 3405],\n [2199, 3397],\n [2193, 3396],\n [2184, 3385],\n [2173, 3383],\n [2169, 3381],\n [2164, 3373],\n [2159, 3373],\n [2152, 3365],\n [2143, 3362],\n [2137, 3362],\n [2126, 3354],\n [2118, 3345],\n [2108, 3340],\n [2104, 3341],\n [2097, 3338],\n [2094, 3340],\n [2091, 3337],\n [2091, 3334],\n [2086, 3339],\n [2076, 3331],\n [2070, 3329],\n [2071, 3326],\n [2063, 3315],\n [2059, 3307],\n [2056, 3305],\n [2057, 3292],\n [2054, 3288],\n [2059, 3286],\n [2065, 3280],\n [2068, 3273],\n [2072, 3255],\n [2083, 3244],\n [2100, 3230],\n [2119, 3197],\n [2122, 3195],\n [2141, 3190],\n [2143, 3178],\n [2151, 3171],\n [2153, 3166],\n [2152, 3156],\n [2140, 3148],\n [2125, 3143],\n [2119, 3139],\n [2102, 3115],\n [2082, 3099],\n [2075, 3091],\n [2064, 3080],\n [2055, 3068],\n [2041, 3056],\n [2013, 3040],\n [1971, 3018],\n [1968, 3014],\n [1969, 2989],\n [1966, 2981],\n [1966, 2971],\n [1960, 2967],\n [1955, 2956],\n [1944, 2945],\n [1928, 2936],\n [1919, 2933],\n [1922, 2940],\n [1921, 2944],\n [1915, 2952],\n [1870, 2965],\n [1839, 2952],\n [1791, 2943],\n [1770, 2935],\n [1660, 3203],\n [1674, 3197],\n [1678, 3193],\n [1678, 3190],\n [1685, 3182],\n [1692, 3180],\n [1740, 3277],\n [1751, 3286],\n [1758, 3295],\n [1766, 3300],\n [1783, 3335],\n [1766, 3344],\n [1775, 3364],\n [1771, 3366],\n [1783, 3389],\n [1786, 3387],\n [1797, 3406],\n [1786, 3413],\n [1786, 3418],\n [1783, 3424],\n [1778, 3426],\n [1774, 3425],\n [1765, 3426],\n [1762, 3434],\n [1769, 3440],\n [1770, 3446],\n [1767, 3450],\n [1768, 3455],\n [1774, 3465],\n [1769, 3474],\n [1762, 3478],\n [1757, 3491],\n [1764, 3494],\n [1769, 3500],\n [1771, 3515],\n [1775, 3519],\n [1776, 3526],\n [1768, 3533],\n [1771, 3541],\n [1772, 3550],\n [1778, 3555],\n [1779, 3558],\n [1776, 3564],\n [1778, 3565],\n [1777, 3567],\n [1774, 3569],\n [1772, 3582],\n [1773, 3586],\n [1768, 3590],\n [1767, 3595],\n [1848, 3621],\n [2012, 3669]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '035',\n 'FIPS': '34035',\n 'STATE': 'NJ',\n 'NAME': 'Somerset',\n 'LSAD': 'County'},\n 'id': 2211,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1079, 3382],\n [1085, 3370],\n [1088, 3347],\n [1087, 3340],\n [1082, 3331],\n [1082, 3324],\n [1085, 3316],\n [1099, 3303],\n [1110, 3298],\n [1128, 3296],\n [1135, 3299],\n [1151, 3314],\n [1159, 3318],\n [1166, 3319],\n [1195, 3314],\n [1219, 3304],\n [1251, 3266],\n [1265, 3254],\n [1269, 3244],\n [1271, 3224],\n [1269, 3194],\n [1275, 3147],\n [1275, 3138],\n [1272, 3129],\n [1267, 3122],\n [1267, 3106],\n [1263, 3088],\n [1267, 3075],\n [1274, 3046],\n [1276, 3026],\n [1280, 3017],\n [1284, 3013],\n [1298, 3009],\n [1312, 2995],\n [1324, 2990],\n [1329, 2989],\n [1340, 2991],\n [1360, 2997],\n [1371, 3002],\n [1381, 2999],\n [1390, 2991],\n [1410, 2982],\n [1416, 2977],\n [1433, 2936],\n [1440, 2915],\n [1444, 2901],\n [1447, 2872],\n [1453, 2864],\n [1499, 2823],\n [1506, 2821],\n [1516, 2820],\n [1523, 2816],\n [1539, 2802],\n [1557, 2782],\n [1569, 2762],\n [1595, 2697],\n [1604, 2688],\n [1622, 2679],\n [1628, 2674],\n [1663, 2656],\n [1698, 2630],\n [1714, 2598],\n [1723, 2572],\n [1727, 2568],\n [1738, 2564],\n [1748, 2558],\n [1770, 2525],\n [1771, 2512],\n [1767, 2499],\n [1743, 2477],\n [1735, 2475],\n [1722, 2476],\n [1716, 2475],\n [1701, 2465],\n [1683, 2449],\n [1673, 2449],\n [1656, 2453],\n [1633, 2462],\n [1624, 2461],\n [1619, 2455],\n [1615, 2448],\n [1609, 2432],\n [1605, 2417],\n [1601, 2411],\n [1593, 2405],\n [1577, 2397],\n [1572, 2388],\n [1570, 2381],\n [1564, 2376],\n [1540, 2369],\n [1529, 2364],\n [1498, 2353],\n [1481, 2355],\n [1474, 2354],\n [1446, 2340],\n [1403, 2312],\n [1394, 2322],\n [1389, 2323],\n [1388, 2329],\n [1394, 2334],\n [1394, 2345],\n [1405, 2356],\n [1408, 2365],\n [1420, 2368],\n [1426, 2380],\n [1426, 2390],\n [1429, 2397],\n [1429, 2402],\n [1421, 2406],\n [1422, 2416],\n [1416, 2425],\n [1418, 2428],\n [1419, 2438],\n [1418, 2443],\n [1414, 2444],\n [1409, 2442],\n [1404, 2448],\n [1395, 2447],\n [1390, 2450],\n [1390, 2454],\n [1384, 2454],\n [1379, 2460],\n [1374, 2460],\n [1377, 2469],\n [1375, 2471],\n [1368, 2463],\n [1184, 2606],\n [1065, 2701],\n [937, 2799],\n [745, 2952],\n [660, 3017],\n [769, 3151],\n [872, 3239],\n [880, 3244],\n [938, 3292],\n [977, 3322],\n [992, 3332],\n [1079, 3382]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '017',\n 'FIPS': '42017',\n 'STATE': 'PA',\n 'NAME': 'Bucks',\n 'LSAD': 'County'},\n 'id': 2197,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1343, 2482],\n [1368, 2463],\n [1375, 2471],\n [1377, 2469],\n [1374, 2460],\n [1379, 2460],\n [1384, 2454],\n [1390, 2454],\n [1390, 2450],\n [1395, 2447],\n [1404, 2448],\n [1409, 2442],\n [1414, 2444],\n [1418, 2443],\n [1419, 2438],\n [1418, 2428],\n [1416, 2425],\n [1422, 2416],\n [1421, 2406],\n [1429, 2402],\n [1429, 2397],\n [1426, 2390],\n [1426, 2380],\n [1420, 2368],\n [1408, 2365],\n [1405, 2356],\n [1394, 2345],\n [1394, 2334],\n [1388, 2329],\n [1389, 2323],\n [1394, 2322],\n [1403, 2312],\n [1389, 2301],\n [1349, 2260],\n [1308, 2244],\n [1297, 2236],\n [1291, 2228],\n [1279, 2205],\n [1260, 2183],\n [1236, 2172],\n [1208, 2163],\n [1180, 2146],\n [1171, 2133],\n [1168, 2119],\n [1167, 2094],\n [1169, 2081],\n [1179, 2052],\n [1175, 2030],\n [1158, 2004],\n [1154, 2000],\n [1146, 1997],\n [1099, 1995],\n [1090, 1993],\n [1058, 1964],\n [1051, 1975],\n [1051, 1984],\n [1045, 1983],\n [1023, 1986],\n [1015, 1977],\n [1004, 1985],\n [983, 1985],\n [980, 1996],\n [983, 1996],\n [980, 2001],\n [983, 2002],\n [980, 2007],\n [983, 2008],\n [984, 2014],\n [988, 2015],\n [992, 2020],\n [990, 2021],\n [994, 2027],\n [993, 2029],\n [999, 2038],\n [996, 2040],\n [1001, 2045],\n [999, 2049],\n [1006, 2056],\n [1005, 2071],\n [1011, 2082],\n [1011, 2086],\n [1009, 2087],\n [1013, 2093],\n [1020, 2092],\n [1023, 2101],\n [1020, 2102],\n [1016, 2102],\n [1016, 2109],\n [1006, 2112],\n [1001, 2118],\n [999, 2128],\n [1002, 2135],\n [1003, 2138],\n [1000, 2142],\n [1004, 2146],\n [1004, 2151],\n [995, 2154],\n [991, 2151],\n [986, 2155],\n [979, 2153],\n [972, 2160],\n [964, 2161],\n [957, 2172],\n [982, 2187],\n [993, 2196],\n [1063, 2239],\n [1065, 2242],\n [1056, 2249],\n [1048, 2259],\n [1027, 2273],\n [1018, 2281],\n [1007, 2292],\n [1002, 2299],\n [987, 2313],\n [980, 2322],\n [1040, 2396],\n [1091, 2358],\n [1108, 2381],\n [1206, 2307],\n [1210, 2313],\n [1228, 2327],\n [1238, 2340],\n [1224, 2351],\n [1239, 2369],\n [1245, 2377],\n [1252, 2383],\n [1280, 2421],\n [1335, 2471],\n [1343, 2482]]]},\n 'properties': {'STATE_FIPS': '42',\n 'COUNTY_FIP': '101',\n 'FIPS': '42101',\n 'STATE': 'PA',\n 'NAME': 'Philadelphia',\n 'LSAD': 'County'},\n 'id': 2177,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1732, 3028],\n [1770, 2935],\n [1791, 2943],\n [1839, 2952],\n [1870, 2965],\n [1915, 2952],\n [1921, 2944],\n [1922, 2940],\n [1916, 2919],\n [1912, 2916],\n [1904, 2878],\n [1904, 2869],\n [1914, 2857],\n [1912, 2847],\n [1915, 2845],\n [1915, 2840],\n [1916, 2838],\n [1925, 2839],\n [1936, 2833],\n [1943, 2832],\n [1947, 2821],\n [1953, 2819],\n [1957, 2820],\n [1969, 2816],\n [1972, 2803],\n [1976, 2799],\n [1983, 2797],\n [1991, 2790],\n [1995, 2791],\n [1999, 2785],\n [2007, 2783],\n [2010, 2776],\n [2016, 2773],\n [2021, 2773],\n [2027, 2775],\n [2028, 2777],\n [2032, 2775],\n [2036, 2769],\n [2040, 2771],\n [2045, 2776],\n [2052, 2780],\n [2061, 2772],\n [2061, 2765],\n [2072, 2766],\n [2077, 2759],\n [2086, 2754],\n [2088, 2754],\n [2091, 2751],\n [2095, 2754],\n [2119, 2741],\n [2116, 2702],\n [2112, 2702],\n [2112, 2700],\n [2119, 2689],\n [2121, 2683],\n [2069, 2652],\n [2031, 2632],\n [2025, 2624],\n [2023, 2615],\n [2011, 2600],\n [2002, 2581],\n [1991, 2573],\n [1985, 2576],\n [1968, 2569],\n [1957, 2562],\n [1954, 2562],\n [1952, 2574],\n [1948, 2575],\n [1927, 2567],\n [1966, 2483],\n [1945, 2480],\n [1937, 2485],\n [1938, 2487],\n [1933, 2485],\n [1926, 2487],\n [1924, 2489],\n [1920, 2487],\n [1916, 2488],\n [1914, 2490],\n [1915, 2495],\n [1914, 2497],\n [1913, 2503],\n [1908, 2504],\n [1908, 2503],\n [1904, 2503],\n [1902, 2506],\n [1899, 2503],\n [1897, 2508],\n [1893, 2509],\n [1892, 2513],\n [1887, 2515],\n [1885, 2513],\n [1880, 2517],\n [1878, 2516],\n [1874, 2521],\n [1868, 2521],\n [1867, 2524],\n [1862, 2528],\n [1859, 2528],\n [1857, 2534],\n [1853, 2533],\n [1852, 2536],\n [1849, 2537],\n [1847, 2537],\n [1846, 2534],\n [1845, 2537],\n [1841, 2538],\n [1838, 2535],\n [1835, 2536],\n [1840, 2543],\n [1838, 2548],\n [1840, 2550],\n [1832, 2550],\n [1831, 2554],\n [1824, 2559],\n [1823, 2553],\n [1822, 2557],\n [1816, 2556],\n [1813, 2561],\n [1808, 2560],\n [1810, 2567],\n [1806, 2567],\n [1799, 2570],\n [1796, 2566],\n [1790, 2566],\n [1786, 2563],\n [1788, 2560],\n [1783, 2554],\n [1786, 2549],\n [1790, 2547],\n [1787, 2539],\n [1788, 2537],\n [1796, 2541],\n [1793, 2527],\n [1783, 2517],\n [1782, 2510],\n [1774, 2501],\n [1767, 2500],\n [1771, 2512],\n [1770, 2525],\n [1748, 2558],\n [1738, 2564],\n [1727, 2568],\n [1723, 2572],\n [1714, 2598],\n [1698, 2630],\n [1663, 2656],\n [1628, 2674],\n [1622, 2679],\n [1604, 2688],\n [1595, 2697],\n [1569, 2762],\n [1557, 2782],\n [1539, 2802],\n [1523, 2816],\n [1516, 2820],\n [1506, 2821],\n [1499, 2823],\n [1486, 2834],\n [1453, 2864],\n [1448, 2871],\n [1464, 2866],\n [1575, 2880],\n [1555, 2940],\n [1654, 2953],\n [1644, 3014],\n [1732, 3028]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '021',\n 'FIPS': '34021',\n 'STATE': 'NJ',\n 'NAME': 'Mercer',\n 'LSAD': 'County'},\n 'id': 2196,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1799, 2570],\n [1806, 2567],\n [1810, 2567],\n [1808, 2560],\n [1813, 2561],\n [1816, 2556],\n [1822, 2557],\n [1823, 2553],\n [1824, 2559],\n [1831, 2554],\n [1832, 2550],\n [1840, 2550],\n [1838, 2548],\n [1840, 2543],\n [1835, 2536],\n [1838, 2535],\n [1841, 2538],\n [1845, 2537],\n [1846, 2534],\n [1847, 2537],\n [1849, 2537],\n [1852, 2536],\n [1853, 2533],\n [1857, 2534],\n [1859, 2528],\n [1862, 2528],\n [1867, 2524],\n [1868, 2521],\n [1874, 2521],\n [1878, 2516],\n [1880, 2517],\n [1885, 2513],\n [1887, 2515],\n [1892, 2513],\n [1893, 2509],\n [1897, 2508],\n [1899, 2503],\n [1902, 2506],\n [1904, 2503],\n [1908, 2503],\n [1908, 2504],\n [1913, 2503],\n [1914, 2497],\n [1915, 2495],\n [1914, 2490],\n [1916, 2488],\n [1920, 2487],\n [1924, 2489],\n [1926, 2487],\n [1933, 2485],\n [1938, 2487],\n [1937, 2485],\n [1945, 2480],\n [1966, 2483],\n [2052, 2289],\n [2084, 2203],\n [2167, 1994],\n [2254, 1789],\n [2253, 1454],\n [2250, 1450],\n [2244, 1432],\n [2242, 1417],\n [2238, 1409],\n [2235, 1408],\n [2232, 1404],\n [2226, 1404],\n [2224, 1406],\n [2221, 1405],\n [2216, 1405],\n [2212, 1402],\n [2214, 1393],\n [2219, 1390],\n [2214, 1380],\n [2209, 1380],\n [2201, 1373],\n [2199, 1373],\n [2191, 1377],\n [2187, 1376],\n [2184, 1374],\n [2184, 1369],\n [2190, 1359],\n [2190, 1353],\n [2188, 1350],\n [2182, 1350],\n [2175, 1357],\n [2172, 1363],\n [2176, 1378],\n [2172, 1383],\n [2169, 1384],\n [2164, 1382],\n [2162, 1378],\n [2162, 1367],\n [2158, 1361],\n [2154, 1362],\n [2152, 1366],\n [2150, 1376],\n [2148, 1379],\n [2144, 1379],\n [2139, 1377],\n [2134, 1371],\n [2130, 1369],\n [2126, 1372],\n [2120, 1382],\n [2113, 1383],\n [2108, 1379],\n [2103, 1379],\n [2101, 1381],\n [2099, 1391],\n [2092, 1395],\n [2088, 1403],\n [2080, 1402],\n [2076, 1404],\n [2072, 1412],\n [2067, 1411],\n [2059, 1403],\n [2054, 1403],\n [2051, 1405],\n [2045, 1411],\n [2037, 1413],\n [2034, 1417],\n [2031, 1425],\n [2033, 1434],\n [2022, 1442],\n [2015, 1457],\n [2000, 1455],\n [1992, 1459],\n [1983, 1458],\n [1975, 1468],\n [1969, 1471],\n [1966, 1481],\n [1964, 1484],\n [1954, 1488],\n [1936, 1502],\n [1929, 1506],\n [1926, 1505],\n [1916, 1512],\n [1914, 1512],\n [1911, 1509],\n [1910, 1503],\n [1906, 1499],\n [1902, 1501],\n [1902, 1507],\n [1900, 1513],\n [1896, 1513],\n [1893, 1505],\n [1890, 1504],\n [1889, 1505],\n [1888, 1510],\n [1878, 1509],\n [1878, 1514],\n [1874, 1515],\n [1871, 1511],\n [1868, 1512],\n [1868, 1518],\n [1866, 1520],\n [1861, 1521],\n [1863, 1530],\n [1861, 1538],\n [1865, 1546],\n [1862, 1550],\n [1863, 1554],\n [1863, 1559],\n [1860, 1560],\n [1862, 1563],\n [1861, 1566],\n [1863, 1569],\n [1860, 1591],\n [1854, 1601],\n [1854, 1606],\n [1851, 1615],\n [1846, 1623],\n [1842, 1625],\n [1837, 1634],\n [1718, 1733],\n [1716, 1731],\n [1713, 1735],\n [1706, 1738],\n [1702, 1745],\n [1696, 1747],\n [1693, 1758],\n [1684, 1761],\n [1680, 1769],\n [1681, 1771],\n [1678, 1775],\n [1676, 1776],\n [1669, 1787],\n [1659, 1794],\n [1646, 1809],\n [1632, 1813],\n [1628, 1816],\n [1603, 1822],\n [1591, 1821],\n [1587, 1819],\n [1584, 1819],\n [1579, 1815],\n [1560, 1811],\n [1545, 1805],\n [1526, 1806],\n [1517, 1810],\n [1513, 1819],\n [1506, 1823],\n [1472, 1980],\n [1464, 2006],\n [1451, 2015],\n [1447, 2016],\n [1443, 2024],\n [1439, 2027],\n [1435, 2032],\n [1435, 2041],\n [1430, 2055],\n [1421, 2065],\n [1418, 2069],\n [1402, 2070],\n [1392, 2080],\n [1389, 2081],\n [1387, 2086],\n [1388, 2089],\n [1393, 2089],\n [1393, 2094],\n [1397, 2095],\n [1402, 2102],\n [1400, 2105],\n [1392, 2106],\n [1385, 2105],\n [1381, 2107],\n [1376, 2106],\n [1368, 2106],\n [1364, 2109],\n [1359, 2108],\n [1352, 2115],\n [1345, 2116],\n [1344, 2118],\n [1342, 2125],\n [1346, 2132],\n [1346, 2137],\n [1340, 2142],\n [1340, 2149],\n [1338, 2150],\n [1337, 2161],\n [1342, 2163],\n [1342, 2167],\n [1340, 2170],\n [1343, 2172],\n [1343, 2175],\n [1351, 2181],\n [1345, 2182],\n [1341, 2189],\n [1344, 2192],\n [1340, 2191],\n [1338, 2199],\n [1336, 2201],\n [1335, 2198],\n [1328, 2202],\n [1325, 2207],\n [1324, 2204],\n [1321, 2204],\n [1314, 2212],\n [1305, 2210],\n [1303, 2207],\n [1300, 2209],\n [1296, 2208],\n [1293, 2203],\n [1278, 2204],\n [1291, 2228],\n [1297, 2236],\n [1308, 2244],\n [1349, 2260],\n [1389, 2301],\n [1402, 2312],\n [1446, 2340],\n [1474, 2354],\n [1481, 2355],\n [1498, 2353],\n [1529, 2364],\n [1540, 2369],\n [1564, 2376],\n [1568, 2379],\n [1574, 2393],\n [1577, 2397],\n [1593, 2405],\n [1601, 2411],\n [1605, 2417],\n [1609, 2432],\n [1615, 2448],\n [1619, 2455],\n [1624, 2461],\n [1633, 2462],\n [1656, 2453],\n [1678, 2448],\n [1683, 2449],\n [1701, 2465],\n [1716, 2475],\n [1722, 2476],\n [1735, 2475],\n [1743, 2477],\n [1767, 2500],\n [1774, 2501],\n [1782, 2510],\n [1783, 2517],\n [1793, 2527],\n [1796, 2541],\n [1788, 2537],\n [1787, 2539],\n [1790, 2547],\n [1786, 2549],\n [1783, 2554],\n [1788, 2560],\n [1786, 2563],\n [1790, 2566],\n [1796, 2566],\n [1799, 2570]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '005',\n 'FIPS': '34005',\n 'STATE': 'NJ',\n 'NAME': 'Burlington',\n 'LSAD': 'County'},\n 'id': 2178,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[217, 1692],\n [217, 1571],\n [219, 1532],\n [249, 1041],\n [240, 1045],\n [235, 1044],\n [235, 1047],\n [223, 1051],\n [222, 1046],\n [216, 1048],\n [213, 1046],\n [209, 1046],\n [206, 1041],\n [198, 1042],\n [193, 1037],\n [191, 1038],\n [186, 1046],\n [176, 1047],\n [173, 1050],\n [166, 1049],\n [155, 1035],\n [139, 1029],\n [134, 1023],\n [130, 1024],\n [120, 1017],\n [111, 1023],\n [107, 1021],\n [102, 1023],\n [81, 1017],\n [76, 1010],\n [71, 1012],\n [63, 1019],\n [49, 1017],\n [21, 1022],\n [14, 1030],\n [8, 1030],\n [0, 1025],\n [-5, 1023],\n [-11, 1025],\n [-17, 1032],\n [-21, 1034],\n [-39, 1036],\n [-48, 1033],\n [-56, 1022],\n [-60, 1021],\n [-64, 1021],\n [-75, 1034],\n [-80, 1037],\n [-80, 1144],\n [-66, 1150],\n [-57, 1168],\n [-57, 1174],\n [-76, 1194],\n [-80, 1194],\n [-80, 1260],\n [-71, 1292],\n [-56, 1329],\n [-43, 1345],\n [-43, 1367],\n [-48, 1381],\n [-80, 1391],\n [-80, 1691],\n [0, 1691],\n [217, 1692]]]},\n 'properties': {'STATE_FIPS': '24',\n 'COUNTY_FIP': '015',\n 'FIPS': '24015',\n 'STATE': 'MD',\n 'NAME': 'Cecil',\n 'LSAD': 'County'},\n 'id': 2129,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1272, 1811],\n [1283, 1808],\n [1285, 1809],\n [1287, 1804],\n [1294, 1799],\n [1292, 1795],\n [1294, 1786],\n [1300, 1777],\n [1303, 1772],\n [1302, 1767],\n [1308, 1764],\n [1313, 1759],\n [1315, 1754],\n [1333, 1738],\n [1334, 1735],\n [1332, 1727],\n [1335, 1722],\n [1334, 1714],\n [1331, 1708],\n [1373, 1681],\n [1374, 1670],\n [1381, 1667],\n [1384, 1663],\n [1397, 1657],\n [1407, 1655],\n [1413, 1656],\n [1417, 1655],\n [1425, 1656],\n [1434, 1649],\n [1447, 1647],\n [1461, 1637],\n [1463, 1634],\n [1466, 1633],\n [1467, 1629],\n [1472, 1626],\n [1472, 1621],\n [1476, 1618],\n [1480, 1611],\n [1484, 1611],\n [1486, 1600],\n [1498, 1585],\n [1496, 1582],\n [1498, 1574],\n [1497, 1569],\n [1499, 1567],\n [1496, 1561],\n [1498, 1559],\n [1501, 1539],\n [1507, 1522],\n [1522, 1508],\n [1521, 1502],\n [1523, 1495],\n [1536, 1486],\n [1537, 1482],\n [1544, 1477],\n [1387, 1300],\n [1075, 1588],\n [1044, 1578],\n [1039, 1581],\n [1026, 1578],\n [1004, 1584],\n [1000, 1592],\n [999, 1606],\n [996, 1610],\n [991, 1611],\n [984, 1616],\n [972, 1617],\n [963, 1613],\n [961, 1615],\n [948, 1612],\n [938, 1621],\n [918, 1631],\n [914, 1630],\n [912, 1627],\n [907, 1629],\n [909, 1632],\n [907, 1634],\n [898, 1634],\n [895, 1631],\n [890, 1631],\n [889, 1639],\n [891, 1643],\n [884, 1644],\n [883, 1648],\n [878, 1651],\n [876, 1658],\n [870, 1660],\n [868, 1659],\n [859, 1664],\n [856, 1671],\n [840, 1675],\n [839, 1682],\n [836, 1681],\n [831, 1684],\n [832, 1689],\n [831, 1692],\n [828, 1692],\n [823, 1697],\n [822, 1696],\n [817, 1700],\n [817, 1704],\n [821, 1717],\n [816, 1725],\n [819, 1727],\n [815, 1727],\n [817, 1729],\n [815, 1732],\n [817, 1735],\n [812, 1742],\n [803, 1739],\n [801, 1742],\n [802, 1747],\n [800, 1746],\n [800, 1749],\n [796, 1749],\n [796, 1745],\n [793, 1747],\n [794, 1749],\n [789, 1753],\n [791, 1756],\n [794, 1754],\n [797, 1756],\n [797, 1759],\n [794, 1760],\n [798, 1765],\n [788, 1767],\n [787, 1762],\n [785, 1759],\n [783, 1762],\n [784, 1766],\n [778, 1766],\n [774, 1771],\n [776, 1782],\n [779, 1783],\n [782, 1779],\n [785, 1781],\n [790, 1790],\n [788, 1791],\n [785, 1788],\n [783, 1789],\n [781, 1794],\n [782, 1799],\n [779, 1807],\n [777, 1807],\n [775, 1803],\n [771, 1804],\n [774, 1810],\n [772, 1816],\n [769, 1817],\n [764, 1812],\n [757, 1813],\n [748, 1809],\n [734, 1808],\n [723, 1803],\n [728, 1808],\n [775, 1833],\n [761, 1843],\n [797, 1869],\n [849, 1916],\n [868, 1927],\n [884, 1933],\n [895, 1934],\n [914, 1935],\n [938, 1932],\n [970, 1934],\n [1011, 1943],\n [1043, 1956],\n [1059, 1965],\n [1090, 1993],\n [1099, 1995],\n [1146, 1997],\n [1154, 2000],\n [1161, 2008],\n [1177, 1998],\n [1180, 1993],\n [1173, 1989],\n [1174, 1987],\n [1190, 1978],\n [1184, 1976],\n [1187, 1971],\n [1188, 1965],\n [1192, 1959],\n [1195, 1960],\n [1193, 1968],\n [1201, 1959],\n [1196, 1959],\n [1201, 1952],\n [1208, 1953],\n [1205, 1956],\n [1209, 1960],\n [1211, 1960],\n [1213, 1957],\n [1211, 1955],\n [1213, 1943],\n [1216, 1942],\n [1215, 1947],\n [1228, 1938],\n [1229, 1931],\n [1235, 1930],\n [1238, 1924],\n [1241, 1924],\n [1244, 1919],\n [1239, 1912],\n [1241, 1910],\n [1242, 1906],\n [1245, 1903],\n [1242, 1898],\n [1245, 1891],\n [1241, 1887],\n [1241, 1884],\n [1237, 1879],\n [1240, 1870],\n [1236, 1868],\n [1238, 1866],\n [1242, 1865],\n [1243, 1861],\n [1248, 1855],\n [1247, 1853],\n [1256, 1849],\n [1259, 1845],\n [1255, 1839],\n [1255, 1836],\n [1257, 1835],\n [1259, 1827],\n [1249, 1820],\n [1246, 1823],\n [1241, 1813],\n [1239, 1801],\n [1252, 1804],\n [1257, 1790],\n [1264, 1795],\n [1261, 1802],\n [1269, 1806],\n [1268, 1807],\n [1272, 1811]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '015',\n 'FIPS': '34015',\n 'STATE': 'NJ',\n 'NAME': 'Gloucester',\n 'LSAD': 'County'},\n 'id': 2180,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[535, 1914],\n [580, 1912],\n [610, 1909],\n [639, 1903],\n [691, 1885],\n [742, 1857],\n [775, 1833],\n [728, 1808],\n [712, 1791],\n [714, 1789],\n [707, 1781],\n [696, 1775],\n [691, 1766],\n [691, 1761],\n [682, 1733],\n [675, 1718],\n [670, 1697],\n [670, 1679],\n [668, 1677],\n [659, 1680],\n [654, 1678],\n [643, 1653],\n [627, 1645],\n [624, 1640],\n [623, 1624],\n [594, 1636],\n [547, 1568],\n [510, 1558],\n [472, 1501],\n [470, 1491],\n [472, 1486],\n [471, 1473],\n [474, 1456],\n [485, 1442],\n [509, 1425],\n [511, 1421],\n [545, 1390],\n [542, 1383],\n [536, 1349],\n [535, 1324],\n [549, 1311],\n [540, 1288],\n [526, 1290],\n [509, 1265],\n [502, 1233],\n [507, 1198],\n [520, 1180],\n [522, 1174],\n [534, 1164],\n [533, 1157],\n [556, 1141],\n [581, 1115],\n [585, 1101],\n [603, 1068],\n [619, 1019],\n [614, 1017],\n [613, 1010],\n [606, 1006],\n [603, 1008],\n [597, 1006],\n [595, 1002],\n [597, 998],\n [595, 996],\n [591, 998],\n [587, 996],\n [587, 992],\n [585, 991],\n [580, 993],\n [579, 997],\n [577, 998],\n [573, 992],\n [570, 991],\n [567, 992],\n [567, 995],\n [565, 997],\n [562, 997],\n [558, 993],\n [559, 989],\n [562, 989],\n [563, 981],\n [558, 981],\n [554, 988],\n [549, 980],\n [550, 977],\n [553, 976],\n [552, 969],\n [555, 967],\n [555, 962],\n [551, 958],\n [543, 956],\n [537, 950],\n [535, 945],\n [537, 940],\n [528, 921],\n [519, 916],\n [514, 912],\n [510, 914],\n [510, 916],\n [504, 917],\n [500, 911],\n [496, 914],\n [489, 911],\n [486, 916],\n [482, 911],\n [474, 912],\n [471, 911],\n [468, 914],\n [463, 914],\n [458, 911],\n [454, 903],\n [451, 904],\n [445, 898],\n [430, 897],\n [430, 894],\n [422, 888],\n [417, 880],\n [403, 880],\n [396, 878],\n [391, 879],\n [383, 878],\n [375, 881],\n [368, 890],\n [324, 894],\n [258, 889],\n [219, 1532],\n [217, 1571],\n [217, 1692],\n [239, 1693],\n [250, 1722],\n [269, 1760],\n [293, 1794],\n [321, 1825],\n [344, 1845],\n [366, 1861],\n [400, 1880],\n [431, 1894],\n [466, 1904],\n [501, 1911],\n [535, 1914]]],\n [[[551, 1518],\n [550, 1507],\n [554, 1484],\n [553, 1479],\n [556, 1472],\n [547, 1471],\n [539, 1487],\n [533, 1506],\n [534, 1512],\n [551, 1518]]],\n [[[521, 1459],\n [541, 1443],\n [543, 1430],\n [526, 1439],\n [523, 1445],\n [521, 1459]]]]},\n 'properties': {'STATE_FIPS': '10',\n 'COUNTY_FIP': '003',\n 'FIPS': '10003',\n 'STATE': 'DE',\n 'NAME': 'New Castle',\n 'LSAD': 'County'},\n 'id': 2130,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[276, 601],\n [314, 0],\n [314, -1],\n [319, -80],\n [-15, -80],\n [0, -66],\n [7, -49],\n [14, -44],\n [38, -30],\n [49, -29],\n [55, -20],\n [60, -19],\n [59, -14],\n [50, -11],\n [45, -5],\n [47, -2],\n [51, 0],\n [53, 4],\n [36, 13],\n [33, 23],\n [26, 24],\n [14, 30],\n [14, 35],\n [26, 42],\n [27, 44],\n [26, 45],\n [16, 46],\n [10, 53],\n [22, 62],\n [22, 65],\n [19, 71],\n [11, 72],\n [4, 84],\n [0, 83],\n [-3, 82],\n [-6, 85],\n [-10, 98],\n [-9, 101],\n [-2, 101],\n [0, 104],\n [0, 107],\n [-3, 110],\n [-16, 104],\n [-20, 108],\n [-20, 115],\n [-18, 116],\n [-6, 115],\n [-4, 117],\n [-10, 126],\n [-16, 129],\n [-16, 130],\n [-12, 133],\n [-10, 140],\n [-11, 145],\n [-16, 149],\n [-15, 153],\n [-9, 156],\n [-8, 158],\n [-16, 167],\n [-16, 172],\n [-9, 172],\n [-10, 176],\n [-17, 179],\n [-18, 190],\n [-22, 200],\n [-22, 201],\n [-17, 202],\n [-16, 204],\n [-15, 210],\n [-17, 213],\n [-21, 214],\n [-23, 217],\n [-14, 220],\n [-14, 222],\n [-19, 222],\n [-20, 231],\n [-10, 234],\n [-7, 238],\n [-7, 250],\n [-4, 254],\n [-2, 253],\n [-1, 257],\n [-8, 270],\n [0, 278],\n [1, 283],\n [0, 284],\n [-3, 285],\n [-5, 289],\n [0, 292],\n [4, 295],\n [4, 299],\n [7, 307],\n [13, 311],\n [11, 315],\n [23, 322],\n [26, 332],\n [33, 335],\n [35, 339],\n [39, 340],\n [42, 348],\n [42, 352],\n [49, 352],\n [49, 354],\n [47, 361],\n [49, 364],\n [57, 359],\n [68, 366],\n [68, 374],\n [71, 377],\n [73, 382],\n [80, 384],\n [78, 387],\n [79, 389],\n [79, 393],\n [82, 396],\n [84, 404],\n [87, 405],\n [89, 414],\n [88, 417],\n [86, 418],\n [86, 421],\n [89, 422],\n [96, 432],\n [99, 440],\n [108, 443],\n [112, 447],\n [116, 452],\n [129, 466],\n [132, 473],\n [130, 495],\n [133, 500],\n [137, 502],\n [143, 520],\n [149, 535],\n [153, 536],\n [167, 548],\n [186, 558],\n [197, 566],\n [202, 573],\n [209, 575],\n [213, 581],\n [236, 584],\n [262, 592],\n [276, 601]]]},\n 'properties': {'STATE_FIPS': '24',\n 'COUNTY_FIP': '011',\n 'FIPS': '24011',\n 'STATE': 'MD',\n 'NAME': 'Caroline',\n 'LSAD': 'County'},\n 'id': 2136,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[619, 1019],\n [629, 1007],\n [646, 998],\n [649, 993],\n [646, 983],\n [651, 976],\n [682, 953],\n [695, 949],\n [726, 921],\n [729, 913],\n [731, 889],\n [742, 867],\n [771, 829],\n [778, 810],\n [774, 789],\n [774, 752],\n [787, 738],\n [793, 716],\n [790, 685],\n [783, 682],\n [771, 660],\n [767, 625],\n [781, 498],\n [780, 457],\n [789, 443],\n [788, 441],\n [800, 428],\n [812, 424],\n [862, 379],\n [869, 369],\n [902, 310],\n [907, 296],\n [912, 271],\n [910, 240],\n [911, 231],\n [908, 233],\n [909, 239],\n [904, 244],\n [900, 245],\n [897, 245],\n [893, 238],\n [887, 237],\n [884, 239],\n [881, 240],\n [877, 233],\n [872, 231],\n [865, 234],\n [867, 241],\n [864, 248],\n [863, 248],\n [855, 234],\n [852, 234],\n [841, 253],\n [832, 246],\n [829, 253],\n [830, 256],\n [823, 260],\n [817, 258],\n [810, 260],\n [808, 249],\n [799, 247],\n [796, 251],\n [793, 250],\n [792, 244],\n [785, 238],\n [781, 233],\n [785, 221],\n [783, 218],\n [779, 215],\n [783, 211],\n [786, 213],\n [781, 200],\n [784, 195],\n [783, 193],\n [780, 192],\n [778, 187],\n [781, 180],\n [779, 178],\n [776, 177],\n [775, 181],\n [770, 182],\n [770, 176],\n [759, 179],\n [757, 171],\n [753, 174],\n [751, 171],\n [741, 169],\n [732, 165],\n [724, 169],\n [716, 169],\n [695, 162],\n [688, 166],\n [670, 156],\n [659, 152],\n [654, 143],\n [655, 131],\n [651, 125],\n [645, 122],\n [642, 113],\n [640, 111],\n [635, 109],\n [632, 110],\n [625, 105],\n [607, 62],\n [584, 51],\n [585, 47],\n [580, 39],\n [577, 38],\n [573, 39],\n [566, 35],\n [557, 24],\n [313, 14],\n [258, 889],\n [324, 894],\n [368, 890],\n [375, 881],\n [383, 878],\n [391, 879],\n [396, 878],\n [403, 880],\n [417, 880],\n [422, 888],\n [430, 894],\n [430, 897],\n [445, 898],\n [451, 904],\n [454, 903],\n [458, 911],\n [463, 914],\n [468, 914],\n [471, 911],\n [474, 912],\n [482, 911],\n [486, 916],\n [489, 911],\n [496, 914],\n [500, 911],\n [504, 917],\n [510, 916],\n [510, 914],\n [514, 912],\n [519, 916],\n [528, 921],\n [537, 940],\n [535, 945],\n [537, 950],\n [543, 956],\n [551, 958],\n [555, 962],\n [555, 967],\n [552, 969],\n [553, 976],\n [550, 977],\n [549, 980],\n [554, 988],\n [558, 981],\n [563, 981],\n [562, 989],\n [559, 989],\n [558, 993],\n [562, 997],\n [565, 997],\n [567, 995],\n [567, 992],\n [570, 991],\n [573, 992],\n [577, 998],\n [579, 997],\n [580, 993],\n [585, 991],\n [587, 992],\n [587, 996],\n [591, 998],\n [595, 996],\n [597, 998],\n [595, 1002],\n [597, 1006],\n [603, 1008],\n [606, 1006],\n [613, 1010],\n [614, 1017],\n [619, 1019]]]},\n 'properties': {'STATE_FIPS': '10',\n 'COUNTY_FIP': '001',\n 'FIPS': '10001',\n 'STATE': 'DE',\n 'NAME': 'Kent',\n 'LSAD': 'County'},\n 'id': 2138,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1272, 1811],\n [1268, 1807],\n [1269, 1806],\n [1261, 1802],\n [1264, 1795],\n [1257, 1790],\n [1252, 1804],\n [1239, 1801],\n [1241, 1813],\n [1246, 1823],\n [1249, 1820],\n [1259, 1827],\n [1257, 1835],\n [1255, 1836],\n [1255, 1839],\n [1259, 1845],\n [1256, 1849],\n [1247, 1853],\n [1248, 1855],\n [1243, 1861],\n [1242, 1865],\n [1238, 1866],\n [1236, 1868],\n [1240, 1870],\n [1237, 1879],\n [1241, 1884],\n [1241, 1887],\n [1245, 1891],\n [1242, 1898],\n [1245, 1903],\n [1242, 1906],\n [1241, 1910],\n [1239, 1912],\n [1244, 1919],\n [1241, 1924],\n [1238, 1924],\n [1235, 1930],\n [1229, 1931],\n [1228, 1938],\n [1215, 1947],\n [1216, 1942],\n [1213, 1943],\n [1211, 1955],\n [1213, 1957],\n [1211, 1960],\n [1209, 1960],\n [1205, 1956],\n [1208, 1953],\n [1201, 1952],\n [1196, 1959],\n [1201, 1959],\n [1193, 1968],\n [1195, 1960],\n [1192, 1959],\n [1188, 1965],\n [1187, 1971],\n [1184, 1976],\n [1190, 1978],\n [1174, 1987],\n [1173, 1989],\n [1180, 1993],\n [1177, 1998],\n [1161, 2008],\n [1175, 2030],\n [1179, 2052],\n [1169, 2081],\n [1167, 2094],\n [1168, 2119],\n [1171, 2133],\n [1180, 2146],\n [1208, 2163],\n [1236, 2172],\n [1260, 2183],\n [1278, 2204],\n [1293, 2203],\n [1296, 2208],\n [1300, 2209],\n [1303, 2207],\n [1305, 2210],\n [1314, 2212],\n [1321, 2204],\n [1324, 2204],\n [1325, 2207],\n [1328, 2202],\n [1335, 2198],\n [1336, 2201],\n [1338, 2199],\n [1340, 2191],\n [1344, 2192],\n [1341, 2189],\n [1345, 2182],\n [1351, 2181],\n [1343, 2175],\n [1343, 2172],\n [1340, 2170],\n [1342, 2167],\n [1342, 2163],\n [1337, 2161],\n [1338, 2150],\n [1340, 2149],\n [1340, 2142],\n [1346, 2137],\n [1346, 2132],\n [1342, 2125],\n [1344, 2118],\n [1345, 2116],\n [1352, 2115],\n [1359, 2108],\n [1364, 2109],\n [1368, 2106],\n [1376, 2106],\n [1381, 2107],\n [1385, 2105],\n [1392, 2106],\n [1400, 2105],\n [1402, 2102],\n [1397, 2095],\n [1393, 2094],\n [1393, 2089],\n [1388, 2089],\n [1387, 2086],\n [1389, 2081],\n [1392, 2080],\n [1402, 2070],\n [1418, 2069],\n [1421, 2065],\n [1430, 2055],\n [1435, 2041],\n [1435, 2032],\n [1439, 2027],\n [1443, 2024],\n [1447, 2016],\n [1451, 2015],\n [1464, 2006],\n [1472, 1980],\n [1506, 1823],\n [1513, 1819],\n [1517, 1810],\n [1526, 1806],\n [1545, 1805],\n [1560, 1811],\n [1579, 1815],\n [1584, 1819],\n [1587, 1819],\n [1591, 1821],\n [1603, 1822],\n [1628, 1816],\n [1632, 1813],\n [1646, 1809],\n [1659, 1794],\n [1669, 1787],\n [1676, 1776],\n [1678, 1775],\n [1681, 1771],\n [1680, 1769],\n [1684, 1761],\n [1693, 1758],\n [1696, 1747],\n [1702, 1745],\n [1706, 1738],\n [1713, 1735],\n [1716, 1731],\n [1718, 1733],\n [1749, 1707],\n [1544, 1477],\n [1537, 1482],\n [1536, 1486],\n [1523, 1495],\n [1521, 1502],\n [1522, 1508],\n [1507, 1522],\n [1501, 1539],\n [1498, 1559],\n [1496, 1561],\n [1499, 1567],\n [1497, 1569],\n [1498, 1574],\n [1496, 1582],\n [1498, 1585],\n [1486, 1600],\n [1484, 1611],\n [1480, 1611],\n [1476, 1618],\n [1472, 1621],\n [1472, 1626],\n [1467, 1629],\n [1466, 1633],\n [1463, 1634],\n [1461, 1637],\n [1447, 1647],\n [1434, 1649],\n [1425, 1656],\n [1417, 1655],\n [1413, 1656],\n [1407, 1655],\n [1397, 1657],\n [1384, 1663],\n [1381, 1667],\n [1374, 1670],\n [1373, 1681],\n [1331, 1708],\n [1334, 1714],\n [1335, 1722],\n [1332, 1727],\n [1334, 1735],\n [1333, 1738],\n [1315, 1754],\n [1313, 1759],\n [1308, 1764],\n [1302, 1767],\n [1303, 1772],\n [1300, 1777],\n [1294, 1786],\n [1292, 1795],\n [1294, 1799],\n [1287, 1804],\n [1285, 1809],\n [1283, 1808],\n [1272, 1811]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '007',\n 'FIPS': '34007',\n 'STATE': 'NJ',\n 'NAME': 'Camden',\n 'LSAD': 'County'},\n 'id': 2179,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[763, 1054],\n [751, 1058],\n [736, 1068],\n [721, 1088],\n [688, 1157],\n [672, 1156],\n [661, 1161],\n [629, 1184],\n [625, 1195],\n [584, 1198],\n [575, 1217],\n [573, 1234],\n [575, 1266],\n [596, 1269],\n [598, 1273],\n [594, 1275],\n [593, 1283],\n [593, 1293],\n [598, 1323],\n [598, 1332],\n [597, 1339],\n [591, 1342],\n [588, 1349],\n [590, 1354],\n [609, 1377],\n [616, 1391],\n [620, 1400],\n [619, 1420],\n [615, 1425],\n [609, 1430],\n [600, 1431],\n [583, 1448],\n [571, 1455],\n [559, 1465],\n [553, 1479],\n [554, 1484],\n [550, 1507],\n [551, 1518],\n [555, 1527],\n [568, 1538],\n [576, 1548],\n [586, 1551],\n [616, 1591],\n [620, 1602],\n [624, 1623],\n [624, 1640],\n [627, 1645],\n [643, 1653],\n [654, 1678],\n [659, 1680],\n [668, 1677],\n [670, 1679],\n [670, 1697],\n [675, 1718],\n [682, 1733],\n [691, 1761],\n [691, 1766],\n [696, 1775],\n [707, 1781],\n [714, 1789],\n [712, 1791],\n [723, 1803],\n [734, 1808],\n [748, 1809],\n [757, 1813],\n [764, 1812],\n [769, 1817],\n [772, 1816],\n [774, 1810],\n [771, 1804],\n [775, 1803],\n [777, 1807],\n [779, 1807],\n [782, 1799],\n [781, 1794],\n [783, 1789],\n [785, 1788],\n [788, 1791],\n [790, 1790],\n [785, 1781],\n [782, 1779],\n [779, 1783],\n [776, 1782],\n [774, 1771],\n [778, 1766],\n [784, 1766],\n [783, 1762],\n [785, 1759],\n [787, 1762],\n [788, 1767],\n [798, 1765],\n [794, 1760],\n [797, 1759],\n [797, 1756],\n [794, 1754],\n [791, 1756],\n [789, 1753],\n [794, 1749],\n [793, 1747],\n [796, 1745],\n [796, 1749],\n [800, 1749],\n [800, 1746],\n [802, 1747],\n [801, 1742],\n [803, 1739],\n [812, 1742],\n [817, 1735],\n [815, 1732],\n [817, 1729],\n [815, 1727],\n [819, 1727],\n [816, 1725],\n [821, 1717],\n [817, 1704],\n [817, 1700],\n [822, 1696],\n [823, 1697],\n [828, 1692],\n [831, 1692],\n [832, 1689],\n [831, 1684],\n [836, 1681],\n [839, 1682],\n [840, 1675],\n [856, 1671],\n [859, 1664],\n [868, 1659],\n [870, 1660],\n [876, 1658],\n [878, 1651],\n [883, 1648],\n [884, 1644],\n [891, 1643],\n [889, 1639],\n [890, 1631],\n [895, 1631],\n [898, 1634],\n [907, 1634],\n [909, 1632],\n [907, 1629],\n [912, 1627],\n [914, 1630],\n [918, 1631],\n [938, 1621],\n [948, 1612],\n [961, 1615],\n [963, 1613],\n [972, 1617],\n [984, 1616],\n [991, 1611],\n [996, 1610],\n [999, 1606],\n [1000, 1592],\n [1004, 1584],\n [1026, 1578],\n [1039, 1581],\n [1044, 1578],\n [1075, 1588],\n [1275, 1402],\n [1269, 1387],\n [1268, 1378],\n [1264, 1373],\n [1257, 1357],\n [1262, 1348],\n [1260, 1340],\n [1260, 1334],\n [1262, 1334],\n [1258, 1324],\n [1260, 1318],\n [1256, 1309],\n [1256, 1303],\n [1253, 1299],\n [1252, 1291],\n [1253, 1289],\n [1252, 1283],\n [1253, 1282],\n [1249, 1275],\n [1251, 1267],\n [1254, 1264],\n [1257, 1257],\n [1256, 1251],\n [1259, 1245],\n [1257, 1239],\n [1254, 1237],\n [1253, 1229],\n [1251, 1229],\n [1252, 1227],\n [1250, 1224],\n [1251, 1222],\n [1248, 1219],\n [1247, 1215],\n [1249, 1212],\n [1247, 1211],\n [1246, 1206],\n [1248, 1202],\n [1243, 1192],\n [1178, 1249],\n [1016, 1384],\n [1003, 1367],\n [902, 1257],\n [891, 1251],\n [867, 1255],\n [855, 1230],\n [854, 1219],\n [851, 1216],\n [845, 1216],\n [844, 1212],\n [836, 1205],\n [836, 1201],\n [829, 1191],\n [820, 1188],\n [813, 1192],\n [813, 1194],\n [802, 1193],\n [783, 1201],\n [771, 1194],\n [761, 1182],\n [762, 1179],\n [768, 1178],\n [766, 1169],\n [769, 1165],\n [765, 1159],\n [760, 1160],\n [759, 1156],\n [762, 1153],\n [768, 1157],\n [769, 1153],\n [766, 1147],\n [764, 1147],\n [760, 1149],\n [755, 1145],\n [757, 1140],\n [762, 1138],\n [765, 1142],\n [768, 1141],\n [768, 1135],\n [771, 1131],\n [770, 1129],\n [766, 1128],\n [765, 1126],\n [766, 1122],\n [761, 1121],\n [762, 1114],\n [756, 1113],\n [755, 1105],\n [760, 1100],\n [762, 1093],\n [764, 1092],\n [766, 1094],\n [767, 1100],\n [775, 1098],\n [775, 1094],\n [773, 1091],\n [767, 1086],\n [767, 1084],\n [772, 1080],\n [772, 1076],\n [769, 1074],\n [763, 1074],\n [758, 1076],\n [757, 1071],\n [761, 1066],\n [758, 1062],\n [758, 1060],\n [763, 1054]]],\n [[[763, 1054],\n [765, 1055],\n [767, 1060],\n [770, 1060],\n [772, 1050],\n [763, 1054]]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '033',\n 'FIPS': '34033',\n 'STATE': 'NJ',\n 'NAME': 'Salem',\n 'LSAD': 'County'},\n 'id': 2131,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1275, 1402],\n [1575, 1130],\n [1573, 1127],\n [1574, 1123],\n [1579, 1112],\n [1580, 1106],\n [1577, 1095],\n [1572, 1086],\n [1573, 1080],\n [1572, 1075],\n [1580, 1055],\n [1581, 1041],\n [1579, 1031],\n [1569, 1012],\n [1570, 1000],\n [1564, 981],\n [1564, 974],\n [1562, 968],\n [1563, 948],\n [1568, 940],\n [1563, 941],\n [1557, 929],\n [1549, 919],\n [1537, 911],\n [1515, 773],\n [1490, 757],\n [1479, 754],\n [1476, 743],\n [1474, 742],\n [1476, 740],\n [1474, 739],\n [1473, 735],\n [1475, 732],\n [1474, 730],\n [1476, 727],\n [1473, 727],\n [1473, 724],\n [1477, 722],\n [1476, 719],\n [1479, 717],\n [1474, 710],\n [1473, 701],\n [1475, 698],\n [1483, 700],\n [1484, 697],\n [1478, 691],\n [1478, 686],\n [1480, 685],\n [1481, 687],\n [1491, 685],\n [1488, 679],\n [1490, 673],\n [1493, 672],\n [1492, 669],\n [1493, 667],\n [1489, 665],\n [1420, 689],\n [1400, 693],\n [1368, 691],\n [1327, 695],\n [1323, 697],\n [1325, 706],\n [1331, 712],\n [1331, 716],\n [1327, 726],\n [1313, 736],\n [1305, 737],\n [1296, 729],\n [1289, 733],\n [1274, 733],\n [1240, 723],\n [1218, 729],\n [1209, 729],\n [1198, 722],\n [1180, 688],\n [1166, 669],\n [1163, 670],\n [1124, 711],\n [1125, 739],\n [1117, 772],\n [1107, 788],\n [1099, 795],\n [1086, 793],\n [1079, 813],\n [1066, 825],\n [1056, 825],\n [1013, 847],\n [1010, 853],\n [1012, 859],\n [1009, 869],\n [999, 895],\n [970, 903],\n [954, 894],\n [950, 881],\n [945, 876],\n [920, 899],\n [906, 915],\n [889, 957],\n [888, 969],\n [879, 981],\n [867, 987],\n [848, 985],\n [834, 973],\n [797, 1005],\n [791, 1015],\n [790, 1030],\n [784, 1045],\n [772, 1050],\n [770, 1060],\n [767, 1060],\n [765, 1055],\n [763, 1054],\n [758, 1060],\n [758, 1062],\n [761, 1066],\n [757, 1071],\n [757, 1075],\n [758, 1076],\n [763, 1074],\n [769, 1074],\n [772, 1076],\n [772, 1080],\n [767, 1084],\n [767, 1086],\n [773, 1091],\n [775, 1094],\n [775, 1098],\n [767, 1100],\n [766, 1094],\n [764, 1092],\n [762, 1093],\n [760, 1100],\n [755, 1103],\n [754, 1109],\n [756, 1113],\n [762, 1114],\n [761, 1121],\n [766, 1122],\n [765, 1126],\n [766, 1128],\n [770, 1129],\n [771, 1131],\n [768, 1135],\n [768, 1141],\n [765, 1142],\n [762, 1138],\n [757, 1140],\n [755, 1145],\n [760, 1149],\n [764, 1147],\n [766, 1147],\n [769, 1153],\n [768, 1157],\n [762, 1153],\n [759, 1156],\n [760, 1160],\n [765, 1159],\n [769, 1165],\n [766, 1169],\n [768, 1178],\n [762, 1179],\n [761, 1182],\n [771, 1194],\n [783, 1201],\n [802, 1193],\n [813, 1194],\n [813, 1192],\n [820, 1188],\n [829, 1191],\n [836, 1201],\n [836, 1205],\n [844, 1212],\n [845, 1216],\n [851, 1216],\n [854, 1219],\n [855, 1230],\n [867, 1255],\n [891, 1251],\n [902, 1257],\n [1003, 1367],\n [1016, 1384],\n [1178, 1249],\n [1243, 1192],\n [1248, 1202],\n [1246, 1206],\n [1247, 1211],\n [1249, 1212],\n [1247, 1215],\n [1248, 1219],\n [1251, 1222],\n [1250, 1224],\n [1252, 1227],\n [1251, 1229],\n [1253, 1229],\n [1254, 1237],\n [1257, 1239],\n [1259, 1245],\n [1256, 1251],\n [1257, 1257],\n [1254, 1264],\n [1251, 1267],\n [1249, 1275],\n [1253, 1282],\n [1252, 1283],\n [1253, 1289],\n [1252, 1291],\n [1253, 1299],\n [1256, 1303],\n [1256, 1309],\n [1260, 1318],\n [1258, 1324],\n [1262, 1334],\n [1260, 1334],\n [1260, 1340],\n [1262, 1348],\n [1257, 1357],\n [1264, 1373],\n [1268, 1378],\n [1269, 1387],\n [1275, 1402]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '011',\n 'FIPS': '34011',\n 'STATE': 'NJ',\n 'NAME': 'Cumberland',\n 'LSAD': 'County'},\n 'id': 2133,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1563, 941],\n [1568, 940],\n [1568, 932],\n [1576, 930],\n [1582, 926],\n [1602, 924],\n [1611, 916],\n [1620, 905],\n [1627, 909],\n [1629, 907],\n [1643, 907],\n [1646, 904],\n [1651, 909],\n [1656, 911],\n [1659, 908],\n [1664, 908],\n [1666, 905],\n [1671, 909],\n [1676, 908],\n [1679, 909],\n [1689, 902],\n [1687, 894],\n [1688, 894],\n [1696, 897],\n [1699, 894],\n [1706, 893],\n [1709, 889],\n [1720, 894],\n [1725, 891],\n [1726, 886],\n [1735, 885],\n [1744, 888],\n [1748, 893],\n [1758, 892],\n [1764, 888],\n [1773, 893],\n [1775, 892],\n [1773, 886],\n [1778, 881],\n [1782, 880],\n [1785, 886],\n [1788, 886],\n [1789, 880],\n [1791, 878],\n [1794, 884],\n [1798, 885],\n [1802, 878],\n [1805, 875],\n [1810, 879],\n [1816, 878],\n [1820, 883],\n [1824, 885],\n [1828, 883],\n [1831, 884],\n [1835, 890],\n [1837, 890],\n [1840, 887],\n [1840, 883],\n [1838, 877],\n [1840, 875],\n [1843, 876],\n [1845, 881],\n [1845, 889],\n [1849, 891],\n [1864, 890],\n [1862, 879],\n [1863, 877],\n [1870, 874],\n [1875, 875],\n [1879, 882],\n [1885, 887],\n [1889, 888],\n [1900, 886],\n [1913, 881],\n [1918, 882],\n [1960, 913],\n [1967, 914],\n [1994, 894],\n [2011, 893],\n [2023, 900],\n [2031, 899],\n [2033, 896],\n [2019, 883],\n [2016, 871],\n [2005, 855],\n [1976, 841],\n [1951, 818],\n [1927, 791],\n [1895, 747],\n [1880, 730],\n [1873, 705],\n [1844, 669],\n [1781, 557],\n [1780, 551],\n [1782, 547],\n [1796, 534],\n [1794, 525],\n [1746, 472],\n [1688, 375],\n [1676, 332],\n [1667, 317],\n [1645, 306],\n [1628, 293],\n [1583, 247],\n [1563, 220],\n [1562, 222],\n [1554, 226],\n [1537, 223],\n [1501, 205],\n [1481, 199],\n [1462, 198],\n [1419, 203],\n [1413, 207],\n [1406, 220],\n [1430, 334],\n [1439, 361],\n [1455, 398],\n [1506, 496],\n [1514, 517],\n [1522, 544],\n [1531, 601],\n [1530, 630],\n [1503, 660],\n [1489, 665],\n [1493, 667],\n [1492, 669],\n [1493, 672],\n [1490, 673],\n [1488, 679],\n [1491, 685],\n [1481, 687],\n [1480, 685],\n [1478, 686],\n [1478, 691],\n [1484, 697],\n [1482, 701],\n [1475, 698],\n [1473, 701],\n [1474, 710],\n [1479, 717],\n [1476, 719],\n [1477, 722],\n [1473, 724],\n [1473, 727],\n [1476, 727],\n [1474, 730],\n [1475, 732],\n [1473, 735],\n [1474, 739],\n [1476, 740],\n [1474, 742],\n [1476, 743],\n [1479, 754],\n [1490, 757],\n [1515, 773],\n [1537, 911],\n [1549, 919],\n [1557, 929],\n [1563, 941]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '009',\n 'FIPS': '34009',\n 'STATE': 'NJ',\n 'NAME': 'Cape May',\n 'LSAD': 'County'},\n 'id': 2134,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2885, 4176],\n [2960, 4130],\n [2976, 4129],\n [2972, 4096],\n [2941, 3976],\n [2925, 3922],\n [2889, 3842],\n [2875, 3801],\n [2844, 3745],\n [2831, 3752],\n [2832, 3760],\n [2803, 3780],\n [2803, 3784],\n [2806, 3789],\n [2802, 3794],\n [2797, 3795],\n [2792, 3789],\n [2792, 3785],\n [2788, 3785],\n [2787, 3781],\n [2785, 3780],\n [2786, 3778],\n [2781, 3781],\n [2780, 3774],\n [2775, 3774],\n [2769, 3765],\n [2742, 3763],\n [2733, 3760],\n [2727, 3755],\n [2722, 3747],\n [2718, 3744],\n [2710, 3742],\n [2708, 3736],\n [2692, 3711],\n [2690, 3703],\n [2693, 3687],\n [2690, 3677],\n [2686, 3679],\n [2683, 3677],\n [2677, 3687],\n [2679, 3692],\n [2675, 3703],\n [2672, 3702],\n [2669, 3705],\n [2662, 3706],\n [2657, 3703],\n [2653, 3694],\n [2650, 3692],\n [2640, 3696],\n [2636, 3695],\n [2633, 3699],\n [2632, 3707],\n [2607, 3723],\n [2619, 3744],\n [2620, 3749],\n [2618, 3760],\n [2623, 3784],\n [2638, 3790],\n [2641, 3793],\n [2643, 3799],\n [2645, 3808],\n [2641, 3826],\n [2644, 3833],\n [2648, 3849],\n [2647, 3855],\n [2649, 3864],\n [2656, 3864],\n [2659, 3857],\n [2661, 3856],\n [2665, 3860],\n [2666, 3864],\n [2665, 3871],\n [2661, 3874],\n [2656, 3885],\n [2654, 3892],\n [2646, 3904],\n [2632, 3915],\n [2634, 3930],\n [2627, 3941],\n [2630, 3956],\n [2628, 3967],\n [2633, 3981],\n [2630, 3985],\n [2619, 3987],\n [2616, 3992],\n [2615, 3999],\n [2619, 4007],\n [2612, 4020],\n [2606, 4022],\n [2616, 4070],\n [2583, 4096],\n [2574, 4104],\n [2573, 4096],\n [2573, 4090],\n [2518, 4096],\n [2494, 4099],\n [2460, 4120],\n [2437, 4158],\n [2425, 4170],\n [2427, 4176],\n [2885, 4176]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '003',\n 'FIPS': '34003',\n 'STATE': 'NJ',\n 'NAME': 'Bergen',\n 'LSAD': 'County'},\n 'id': 2229,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2234, 4176],\n [2235, 4173],\n [2240, 4168],\n [2251, 4165],\n [2255, 4159],\n [2259, 4157],\n [2265, 4162],\n [2274, 4161],\n [2281, 4157],\n [2292, 4157],\n [2293, 4160],\n [2298, 4162],\n [2306, 4160],\n [2310, 4156],\n [2310, 4144],\n [2318, 4144],\n [2324, 4148],\n [2325, 4146],\n [2329, 4148],\n [2334, 4147],\n [2334, 4142],\n [2341, 4140],\n [2344, 4137],\n [2363, 4139],\n [2370, 4132],\n [2382, 4133],\n [2384, 4140],\n [2387, 4140],\n [2388, 4136],\n [2388, 4128],\n [2391, 4125],\n [2391, 4117],\n [2396, 4111],\n [2389, 4103],\n [2389, 4096],\n [2392, 4094],\n [2399, 4096],\n [2407, 4094],\n [2412, 4096],\n [2412, 4090],\n [2418, 4085],\n [2417, 4079],\n [2413, 4081],\n [2412, 4075],\n [2413, 4071],\n [2415, 4069],\n [2414, 4053],\n [2418, 4047],\n [2415, 4025],\n [2407, 4002],\n [2401, 3997],\n [2402, 3995],\n [2402, 3989],\n [2407, 3986],\n [2405, 3984],\n [2408, 3980],\n [2408, 3975],\n [2416, 3978],\n [2416, 3973],\n [2426, 3972],\n [2433, 3959],\n [2432, 3957],\n [2430, 3957],\n [2426, 3962],\n [2426, 3956],\n [2424, 3953],\n [2427, 3948],\n [2424, 3942],\n [2425, 3938],\n [2427, 3936],\n [2413, 3937],\n [2411, 3934],\n [2407, 3933],\n [2408, 3938],\n [2404, 3940],\n [2411, 3942],\n [2411, 3944],\n [2406, 3945],\n [2400, 3941],\n [2397, 3942],\n [2396, 3944],\n [2397, 3945],\n [2396, 3948],\n [2397, 3953],\n [2390, 3954],\n [2380, 3950],\n [2381, 3956],\n [2376, 3952],\n [2370, 3951],\n [2367, 3952],\n [2364, 3949],\n [2358, 3948],\n [2358, 3957],\n [2355, 3957],\n [2353, 3955],\n [2351, 3956],\n [2352, 3959],\n [2347, 3958],\n [2345, 3956],\n [2348, 3956],\n [2348, 3953],\n [2344, 3953],\n [2342, 3959],\n [2340, 3955],\n [2335, 3952],\n [2330, 3939],\n [2335, 3937],\n [2335, 3935],\n [2331, 3935],\n [2328, 3931],\n [2333, 3929],\n [2328, 3927],\n [2327, 3923],\n [2329, 3918],\n [2326, 3902],\n [2330, 3902],\n [2330, 3900],\n [2334, 3898],\n [2330, 3894],\n [2335, 3891],\n [2330, 3888],\n [2332, 3885],\n [2329, 3884],\n [2331, 3878],\n [2337, 3883],\n [2339, 3878],\n [2347, 3877],\n [2353, 3873],\n [2356, 3876],\n [2359, 3874],\n [2358, 3871],\n [2354, 3869],\n [2357, 3861],\n [2349, 3861],\n [2347, 3858],\n [2348, 3854],\n [2346, 3851],\n [2345, 3847],\n [2341, 3844],\n [2343, 3835],\n [2347, 3834],\n [2345, 3830],\n [2342, 3829],\n [2341, 3816],\n [2343, 3811],\n [2334, 3803],\n [2338, 3792],\n [2335, 3785],\n [2327, 3774],\n [2320, 3776],\n [2313, 3774],\n [2311, 3763],\n [2303, 3757],\n [2298, 3749],\n [2291, 3748],\n [2291, 3742],\n [2288, 3739],\n [2287, 3711],\n [2279, 3701],\n [2282, 3700],\n [2284, 3694],\n [2280, 3687],\n [2283, 3686],\n [2282, 3680],\n [2278, 3678],\n [2274, 3678],\n [2272, 3675],\n [2275, 3674],\n [2277, 3669],\n [2287, 3675],\n [2286, 3669],\n [2291, 3668],\n [2295, 3665],\n [2301, 3665],\n [2301, 3662],\n [2298, 3655],\n [2287, 3652],\n [2286, 3650],\n [2291, 3646],\n [2288, 3642],\n [2279, 3637],\n [2282, 3626],\n [2280, 3622],\n [2276, 3622],\n [2272, 3623],\n [2268, 3621],\n [2272, 3615],\n [2262, 3604],\n [2258, 3607],\n [2253, 3606],\n [2253, 3592],\n [2246, 3590],\n [2236, 3592],\n [2228, 3583],\n [2227, 3577],\n [2222, 3577],\n [2217, 3568],\n [2200, 3560],\n [2197, 3555],\n [2194, 3545],\n [2189, 3545],\n [2184, 3542],\n [2181, 3537],\n [2169, 3529],\n [2164, 3529],\n [2162, 3524],\n [2164, 3518],\n [2162, 3514],\n [2163, 3512],\n [2160, 3507],\n [2154, 3508],\n [2150, 3506],\n [2149, 3503],\n [2137, 3496],\n [2133, 3498],\n [2128, 3493],\n [2116, 3491],\n [2117, 3487],\n [2114, 3485],\n [2112, 3488],\n [2106, 3487],\n [2106, 3484],\n [2102, 3482],\n [2100, 3484],\n [2094, 3483],\n [2095, 3479],\n [2091, 3478],\n [2088, 3480],\n [2085, 3477],\n [2086, 3475],\n [2082, 3466],\n [2075, 3460],\n [2071, 3463],\n [2070, 3462],\n [2061, 3461],\n [2060, 3464],\n [2055, 3465],\n [2059, 3469],\n [2056, 3469],\n [2054, 3479],\n [2056, 3482],\n [2051, 3486],\n [2050, 3490],\n [2044, 3491],\n [2043, 3494],\n [2050, 3495],\n [2051, 3498],\n [2056, 3501],\n [2052, 3521],\n [2053, 3527],\n [2055, 3529],\n [2058, 3537],\n [2062, 3535],\n [2069, 3537],\n [2069, 3539],\n [2066, 3541],\n [2067, 3545],\n [2070, 3544],\n [2073, 3547],\n [2073, 3559],\n [2071, 3561],\n [2069, 3561],\n [2068, 3568],\n [2061, 3574],\n [2056, 3575],\n [2054, 3578],\n [2057, 3581],\n [2058, 3587],\n [2052, 3591],\n [2051, 3594],\n [2048, 3595],\n [2048, 3598],\n [2052, 3611],\n [2046, 3617],\n [2043, 3616],\n [2035, 3622],\n [2028, 3621],\n [2026, 3623],\n [2022, 3622],\n [2023, 3646],\n [2017, 3652],\n [2019, 3655],\n [2018, 3663],\n [2012, 3669],\n [1848, 3621],\n [1765, 3594],\n [1755, 3595],\n [1740, 3603],\n [1740, 3607],\n [1725, 3617],\n [1704, 3625],\n [1666, 3634],\n [1659, 3638],\n [1644, 3636],\n [1638, 3636],\n [1638, 3638],\n [1633, 3639],\n [1622, 3639],\n [1617, 3642],\n [1594, 3665],\n [1592, 3670],\n [1526, 3726],\n [1532, 3732],\n [1535, 3733],\n [1539, 3731],\n [1546, 3737],\n [1558, 3742],\n [1562, 3755],\n [1567, 3756],\n [1569, 3752],\n [1576, 3756],\n [1583, 3757],\n [1588, 3765],\n [1589, 3771],\n [1592, 3771],\n [1598, 3780],\n [1606, 3786],\n [1606, 3792],\n [1613, 3799],\n [1611, 3804],\n [1617, 3812],\n [1630, 3821],\n [1627, 3829],\n [1622, 3833],\n [1625, 3843],\n [1627, 3845],\n [1637, 3849],\n [1642, 3855],\n [1643, 3865],\n [1652, 3869],\n [1654, 3874],\n [1646, 3880],\n [1645, 3883],\n [1648, 3894],\n [1647, 3908],\n [1651, 3914],\n [1668, 3923],\n [1671, 3928],\n [1671, 3935],\n [1681, 3943],\n [1687, 3954],\n [1691, 3952],\n [1706, 3966],\n [1708, 3965],\n [1711, 3968],\n [1713, 3965],\n [1715, 3968],\n [1722, 3968],\n [1727, 3972],\n [1727, 3976],\n [1734, 3980],\n [1749, 3979],\n [1756, 3982],\n [1761, 3974],\n [1769, 3970],\n [1783, 3958],\n [1785, 3951],\n [1782, 3942],\n [1786, 3940],\n [1792, 3945],\n [1796, 3946],\n [1808, 3954],\n [1814, 3951],\n [1818, 3952],\n [1820, 3959],\n [1827, 3961],\n [1832, 3960],\n [1846, 3969],\n [1855, 3977],\n [1871, 3984],\n [1872, 3987],\n [1870, 3992],\n [1871, 3998],\n [1873, 4001],\n [1889, 4014],\n [1897, 4029],\n [1897, 4040],\n [1888, 4056],\n [1889, 4068],\n [1910, 4096],\n [1938, 4131],\n [1978, 4176],\n [2190, 4176],\n [2189, 4174],\n [2196, 4170],\n [2202, 4172],\n [2203, 4176],\n [2234, 4176]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '027',\n 'FIPS': '34027',\n 'STATE': 'NJ',\n 'NAME': 'Morris',\n 'LSAD': 'County'},\n 'id': 2228,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2352, 3959],\n [2351, 3956],\n [2353, 3955],\n [2355, 3957],\n [2358, 3957],\n [2358, 3948],\n [2364, 3949],\n [2367, 3952],\n [2370, 3951],\n [2376, 3952],\n [2381, 3956],\n [2380, 3950],\n [2390, 3954],\n [2397, 3953],\n [2396, 3948],\n [2397, 3945],\n [2396, 3944],\n [2397, 3942],\n [2400, 3941],\n [2406, 3945],\n [2411, 3944],\n [2411, 3942],\n [2404, 3940],\n [2408, 3938],\n [2407, 3933],\n [2411, 3934],\n [2413, 3937],\n [2427, 3936],\n [2433, 3931],\n [2437, 3917],\n [2443, 3911],\n [2451, 3909],\n [2453, 3906],\n [2472, 3904],\n [2527, 3864],\n [2529, 3868],\n [2536, 3865],\n [2534, 3860],\n [2632, 3788],\n [2623, 3784],\n [2618, 3760],\n [2620, 3749],\n [2619, 3744],\n [2607, 3723],\n [2606, 3710],\n [2596, 3695],\n [2592, 3684],\n [2584, 3671],\n [2580, 3648],\n [2586, 3626],\n [2589, 3623],\n [2596, 3622],\n [2606, 3623],\n [2610, 3626],\n [2614, 3633],\n [2621, 3637],\n [2643, 3638],\n [2650, 3633],\n [2651, 3629],\n [2645, 3598],\n [2647, 3588],\n [2657, 3563],\n [2623, 3508],\n [2620, 3507],\n [2588, 3532],\n [2587, 3536],\n [2585, 3537],\n [2577, 3538],\n [2575, 3535],\n [2528, 3532],\n [2516, 3540],\n [2511, 3558],\n [2498, 3571],\n [2448, 3583],\n [2406, 3600],\n [2398, 3598],\n [2393, 3595],\n [2392, 3591],\n [2386, 3584],\n [2382, 3583],\n [2368, 3587],\n [2361, 3594],\n [2354, 3594],\n [2348, 3590],\n [2323, 3606],\n [2304, 3624],\n [2280, 3633],\n [2279, 3637],\n [2288, 3642],\n [2291, 3646],\n [2286, 3650],\n [2287, 3652],\n [2298, 3655],\n [2301, 3662],\n [2301, 3665],\n [2295, 3665],\n [2291, 3668],\n [2286, 3669],\n [2287, 3675],\n [2277, 3669],\n [2275, 3674],\n [2272, 3675],\n [2274, 3678],\n [2278, 3678],\n [2282, 3680],\n [2283, 3686],\n [2280, 3687],\n [2284, 3694],\n [2282, 3700],\n [2279, 3701],\n [2287, 3711],\n [2288, 3739],\n [2291, 3742],\n [2291, 3748],\n [2298, 3749],\n [2303, 3757],\n [2311, 3763],\n [2313, 3774],\n [2320, 3776],\n [2327, 3774],\n [2335, 3785],\n [2338, 3792],\n [2334, 3803],\n [2343, 3811],\n [2341, 3816],\n [2342, 3829],\n [2345, 3830],\n [2347, 3834],\n [2343, 3835],\n [2341, 3844],\n [2345, 3847],\n [2346, 3851],\n [2348, 3854],\n [2347, 3858],\n [2349, 3861],\n [2357, 3861],\n [2354, 3869],\n [2358, 3871],\n [2359, 3874],\n [2356, 3876],\n [2353, 3873],\n [2347, 3877],\n [2339, 3878],\n [2337, 3883],\n [2331, 3878],\n [2329, 3884],\n [2332, 3885],\n [2330, 3888],\n [2335, 3891],\n [2330, 3894],\n [2334, 3898],\n [2330, 3900],\n [2330, 3902],\n [2326, 3902],\n [2329, 3918],\n [2327, 3923],\n [2328, 3927],\n [2333, 3929],\n [2328, 3931],\n [2331, 3935],\n [2335, 3935],\n [2335, 3937],\n [2330, 3939],\n [2331, 3942],\n [2335, 3952],\n [2340, 3955],\n [2342, 3959],\n [2344, 3953],\n [2348, 3953],\n [2348, 3956],\n [2345, 3956],\n [2347, 3958],\n [2352, 3959]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '013',\n 'FIPS': '34013',\n 'STATE': 'NJ',\n 'NAME': 'Essex',\n 'LSAD': 'County'},\n 'id': 2206,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2380, 3382],\n [2380, 3379],\n [2378, 3378],\n [2380, 3376],\n [2377, 3366],\n [2385, 3361],\n [2397, 3350],\n [2443, 3360],\n [2446, 3370],\n [2467, 3365],\n [2478, 3370],\n [2484, 3363],\n [2498, 3366],\n [2504, 3368],\n [2508, 3373],\n [2512, 3369],\n [2513, 3362],\n [2521, 3355],\n [2517, 3320],\n [2509, 3290],\n [2504, 3283],\n [2484, 3287],\n [2460, 3269],\n [2456, 3255],\n [2463, 3214],\n [2431, 3172],\n [2425, 3151],\n [2432, 3120],\n [2440, 3106],\n [2477, 3093],\n [2494, 3084],\n [2494, 3083],\n [2497, 3080],\n [2490, 3067],\n [2483, 3068],\n [2481, 3065],\n [2479, 3067],\n [2461, 3042],\n [2461, 3006],\n [2458, 3003],\n [2460, 2996],\n [2455, 2990],\n [2271, 2799],\n [2248, 2769],\n [2249, 2752],\n [2150, 2698],\n [2146, 2700],\n [2116, 2702],\n [2119, 2741],\n [2095, 2754],\n [2091, 2751],\n [2088, 2754],\n [2086, 2754],\n [2077, 2759],\n [2072, 2766],\n [2061, 2765],\n [2061, 2772],\n [2052, 2780],\n [2045, 2776],\n [2040, 2771],\n [2036, 2769],\n [2032, 2775],\n [2028, 2777],\n [2027, 2775],\n [2021, 2773],\n [2016, 2773],\n [2010, 2776],\n [2007, 2783],\n [1999, 2785],\n [1995, 2791],\n [1991, 2790],\n [1983, 2797],\n [1976, 2799],\n [1972, 2803],\n [1969, 2816],\n [1957, 2820],\n [1953, 2819],\n [1947, 2821],\n [1943, 2832],\n [1936, 2833],\n [1925, 2839],\n [1916, 2838],\n [1915, 2840],\n [1915, 2845],\n [1912, 2847],\n [1914, 2857],\n [1904, 2869],\n [1904, 2878],\n [1912, 2916],\n [1916, 2919],\n [1919, 2933],\n [1928, 2936],\n [1944, 2945],\n [1955, 2956],\n [1960, 2967],\n [1966, 2971],\n [1966, 2981],\n [1969, 2989],\n [1969, 3016],\n [1983, 3025],\n [2013, 3040],\n [2041, 3056],\n [2055, 3068],\n [2064, 3080],\n [2075, 3091],\n [2082, 3099],\n [2102, 3115],\n [2119, 3139],\n [2125, 3143],\n [2140, 3148],\n [2152, 3156],\n [2153, 3166],\n [2151, 3171],\n [2143, 3178],\n [2141, 3190],\n [2122, 3195],\n [2119, 3197],\n [2100, 3230],\n [2083, 3244],\n [2072, 3255],\n [2068, 3273],\n [2065, 3280],\n [2059, 3286],\n [2054, 3288],\n [2057, 3292],\n [2056, 3305],\n [2059, 3307],\n [2063, 3315],\n [2071, 3326],\n [2070, 3329],\n [2076, 3331],\n [2086, 3339],\n [2091, 3334],\n [2091, 3337],\n [2094, 3340],\n [2097, 3338],\n [2104, 3341],\n [2108, 3340],\n [2118, 3345],\n [2126, 3354],\n [2137, 3362],\n [2143, 3362],\n [2147, 3364],\n [2154, 3355],\n [2156, 3357],\n [2203, 3362],\n [2279, 3370],\n [2380, 3382]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '023',\n 'FIPS': '34023',\n 'STATE': 'NJ',\n 'NAME': 'Middlesex',\n 'LSAD': 'County'},\n 'id': 2194,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2280, 3633],\n [2304, 3624],\n [2323, 3606],\n [2348, 3590],\n [2354, 3594],\n [2361, 3594],\n [2368, 3587],\n [2382, 3583],\n [2386, 3584],\n [2392, 3591],\n [2393, 3595],\n [2398, 3598],\n [2406, 3600],\n [2448, 3583],\n [2498, 3571],\n [2511, 3558],\n [2516, 3540],\n [2528, 3532],\n [2575, 3535],\n [2577, 3538],\n [2585, 3537],\n [2587, 3536],\n [2588, 3532],\n [2620, 3507],\n [2623, 3508],\n [2587, 3450],\n [2558, 3454],\n [2551, 3454],\n [2527, 3425],\n [2521, 3355],\n [2513, 3362],\n [2512, 3369],\n [2508, 3373],\n [2504, 3368],\n [2498, 3366],\n [2484, 3363],\n [2478, 3370],\n [2467, 3365],\n [2446, 3370],\n [2443, 3360],\n [2397, 3350],\n [2385, 3361],\n [2377, 3366],\n [2380, 3376],\n [2378, 3378],\n [2380, 3379],\n [2380, 3382],\n [2279, 3370],\n [2203, 3362],\n [2156, 3357],\n [2154, 3355],\n [2147, 3364],\n [2152, 3365],\n [2159, 3373],\n [2164, 3373],\n [2169, 3381],\n [2173, 3383],\n [2184, 3385],\n [2193, 3396],\n [2199, 3397],\n [2203, 3402],\n [2206, 3414],\n [2213, 3418],\n [2217, 3429],\n [2219, 3444],\n [2220, 3446],\n [2226, 3447],\n [2229, 3455],\n [2229, 3462],\n [2235, 3473],\n [2235, 3481],\n [2236, 3487],\n [2234, 3493],\n [2231, 3495],\n [2224, 3491],\n [2220, 3485],\n [2214, 3483],\n [2211, 3478],\n [2208, 3477],\n [2202, 3485],\n [2198, 3487],\n [2196, 3491],\n [2185, 3486],\n [2175, 3475],\n [2164, 3469],\n [2150, 3506],\n [2154, 3508],\n [2160, 3507],\n [2163, 3512],\n [2162, 3514],\n [2164, 3518],\n [2162, 3524],\n [2164, 3529],\n [2169, 3529],\n [2181, 3537],\n [2184, 3542],\n [2189, 3545],\n [2194, 3545],\n [2197, 3555],\n [2200, 3560],\n [2217, 3568],\n [2222, 3577],\n [2227, 3577],\n [2228, 3583],\n [2236, 3592],\n [2246, 3590],\n [2253, 3592],\n [2253, 3606],\n [2258, 3607],\n [2262, 3604],\n [2272, 3615],\n [2268, 3621],\n [2272, 3623],\n [2276, 3622],\n [2280, 3622],\n [2282, 3626],\n [2280, 3633]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '039',\n 'FIPS': '34039',\n 'STATE': 'NJ',\n 'NAME': 'Union',\n 'LSAD': 'County'},\n 'id': 2204,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[2941, 3976],\n [3026, 3943],\n [3031, 3954],\n [3034, 3955],\n [3033, 3958],\n [3036, 3961],\n [3039, 3961],\n [3036, 3956],\n [3042, 3955],\n [3048, 3952],\n [3048, 3950],\n [3053, 3950],\n [3057, 3931],\n [3078, 3922],\n [3079, 3925],\n [3137, 3905],\n [3135, 3901],\n [3134, 3882],\n [3129, 3862],\n [3130, 3854],\n [3135, 3849],\n [3139, 3841],\n [3140, 3824],\n [3136, 3820],\n [3130, 3830],\n [3126, 3839],\n [3128, 3848],\n [3124, 3857],\n [3122, 3856],\n [3117, 3850],\n [3114, 3842],\n [3103, 3845],\n [3094, 3839],\n [3090, 3817],\n [3091, 3809],\n [3096, 3798],\n [3106, 3785],\n [3117, 3779],\n [3133, 3751],\n [3131, 3749],\n [3122, 3749],\n [3097, 3759],\n [3088, 3760],\n [3074, 3755],\n [3038, 3749],\n [3022, 3744],\n [3011, 3732],\n [3010, 3724],\n [2998, 3722],\n [2982, 3725],\n [2981, 3730],\n [2949, 3742],\n [2940, 3748],\n [2935, 3754],\n [2928, 3754],\n [2921, 3765],\n [2920, 3772],\n [2919, 3818],\n [2926, 3837],\n [2938, 3859],\n [2952, 3877],\n [2957, 3891],\n [2957, 3896],\n [2953, 3901],\n [2946, 3897],\n [2945, 3895],\n [2938, 3897],\n [2936, 3900],\n [2919, 3907],\n [2925, 3922],\n [2941, 3976]]],\n [[[3156, 3866],\n [3162, 3860],\n [3164, 3854],\n [3162, 3836],\n [3157, 3835],\n [3152, 3842],\n [3152, 3864],\n [3156, 3866]]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '005',\n 'FIPS': '36005',\n 'STATE': 'NY',\n 'NAME': 'Bronx',\n 'LSAD': 'County'},\n 'id': 2199,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2797, 3795],\n [2802, 3794],\n [2806, 3789],\n [2803, 3784],\n [2803, 3780],\n [2832, 3760],\n [2831, 3752],\n [2844, 3745],\n [2802, 3666],\n [2786, 3575],\n [2766, 3578],\n [2747, 3549],\n [2722, 3481],\n [2694, 3468],\n [2685, 3461],\n [2613, 3446],\n [2587, 3450],\n [2657, 3563],\n [2647, 3588],\n [2645, 3598],\n [2651, 3629],\n [2650, 3633],\n [2643, 3638],\n [2621, 3637],\n [2614, 3633],\n [2610, 3626],\n [2606, 3623],\n [2596, 3622],\n [2589, 3623],\n [2583, 3633],\n [2580, 3648],\n [2582, 3665],\n [2586, 3675],\n [2592, 3684],\n [2596, 3695],\n [2606, 3710],\n [2607, 3723],\n [2632, 3707],\n [2633, 3699],\n [2636, 3695],\n [2640, 3696],\n [2650, 3692],\n [2653, 3694],\n [2657, 3703],\n [2662, 3706],\n [2669, 3705],\n [2672, 3702],\n [2675, 3703],\n [2679, 3692],\n [2677, 3687],\n [2683, 3677],\n [2686, 3679],\n [2690, 3677],\n [2693, 3687],\n [2690, 3703],\n [2692, 3711],\n [2708, 3736],\n [2710, 3742],\n [2718, 3744],\n [2722, 3747],\n [2727, 3755],\n [2733, 3760],\n [2742, 3763],\n [2769, 3765],\n [2775, 3774],\n [2780, 3774],\n [2781, 3781],\n [2786, 3778],\n [2785, 3780],\n [2787, 3781],\n [2788, 3785],\n [2792, 3785],\n [2792, 3789],\n [2797, 3795]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '017',\n 'FIPS': '34017',\n 'STATE': 'NJ',\n 'NAME': 'Hudson',\n 'LSAD': 'County'},\n 'id': 2205,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2711, 3458],\n [2720, 3444],\n [2723, 3411],\n [2734, 3388],\n [2744, 3372],\n [2735, 3353],\n [2722, 3335],\n [2689, 3301],\n [2659, 3263],\n [2658, 3265],\n [2644, 3255],\n [2622, 3231],\n [2617, 3238],\n [2611, 3241],\n [2605, 3240],\n [2587, 3225],\n [2562, 3211],\n [2556, 3213],\n [2531, 3196],\n [2515, 3192],\n [2502, 3179],\n [2482, 3176],\n [2462, 3166],\n [2457, 3167],\n [2451, 3178],\n [2449, 3189],\n [2454, 3200],\n [2468, 3214],\n [2470, 3233],\n [2461, 3257],\n [2488, 3279],\n [2506, 3279],\n [2515, 3290],\n [2525, 3345],\n [2535, 3360],\n [2537, 3369],\n [2536, 3396],\n [2529, 3398],\n [2528, 3403],\n [2530, 3426],\n [2546, 3446],\n [2559, 3453],\n [2568, 3452],\n [2574, 3446],\n [2599, 3440],\n [2647, 3446],\n [2696, 3458],\n [2711, 3458]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '085',\n 'FIPS': '36085',\n 'STATE': 'NY',\n 'NAME': 'Richmond',\n 'LSAD': 'County'},\n 'id': 2210,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2891, 3633],\n [2906, 3626],\n [2913, 3615],\n [2925, 3611],\n [2933, 3596],\n [2934, 3590],\n [2932, 3587],\n [2937, 3577],\n [2936, 3574],\n [2950, 3564],\n [2949, 3562],\n [2952, 3559],\n [2950, 3557],\n [2961, 3549],\n [2959, 3546],\n [2966, 3541],\n [2966, 3533],\n [2972, 3523],\n [2976, 3529],\n [2978, 3525],\n [2982, 3528],\n [2983, 3527],\n [3005, 3546],\n [3013, 3548],\n [3017, 3522],\n [3020, 3523],\n [3025, 3502],\n [3029, 3503],\n [3032, 3488],\n [3028, 3487],\n [3029, 3480],\n [3021, 3477],\n [3031, 3460],\n [3033, 3447],\n [3043, 3449],\n [3064, 3420],\n [3063, 3379],\n [3040, 3344],\n [2998, 3317],\n [2911, 3300],\n [2902, 3305],\n [2894, 3314],\n [2834, 3308],\n [2819, 3309],\n [2804, 3316],\n [2803, 3323],\n [2819, 3347],\n [2817, 3357],\n [2806, 3367],\n [2774, 3374],\n [2764, 3390],\n [2760, 3413],\n [2766, 3436],\n [2775, 3454],\n [2795, 3478],\n [2792, 3516],\n [2788, 3521],\n [2793, 3518],\n [2798, 3520],\n [2799, 3522],\n [2816, 3536],\n [2825, 3557],\n [2831, 3566],\n [2852, 3568],\n [2862, 3574],\n [2866, 3570],\n [2866, 3575],\n [2869, 3589],\n [2878, 3603],\n [2876, 3630],\n [2878, 3628],\n [2889, 3633],\n [2891, 3633]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '047',\n 'FIPS': '36047',\n 'STATE': 'NY',\n 'NAME': 'Kings',\n 'LSAD': 'County'},\n 'id': 2203,\n 'type': 'Feature'},\n {'geometry': {'type': 'MultiPolygon',\n 'coordinates': [[[[2919, 3907],\n [2936, 3900],\n [2938, 3897],\n [2945, 3895],\n [2946, 3897],\n [2953, 3901],\n [2957, 3896],\n [2957, 3891],\n [2952, 3877],\n [2938, 3859],\n [2926, 3837],\n [2919, 3813],\n [2921, 3765],\n [2928, 3754],\n [2935, 3754],\n [2940, 3748],\n [2949, 3742],\n [2952, 3732],\n [2945, 3727],\n [2941, 3721],\n [2927, 3705],\n [2921, 3708],\n [2918, 3706],\n [2916, 3709],\n [2915, 3705],\n [2911, 3701],\n [2912, 3697],\n [2916, 3695],\n [2915, 3693],\n [2903, 3681],\n [2887, 3656],\n [2882, 3645],\n [2878, 3640],\n [2876, 3630],\n [2878, 3603],\n [2869, 3589],\n [2866, 3575],\n [2866, 3570],\n [2862, 3574],\n [2852, 3568],\n [2830, 3565],\n [2816, 3536],\n [2799, 3522],\n [2798, 3520],\n [2793, 3518],\n [2787, 3523],\n [2786, 3532],\n [2790, 3545],\n [2795, 3548],\n [2797, 3561],\n [2793, 3571],\n [2786, 3575],\n [2802, 3666],\n [2875, 3801],\n [2889, 3842],\n [2919, 3907]]],\n [[[2763, 3558],\n [2766, 3555],\n [2757, 3535],\n [2753, 3539],\n [2763, 3558]]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '061',\n 'FIPS': '36061',\n 'STATE': 'NY',\n 'NAME': 'New York',\n 'LSAD': 'County'},\n 'id': 2200,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[3088, 3760],\n [3097, 3759],\n [3122, 3749],\n [3131, 3749],\n [3133, 3751],\n [3140, 3740],\n [3148, 3740],\n [3159, 3751],\n [3190, 3709],\n [3190, 3712],\n [3228, 3682],\n [3255, 3660],\n [3257, 3655],\n [3258, 3633],\n [3247, 3611],\n [3228, 3606],\n [3214, 3600],\n [3219, 3578],\n [3222, 3558],\n [3220, 3551],\n [3221, 3519],\n [3217, 3493],\n [3222, 3468],\n [3217, 3463],\n [3199, 3457],\n [3198, 3446],\n [3201, 3434],\n [3197, 3432],\n [3198, 3437],\n [3198, 3438],\n [3194, 3438],\n [3193, 3431],\n [3162, 3415],\n [3163, 3394],\n [3171, 3387],\n [3178, 3386],\n [3178, 3384],\n [3189, 3389],\n [3190, 3387],\n [3192, 3388],\n [3203, 3370],\n [3203, 3354],\n [3204, 3352],\n [3195, 3352],\n [3189, 3349],\n [3179, 3339],\n [3181, 3347],\n [3149, 3348],\n [3103, 3336],\n [3063, 3322],\n [2998, 3290],\n [2908, 3256],\n [2909, 3278],\n [2920, 3289],\n [2915, 3298],\n [2911, 3300],\n [2998, 3317],\n [3040, 3344],\n [3063, 3379],\n [3064, 3420],\n [3043, 3449],\n [3033, 3447],\n [3031, 3460],\n [3021, 3477],\n [3029, 3480],\n [3028, 3487],\n [3032, 3488],\n [3029, 3503],\n [3025, 3502],\n [3020, 3523],\n [3017, 3522],\n [3013, 3548],\n [3005, 3546],\n [2983, 3527],\n [2982, 3528],\n [2978, 3525],\n [2976, 3529],\n [2972, 3523],\n [2966, 3533],\n [2966, 3541],\n [2959, 3546],\n [2961, 3549],\n [2950, 3557],\n [2952, 3559],\n [2949, 3562],\n [2950, 3564],\n [2936, 3574],\n [2937, 3577],\n [2932, 3587],\n [2934, 3590],\n [2933, 3596],\n [2925, 3611],\n [2913, 3615],\n [2906, 3626],\n [2891, 3633],\n [2889, 3633],\n [2878, 3628],\n [2876, 3630],\n [2878, 3640],\n [2882, 3645],\n [2887, 3656],\n [2903, 3681],\n [2915, 3693],\n [2916, 3695],\n [2912, 3697],\n [2911, 3701],\n [2915, 3705],\n [2916, 3709],\n [2918, 3706],\n [2921, 3708],\n [2927, 3705],\n [2941, 3721],\n [2945, 3727],\n [2952, 3732],\n [2949, 3742],\n [2981, 3730],\n [2982, 3725],\n [2998, 3722],\n [3010, 3724],\n [3011, 3732],\n [3022, 3744],\n [3038, 3749],\n [3074, 3755],\n [3088, 3760]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '081',\n 'FIPS': '36081',\n 'STATE': 'NY',\n 'NAME': 'Queens',\n 'LSAD': 'County'},\n 'id': 2202,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2801, 3129],\n [2811, 3126],\n [2828, 3114],\n [2853, 3059],\n [2855, 2998],\n [2863, 2928],\n [2863, 2883],\n [2855, 2790],\n [2848, 2752],\n [2831, 2672],\n [2778, 2453],\n [2772, 2416],\n [2775, 2412],\n [2765, 2418],\n [2763, 2417],\n [2757, 2420],\n [2749, 2418],\n [2740, 2412],\n [2738, 2405],\n [2733, 2403],\n [2718, 2389],\n [2700, 2402],\n [2684, 2424],\n [2685, 2431],\n [2683, 2435],\n [2685, 2438],\n [2681, 2448],\n [2682, 2464],\n [2680, 2465],\n [2677, 2463],\n [2670, 2472],\n [2671, 2475],\n [2665, 2480],\n [2603, 2407],\n [2597, 2409],\n [2596, 2413],\n [2592, 2416],\n [2591, 2419],\n [2588, 2423],\n [2571, 2424],\n [2561, 2430],\n [2556, 2429],\n [2551, 2431],\n [2546, 2430],\n [2539, 2433],\n [2533, 2432],\n [2525, 2434],\n [2513, 2429],\n [2503, 2429],\n [2495, 2427],\n [2483, 2429],\n [2480, 2432],\n [2473, 2433],\n [2465, 2445],\n [2467, 2453],\n [2469, 2454],\n [2470, 2466],\n [2458, 2494],\n [2453, 2500],\n [2447, 2503],\n [2443, 2503],\n [2445, 2509],\n [2443, 2518],\n [2446, 2524],\n [2442, 2535],\n [2438, 2540],\n [2229, 2548],\n [2138, 2464],\n [2054, 2391],\n [2016, 2370],\n [1927, 2567],\n [1948, 2575],\n [1952, 2574],\n [1954, 2562],\n [1957, 2562],\n [1968, 2569],\n [1985, 2576],\n [1991, 2573],\n [2002, 2581],\n [2011, 2600],\n [2023, 2615],\n [2025, 2624],\n [2031, 2632],\n [2069, 2652],\n [2120, 2682],\n [2119, 2689],\n [2114, 2695],\n [2112, 2702],\n [2146, 2700],\n [2150, 2698],\n [2249, 2752],\n [2248, 2769],\n [2271, 2799],\n [2460, 2996],\n [2458, 3003],\n [2461, 3006],\n [2461, 3042],\n [2479, 3067],\n [2481, 3065],\n [2483, 3068],\n [2490, 3067],\n [2497, 3080],\n [2494, 3083],\n [2494, 3084],\n [2516, 3073],\n [2521, 3060],\n [2521, 3056],\n [2518, 3054],\n [2520, 3050],\n [2527, 3057],\n [2539, 3061],\n [2548, 3073],\n [2567, 3089],\n [2567, 3076],\n [2564, 3074],\n [2566, 3071],\n [2574, 3079],\n [2578, 3075],\n [2580, 3072],\n [2584, 3075],\n [2592, 3071],\n [2599, 3073],\n [2614, 3079],\n [2620, 3086],\n [2624, 3088],\n [2651, 3070],\n [2693, 3056],\n [2711, 3047],\n [2736, 3026],\n [2752, 3018],\n [2812, 3003],\n [2824, 3003],\n [2828, 3019],\n [2834, 3064],\n [2813, 3106],\n [2796, 3120],\n [2796, 3124],\n [2801, 3129]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '025',\n 'FIPS': '34025',\n 'STATE': 'NJ',\n 'NAME': 'Monmouth',\n 'LSAD': 'County'},\n 'id': 2195,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[2229, 2548],\n [2438, 2540],\n [2442, 2535],\n [2446, 2524],\n [2443, 2518],\n [2445, 2509],\n [2443, 2503],\n [2447, 2503],\n [2453, 2500],\n [2458, 2494],\n [2470, 2466],\n [2469, 2454],\n [2467, 2453],\n [2465, 2445],\n [2473, 2433],\n [2480, 2432],\n [2483, 2429],\n [2495, 2427],\n [2503, 2429],\n [2513, 2429],\n [2525, 2434],\n [2533, 2432],\n [2539, 2433],\n [2546, 2430],\n [2551, 2431],\n [2556, 2429],\n [2561, 2430],\n [2571, 2424],\n [2588, 2423],\n [2591, 2419],\n [2592, 2416],\n [2596, 2413],\n [2597, 2409],\n [2603, 2407],\n [2665, 2480],\n [2671, 2475],\n [2670, 2472],\n [2677, 2463],\n [2680, 2465],\n [2682, 2464],\n [2681, 2448],\n [2685, 2438],\n [2683, 2435],\n [2685, 2431],\n [2684, 2424],\n [2700, 2402],\n [2718, 2389],\n [2733, 2403],\n [2738, 2405],\n [2740, 2412],\n [2749, 2418],\n [2757, 2420],\n [2763, 2417],\n [2765, 2418],\n [2776, 2411],\n [2773, 2409],\n [2764, 2374],\n [2728, 2180],\n [2709, 2050],\n [2689, 1840],\n [2680, 1779],\n [2681, 1770],\n [2678, 1763],\n [2656, 1727],\n [2615, 1630],\n [2544, 1509],\n [2471, 1376],\n [2459, 1363],\n [2418, 1299],\n [2396, 1277],\n [2381, 1273],\n [2378, 1286],\n [2369, 1285],\n [2367, 1272],\n [2353, 1282],\n [2346, 1284],\n [2330, 1285],\n [2306, 1283],\n [2296, 1276],\n [2267, 1270],\n [2234, 1349],\n [2224, 1363],\n [2216, 1366],\n [2215, 1368],\n [2216, 1378],\n [2214, 1380],\n [2219, 1390],\n [2214, 1393],\n [2212, 1402],\n [2216, 1405],\n [2221, 1405],\n [2224, 1406],\n [2226, 1404],\n [2232, 1404],\n [2235, 1408],\n [2238, 1409],\n [2242, 1417],\n [2244, 1432],\n [2250, 1450],\n [2253, 1454],\n [2254, 1789],\n [2167, 1994],\n [2084, 2203],\n [2052, 2289],\n [2016, 2370],\n [2054, 2391],\n [2138, 2464],\n [2229, 2548]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '029',\n 'FIPS': '34029',\n 'STATE': 'NJ',\n 'NAME': 'Ocean',\n 'LSAD': 'County'},\n 'id': 2176,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[3554, 3986],\n [3563, 3979],\n [3567, 3971],\n [3568, 3972],\n [3574, 3953],\n [3579, 3944],\n [3583, 3941],\n [3585, 3898],\n [3597, 3881],\n [3604, 3879],\n [3602, 3864],\n [3612, 3843],\n [3615, 3828],\n [3661, 3502],\n [3660, 3492],\n [3660, 3476],\n [3661, 3473],\n [3658, 3473],\n [3661, 3384],\n [3622, 3372],\n [3572, 3360],\n [3440, 3315],\n [3442, 3337],\n [3428, 3340],\n [3388, 3342],\n [3336, 3332],\n [3179, 3335],\n [3179, 3339],\n [3189, 3349],\n [3195, 3352],\n [3204, 3352],\n [3203, 3354],\n [3203, 3370],\n [3192, 3388],\n [3190, 3387],\n [3189, 3389],\n [3178, 3384],\n [3178, 3386],\n [3171, 3387],\n [3163, 3394],\n [3162, 3415],\n [3193, 3431],\n [3194, 3438],\n [3198, 3438],\n [3198, 3437],\n [3197, 3432],\n [3201, 3434],\n [3198, 3446],\n [3199, 3457],\n [3217, 3463],\n [3222, 3468],\n [3217, 3493],\n [3221, 3519],\n [3220, 3551],\n [3222, 3558],\n [3219, 3578],\n [3214, 3600],\n [3228, 3606],\n [3247, 3611],\n [3258, 3633],\n [3256, 3658],\n [3190, 3712],\n [3190, 3709],\n [3159, 3751],\n [3180, 3790],\n [3179, 3801],\n [3217, 3851],\n [3220, 3859],\n [3214, 3875],\n [3216, 3877],\n [3239, 3884],\n [3294, 3859],\n [3323, 3872],\n [3325, 3900],\n [3344, 3928],\n [3355, 3938],\n [3365, 3941],\n [3379, 3938],\n [3402, 3947],\n [3411, 3956],\n [3448, 3972],\n [3454, 3972],\n [3480, 3959],\n [3522, 3970],\n [3528, 3967],\n [3550, 3977],\n [3554, 3986]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '059',\n 'FIPS': '36059',\n 'STATE': 'NY',\n 'NAME': 'Nassau',\n 'LSAD': 'County'},\n 'id': 2201,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[1749, 1707],\n [1837, 1634],\n [1842, 1625],\n [1846, 1623],\n [1851, 1615],\n [1854, 1606],\n [1854, 1601],\n [1860, 1591],\n [1863, 1569],\n [1861, 1566],\n [1862, 1563],\n [1860, 1560],\n [1863, 1559],\n [1863, 1554],\n [1862, 1550],\n [1865, 1546],\n [1861, 1538],\n [1863, 1530],\n [1861, 1521],\n [1866, 1520],\n [1868, 1518],\n [1868, 1512],\n [1871, 1511],\n [1874, 1515],\n [1878, 1514],\n [1878, 1509],\n [1888, 1510],\n [1889, 1505],\n [1890, 1504],\n [1893, 1505],\n [1896, 1513],\n [1900, 1513],\n [1902, 1507],\n [1902, 1501],\n [1906, 1499],\n [1910, 1503],\n [1911, 1509],\n [1914, 1512],\n [1916, 1512],\n [1926, 1505],\n [1929, 1506],\n [1936, 1502],\n [1954, 1488],\n [1964, 1484],\n [1966, 1481],\n [1969, 1471],\n [1975, 1468],\n [1983, 1458],\n [1992, 1459],\n [2000, 1455],\n [2015, 1457],\n [2022, 1442],\n [2033, 1434],\n [2031, 1425],\n [2034, 1417],\n [2037, 1413],\n [2045, 1411],\n [2051, 1405],\n [2054, 1403],\n [2059, 1403],\n [2067, 1411],\n [2072, 1412],\n [2076, 1404],\n [2080, 1402],\n [2088, 1403],\n [2092, 1395],\n [2099, 1391],\n [2101, 1381],\n [2103, 1379],\n [2108, 1379],\n [2113, 1383],\n [2120, 1382],\n [2126, 1372],\n [2130, 1369],\n [2134, 1371],\n [2139, 1377],\n [2144, 1379],\n [2148, 1379],\n [2150, 1376],\n [2152, 1366],\n [2154, 1362],\n [2158, 1361],\n [2162, 1367],\n [2162, 1378],\n [2164, 1382],\n [2169, 1384],\n [2172, 1383],\n [2176, 1378],\n [2172, 1363],\n [2178, 1354],\n [2182, 1350],\n [2185, 1349],\n [2190, 1353],\n [2190, 1359],\n [2184, 1369],\n [2184, 1374],\n [2187, 1376],\n [2191, 1377],\n [2199, 1373],\n [2201, 1373],\n [2209, 1380],\n [2214, 1380],\n [2216, 1378],\n [2215, 1368],\n [2216, 1366],\n [2224, 1363],\n [2234, 1349],\n [2267, 1270],\n [2296, 1276],\n [2306, 1283],\n [2330, 1285],\n [2346, 1284],\n [2353, 1282],\n [2367, 1272],\n [2365, 1261],\n [2373, 1242],\n [2378, 1240],\n [2382, 1233],\n [2378, 1218],\n [2334, 1144],\n [2287, 1088],\n [2229, 1041],\n [2227, 1018],\n [2221, 1010],\n [2152, 980],\n [2062, 921],\n [2033, 896],\n [2029, 900],\n [2023, 900],\n [2011, 893],\n [1994, 894],\n [1967, 914],\n [1960, 913],\n [1918, 882],\n [1913, 881],\n [1900, 886],\n [1889, 888],\n [1885, 887],\n [1879, 882],\n [1875, 875],\n [1870, 874],\n [1863, 877],\n [1862, 879],\n [1864, 890],\n [1849, 891],\n [1845, 889],\n [1845, 881],\n [1843, 876],\n [1840, 875],\n [1838, 877],\n [1840, 883],\n [1840, 887],\n [1837, 890],\n [1835, 890],\n [1831, 884],\n [1828, 883],\n [1824, 885],\n [1820, 883],\n [1816, 878],\n [1810, 879],\n [1805, 875],\n [1802, 878],\n [1798, 885],\n [1794, 884],\n [1791, 878],\n [1789, 880],\n [1788, 886],\n [1785, 886],\n [1782, 880],\n [1778, 881],\n [1773, 886],\n [1775, 892],\n [1773, 893],\n [1764, 888],\n [1758, 892],\n [1748, 893],\n [1744, 888],\n [1735, 885],\n [1726, 886],\n [1725, 891],\n [1720, 894],\n [1709, 889],\n [1706, 893],\n [1699, 894],\n [1696, 897],\n [1688, 894],\n [1687, 894],\n [1689, 902],\n [1679, 909],\n [1676, 908],\n [1671, 909],\n [1666, 905],\n [1664, 908],\n [1659, 908],\n [1656, 911],\n [1651, 909],\n [1646, 904],\n [1643, 907],\n [1629, 907],\n [1627, 909],\n [1620, 905],\n [1611, 916],\n [1602, 924],\n [1582, 926],\n [1576, 930],\n [1568, 932],\n [1568, 940],\n [1563, 948],\n [1562, 968],\n [1564, 974],\n [1564, 981],\n [1570, 1000],\n [1569, 1012],\n [1579, 1031],\n [1581, 1041],\n [1580, 1055],\n [1572, 1075],\n [1573, 1080],\n [1572, 1086],\n [1577, 1095],\n [1580, 1106],\n [1579, 1112],\n [1574, 1123],\n [1573, 1127],\n [1575, 1130],\n [1387, 1300],\n [1749, 1707]]]},\n 'properties': {'STATE_FIPS': '34',\n 'COUNTY_FIP': '001',\n 'FIPS': '34001',\n 'STATE': 'NJ',\n 'NAME': 'Atlantic',\n 'LSAD': 'County'},\n 'id': 2132,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[812, 261],\n [817, 258],\n [823, 260],\n [830, 256],\n [829, 253],\n [832, 246],\n [841, 253],\n [852, 234],\n [855, 234],\n [863, 248],\n [865, 247],\n [867, 241],\n [865, 234],\n [872, 231],\n [877, 233],\n [881, 240],\n [884, 239],\n [887, 237],\n [893, 238],\n [897, 245],\n [904, 244],\n [909, 239],\n [908, 233],\n [925, 218],\n [911, 191],\n [922, 169],\n [982, 102],\n [1027, 41],\n [1067, 0],\n [1088, -29],\n [1134, -61],\n [1170, -75],\n [1200, -74],\n [1224, -63],\n [1229, -53],\n [1224, -36],\n [1229, -35],\n [1235, -47],\n [1242, -80],\n [319, -80],\n [314, 0],\n [313, 14],\n [557, 24],\n [566, 35],\n [573, 39],\n [577, 38],\n [580, 39],\n [585, 47],\n [584, 51],\n [607, 62],\n [625, 105],\n [632, 110],\n [635, 109],\n [640, 111],\n [642, 113],\n [645, 122],\n [651, 125],\n [655, 131],\n [654, 143],\n [659, 152],\n [670, 156],\n [688, 166],\n [695, 162],\n [716, 169],\n [724, 169],\n [732, 165],\n [741, 169],\n [751, 171],\n [753, 174],\n [757, 171],\n [759, 179],\n [770, 176],\n [770, 182],\n [775, 181],\n [776, 177],\n [779, 178],\n [781, 180],\n [778, 187],\n [780, 192],\n [783, 193],\n [784, 195],\n [781, 200],\n [786, 213],\n [783, 211],\n [779, 215],\n [783, 218],\n [785, 221],\n [781, 233],\n [785, 238],\n [792, 244],\n [793, 250],\n [796, 251],\n [799, 247],\n [808, 249],\n [810, 260],\n [812, 261]]]},\n 'properties': {'STATE_FIPS': '10',\n 'COUNTY_FIP': '005',\n 'FIPS': '10005',\n 'STATE': 'DE',\n 'NAME': 'Sussex',\n 'LSAD': 'County'},\n 'id': 2175,\n 'type': 'Feature'},\n {'geometry': {'type': 'Polygon',\n 'coordinates': [[[4106, 4092],\n [4117, 4081],\n [4159, 4083],\n [4176, 4076],\n [4176, 3486],\n [4096, 3462],\n [3974, 3424],\n [3896, 3406],\n [3832, 3405],\n [3827, 3408],\n [3813, 3434],\n [3766, 3424],\n [3707, 3399],\n [3661, 3384],\n [3658, 3473],\n [3661, 3473],\n [3660, 3476],\n [3660, 3492],\n [3661, 3502],\n [3615, 3828],\n [3612, 3843],\n [3602, 3864],\n [3604, 3879],\n [3597, 3881],\n [3585, 3898],\n [3583, 3941],\n [3579, 3944],\n [3574, 3953],\n [3568, 3972],\n [3567, 3971],\n [3563, 3979],\n [3554, 3986],\n [3562, 4023],\n [3571, 4031],\n [3581, 4023],\n [3603, 4015],\n [3642, 4009],\n [3652, 3999],\n [3654, 3983],\n [3687, 3981],\n [3691, 3990],\n [3690, 4023],\n [3694, 4046],\n [3696, 4048],\n [3706, 4049],\n [3733, 4014],\n [3745, 4003],\n [3764, 3993],\n [3775, 3991],\n [3777, 3995],\n [3795, 3999],\n [3848, 3989],\n [3944, 3952],\n [4061, 3998],\n [4065, 4010],\n [4067, 4050],\n [4053, 4061],\n [4046, 4074],\n [4078, 4071],\n [4096, 4085],\n [4106, 4092]]]},\n 'properties': {'STATE_FIPS': '36',\n 'COUNTY_FIP': '103',\n 'FIPS': '36103',\n 'STATE': 'NY',\n 'NAME': 'Suffolk',\n 'LSAD': 'County'},\n 'id': 2231,\n 'type': 'Feature'}],\n 'type': 'FeatureCollection'}}" + }, + { + "objectID": "overview.html", + "href": "overview.html", + "title": "Cloud-Optimized Geospatial Formats Overview", + "section": "", + "text": "These slides were generated with https://quarto.org/docs/presentations/revealjs. Source: https://github.com/cloudnativegeo/cloud-optimized-geospatial-formats-guide." + }, + { + "objectID": "overview.html#what-does-cloud-optimized-mean-1", + "href": "overview.html#what-does-cloud-optimized-mean-1", + "title": "Cloud-Optimized Geospatial Formats Overview", + "section": "What Does Cloud-Optimized Mean?", + "text": "What Does Cloud-Optimized Mean?\n\nFile metadata in one read\nWhen accessing data over the internet, such as when data is in cloud storage, latency is high when compared with local storage so it is preferable to fetch lots of data in fewer reads.\nAn easy win is metadata in one read, which can be used to read a cloud-native dataset.\nA cloud-native dataset is one with small addressable chunks via files, internal tiles, or both." + }, + { + "objectID": "overview.html#what-does-cloud-optimized-mean-2", + "href": "overview.html#what-does-cloud-optimized-mean-2", + "title": "Cloud-Optimized Geospatial Formats Overview", + "section": "What Does Cloud-Optimized Mean?", + "text": "What Does Cloud-Optimized Mean?\n\n\n\nAccessible over HTTP using range requests.\nThis makes it compatible with object storage (a file storage alternative to local disk) and thus accessible via HTTP, from many compute instances.\nSupports lazy access and intelligent subsetting.\nIntegrates with high-level analysis libraries and distributed frameworks.\n\n\n\n\n\n\n\nimage credit: Ryan Abernathey" + }, + { + "objectID": "overview.html#what-are-cogs-1", + "href": "overview.html#what-are-cogs-1", + "title": "Cloud-Optimized Geospatial Formats Overview", + "section": "What are COGs?", + "text": "What are COGs?\n\n\n\nCOGs have internal file directories (IFDs) which are used to tell clients where to find different overview levels and data within the file.\nClients can use this metadata to read only the data they need to visualize or calculate.\nThis internal organization is friendly for consumption by clients issuing HTTP GET range request (“bytes: start_offset-end_offset” HTTP header)\n\n\n\n\n\n\n\nimage source: https://medium.com/devseed/cog-talk-part-1-whats-new-941facbcd3d1" + }, + { + "objectID": "overview.html#zarr-specs-in-development", + "href": "overview.html#zarr-specs-in-development", + "title": "Cloud-Optimized Geospatial Formats Overview", + "section": "Zarr Specs in Development", + "text": "Zarr Specs in Development\n\nV2 and older specs exist, however,\nA cross-organization working group has just formed to establish a GeoZarr standards working group, organized by Brianna Pagán (NASA) and includes representatives from many other orgs in the industry.\nThe GeoZarr spec defines conventions for how geospatial data should be organized in a Zarr store. The spec details how the Zarr DataArray and DataSet metadata, and subsequent organization of data, must be in order to be conformant as GeoZarr archive.\nThere is a proposal for Zarr v3 which will address challenges in language support, and storage organization to address the issues of high-latency reads and volume of reads for the many objects stored.\nThere is recent work on a parquet alternative to JSON for indexing." + }, + { + "objectID": "overview.html#copc-cloud-optimized-point-clouds", + "href": "overview.html#copc-cloud-optimized-point-clouds", + "title": "Cloud-Optimized Geospatial Formats Overview", + "section": "COPC (Cloud-Optimized Point Clouds)", + "text": "COPC (Cloud-Optimized Point Clouds)\n\n\n\nimage source: https://copc.io/\n\nPoint clouds are a set of data points in space, such as gathered from LiDAR measurements.\nCOPC is a valid LAZ file.\nSimilar to COGs but for point clouds: COPC is just one file, but data is reorganized into a clustered octree instead of regularly gridded overviews.\n2 key features:\n\nSupport for partial decompression via storage of data in a series of chunks\nVariable-length records (VLRs) can store application-specific metadata of any kind. VLRs describe the octree structure.\n\nLimitation: Not all attribute types are compatible." + }, + { + "objectID": "overview.html#not-quite", + "href": "overview.html#not-quite", + "title": "Cloud-Optimized Geospatial Formats Overview", + "section": "Not Quite", + "text": "Not Quite\n\nThese formats and their tooling are in active development\nSome formats were not mentioned, such as EPT, geopkg, tiledb, Cloud-Optimized HDF5. This presentation was scoped to those known best by the authors.\nThis site will continue to be updated with new content." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-examples.html", + "href": "cloud-optimized-geotiffs/cogs-examples.html", + "title": "Examples of Working with COGs", + "section": "", + "text": "The packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:\nconda create -f environment.yml\nor\nmamba create -f environment.yml\nThis notebook has been tested to work with the listed Conda environment." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-examples.html#environment", + "href": "cloud-optimized-geotiffs/cogs-examples.html#environment", + "title": "Examples of Working with COGs", + "section": "", + "text": "The packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:\nconda create -f environment.yml\nor\nmamba create -f environment.yml\nThis notebook has been tested to work with the listed Conda environment." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-examples.html#setup", + "href": "cloud-optimized-geotiffs/cogs-examples.html#setup", + "title": "Examples of Working with COGs", + "section": "Setup", + "text": "Setup\nFor demonstrating some COG concepts, we will download a regular GeoTIFF, create a Cloud-Optimized GeoTIFF and explore how they are different.\nFirst we use the earthaccess library to setup credentials to fetch data from NASA’s EarthData catalog.\n\nimport earthaccess\nimport rasterio\nfrom rasterio.plot import show\nfrom rio_cogeo import cog_validate, cog_info\n\n/Users/kyle/local/micromamba/envs/coguide-cog/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n from .autonotebook import tqdm as notebook_tqdm\n\n\n\nearthaccess.login()\n\nEARTHDATA_USERNAME and EARTHDATA_PASSWORD are not set in the current environment, try setting them or use a different strategy (netrc, interactive)\nYou're now authenticated with NASA Earthdata Login\nUsing token with expiration date: 10/24/2023\nUsing .netrc file for EDL\n\n\n<earthaccess.auth.Auth at 0x10427d390>" + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-examples.html#download-a-geotiff-from-earthdata", + "href": "cloud-optimized-geotiffs/cogs-examples.html#download-a-geotiff-from-earthdata", + "title": "Examples of Working with COGs", + "section": "Download a GeoTIFF from EarthData", + "text": "Download a GeoTIFF from EarthData\nNote: The whole point of is that we don’t download data. So in future examples, we will demonstrate how to access just subsets of data using COG and compare that with a GeoTIFF.\n\n# Download data\nshort_name = 'VCF5KYR'\nversion = '001'\n\nveg_item_results = earthaccess.search_data(\n short_name=short_name,\n version=version,\n count=1\n)\n\nGranules found: 33\n\n\n\ntest_data_dir = \"./test_data\"\nveg_files = earthaccess.download(veg_item_results, test_data_dir)\nveg_gtiff_filename = f\"{test_data_dir}/{veg_files[0]}\"\n\n Getting 1 granules, approx download size: 0.07 GB\nFile VCF5KYR_1982001_001_2018224204211.tif already downloaded\n\n\nQUEUEING TASKS | : 100%|██████████| 1/1 [00:00<00:00, 900.84it/s]\nPROCESSING TASKS | : 100%|██████████| 1/1 [00:00<00:00, 15887.52it/s]\nCOLLECTING RESULTS | : 100%|██████████| 1/1 [00:00<00:00, 29330.80it/s]\n\n\n\nTo learn more about the example data see the Vegetation Continuous Fields (VCF) information page." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-examples.html#is-it-a-valid-cog", + "href": "cloud-optimized-geotiffs/cogs-examples.html#is-it-a-valid-cog", + "title": "Examples of Working with COGs", + "section": "Is it a valid COG?", + "text": "Is it a valid COG?\nWe can use rio_cogeo.cog_validate to check. It returns is_valid, errors and warnings.\n\ncog_validate(veg_gtiff_filename)\n\nThe following warnings were found:\n- The file is greater than 512xH or 512xW, it is recommended to include internal overviews\n\nThe following errors were found:\n- The file is greater than 512xH or 512xW, but is not tiled\n\n\n(False,\n ['The file is greater than 512xH or 512xW, but is not tiled'],\n ['The file is greater than 512xH or 512xW, it is recommended to include internal overviews'])\n\n\nReturn values:\n\nis_valid is False: this is not a valid COG.\nerrors are 'The file is greater than 512xH or 512xW, but is not tiled'. To be a valid COG, the file should be tiled since it has a height and width both greater than 512.\nwarnings are 'The file is greater than 512xH or 512xW, it is recommended to include internal overviews'. It is recommended to provide overviews." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-examples.html#converting-a-geotiff-to-cog", + "href": "cloud-optimized-geotiffs/cogs-examples.html#converting-a-geotiff-to-cog", + "title": "Examples of Working with COGs", + "section": "Converting a GeoTIFF to COG", + "text": "Converting a GeoTIFF to COG\nWe can use rio_cogeo.cog_create to convert a GeoTIFF into a Cloud Optimized GeoTIFF\n\nveg_cog_filename = veg_gtiff_filename.replace(\".tif\", \"_cog.tif\")\n\n!rio cogeo create {veg_gtiff_filename} {veg_cog_filename}\n\nReading input: /Users/kyle/ds/cloud-optimized-geospatial-formats-guide/cloud-optimized-geotiffs/test_data/VCF5KYR_1982001_001_2018224204211.tif\n [####################################] 100%\nAdding overviews...\nUpdating dataset tags...\nWriting output to: /Users/kyle/ds/cloud-optimized-geospatial-formats-guide/cloud-optimized-geotiffs/test_data/VCF5KYR_1982001_001_2018224204211_cog.tif\n\n\n\ncog_validate(veg_cog_filename)\n\n(True, [], [])\n\n\nThis is a valid COG, so we will use it to compare with our GeoTIFF." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-examples.html#data-structure", + "href": "cloud-optimized-geotiffs/cogs-examples.html#data-structure", + "title": "Examples of Working with COGs", + "section": "Data Structure", + "text": "Data Structure\nDimensions Dimensions are the number of bands, rows and columns stored in a GeoTIFF. More Info\nInternal Blocks (aka chunks or internal tiles) Internal blocks are required if the dimensions of data are over 512x512. More Info\nLet’s check out the dimensions and blocks of our GeoTIFF and Cloud-Optimized GeoTIFF.\n\nveg_gtiff_rio = rasterio.open(veg_gtiff_filename)\nveg_cog_rio = rasterio.open(veg_cog_filename)\n\n\nprint(veg_gtiff_rio.shape)\nveg_cog_rio.shape\n\n(3600, 7200)\n\n\n(3600, 7200)\n\n\nThey have the same dimensions which is what we expect, so that is good!\nWe can also print information about the GeoTIFF’s IFD (Internal File Directory). Only one item is returned because the GeoTIFF doesn’t have overviews. When we print the IFD info for the COG, which has overviews, we see more items returned.\n\ncog_info(veg_gtiff_filename).IFD\n\n[IFD(Level=0, Width=7200, Height=3600, Blocksize=(1, 7200), Decimation=0)]\n\n\n\ncog_info(veg_cog_filename).IFD\n\n[IFD(Level=0, Width=7200, Height=3600, Blocksize=(512, 512), Decimation=0),\n IFD(Level=1, Width=3600, Height=1800, Blocksize=(128, 128), Decimation=2),\n IFD(Level=2, Width=1800, Height=900, Blocksize=(128, 128), Decimation=4),\n IFD(Level=3, Width=900, Height=450, Blocksize=(128, 128), Decimation=8)]\n\n\nNote for IFD Level 0, the regular GeoTIFF has a blocksize of (1, 7200) which implies each row of data is a separate block. So whenever reading in data, even if only a few columns are required, the full row must be read." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-examples.html#overviews", + "href": "cloud-optimized-geotiffs/cogs-examples.html#overviews", + "title": "Examples of Working with COGs", + "section": "Overviews", + "text": "Overviews\nOverviews are downsampled (aggregated) data intended for visualization.\nThe smallest size overview should match the tiling components’ fetch size, typically 256x256. Due to aspect ratio variation just aim to have at least one dimension at or slightly less than 256. > The COG driver in GDAL, or rio cogeo tools should do this.\nThere are many resampling algorithms for generating overviews. The best resampling algorithm depends on the range, type, and distribution of the data. When creating overviews several options should be compared before deciding which resampling method to apply.\nGDAL >= 3.2 allows for the overview resampling method to be set directly.\n\n\nveg_gtiff_rio.overviews(1)\n\n[]\n\n\n\nveg_cog_rio.overviews(1)\n\n[2, 4, 8]\n\n\nBy displaying each overview, we can see how the dimensions get coarser for each overview level.\n\ndef show_overviews(geotiff): \n for overview in geotiff.overviews(1):\n out_height = int(geotiff.height // overview)\n out_width = int(geotiff.width // overview)\n print(f\"out height: {out_height}\")\n print(f\"out width: {out_width}\") \n # read first band of file and set shape of new output array\n window_size_height = round(out_height/8)\n window_size_width = round(out_width/8)\n image = veg_cog_rio.read(1, out_shape=(1, out_height, out_width))[\n window_size_height:(window_size_height*2),\n window_size_width:(window_size_width*2),\n ]\n show(image)\n \nshow_overviews(veg_cog_rio)\n\nout height: 1800\nout width: 3600\nout height: 900\nout width: 1800\nout height: 450\nout width: 900\n\n\n\n\n\n\n\n\n\n\n\nWe can generate more and different overviews, through different tilesizes and resampling.\n\nimport gen_overviews\n\n\ntmp_dst = gen_overviews.create_overviews_from_gtiff(veg_gtiff_rio)\ntmp_cog = rasterio.open(tmp_dst)\ncog_info(tmp_dst).IFD\n\n\n\n\n[IFD(Level=0, Width=7200, Height=3600, Blocksize=(1, 7200), Decimation=0),\n IFD(Level=1, Width=3600, Height=1800, Blocksize=(128, 128), Decimation=2),\n IFD(Level=2, Width=1800, Height=900, Blocksize=(128, 128), Decimation=4),\n IFD(Level=3, Width=900, Height=450, Blocksize=(128, 128), Decimation=8),\n IFD(Level=4, Width=450, Height=225, Blocksize=(128, 128), Decimation=16)]\n\n\nNote: Now we have overviews but there are still no tiles on the Level 0 IFD.\n\noverviews = tmp_cog.overviews(1)\noverviews\n\n[2, 4, 8, 16]\n\n\n\nshow_overviews(tmp_cog)\n\nout height: 1800\nout width: 3600\nout height: 900\nout width: 1800\nout height: 450\nout width: 900\nout height: 225\nout width: 450" + }, + { + "objectID": "geoparquet/geoparquet-example.html", + "href": "geoparquet/geoparquet-example.html", + "title": "GeoParquet Example", + "section": "", + "text": "This notebook will give an overview of how to read and write GeoParquet files with GeoPandas, putting an emphasis on cloud-native operations where possible.\nThe easiest way to read and write GeoParquet files is to use GeoPandas’ read_parquet and to_parquet functions." + }, + { + "objectID": "geoparquet/geoparquet-example.html#environment", + "href": "geoparquet/geoparquet-example.html#environment", + "title": "GeoParquet Example", + "section": "Environment", + "text": "Environment\nThe packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:\nconda create -f environment.yml\nor\nmamba create -f environment.yml\nThis notebook has been tested to work with the listed Conda environment. If you don’t want to use Conda or Mamba, install the latest versions of geopandas, fsspec, and pyarrow with pip. Note that you’ll also need the GDAL CLI with Parquet driver. If you’re on MacOS, you can install that via brew install gdal." + }, + { + "objectID": "geoparquet/geoparquet-example.html#imports", + "href": "geoparquet/geoparquet-example.html#imports", + "title": "GeoParquet Example", + "section": "Imports", + "text": "Imports\n\nfrom urllib.request import urlretrieve\n\nimport fsspec\nimport geopandas as gpd\nfrom fsspec.implementations.http import HTTPFileSystem" + }, + { + "objectID": "geoparquet/geoparquet-example.html#comparison-with-flatgeobuf", + "href": "geoparquet/geoparquet-example.html#comparison-with-flatgeobuf", + "title": "GeoParquet Example", + "section": "Comparison with FlatGeobuf", + "text": "Comparison with FlatGeobuf\nIn order to compare reading GeoParquet with FlatGeobuf, we’ll cover reading and writing GeoParquet files on local disk storage. To be consistent with the FlatGeobuf example, we’ll fetch the same US counties FlatGeobuf file (13 MB) and convert it to GeoParquet using ogr2ogr.\n\n# URL to download\nurl = \"https://flatgeobuf.org/test/data/UScounties.fgb\"\n\n# Download, saving to the current directory\nlocal_fgb_path, _ = urlretrieve(url, \"countries.fgb\")\n\n\n!ogr2ogr countries.parquet countries.fgb\n\nLoading this GeoParquet file is really fast! 13% faster than loading the same data via FlatGeobuf (shown in the FlatGeobuf example notebook).\n\n%time gdf = gpd.read_parquet(\"countries.parquet\")\n\nCPU times: user 23.8 ms, sys: 11.8 ms, total: 35.6 ms\nWall time: 34.1 ms\n\n\n\ngdf\n\n\n\n\n\n\n\n\nSTATE_FIPS\nCOUNTY_FIP\nFIPS\nSTATE\nNAME\nLSAD\ngeometry\n\n\n\n\n0\n23\n009\n23009\nME\nHancock\nCounty\nMULTIPOLYGON (((-68.53108 44.33278, -68.53348 ...\n\n\n1\n33\n007\n33007\nNH\nCoos\nCounty\nMULTIPOLYGON (((-71.05975 45.01485, -71.06939 ...\n\n\n2\n50\n009\n50009\nVT\nEssex\nCounty\nMULTIPOLYGON (((-71.49463 44.90874, -71.49392 ...\n\n\n3\n50\n019\n50019\nVT\nOrleans\nCounty\nMULTIPOLYGON (((-72.14193 45.00600, -72.16051 ...\n\n\n4\n23\n007\n23007\nME\nFranklin\nCounty\nMULTIPOLYGON (((-70.83471 45.27514, -70.77984 ...\n\n\n...\n...\n...\n...\n...\n...\n...\n...\n\n\n3216\n15\n003\n15003\nHI\nHonolulu\nCounty\nMULTIPOLYGON (((-171.73761 25.79210, -171.7513...\n\n\n3217\n15\n007\n15007\nHI\nKauai\nCounty\nMULTIPOLYGON (((-160.55535 21.66345, -160.5541...\n\n\n3218\n15\n009\n15009\nHI\nMaui\nCounty\nMULTIPOLYGON (((-157.06121 20.89150, -157.0611...\n\n\n3219\n15\n001\n15001\nHI\nHawaii\nCounty\nMULTIPOLYGON (((-155.08767 19.72887, -155.0909...\n\n\n3220\n15\n005\n15005\nHI\nKalawao\nCounty\nMULTIPOLYGON (((-157.01455 21.18550, -157.0145...\n\n\n\n\n3221 rows × 7 columns" + }, + { + "objectID": "geoparquet/geoparquet-example.html#writing-to-local-disk", + "href": "geoparquet/geoparquet-example.html#writing-to-local-disk", + "title": "GeoParquet Example", + "section": "Writing to local disk", + "text": "Writing to local disk\nWe can use GeoDataFrame.to_parquet to write out this data to GeoParquet files locally. This is about 3x faster than writing the same dataset to FlatGeobuf, but note that FlatGeobuf’s writing is also calculating a spatial index.\n\n%time gdf.to_parquet(\"countries_written.parquet\")\n\nCPU times: user 42.3 ms, sys: 12.6 ms, total: 55 ms\nWall time: 53.9 ms" + }, + { + "objectID": "geoparquet/geoparquet-example.html#reading-from-the-cloud", + "href": "geoparquet/geoparquet-example.html#reading-from-the-cloud", + "title": "GeoParquet Example", + "section": "Reading from the cloud", + "text": "Reading from the cloud\nAs of GeoParquet version 1.0.0-rc.1, spatial indexing has not yet been implemented. Therefore, there is not yet an API in GeoPandas to read data given a specific bounding box.\nWhat is already efficient in GeoParquet is reading only specified columns from a dataset.\n\nurl = \"https://data.source.coop/cholmes/eurocrops/unprojected/geoparquet/FR_2018_EC21.parquet\"\n\nNote that since we’re fetching this data directly from the cloud, we need to pass in an fsspec filesystem object. Otherwise GeoPandas will attempt to load a local file.\n\nfilesystem = HTTPFileSystem()\n\nBy default, calling read_parquet will fetch the entire file and parse it all into a single GeoDataFrame. Since this is a 3GB file, downloading the file takes a long time:\n\n# This cell will take a few minutes to run, because it downloads the entire file\n# %time gdf = gpd.read_parquet(url, filesystem=filesystem)\n\nWe can make this faster by only fetching specific columns. Because GeoParquet stores data in a columnar fashion, when selecting only specific columns we can download a lot less data.\n\n# This cell will take a few minutes to run, because it downloads the entire file for these columns\n# %time gdf = gpd.read_parquet(url, columns=[\"ID_PARCEL\", \"geometry\"], filesystem=filesystem)" + }, + { + "objectID": "geoparquet/geoparquet-example.html#working-with-geoparquet-row-groups-advanced", + "href": "geoparquet/geoparquet-example.html#working-with-geoparquet-row-groups-advanced", + "title": "GeoParquet Example", + "section": "Working with GeoParquet row groups (Advanced)", + "text": "Working with GeoParquet row groups (Advanced)\nAs described in the intro document, GeoParquet is a chunked format, which allows you to access one of the chunks of rows very efficiently. This can allow you to stream a dataset — loading and operating on one chunk at a time — if the dataset is larger than your memory.\nGeoPandas does not yet have built-in support for working with row groups, so this section will use the underlying pyarrow library directly.\n\nimport pyarrow.parquet as pq\nfrom geopandas.io.arrow import _arrow_to_geopandas\n\nFirst, we’ll create a ParquetFile object from the remote URL. All this does is load the metadata from the file, allowing you to inspect the schema and number of columns, rows, and row groups. Because this doesn’t load any actual data, it’s nearly instant to complete.\n\nparquet_file = pq.ParquetFile(url, filesystem=filesystem)\n\nWe can access the column names in the dataset:\n\nparquet_file.schema_arrow.names\n\n['ID_PARCEL',\n 'SURF_PARC',\n 'CODE_CULTU',\n 'CODE_GROUP',\n 'CULTURE_D1',\n 'CULTURE_D2',\n 'EC_org_n',\n 'EC_trans_n',\n 'EC_hcat_n',\n 'EC_hcat_c',\n 'geometry']\n\n\nThis Parquet file includes 9.5 million rows:\n\nparquet_file.metadata.num_rows\n\n9517874\n\n\nAnd 146 row groups. Given that each row group is about the same number of rows, each one contains around 65,000 rows.\n\nparquet_file.num_row_groups\n\n146\n\n\nThen to load one of the row groups by numeric index, we can call ParquetFile.read_row_group.\n\npyarrow_table = parquet_file.read_row_group(0)\n\nNote that this returns a pyarrow.Table, not a geopandas.GeoDataFrame. To convert between the two, we can use _arrow_to_geopandas. This conversion is very fast.\n\ngeopandas_gdf = _arrow_to_geopandas(pyarrow_table, parquet_file.metadata.metadata)\n\nAs expected, this row group contains right around 65,000 rows\n\ngeopandas_gdf.shape\n\n(65536, 11)\n\n\n\ngeopandas_gdf.head()\n\n\n\n\n\n\n\n\nID_PARCEL\nSURF_PARC\nCODE_CULTU\nCODE_GROUP\nCULTURE_D1\nCULTURE_D2\nEC_org_n\nEC_trans_n\nEC_hcat_n\nEC_hcat_c\ngeometry\n\n\n\n\n0\n123563\n6.38\nCZH\n5\nNone\nNone\nColza d’hiver\nWinter rapeseed\nwinter_rapeseed_rape\n3301060401\nMULTIPOLYGON (((3.33896 49.84122, 3.33948 49.8...\n\n\n1\n5527076\n2.30\nPPH\n18\nNone\nNone\nPrairie permanente - herbe prédominante (resso...\nPermanent pasture - predominantly grass (woody...\npasture_meadow_grassland_grass\n3302000000\nMULTIPOLYGON (((-1.44483 49.61280, -1.44467 49...\n\n\n2\n11479241\n6.33\nPPH\n18\nNone\nNone\nPrairie permanente - herbe prédominante (resso...\nPermanent pasture - predominantly grass (woody...\npasture_meadow_grassland_grass\n3302000000\nMULTIPOLYGON (((2.87821 46.53674, 2.87820 46.5...\n\n\n3\n12928442\n5.10\nPPH\n18\nNone\nNone\nPrairie permanente - herbe prédominante (resso...\nPermanent pasture - predominantly grass (woody...\npasture_meadow_grassland_grass\n3302000000\nMULTIPOLYGON (((-0.19026 48.28723, -0.19025 48...\n\n\n4\n318389\n0.92\nPPH\n18\nNone\nNone\nPrairie permanente - herbe prédominante (resso...\nPermanent pasture - predominantly grass (woody...\npasture_meadow_grassland_grass\n3302000000\nMULTIPOLYGON (((5.72084 44.03576, 5.72081 44.0...\n\n\n\n\n\n\n\nAs before, we can speed up the data fetching by requesting only specific columns in the read_row_group call.:\n\npyarrow_table = parquet_file.read_row_group(0, columns=[\"ID_PARCEL\", \"geometry\"])\n\nThen the resulting GeoDataFrame will only have those two columns:\n\n_arrow_to_geopandas(pyarrow_table, parquet_file.metadata.metadata).head()\n\n\n\n\n\n\n\n\nID_PARCEL\ngeometry\n\n\n\n\n0\n123563\nMULTIPOLYGON (((3.33896 49.84122, 3.33948 49.8...\n\n\n1\n5527076\nMULTIPOLYGON (((-1.44483 49.61280, -1.44467 49...\n\n\n2\n11479241\nMULTIPOLYGON (((2.87821 46.53674, 2.87820 46.5...\n\n\n3\n12928442\nMULTIPOLYGON (((-0.19026 48.28723, -0.19025 48...\n\n\n4\n318389\nMULTIPOLYGON (((5.72084 44.03576, 5.72081 44.0..." + }, + { + "objectID": "cookbooks/index.html", + "href": "cookbooks/index.html", + "title": "Cloud-Optimized Cookbooks", + "section": "", + "text": "Cookbooks should address common questions and present solutions for cloud-optimized access and visualization.\nCookbooks:\n\nZarr Visualization Cookbook (in development)" + }, + { + "objectID": "flatgeobuf/intro.html", + "href": "flatgeobuf/intro.html", + "title": "FlatGeobuf", + "section": "", + "text": "FlatGeobuf\nFlatGeobuf is a binary file format for geographic vector data, such as points, lines, and polygons.\nUnlike some formats like Cloud-Optimized GeoTIFF, which builds on the previous success of TIFF and GeoTIFF, FlatGeobuf is a new format, designed from the ground up to be faster for geospatial data.\nFlatGeobuf is widely supported — via its GDAL implementation — in many programming languages as well as applications like QGIS.\nFlatGeobuf supports any vector geometry type defined in the OGC Simple Features specification. This includes the standard building blocks of Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, and GeometryCollection, but also includes more obscure types such as CircularString, Surface, and TIN (Triangulated irregular network). A best practice is to store only geometries with the same type, as that allows readers to know which geometry type is stored without scanning the entire file.\nAn optional row-based spatial index optimizes for remote reading.\n\nFile layout\nThe internal layout of the file has four sections: magic bytes (aka signature), header, index, and data (aka features).\n\n\nImage source: Horace Williams, Kicking the Tires: Flatgeobuf\n\n\nThe file signature is 8 “magic bytes” indicating the file type and specification version, which allows readers to know a file is FlatGeobuf, even if it’s missing a file extension.\nNext comes the header, which stores the bounding box of the dataset, the geometry type of the features (if known and unique), the attribute schema, the number of features, and coordinate reference system information.\nAfter the file header is an optional spatial index. If included, this lets a reader skip reading features that are not within a provided spatial query.\nLast come the individual features. The rest of the file is a sequence of feature records, placed end to end in a row-wise fashion.\n\n\n\nRow based\nInternally, features are laid out in a row-oriented fashion rather than a column-oriented fasion. This means that it’s relatively cheap to select specific records from the file, but relatively expensive to select a specific column. This is ideal for a small spatial query (assuming an index exists in the file) but to load all geometries requires loading all attribute information as well.\n\n\nNo internal compression\nFlatGeobuf does not support compression while maintaining the ability to seek within the file. In particular, FlatGeobuf’s spatial index describes the byte ranges in the uncompressed file. Those byte ranges will be incorrect if the file is compressed.\nA compression like gzip can be applied to the FlatGeobuf file in full, but keep in mind that storing the compressed file will eliminate random access support.\n\n\nNo append support\nFlatGeobuf is a write-only format, and doesn’t support appending, as that would invalidate the spatial index in the file.\n\n\nRandom access supported via spatial index\nFlatGeobuf optionally supports a spatial index at the beginning of the file, which can speed up reading portions of a file based on a spatial query. For more information on how this spatial index works, refer to the Hilbert R Tree page.\n\n\n\n\n\n\nNote\n\n\n\nNote that because FlatGeobuf has no internal chunking, the spatial index references every single object in the file. This means that for datasets with many small geometries, like points, the spatial index will be very large as a proportion of the file size.\n\n\n\n\n\nStreaming features is supported\nFlatGeobuf supports streaming, meaning that you can use part of the file before the entire file has finished downloading. This is different than random access, because you have no ability to skip around in the file.\nStreaming can be valuable because it makes an application seem more responsive; you can have something happen without having to wait for the full download to complete. A good example of this is this example by FlatGeobuf’s author Björn Harrtell. As the file is downloaded to the browser, portions of the file get rendered progressively in parts.\nThis works even with full-file compression like gzip or deflate because those compression algorithms support streaming decompression.\n\n\nBroad type system\nFlatGeobuf supports attributes with a range of types:\n\nByte: Signed 8-bit integer\nUByte: Unsigned 8-bit integer\nBool: Boolean\nShort: Signed 16-bit integer\nUShort: Unsigned 16-bit integer\nInt: Signed 32-bit integer\nUInt: Unsigned 32-bit integer\nLong: Signed 64-bit integer\nULong: Unsigned 64-bit integer\nFloat: Single precision floating point number\nDouble: Double precision floating point number\nString: UTF8 string\nJson: General JSON type intended to be application specific\nDateTime: ISO 8601 date time\nBinary: General binary type intended to be application specific\n\n\n\n\n\n\n\nNote\n\n\n\nNote that FlatGeobuf is unable to store nested types without overhead. It doesn’t support a “list” or “dict” type apart from JSON, which has a parsing overhead.\nIn some situations, having strong nested type support can be useful. For example STAC stored as GeoParquet has columns that are nested, such as the assets column that needs to store a dictionary-like mapping from asset names to their information. FlatGeobuf is able to store such data by serializing it to JSON, but it’s not possible to see the nested schema before parsing the full dataset.\n\n\n\n\nKnown table schema\nFlatGeobuf declares the schema of properties at the beginning of the file. This makes it much easier to read the file — compared to a fully schemaless format like GeoJSON — because the reader knows what data type each attribute has in advance.\n\n\nReferences\n\nflatgeobuf.org: Official project website.\nFlatgeobuf: Implementer’s Guide" + }, + { + "objectID": "flatgeobuf/flatgeobuf.html", + "href": "flatgeobuf/flatgeobuf.html", + "title": "FlatGeobuf example", + "section": "", + "text": "This notebook will give an overview of how to read and write FlatGeobuf files with GeoPandas, putting an emphasis on cloud-native operations where possible.\nThe primary way to interact with FlatGeobuf in Python is via bindings to GDAL, as there is no pure-Python implementation of FlatGeobuf.\nThere are two different Python libraries for interacting between Python and GDAL’s vector support: fiona and pyogrio. Both of these are integrated into geopandas.read_file via the engine keyword, but pyogrio is much faster. Set engine=\"pyogrio\" when using read_file or GeoDataFrame.to_file to speed up reading and writing significantly. We also suggest passing use_arrow=True when reading for a slight extra speedup (this is not supported when writing)." + }, + { + "objectID": "flatgeobuf/flatgeobuf.html#local-vs-remote-reading", + "href": "flatgeobuf/flatgeobuf.html#local-vs-remote-reading", + "title": "FlatGeobuf example", + "section": "Local vs Remote reading", + "text": "Local vs Remote reading\nThe cloud-native vector ecosystem is young and doesn’t work as seamlessly as the COG and Zarr for subsetted access. We download data here to demonstrate important concepts but look to update these methods once better datasets and tools are available for working with FlatGeobuf without downloading entire files.\nAt the end of the notebook we have an example with reading via a spatial filter. Keep in mind that using a large spatial filter will cause the read to take a long time." + }, + { + "objectID": "flatgeobuf/flatgeobuf.html#environment", + "href": "flatgeobuf/flatgeobuf.html#environment", + "title": "FlatGeobuf example", + "section": "Environment", + "text": "Environment\nThe packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:\nconda create -f environment.yml\nor\nmamba create -f environment.yml\nAlternatively, you can install the versions of pyogrio and geopandas used in this notebook with pip:\npip install pyogrio==0.6.0 geopandas==0.13.2" + }, + { + "objectID": "flatgeobuf/flatgeobuf.html#imports", + "href": "flatgeobuf/flatgeobuf.html#imports", + "title": "FlatGeobuf example", + "section": "Imports", + "text": "Imports\n\nfrom tempfile import TemporaryDirectory\nfrom urllib.request import urlretrieve\n\nimport geopandas as gpd\nimport pyogrio" + }, + { + "objectID": "flatgeobuf/flatgeobuf.html#reading-from-local-disk", + "href": "flatgeobuf/flatgeobuf.html#reading-from-local-disk", + "title": "FlatGeobuf example", + "section": "Reading from local disk", + "text": "Reading from local disk\nFirst we’ll cover reading FlatGeobuf from local disk storage. As a first example, we’ll use the US counties FlatGeobuf data from this example. This file is only 13 MB in size, which we’ll download to cover simple loading from disk.\n\n# Create a temporary directory in which to save the file\ntmpdir = TemporaryDirectory()\n\n# URL to download\nurl = \"https://flatgeobuf.org/test/data/UScounties.fgb\"\n\n# Download, saving the output path\nlocal_fgb_path, _ = urlretrieve(url, f\"{tmpdir.name}/countries.fgb\")\n\nIn each of the cases below, we use geopandas.read_file to read the file into a GeoDataFrame.\nFirst we’ll show that reading this file with engine=\"fiona\" (the default) is slower. Taking an extra 500 milliseconds might not seem like a lot, but this file contains only 3,000 rows, so this difference gets magnified with larger files.\n\n%time gdf = gpd.read_file(local_fgb_path, engine=\"fiona\")\n\nCPU times: user 565 ms, sys: 16.9 ms, total: 582 ms\nWall time: 685 ms\n\n\nPassing engine=\"pyogrio\" speeds up loading by 18x here!\n\n%time gdf = gpd.read_file(local_fgb_path, engine=\"pyogrio\")\n\nCPU times: user 25.3 ms, sys: 6.84 ms, total: 32.1 ms\nWall time: 31.3 ms\n\n\nUsing use_arrow=True often makes loading slightly faster again! We’re now 21x faster than using fiona.\n\n%time gdf = gpd.read_file(local_fgb_path, engine=\"pyogrio\", use_arrow=True)\n\nCPU times: user 19.7 ms, sys: 10.1 ms, total: 29.7 ms\nWall time: 29.1 ms" + }, + { + "objectID": "flatgeobuf/flatgeobuf.html#writing-to-local-disk", + "href": "flatgeobuf/flatgeobuf.html#writing-to-local-disk", + "title": "FlatGeobuf example", + "section": "Writing to local disk", + "text": "Writing to local disk\nSimilarly, we can use GeoDataFrame.to_file to write to a local FlatGeobuf file. As expected, writing can be much faster if you pass engine=\"pyogrio\".\nBy default, this writes a spatial index to the created FlatGeobuf file.\n\n%time gdf.to_file(f\"{tmpdir.name}/out_fiona.fgb\")\n\nCPU times: user 362 ms, sys: 44.4 ms, total: 407 ms\nWall time: 418 ms\n\n\n\n%time gdf.to_file(f\"{tmpdir.name}/out_pyogrio.fgb\", engine=\"pyogrio\")\n\nCPU times: user 60.8 ms, sys: 23.4 ms, total: 84.2 ms\nWall time: 83.5 ms" + }, + { + "objectID": "flatgeobuf/flatgeobuf.html#reading-from-the-cloud", + "href": "flatgeobuf/flatgeobuf.html#reading-from-the-cloud", + "title": "FlatGeobuf example", + "section": "Reading from the cloud", + "text": "Reading from the cloud\nKnowing how to read and write local files is important, but given that FlatGeobuf is a cloud-optimized format, it’s important to be able to read from cloud-hosted files as well.\nFor this example, we’ll use the EuroCrops data hosted on Source Cooperative because it has versions of the same data in both FlatGeobuf and GeoParquet format. Hopefully using the same dataset for both the FlatGeobuf and GeoParquet example notebooks will be helpful.\n\nurl = \"https://data.source.coop/cholmes/eurocrops/unprojected/flatgeobuf/FR_2018_EC21.fgb\"\n\nUsually when reading from the cloud, you want to filter on some spatial extent. Pyogrio offers a read_info function to access many pieces of information about the file:\n\npyogrio.read_info(url)\n\n{'crs': 'EPSG:4326',\n 'encoding': 'UTF-8',\n 'fields': array(['ID_PARCEL', 'SURF_PARC', 'CODE_CULTU', 'CODE_GROUP', 'CULTURE_D1',\n 'CULTURE_D2', 'EC_org_n', 'EC_trans_n', 'EC_hcat_n', 'EC_hcat_c'],\n dtype=object),\n 'dtypes': array(['object', 'float64', 'object', 'object', 'object', 'object',\n 'object', 'object', 'object', 'object'], dtype=object),\n 'geometry_type': 'MultiPolygon',\n 'features': 9517874,\n 'driver': 'FlatGeobuf',\n 'capabilities': {'random_read': 1,\n 'fast_set_next_by_index': 0,\n 'fast_spatial_filter': 1},\n 'layer_metadata': None,\n 'dataset_metadata': None}\n\n\n\n\n\n\n\n\nNote\n\n\n\nSadly the output of read_info does not yet include the bounding box of the file, even though the FlatGeobuf file contains that information in the header. This may be a reason to consider externalizing metadata using Spatio-Temporal Asset Catalog files (STAC) in the future.\n\n\nFor now we’ll hard-code a region around Valence in the south of France, which we know the be within our dataset.\n\n# The order of bounds is\n# (min longitude, min latitude, max longitude, max latitude)\nbounds = (4.301042, 44.822783, 4.410535, 44.877149)\n\nWe can fetch a dataframe containing only the records in these bounds by passing a bbox argument to read_file. Note that the Coordinate Reference System of this bounding box must match the CRS of the dataset. Here, we know from the output of read_info that the CRS of the dataset is EPSG:4326, so we can pass a longitude-latitude bounding box.\n\n%time crops_gdf = gpd.read_file(url, bbox=bounds)\n\nCPU times: user 144 ms, sys: 21.4 ms, total: 165 ms\nWall time: 6 s\n\n\nPassing engine=\"pyogrio\" is only slightly faster, which may mean that most of the time is taken up in network requests, not in parsing the actual data into Python.\n\n%time crops_gdf = gpd.read_file(url, bbox=bounds, engine=\"pyogrio\")\n\nCPU times: user 26.9 ms, sys: 2.98 ms, total: 29.9 ms\nWall time: 490 ms\n\n\nThis gives us a much smaller dataset of only 400 rows (down from 9.5 million rows in the original dataset).\n\ncrops_gdf.head()\n\n\n\n\n\n\n\n\nID_PARCEL\nSURF_PARC\nCODE_CULTU\nCODE_GROUP\nCULTURE_D1\nCULTURE_D2\nEC_org_n\nEC_trans_n\nEC_hcat_n\nEC_hcat_c\ngeometry\n\n\n\n\n0\n9484573\n11.08\nSPL\n17\nNone\nNone\nSurface pastorale - ressources fourragères lig...\nPastoral area - predominant woody fodder resou...\nother_tree_wood_forest\n3306990000\nMULTIPOLYGON (((4.41142 44.85441, 4.41145 44.8...\n\n\n1\n487218\n2.53\nPPH\n18\nNone\nNone\nPrairie permanente - herbe prédominante (resso...\nPermanent pasture - predominantly grass (woody...\npasture_meadow_grassland_grass\n3302000000\nMULTIPOLYGON (((4.41366 44.85898, 4.41373 44.8...\n\n\n2\n487224\n0.89\nCTG\n22\nNone\nNone\nChâtaigne\nChestnut\nsweet_chestnuts\n3303030500\nMULTIPOLYGON (((4.41159 44.85891, 4.41034 44.8...\n\n\n3\n9484542\n1.31\nCTG\n22\nNone\nNone\nChâtaigne\nChestnut\nsweet_chestnuts\n3303030500\nMULTIPOLYGON (((4.40904 44.85805, 4.41034 44.8...\n\n\n4\n487216\n1.70\nBOP\n17\nNone\nNone\nBois pâturé\nGrazed wood\nother_tree_wood_forest\n3306990000\nMULTIPOLYGON (((4.41135 44.85476, 4.41134 44.8...\n\n\n\n\n\n\n\n\ncrops_gdf.shape\n\n(415, 11)\n\n\nThere are other useful keyword arguments to read_file. Since we’re using the pyogrio engine, we can pass specific column names into read_file, and only those columns will be parsed. In the case of FlatGeobuf, this doesn’t save us much time, because the same amount of data needs to be fetched. (Though if running this cell soon after the previous one, the relevant data will be cached and won’t be downloaded again.)\n\ncolumn_names = [\"ID_PARCEL\", \"SURF_PARC\", \"CODE_CULTU\", \"geometry\"]\n%time crops_gdf = gpd.read_file(url, bbox=bounds, columns=column_names, engine=\"pyogrio\")\n\nCPU times: user 25 ms, sys: 2.47 ms, total: 27.4 ms\nWall time: 706 ms\n\n\n\ncrops_gdf.head()\n\n\n\n\n\n\n\n\nCODE_CULTU\nID_PARCEL\nSURF_PARC\ngeometry\n\n\n\n\n0\nSPL\n9484573\n11.08\nMULTIPOLYGON (((4.41142 44.85441, 4.41145 44.8...\n\n\n1\nPPH\n487218\n2.53\nMULTIPOLYGON (((4.41366 44.85898, 4.41373 44.8...\n\n\n2\nCTG\n487224\n0.89\nMULTIPOLYGON (((4.41159 44.85891, 4.41034 44.8...\n\n\n3\nCTG\n9484542\n1.31\nMULTIPOLYGON (((4.40904 44.85805, 4.41034 44.8...\n\n\n4\nBOP\n487216\n1.70\nMULTIPOLYGON (((4.41135 44.85476, 4.41134 44.8..." + }, + { + "objectID": "zarr/zarr-in-practice.html", + "href": "zarr/zarr-in-practice.html", + "title": "Zarr in Practice", + "section": "", + "text": "This notebook demonstrates how to create, explore and modify a Zarr store.\nThese concepts are explored in more detail in the official Zarr Tutorial.\nIt also shows the use of public Zarr stores for geospatial data." + }, + { + "objectID": "zarr/zarr-in-practice.html#how-to-create-a-zarr-store", + "href": "zarr/zarr-in-practice.html#how-to-create-a-zarr-store", + "title": "Zarr in Practice", + "section": "How to create a Zarr store", + "text": "How to create a Zarr store\n\nimport sys\nimport numpy as np\nimport xarray as xr\nimport zarr\n\n# Here we create a simple Zarr store.\nzstore = zarr.array(np.arange(10))\n\nThis is an in-memory Zarr store. To persist it to disk, we can use .save.\n\nzarr.save(\"test.zarr\", zstore)\n\nWe can open the metadata about this dataset, which gives us some interesting information. The dataset has a shape of 10 chunks of 10, so we know all the data was stored in 1 chunk, and was compressed with the blosc compressor.\n\n!cat test.zarr/.zarray \n\n{\n \"chunks\": [\n 10\n ],\n \"compressor\": {\n \"blocksize\": 0,\n \"clevel\": 5,\n \"cname\": \"lz4\",\n \"id\": \"blosc\",\n \"shuffle\": 1\n },\n \"dtype\": \"<i8\",\n \"fill_value\": 0,\n \"filters\": null,\n \"order\": \"C\",\n \"shape\": [\n 10\n ],\n \"zarr_format\": 2\n}\n\n\nThis was a pretty basic example. Let’s explore the other things we might want to do when creating Zarr." + }, + { + "objectID": "zarr/zarr-in-practice.html#how-to-create-a-group", + "href": "zarr/zarr-in-practice.html#how-to-create-a-group", + "title": "Zarr in Practice", + "section": "How to create a group", + "text": "How to create a group\n\nroot = zarr.group()\ngroup1 = root.create_group('group1')\ngroup2 = root.create_group('group2')\nz1 = group1.create_dataset('ds_in_group', shape=(100,100), chunks=(10,10), dtype='i4')\nz2 = group2.create_dataset('ds_in_group', shape=(1000,1000), chunks=(10,10), dtype='i4')\nroot.tree(expand=True)" + }, + { + "objectID": "zarr/zarr-in-practice.html#how-to-examine-and-modify-the-chunk-shape", + "href": "zarr/zarr-in-practice.html#how-to-examine-and-modify-the-chunk-shape", + "title": "Zarr in Practice", + "section": "How to Examine and Modify the Chunk Shape", + "text": "How to Examine and Modify the Chunk Shape\nIf your data is sufficiently large, Zarr will chose a chunksize for you.\n\nzarr_no_chunks = zarr.array(np.arange(100), chunks=True)\nzarr_no_chunks.chunks, zarr_no_chunks.shape\n\n((100,), (100,))\n\n\n\nzarr_with_chunks = zarr.array(np.arange(10000000), chunks=True)\nzarr_with_chunks.chunks, zarr_with_chunks.shape\n\n((156250,), (10000000,))\n\n\nFor zarr_with_chunks we see the chunks are smaller than the shape, so we know the data has been chunked. Other ways to examine the chunk structure are zarr.info and zarr.cdata_shape.\n\n?zarr_no_chunks.cdata_shape\n\n\nType: property\nString form: <property object at 0x7efde6ecfb00>\nDocstring: \nA tuple of integers describing the number of chunks along each\ndimension of the array.\n\n\n\n\nzarr_no_chunks.cdata_shape, zarr_with_chunks.cdata_shape\n\n((1,), (64,))\n\n\nThe zarr store with chunks has 64 chunks. The number of chunks multiplied by the chunk size equals the length of the whole array.\n\nzarr_with_chunks.cdata_shape[0] * zarr_with_chunks.chunks[0] == zarr_with_chunks.shape[0]\n\nTrue\n\n\n\nWhat’s the storage size of these chunks?\nThe default chunks are pretty small.\n\nsys.getsizeof(zarr_with_chunks.chunk_store['0']) # this is in bytes\n\n8049\n\n\n\nzarr_with_big_chunks = zarr.array(np.arange(10000000), chunks=(500000))\n\n\nzarr_with_big_chunks.chunks, zarr_with_big_chunks.shape, zarr_with_big_chunks.cdata_shape\n\n((500000,), (10000000,), (20,))\n\n\nThis Zarr store has 10 million values, stored in 20 chunks of 500,000 data values.\n\nsys.getsizeof(zarr_with_big_chunks.chunk_store['0'])\n\n24941\n\n\nThese chunks are still pretty small, but this is just a silly example. In the real world, you will likely want to deal in Zarr chunks of 1MB or greater, especially when dealing with remote storatge options where data is read over a network and the number of requests should be minimized." + }, + { + "objectID": "zarr/zarr-in-practice.html#exploring-and-modifying-data-compression", + "href": "zarr/zarr-in-practice.html#exploring-and-modifying-data-compression", + "title": "Zarr in Practice", + "section": "Exploring and Modifying Data Compression", + "text": "Exploring and Modifying Data Compression\nContinuing with data from the example above, we can tell that Zarr has also compressed the data for us using zarr.info or zarr.compressor.\n\nzarr_with_chunks.compressor\n\nBlosc(cname='lz4', clevel=5, shuffle=SHUFFLE, blocksize=0)\n\n\nThe Blosc compressor is actually a meta compressor so actually implements multiple different internal compressors. In this case, it has implemented lz4 compression. We can also explore how much space was saved by using this compression method.\n\nzarr_with_chunks.info\n\n\n\n\nType\nzarr.core.Array\n\n\nData type\nint64\n\n\nShape\n(10000000,)\n\n\nChunk shape\n(156250,)\n\n\nOrder\nC\n\n\nRead-only\nFalse\n\n\nCompressor\nBlosc(cname='lz4', clevel=5, shuffle=SHUFFLE, blocksize=0)\n\n\nStore type\nzarr.storage.KVStore\n\n\nNo. bytes\n80000000 (76.3M)\n\n\nNo. bytes stored\n514193 (502.1K)\n\n\nStorage ratio\n155.6\n\n\nChunks initialized\n64/64\n\n\n\n\n\nWe can see, from the storage ratio above, that compression has made our data 155 times smaller 😱 .\nYou can set compression=None when creating a Zarr array to turn off this behavior, but I’m not sure why you would do that.\nLet’s see what happens when we use a different compression method. We can checkout a full list of numcodecs compressors here: https://numcodecs.readthedocs.io/.\n\nfrom numcodecs import GZip\ncompressor = GZip()\nzstore_gzip_compressed = zarr.array(np.arange(10000000), chunks=True, compressor=compressor)\nzstore_gzip_compressed.info\n\n\n\n\nType\nzarr.core.Array\n\n\nData type\nint64\n\n\nShape\n(10000000,)\n\n\nChunk shape\n(156250,)\n\n\nOrder\nC\n\n\nRead-only\nFalse\n\n\nCompressor\nGZip(level=1)\n\n\nStore type\nzarr.storage.KVStore\n\n\nNo. bytes\n80000000 (76.3M)\n\n\nNo. bytes stored\n15086009 (14.4M)\n\n\nStorage ratio\n5.3\n\n\nChunks initialized\n64/64\n\n\n\n\n\nIn this case, the storage ratio is 5.3 - so not as good! How to chose a compression algorithm is a topic for future investigation." + }, + { + "objectID": "zarr/zarr-in-practice.html#consolidating-metadata", + "href": "zarr/zarr-in-practice.html#consolidating-metadata", + "title": "Zarr in Practice", + "section": "Consolidating metadata", + "text": "Consolidating metadata\nIt’s important to consolidate metadata to minimize requests. Each group and array will have a metadata file, so in order to limit requests to read the whole tree of metadata files, Zarr provides the ability to consolidate metdata into a metadata file at the of the store.\nSo far we have only been dealing in single array Zarr data stores. In this next example, we will create a zarr store with multiple arrays and then consolidate metadata. The speed up with local storage is insignificant, but becomes significant when dealing in remote storage options, which we will see in the following example on accessing cloud storage.\n\nroot = zarr.group()\nzarr_store = 'example.zarr'\n# Let's create many groups and many arrays\nnum_groups, num_arrays_per_group = 100, 100\nfor i in range(num_groups):\n group = root.create_group(f'group-{i}')\n for j in range(num_arrays_per_group):\n group.create_dataset(f'array-{j}', shape=(1000,1000), dtype='i4')\n\nstore = zarr.DirectoryStore(zarr_store)\nzarr.save(store, root)\n\n\n# We don't expect it to exist yet!\n!cat {zarr_store}/.zmetadata\n\ncat: {zarr_store}/.zmetadata: No such file or directory\n\n\n\nzarr.consolidate_metadata(zarr_store)\n\n<zarr.core.Array (100,) <U8>\n\n\n\nzarr.open_consolidated(zarr_store)\n\n<zarr.core.Array (100,) <U8>\n\n\n\n!cat {zarr_store}/.zmetadata\n\n{\n \"metadata\": {\n \".zarray\": {\n \"chunks\": [\n 100\n ],\n \"compressor\": {\n \"blocksize\": 0,\n \"clevel\": 5,\n \"cname\": \"lz4\",\n \"id\": \"blosc\",\n \"shuffle\": 1\n },\n \"dtype\": \"<U8\",\n \"fill_value\": \"\",\n \"filters\": null,\n \"order\": \"C\",\n \"shape\": [\n 100\n ],\n \"zarr_format\": 2\n }\n },\n \"zarr_consolidated_format\": 1\n}" + }, + { + "objectID": "glossary.html", + "href": "glossary.html", + "title": "Glossary", + "section": "", + "text": "This glossary aims to describe all the jargon of geospatial in the cloud! Are we missing something? Create an issue to suggest an improvement.\n\nAmazon S3 (S3)\nThe object storage service offered by Amazon. Part of Amazon Web Services.\n\n\nAmazon Web Services (AWS)\nCloud computing services offered by Amazon.\n\n\nArchive format\nA file format which stores one or more other files, possibly with compression. Examples include ZIP archives and PMTiles.\n\n\nArray Dimensions\nThe number of variables represented by an array. If an array represents longitude, latitude, time, and temperature, the array has four dimensions.\n\n\nAsynchronous\nA manner of scaling computing, to allow more operations to happen at the same time.\nThink of a glass of water. Synchronous computing is akin to having one straw: when you’ve finished drinking all you wish to drink, you give the straw to your friend for them to drink. Asynchronous computing is akin to sharing the straw between you and your friend. There’s still only one straw, but you can hand off sips. Parallel computing (like multithreading or multiprocessing) is like having two straws, where both you and your friend can drink out of the glass at the same time.\n\n\nBandwidth\nThe speed at which data travels over a network. Usually used in reference to downloading or uploading files.\nSee also: latency.\n\n\nChunk\nA grouping of data as part of a file format.\nIn a COG, this refers to a slice of the full array, usually 256 pixels high by 256 pixels wide (256x256), or 512 pixels high by 512 pixels wide (512x512).\nIn a GeoParquet file, this refers to a slice of a group of columns, where the slice has the same number of rows in each column.\n\n\nChunk size\nThe size of each chunk in a file format.\nThe chunk size plays a large part in how efficient random access within the file can be. If the chunk size is too small, then the metadata describing the file and the chunk byte ranges will be very large, and many HTTP range requests may have to be made for each small piece desired within the file. On the other hand, if the chunk size is too large, then a reader will have to read a large amount of data even for a very small query.\n\n\nCloud\nComputing services hosted by an external provider, where the provider pays for the upfront cost of buying hardware, earning a profit by selling services. This allows users to scale workloads efficiently because users do not need to pay large upfront costs for computers. These rented services can include compute time or object storage.\nUsually refers to services hosted by Amazon, Google, or Microsoft.\n\n\nCloud-Optimized\nThe property of a file format to be able to read a meaningful part of the file without needing to download all of the file. In particular, this means the file can be used efficiently from cloud storage via HTTP range requests.\n\n\nCloud-Optimized GeoTIFF (COG)\nAn extension of GeoTIFF with well-defined internal chunking, designed for efficient random access of the contained raster data.\n\n\nCloud-Optimized Point Cloud (COPC)\nA cloud-optimized file format for point cloud data.\n\n\nCompression\nAn algorithm that makes data smaller, at the cost of having to encode data into the compressed format before saving and having to decode data out of the compressed format before usage. In most cases, the benefits of smaller file sizes when stored outweigh the time it takes to encode and decode the compressed format.\nCompression can either be external or internal to a file, and can either be lossless or lossy.\n\n\nContent Delivery Network (CDN)\nA globally-distributed network of storage servers designed to cache HTTP requests so that future requests can use the cached copy instead of asking the origin server or storage.\n\n\nCoordinate Reference System (CRS)\nAlso called a projection\n\n\nData Type\n\n\nDeflate\nA lossless compression codec used as part of ZIP archives and internally within COG and GeoTIFF files.\n\n\nEntwine Point Cloud\nA cloud-optimized file format for point cloud data. Entwine has largely been superseded by COPC because COPC is backwards-compatible with previous point cloud data formats.\n\n\nEPSG code\nA projection definition referring to the EPSG database. EPSG codes tend to be four or five digits and tend to be easier to remember and use than longer definitions, such as WKT strings or PROJJSON. The downside of EPSG codes is that the program needs to have the EPSG database available so that it can perform a lookup from the EPSG code to the full projection definition.\n\n\nExternal compression\nCompression that is not part of a file format’s own specification, and which is added on after the main file has been saved. This tends to be used as part of ZIP archives (with file extension .zip) or with standalone gzip compression (file extension .gz).\nExternal compression tends to make a file no longer cloud-optimized, as it is usually no longer possible to read part of the file without fetching the entire file, as the entire file is necessary for decompression.\nThis is in contrast to internal compression.\n\n\nfsspec\nA Python library for abstracting among several different cloud storage providers. Allows uploading and downloading files to each provider with a consistent API.\n\n\nGDAL\nThe Geospatial Data Abstraction Library, a widely-used open-source library for converting between different raster data formats, as well as reprojecting between coordinate reference systems.\nIts common command-line tools include gdalinfo and gdal_translate. It can be used from Python with the rasterio library or from R with the terra library.\n\n\nGeoDataFrame\n\n\nGeoJSON\nA file format for vector data, built on top of JSON. GeoJSON is a common format for transferring vector data to web browsers, because it’s easy for most programming languages to read and write, but tends to have a large size. It’s not cloud-optimized because it can’t be partially parsed; the entire file needs to be downloaded in order to use.\n\n\nGeoPackage\nA file format for vector data. GeoPackage supports multiple layers as part of a single file. Because a GeoPackage is internally stored as a SQLite database, it is not cloud-optimized because the entire file must be downloaded in order to read any part of the file.\n\n\nGeoPandas\nA Python library for using and managing vector data, organized around GeoDataFrames.\n\n\nGeoParquet\nAn extension of the Parquet file format to store geospatial vector data. Can be read and written by tools including GDAL and GeoPandas.\n\n\nGeoTIFF\nAn extension of TIFF to store geospatially-referenced image data. Includes extra information such as the coordinate reference system and geotransform.\n\n\nGeotransform\nA set of six numbers that describe where a raster image lies within its coordinate reference system.\nThe geotransform describes the resolution and real-world location of each pixel. The geotransform needs to be used in conjunction with a projection definition for pixels to be located accurately.\nFor more information (in a Python context) read Python affine transforms.\n\n\nGoogle Cloud\nCloud computing services provided by Google.\n\n\ngzip\nA type of lossless compression for general use. Gzip is based on the deflate algorithm and tends to be used standalone for external compression. Files that end with .gz have been encoded with gzip compression.\n\n\nHilbert curve\nA type of space-filling curve used as part of many spatial indexes that ensures that objects near each other in two-dimensional space (e.g. longitude-latitude) are also near each other when ordered in a file.\n\n\nHTTP Range Request\nHTTP is the protocol that governs how computers ask for data across a network. HTTP range requests is a part of the HTTP specification that defines how to ask for a specific byte range from a file, instead of the entire file.\nHTTP range requests is a core part of what makes a file format cloud-optimized, because it means that part of a geospatial data file can be read and used without needing to download the entire file.\n\n\nInternal compression\nCompression that is part of a file format’s own specification.\nFile formats such as COG, COPC, and GeoParquet include internal compression. Internal compression is useful for cloud-optimized data formats because it allows internal chunks to be fetched with range requests but still have smaller sizes from compression.\nFor files that have already been internally compressed, adding another layer of external compression, such as ZIP or gzip, will likely not make the file smaller, and only serve to reduce performance by requiring an extra decompression step before the data can be used.\n\n\nJPEG\nA lossy compression codec used for visual images. It tends to have a better compression ratio than lossless compression codecs like deflate or LZW.\n\n\nLatency\nThe time it takes for data to start being retrieved from a server.\nSee also: bandwidth.\n\n\nLERC\nLERC (Limited Error Raster Compression) is a lossy but very efficient compression algorithm for floating point raster data. This compression rounds values to a precision provided by the user and tends to be useful e.g. for elevation data where the source data is known to not have precision beyond a known value.\nLERC is a relatively new algorithm and may not be supported everywhere. For example, GDAL needs to be compiled with the LERC driver in order to load a GeoTIFF with LERC compression.\n\n\nLossless compression\nA type of compression where the exact original values can be recovered after decompression. This means that the compression process does not lose any information. Lossless compression codecs tend to give larger file sizes than lossy compression codecs.\nExamples include deflate, LZW, gzip, and ZSTD.\n\n\nLossy compression\nA type of compression where the exact original values cannot be recovered after decompression. This means that the compression process will lose information. Lossy compression codecs tend to give smaller file sizes than lossless compression codecs.\nExamples include LERC and JPEG.\n\n\nLZW\nA lossless compression codec for general use. It tends to be slightly slower than deflate.\n\n\nMapbox Vector Tile\nA file format for tiled vector data, usually used for visualization on web maps. PMTiles is a cloud-optimized archive format for storing millions of Mapbox Vector Tile files in an efficient manner, accessible via HTTP range requests.\n\n\nMetadata\nInformation about the actual data, saved as part of the file format. This allows for recreating the exact data that existed before saving and for cloud-optimized data formats, usually stores the byte ranges of relevant data sections within the file, which allows for using HTTP range requests for efficient random access to that data section.\n\n\nMicrosoft Azure\nCloud computing services offered by Microsoft.\n\n\nMulti-dimensional raster data\n\n\nMultithreading\nA manner of scaling computing, to allow more operations to happen at the same time.\nThink of a glass of water. Synchronous computing is akin to having one straw: when you’ve finished drinking all you wish to drink, you give the straw to your friend for them to drink. Asynchronous computing is akin to sharing the straw between you and your friend. There’s still only one straw, but you can hand off sips. Parallel computing (including multithreading and multiprocessing) is like having two straws, where both you and your friend can drink out of the glass at the same time.\n\n\nNumpy\nThe foundational Python library for managing n-dimensional array data.\n\n\nObject storage (Cloud storage)\nObject storage, or cloud storage, refers to massively scalable cloud storage solutions like Amazon S3. It is relatively cheap, able to hold files small or large, and supports reading data via HTTP range requests. Most open geospatial data is hosted in such cloud storage solutions.\n\n\nOGR\nA widely-used open-source library for converting between different vector data formats, as well as reprojecting between coordinate reference systems.\nIts common command-line tools include ogrinfo and ogr2ogr. It can be used from Python with the pyogrio or fiona libraries or from R with the sf library.\nOGR is installed as part of GDAL.\n\n\nOverviews\nDownsampled (aggregated) data intended for visualization and stored as part of a file format. Overviews are part of the COG specification, and allow reading “zoomed out” data without needing to read and downsample from “full resolution” data.\n\n\nParquet\nA file format for tabular data with internal chunking and internal compression.\n\n\nPDAL\nThe Point Data Abstraction Library, a widely-used open-source library for converting between different point cloud data formats and managing point cloud data.\n\n\nPMTiles\nA type of cloud-optimized archive format for tiled data. It can be used with either vector or raster tiled data, but is most often used with Mapbox Vector Tile files. The individual tiles in a PMTiles file are accessible via HTTP range requests.\n\n\nPoint Cloud Data\nA type of geospatial data storing three dimensional point locations along with attributes for each point. Point cloud data may come from LIDAR sensors or other photogrammetry, and may represent three-dimensional terrain or buildings.\n\n\nPROJJSON\nA projection definition that uses JSON for encoding.\nThe specification is defined as part of the PROJ project and used as part of the GeoParquet vector file format.\n\n\nRandom access\nThe ability to quickly fetch part of a file without reading the entire file.\nFor example, consider videos on YouTube. If you select to watch a video starting from the ten minute mark, YouTube does not need to download the video up to that point. Rather it is able to use the metadata from the video file to know what byte range in the video file corresponds to the ten minute mark, and then use HTTP range requests to download only the part of the video you’ve reqested.\nThe ability to perform efficient random access over a network is a core part of what makes data cloud-optimized.\n\n\nRaster data\nA type of geospatial data that stores regularly-gridded data. This often comes from aerial or satellite imagery sensors.\n\n\nShapefile\nA vector data file format. There are many reasons to no longer use Shapefile.\n\n\nSpace-filling curve\nAn algorithm that translates two- or n- dimensional data into one-dimensional data. In practice, this is used as part of spatial indexes to group vector geometries nearby within a file according to their two-dimensional location.\n\n\nSpatial index\nA data structure used for searching through spatial data more efficiently.\nFor further reading: A dive into spatial search algorithms.\n\n\nTagged Image File Format (TIFF)\nA file format for image data that supports lossless compression.\n\n\nVector data\nA type of geospatial data to represent points, lines, and polygons.\n\n\nWeb Mercator\nA coordinate reference system often used with tiled data for web maps.\n\n\nWell-Known Binary (WKB)\nA binary encoding for vector geometries that many systems can read and write. For example, GeoParquet uses WKB in its definition of the geometry column.\n\n\nWKT (Geometry encoding)\nA text encoding for vector geometries that many systems can read and write. WKT tends to be larger in size and slower to read and write than WKB, so only use WKT if you need to store geometries in a text file, such as a CSV.\nNote that this is different than WKT (Projection definition).\n\n\nWKT (Projection definition)\nAn encoding to store coordinate reference system information.\nThere have been multiple versions of WKT; it is suggested to use WKT2 whenever possible.\n\n\nZarr\nA chunked, compressed file format for multi-dimensional raster data.\n\n\nZIP Archive\nA type of archive format that is used to group together existing files. It can also be used to apply external compression onto existing files.\n\n\nZSTD\nA very efficient lossless compression codec. ZSTD tends to give a very good compression ratio at very good performance, but may not be available everywhere. Check that your expected programs have access to ZSTD before using this on your data." + }, + { + "objectID": "template.html", + "href": "template.html", + "title": "Template", + "section": "", + "text": "Format Basics (or What is a XX?)\n\n\nExample of Creating this Format\n\n\nExample of Cloud-Optimized Access for this Format" + }, + { + "objectID": "kerchunk/intro.html", + "href": "kerchunk/intro.html", + "title": "Kerchunk", + "section": "", + "text": "Kerchunk is a python library for creating reference files (see next paragraph for an explanation) to support cloud-optimized access to traditional geospatial file formats, like NetCDF. Kerchunk negates the need to create and store copies of data for cloud-optimized access. Given the challenge of creating and maintaining copies of data, Kerchunk is a great tool.\nReference files can be used to instantiate an fsspec.FileSystemReference instance. Kerchunk reference files are json files with key value pairs for reading the underlying data as a Zarr data store. The keys are Zarr metadata paths or paths to zarr data chunks. The values for each key will either be raw data values or a list of the file URL, starting byte, and byte length where the data can be read.\nAs Kerchunk creates Zarr metadata for non-Zarr data, Kerchunk is compatible with Zarr tools that can use Zarr. Kerchunk enables a unified way to access chunked, compressed n-dimensionsional data across a variety of conventional data formats. The kerchunk library now supports NetCDF/HDF5, GRIB2, TIFF. Check the File format backends section of the kerchunk documentation for updates to supported formats.\n\n\n\n\n\n\nWarning\n\n\n\nA major limitation of kerchunk is the chunking of data will always be constrained to the chunk structure of the underlying data format. Read about zarr chunks on the Zarr page.\n\n\nLearn more about kerchunk at kerchunk.readthedocs.io." + }, + { + "objectID": "kerchunk/intro.html#what-is-kerchunk", + "href": "kerchunk/intro.html#what-is-kerchunk", + "title": "Kerchunk", + "section": "", + "text": "Kerchunk is a python library for creating reference files (see next paragraph for an explanation) to support cloud-optimized access to traditional geospatial file formats, like NetCDF. Kerchunk negates the need to create and store copies of data for cloud-optimized access. Given the challenge of creating and maintaining copies of data, Kerchunk is a great tool.\nReference files can be used to instantiate an fsspec.FileSystemReference instance. Kerchunk reference files are json files with key value pairs for reading the underlying data as a Zarr data store. The keys are Zarr metadata paths or paths to zarr data chunks. The values for each key will either be raw data values or a list of the file URL, starting byte, and byte length where the data can be read.\nAs Kerchunk creates Zarr metadata for non-Zarr data, Kerchunk is compatible with Zarr tools that can use Zarr. Kerchunk enables a unified way to access chunked, compressed n-dimensionsional data across a variety of conventional data formats. The kerchunk library now supports NetCDF/HDF5, GRIB2, TIFF. Check the File format backends section of the kerchunk documentation for updates to supported formats.\n\n\n\n\n\n\nWarning\n\n\n\nA major limitation of kerchunk is the chunking of data will always be constrained to the chunk structure of the underlying data format. Read about zarr chunks on the Zarr page.\n\n\nLearn more about kerchunk at kerchunk.readthedocs.io." + }, + { + "objectID": "kerchunk/intro.html#why-kerchunk", + "href": "kerchunk/intro.html#why-kerchunk", + "title": "Kerchunk", + "section": "Why Kerchunk?", + "text": "Why Kerchunk?\nIt is burdensome to create and maintain copies of data. The other pages in this guide introduce data formats which require processing and creating new data products. This process of creating and maintaining new data products, which are essentially copies of existing data, requires time and money. Kerchunk provides a method of providing cloud-optimized access to data that is more traditional archival formats." + }, + { + "objectID": "kerchunk/intro.html#how-to-kerchunk", + "href": "kerchunk/intro.html#how-to-kerchunk", + "title": "Kerchunk", + "section": "How to kerchunk", + "text": "How to kerchunk\nAs noted above, kerchunk is a python library you can use to create a reference file from any of the file formats it supports. The reference file is used by the fsspec.ReferenceFileSystem to read data from local or remote storage.\nHere’s an example:\nimport fsspec\nimport json\nfrom kerchunk.hdf import SingleHdf5ToZarr\n\nlocal_file = 'some_data.nc'\nout_file = 'some_references.json'\n\n# Instantiate the local file system with fsspec to save kerchunk's reference data as json.\nfs = fsspec.filesystem('')\nin_file = fs.open(local_file)\n\n# The inline threshold adjusts the size below which binary blocks are included directly in the output.\n# A higher inline threshold can result in a larger json file but faster loading time overally, since fewer requests are made.\nh5chunks = SingleHdf5ToZarr(in_file, local_file, inline_threshold=300)\nwith fs.open(out_file, 'wb') as f:\n f.write(json.dumps(h5chunks.translate()).encode())\n\n\n\n\n\n\nNote\n\n\n\nThe powerful fsspec library provides a uniform file system interface to many different storage backends and protocols. In addition to abstracting existing protocols, its ReferenceFileSystem class lets you view byte ranges of some other file as a file system. Kerchunk generates these ReferenceFileSystem objects.\n\n\nKerchunk generates a “reference set” which is a set of references to data or URLs under a key value store that matches the Zarr spec. For example, a simple reference file for a NetCDF file might look like:\n{\n \".zgroup\": \"{\\n \\\"zarr_format\\\": 2\\n}\",\n \".zattrs\": \"{\\n \\\"Conventions\\\": \\\"UGRID-0.9.0\\n\\\"}\",\n \"x/.zattrs\": \"{\\n \\\"_ARRAY_DIMENSIONS\\\": [\\n \\\"node\\\"\\n ...\",\n \"x/.zarray\": \"{\\n \\\"chunks\\\": [\\n 9228245\\n ],\\n \\\"compressor\\\": null,\\n \\\"dtype\\\": \\\"<f8\\\",\\n ...\",\n \"x/0\": [\"s3://bucket/path/file.nc\", 294094376, 73825960]\n}\nThe [\"s3://bucket/path/file.nc\", 294094376, 73825960] is the key part, which says that to load the first chunk in the x dimension, the Zarr reader needs to fetch a byte range starting at 294094376 with a length of 73825960 bytes. This allows for efficient cloud-native data access without using the standard NetCDF driver.\nLearn more about how to read and write kerchunk reference files in the Kerchunk in Practice notebook." + }, + { + "objectID": "kerchunk/kerchunk-in-practice.html", + "href": "kerchunk/kerchunk-in-practice.html", + "title": "Kerchunk in Practice", + "section": "", + "text": "In this notebook, we demonstrate how to create a kerchunk reference file for one and then multiple publicly available NetCDF files and how to open a kerchunk store with xarray.\nGenerally, NetCDF should work with kerchunk. Some nested data structures and data types, such as those that can exist in HDF5, won’t work with kerchunk. A future release of this guide will provide further information and/or resources on limitations of kerchunk." + }, + { + "objectID": "kerchunk/kerchunk-in-practice.html#environment", + "href": "kerchunk/kerchunk-in-practice.html#environment", + "title": "Kerchunk in Practice", + "section": "Environment", + "text": "Environment\nThe packages needed for this notebook can be installed with conda or mamba. Using the environment.yml from this folder run:\nconda create -f environment.yml\nor\nmamba create -f environment.yml\nThis notebook has been tested to work with the listed Conda environment." + }, + { + "objectID": "kerchunk/kerchunk-in-practice.html#how-to-create-a-kerchunk-store", + "href": "kerchunk/kerchunk-in-practice.html#how-to-create-a-kerchunk-store", + "title": "Kerchunk in Practice", + "section": "How to create a kerchunk store", + "text": "How to create a kerchunk store\nWe can use the publicly available NEX GDDP CMIP6 dataset for this example. This dataset is provided by NASA and publicly available on AWS S3. You can browse that data in the nex-gddp-cmip6 file browser.\n\nimport json\nimport os\nfrom tempfile import TemporaryDirectory\n\nimport fsspec\nimport imagecodecs.numcodecs\nimport xarray as xr\nfrom kerchunk.combine import MultiZarrToZarr\nfrom kerchunk.hdf import SingleHdf5ToZarr\n\nimagecodecs.numcodecs.register_codecs() \n\n\n# Set variables\n## Since there are a number of CMIP6 models and variables to chose from, we make the model and variable selections variables.\nmodel = \"ACCESS-CM2\"\n# `tasmax` is daily-maximum near-surface air temperature, see https://pcmdi.llnl.gov/mips/cmip3/variableList.html.\nvariable = \"tasmax\"\n## Note we are only reading historical data here, but model data is available for SSPs (Shared Socio-economic Pathways) as well.\n## SSPs are scenarios are used to model the future, so SSP files predict environment variables into the future.\ns3_path = f\"s3://nex-gddp-cmip6/NEX-GDDP-CMIP6/{model}/historical/r1i1p1*/{variable}/*\"\n\n# Initiate fsspec filesystem for reading.\n## We set anon=True because this specific dataset on AWS does not require users to be logged in to access.\nfs_read = fsspec.filesystem(\"s3\", anon=True)\n\n# Retrieve list of available data.\nfile_paths = fs_read.glob(s3_path)\nprint(f\"{len(file_paths)} discovered from {s3_path}\")\n\n65 discovered from s3://nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1*/tasmax/*\n\n\nTo start, we are just going to create a single reference file for a single NetCDF file.\n\nnetcdf_file = file_paths[0]\nnetcdf_file\n\n'nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc'\n\n\n\n# Define a function to generate the kerchunk file so we can use it again for other files.\ndef generate_json_reference(input_file, temp_dir: str):\n \"\"\"\n Use Kerchunk's `SingleHdf5ToZarr` method to create a `Kerchunk` index from a NetCDF file.\n \"\"\"\n with fs_read.open(input_file, **dict(mode=\"rb\")) as infile:\n print(f\"Running kerchunk generation for {input_file}...\")\n # Chunks smaller than `inline_threshold` will be stored directly in the reference file as data (as opposed to a URL and byte range).\n h5chunks = SingleHdf5ToZarr(infile, input_file, inline_threshold=300)\n fname = input_file.split(\"/\")[-1].strip(\".nc\")\n outf = os.path.join(temp_dir, f\"{fname}.json\")\n with open(outf, \"wb\") as f:\n f.write(json.dumps(h5chunks.translate()).encode())\n return outf\n\n\n# Create a temporary directory to store the .json reference files.\n# Alternately, you could write these to cloud storage.\ntd = TemporaryDirectory()\ntemp_dir = td.name\nprint(f\"Writing single file references to {temp_dir}\")\n\nWriting single file references to /var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo\n\n\n\nsingle_kerchunk_reference = generate_json_reference(netcdf_file, temp_dir)\n\nRunning kerchunk generation for nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc...\n\n\nWe might also want to inspect what was just created. Below we load just the first few keys and values of the “refs” part of the kerchunk reference file.\n\n# Read and load the JSON file\nwith open(single_kerchunk_reference, 'r') as file:\n data = json.load(file)\nkeys_to_select = ['.zgroup', 'tasmax/.zarray', 'tasmax/0.0.0']\n\n# Pretty print JSON data\ndata_to_print = {}\nfor key, value in data['refs'].items():\n if key in keys_to_select:\n if isinstance(value, str):\n data_to_print[key] = json.loads(value)\n else:\n data_to_print[key] = value\nprint(json.dumps(data_to_print, indent=4))\n\n{\n \".zgroup\": {\n \"zarr_format\": 2\n },\n \"tasmax/.zarray\": {\n \"chunks\": [\n 1,\n 600,\n 1440\n ],\n \"compressor\": {\n \"id\": \"zlib\",\n \"level\": 5\n },\n \"dtype\": \"<f4\",\n \"fill_value\": 1.0000000200408773e+20,\n \"filters\": [\n {\n \"elementsize\": 4,\n \"id\": \"shuffle\"\n }\n ],\n \"order\": \"C\",\n \"shape\": [\n 365,\n 600,\n 1440\n ],\n \"zarr_format\": 2\n },\n \"tasmax/0.0.0\": [\n \"nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc\",\n 18097,\n 674483\n ]\n}\n\n\nWe can also check that our reference file works with xarray.\n\n# Open dataset as zarr object using fsspec reference file system and Xarray\nfs_single = fsspec.filesystem(\n \"reference\", fo=single_kerchunk_reference, remote_protocol=\"https\"\n)\nsingle_map = fs_single.get_mapper(\"\")\n\n\nds_single = xr.open_dataset(single_map, engine=\"zarr\", backend_kwargs=dict(consolidated=False))\nds_single\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<xarray.Dataset>\nDimensions: (lat: 600, lon: 1440, time: 365)\nCoordinates:\n * lat (lat) float64 0.0 1.23e-321 0.0 ... -3.218e+163 -3.218e+163\n * lon (lon) float64 0.0 2.164e-314 0.0 ... -2.022e-53 -1.699e+282\n * time (time) datetime64[ns] 1950-01-01T12:00:00 ... 1950-12-31T12:00:00\nData variables:\n tasmax (time, lat, lon) float32 ...\nAttributes: (12/22)\n Conventions: CF-1.7\n activity: NEX-GDDP-CMIP6\n cmip6_institution_id: CSIRO-ARCCSS\n cmip6_license: CC-BY-SA 4.0\n cmip6_source_id: ACCESS-CM2\n contact: Dr. Rama Nemani: rama.nemani@nasa.gov, Dr. Bridget...\n ... ...\n scenario: historical\n source: BCSD\n title: ACCESS-CM2, r1i1p1f1, historical, global downscale...\n tracking_id: f85d4c2e-48e4-484f-aad4-6a3f30a04326\n variant_label: r1i1p1f1\n version: 1.0xarray.DatasetDimensions:lat: 600lon: 1440time: 365Coordinates: (3)lat(lat)float640.0 1.23e-321 ... -3.218e+163axis :Ylong_name :latitudestandard_name :latitudeunits :degrees_northarray([ 0.000000e+000, 1.230223e-321, 0.000000e+000, ..., -3.218047e+163,\n -3.218047e+163, -3.218047e+163])lon(lon)float640.0 2.164e-314 ... -1.699e+282axis :Xlong_name :longitudestandard_name :longitudeunits :degrees_eastarray([ 0.000000e+000, 2.163912e-314, 0.000000e+000, ..., 1.902013e-242,\n -2.022208e-053, -1.698612e+282])time(time)datetime64[ns]1950-01-01T12:00:00 ... 1950-12-...axis :Tlong_name :timestandard_name :timearray(['1950-01-01T12:00:00.000000000', '1950-01-02T12:00:00.000000000',\n '1950-01-03T12:00:00.000000000', ..., '1950-12-29T12:00:00.000000000',\n '1950-12-30T12:00:00.000000000', '1950-12-31T12:00:00.000000000'],\n dtype='datetime64[ns]')Data variables: (1)tasmax(time, lat, lon)float32...cell_measures :area: areacellacell_methods :area: mean time: maximumcomment :maximum near-surface (usually, 2 meter) air temperature (add cell_method attribute 'time: max')long_name :Daily Maximum Near-Surface Air Temperaturestandard_name :air_temperatureunits :K[315360000 values with dtype=float32]Indexes: (3)latPandasIndexPandasIndex(Index([ 0.0, 1.23e-321,\n 0.0, 1.23e-321,\n -3.2180465730379564e+163, -3.2180465730379564e+163,\n -3.2180465730379564e+163, -3.2180465730379564e+163,\n -3.2180465730379564e+163, -3.2180465730379564e+163,\n ...\n -3.2180465730379564e+163, -3.2180465730379564e+163,\n -3.2180465730379564e+163, -3.2180465730379564e+163,\n -3.2180465730379564e+163, -3.2180465730379564e+163,\n -3.2180465730379564e+163, -3.2180465730379564e+163,\n -3.2180465730379564e+163, -3.2180465730379564e+163],\n dtype='float64', name='lat', length=600))lonPandasIndexPandasIndex(Index([ 0.0, 2.163911906e-314,\n 0.0, nan,\n 0.0, 0.0,\n 0.0, 0.0,\n 0.0, 0.0,\n ...\n 0.0, 0.0,\n 1.5390572997222847e+73, 1.0494093556865241e-86,\n 7.328222560480262e-213, 3.493934932025909e-195,\n 7.981962361089973e-296, 1.90201295465319e-242,\n -2.022208454662242e-53, -1.698612219286841e+282],\n dtype='float64', name='lon', length=1440))timePandasIndexPandasIndex(DatetimeIndex(['1950-01-01 12:00:00', '1950-01-02 12:00:00',\n '1950-01-03 12:00:00', '1950-01-04 12:00:00',\n '1950-01-05 12:00:00', '1950-01-06 12:00:00',\n '1950-01-07 12:00:00', '1950-01-08 12:00:00',\n '1950-01-09 12:00:00', '1950-01-10 12:00:00',\n ...\n '1950-12-22 12:00:00', '1950-12-23 12:00:00',\n '1950-12-24 12:00:00', '1950-12-25 12:00:00',\n '1950-12-26 12:00:00', '1950-12-27 12:00:00',\n '1950-12-28 12:00:00', '1950-12-29 12:00:00',\n '1950-12-30 12:00:00', '1950-12-31 12:00:00'],\n dtype='datetime64[ns]', name='time', length=365, freq=None))Attributes: (22)Conventions :CF-1.7activity :NEX-GDDP-CMIP6cmip6_institution_id :CSIRO-ARCCSScmip6_license :CC-BY-SA 4.0cmip6_source_id :ACCESS-CM2contact :Dr. Rama Nemani: rama.nemani@nasa.gov, Dr. Bridget Thrasher: bridget@climateanalyticsgroup.orgcreation_date :2021-10-04T14:00:55.510838+00:00disclaimer :This data is considered provisional and subject to change. This data is provided as is without any warranty of any kind, either express or implied, arising by law or otherwise, including but not limited to warranties of completeness, non-infringement, accuracy, merchantability, or fitness for a particular purpose. The user assumes all risk associated with the use of, or inability to use, this data.external_variables :areacellafrequency :dayhistory :2021-10-04T14:00:55.510838+00:00: install global attributesinstitution :NASA Earth Exchange, NASA Ames Research Center, Moffett Field, CA 94035product :outputrealm :atmosreferences :BCSD method: Thrasher et al., 2012, Hydrol. Earth Syst. Sci.,16, 3309-3314. Ref period obs: latest version of the Princeton Global Meteorological Forcings (http://hydrology.princeton.edu/data.php), based on Sheffield et al., 2006, J. Climate, 19 (13), 3088-3111.resolution_id :0.25 degreescenario :historicalsource :BCSDtitle :ACCESS-CM2, r1i1p1f1, historical, global downscaled CMIP6 climate projection datatracking_id :f85d4c2e-48e4-484f-aad4-6a3f30a04326variant_label :r1i1p1f1version :1.0\n\n\nIt worked! But we can do even better. What if you want to open multiple NetCDF files with xarray? Let’s create kerchunk references for 3 files and then combine them.\n\nsubset_files = file_paths[0:3]\nsubset_files\n\n['nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc',\n 'nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1951.nc',\n 'nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1952.nc']\n\n\n\n# Iterate through filelist to generate Kerchunked files. Good use for `dask.bag`, see: https://docs.dask.org/en/stable/bag.html.\noutput_files = []\nfor single_file in subset_files:\n out_file = generate_json_reference(single_file, temp_dir)\n output_files.append(out_file)\n\nRunning kerchunk generation for nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc...\nRunning kerchunk generation for nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1951.nc...\nRunning kerchunk generation for nex-gddp-cmip6/NEX-GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/tasmax/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1952.nc...\n\n\n\noutput_files\n\n['/var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.json',\n '/var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1951.json',\n '/var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo/tasmax_day_ACCESS-CM2_historical_r1i1p1f1_gn_1952.json']\n\n\n\n# combine individual references into single consolidated reference\nmzz = MultiZarrToZarr(\n output_files,\n remote_protocol='s3',\n remote_options={'anon': True},\n concat_dims=['time'],\n coo_map={'time': 'cf:time'},\n # inline_threshold=0 means don't story any raw data in the kerchunk reference file.\n inline_threshold=0\n)\nmulti_kerchunk = mzz.translate()\n\n\n# Write kerchunk .json record\noutput_fname = os.path.join(temp_dir, f\"combined_CMIP6_daily_{model}_{variable}_kerchunk.json\")\nwith open(f\"{output_fname}\", \"wb\") as f:\n print(f\"Writing combined kerchunk reference file {output_fname}\")\n f.write(json.dumps(multi_kerchunk).encode())\n\nWriting combined kerchunk reference file /var/folders/42/5jr6891d4ds4xysz7q0rsghw0000gn/T/tmpn1bas0mo/combined_CMIP6_daily_ACCESS-CM2_tasmax_kerchunk.json\n\n\n\n# open dataset as zarr object using fsspec reference file system and Xarray\nfs_multi = fsspec.filesystem(\n \"reference\",\n fo=multi_kerchunk,\n remote_protocol=\"s3\"\n)\nmulti_map = fs_multi.get_mapper(\"\")\n\n\nds_multi = xr.open_dataset(multi_map, engine=\"zarr\", backend_kwargs=dict(consolidated=False))\nds_multi\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<xarray.Dataset>\nDimensions: (lat: 600, lon: 1440, time: 1096)\nCoordinates:\n * lat (lat) float64 0.0 2.164e-314 0.0 ... 2.961e-314 2.961e-314\n * lon (lon) float64 0.0 2.164e-314 0.0 ... -6.915e+193 -4.603e+95\n * time (time) datetime64[ns] 1950-01-01T12:00:00 ... 1952-12-31T12:00:00\nData variables:\n tasmax (time, lat, lon) float32 ...\nAttributes: (12/22)\n Conventions: CF-1.7\n activity: NEX-GDDP-CMIP6\n cmip6_institution_id: CSIRO-ARCCSS\n cmip6_license: CC-BY-SA 4.0\n cmip6_source_id: ACCESS-CM2\n contact: Dr. Rama Nemani: rama.nemani@nasa.gov, Dr. Bridget...\n ... ...\n scenario: historical\n source: BCSD\n title: ACCESS-CM2, r1i1p1f1, historical, global downscale...\n tracking_id: f85d4c2e-48e4-484f-aad4-6a3f30a04326\n variant_label: r1i1p1f1\n version: 1.0xarray.DatasetDimensions:lat: 600lon: 1440time: 1096Coordinates: (3)lat(lat)float640.0 2.164e-314 ... 2.961e-314axis :Ylong_name :latitudestandard_name :latitudeunits :degrees_northarray([0.000000e+000, 2.163912e-314, 0.000000e+000, ..., 2.961067e-314,\n 2.960919e-314, 2.961067e-314])lon(lon)float640.0 2.164e-314 ... -4.603e+95axis :Xlong_name :longitudestandard_name :longitudeunits :degrees_eastarray([ 0.000000e+000, 2.163912e-314, 0.000000e+000, ..., 2.334981e+006,\n -6.914611e+193, -4.603478e+095])time(time)datetime64[ns]1950-01-01T12:00:00 ... 1952-12-...axis :Tlong_name :timestandard_name :timearray(['1950-01-01T12:00:00.000000000', '1950-01-02T12:00:00.000000000',\n '1950-01-03T12:00:00.000000000', ..., '1952-12-29T12:00:00.000000000',\n '1952-12-30T12:00:00.000000000', '1952-12-31T12:00:00.000000000'],\n dtype='datetime64[ns]')Data variables: (1)tasmax(time, lat, lon)float32...cell_measures :area: areacellacell_methods :area: mean time: maximumcomment :maximum near-surface (usually, 2 meter) air temperature (add cell_method attribute 'time: max')long_name :Daily Maximum Near-Surface Air Temperaturestandard_name :air_temperatureunits :K[946944000 values with dtype=float32]Indexes: (3)latPandasIndexPandasIndex(Index([ 0.0, 2.163911906e-314, 0.0,\n nan, 0.0, 2.847840319e-314,\n 2.847840477e-314, 5e-324, 2.8478403307e-314,\n 2.8478403347e-314,\n ...\n 2.960919408e-314, 2.9610663864e-314, 2.960919313e-314,\n 2.9610664496e-314, 2.9609193446e-314, 2.961066513e-314,\n 2.9609192497e-314, 2.961066576e-314, 2.9609192813e-314,\n 2.9610666394e-314],\n dtype='float64', name='lat', length=600))lonPandasIndexPandasIndex(Index([ 0.0, 2.163911906e-314,\n 0.0, nan,\n 1.8178640317427325e+185, 1.0640025030406259e+248,\n 6.01334685394558e-154, 9.363931581572749e+252,\n 1.2064976717019484e+285, 2.582765705848744e-144,\n ...\n 2.7454590140292026e+40, -3.255930979178767e-308,\n 1.5281971544072024e-111, -7.088607689435405e+42,\n 1.1472324330854862e+22, 3.6014577529949115e+106,\n 9.851096278175061e+67, 2334981.4421286285,\n -6.9146108782833415e+193, -4.603477998061419e+95],\n dtype='float64', name='lon', length=1440))timePandasIndexPandasIndex(DatetimeIndex(['1950-01-01 12:00:00', '1950-01-02 12:00:00',\n '1950-01-03 12:00:00', '1950-01-04 12:00:00',\n '1950-01-05 12:00:00', '1950-01-06 12:00:00',\n '1950-01-07 12:00:00', '1950-01-08 12:00:00',\n '1950-01-09 12:00:00', '1950-01-10 12:00:00',\n ...\n '1952-12-22 12:00:00', '1952-12-23 12:00:00',\n '1952-12-24 12:00:00', '1952-12-25 12:00:00',\n '1952-12-26 12:00:00', '1952-12-27 12:00:00',\n '1952-12-28 12:00:00', '1952-12-29 12:00:00',\n '1952-12-30 12:00:00', '1952-12-31 12:00:00'],\n dtype='datetime64[ns]', name='time', length=1096, freq=None))Attributes: (22)Conventions :CF-1.7activity :NEX-GDDP-CMIP6cmip6_institution_id :CSIRO-ARCCSScmip6_license :CC-BY-SA 4.0cmip6_source_id :ACCESS-CM2contact :Dr. Rama Nemani: rama.nemani@nasa.gov, Dr. Bridget Thrasher: bridget@climateanalyticsgroup.orgcreation_date :2021-10-04T14:00:55.510838+00:00disclaimer :This data is considered provisional and subject to change. This data is provided as is without any warranty of any kind, either express or implied, arising by law or otherwise, including but not limited to warranties of completeness, non-infringement, accuracy, merchantability, or fitness for a particular purpose. The user assumes all risk associated with the use of, or inability to use, this data.external_variables :areacellafrequency :dayhistory :2021-10-04T14:00:55.510838+00:00: install global attributesinstitution :NASA Earth Exchange, NASA Ames Research Center, Moffett Field, CA 94035product :outputrealm :atmosreferences :BCSD method: Thrasher et al., 2012, Hydrol. Earth Syst. Sci.,16, 3309-3314. Ref period obs: latest version of the Princeton Global Meteorological Forcings (http://hydrology.princeton.edu/data.php), based on Sheffield et al., 2006, J. Climate, 19 (13), 3088-3111.resolution_id :0.25 degreescenario :historicalsource :BCSDtitle :ACCESS-CM2, r1i1p1f1, historical, global downscaled CMIP6 climate projection datatracking_id :f85d4c2e-48e4-484f-aad4-6a3f30a04326variant_label :r1i1p1f1version :1.0\n\n\nCool! Now we have 1096 days (3 years) of data." + }, + { + "objectID": "kerchunk/kerchunk-in-practice.html#how-to-read-a-kerchunk-store", + "href": "kerchunk/kerchunk-in-practice.html#how-to-read-a-kerchunk-store", + "title": "Kerchunk in Practice", + "section": "How to read a Kerchunk Store", + "text": "How to read a Kerchunk Store\nWe’ve already demonstrated how to open the datasets with Xarray:\nfs_multi = fsspec.filesystem(\n \"reference\",\n fo=multi_kerchunk,\n remote_protocol=\"s3\"\n)\nLet’s take it line by line to understand what’s happening.\n\nfsspec.filesystem is used to open the kerchunk reference. It is not necessary to have kerchunk installed to read data.\nThe first argument to fsspec.filesystem is the protocol. In the case of a kerchunk reference the protocol is the string \"reference\".\nThe fo argument is the set of reference files used to create a ReferenceFileSystem instance.\nThe remote_protocol argument is the protocol of the filesystem on which the references will be evaluated (unless fs is provided). If not given, will be derived from the first URL that has a protocol in the templates or in the references.\n\nNotice how the fs_multi object we’ve created is a fsspec.implementations.reference.ReferenceFileSystem.\n\ntype(fs_multi)\n\nfsspec.implementations.reference.ReferenceFileSystem\n\n\nRead about all the options for a fsspec.ReferenceFileSystem in the fsspec docs.\nOne other common situation is to load data over HTTP (as opposed to a local filesystem or via the S3 protocol). Here’s an example from the kerchunk case studies that loads a reference file and data files over HTTP:\n\nzarr_all_url='https://sentinel-1-global-coherence-earthbigdata.s3.us-west-2.amazonaws.com/data/wrappers/zarr-all.json'\n\nmapper = fsspec.get_mapper(\n 'reference://',\n fo=zarr_all_url,\n target_protocol='http',\n remote_protocol='http'\n)\ndataset = xr.open_dataset(\n mapper, engine='zarr', backend_kwargs={'consolidated': False}\n)\ndataset\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<xarray.Dataset>\nDimensions: (season: 4, polarization: 4, latitude: 193200,\n longitude: 432000, coherence: 6, flightdirection: 2,\n orbit: 175)\nCoordinates:\n * coherence (coherence) float32 6.0 12.0 18.0 24.0 36.0 48.0\n * flightdirection (flightdirection) object 'A' 'D'\n * latitude (latitude) float32 82.0 82.0 82.0 ... -79.0 -79.0 -79.0\n * longitude (longitude) float32 -180.0 -180.0 -180.0 ... 180.0 180.0\n * orbit (orbit) float64 1.0 2.0 3.0 4.0 ... 172.0 173.0 174.0 175.0\n * polarization (polarization) object 'vv' 'vh' 'hv' 'hh'\n * season (season) object 'winter' 'spring' 'summer' 'fall'\nData variables:\n AMP (season, polarization, latitude, longitude) float32 ...\n COH (season, polarization, coherence, latitude, longitude) float32 ...\n inc (orbit, flightdirection, latitude, longitude) float32 ...\n lsmap (orbit, flightdirection, latitude, longitude) float32 ...\n rho (season, polarization, latitude, longitude) float32 ...\n rmse (season, polarization, latitude, longitude) float32 ...\n tau (season, polarization, latitude, longitude) float32 ...xarray.DatasetDimensions:season: 4polarization: 4latitude: 193200longitude: 432000coherence: 6flightdirection: 2orbit: 175Coordinates: (7)coherence(coherence)float326.0 12.0 18.0 24.0 36.0 48.0array([ 6., 12., 18., 24., 36., 48.], dtype=float32)flightdirection(flightdirection)object'A' 'D'array(['A', 'D'], dtype=object)latitude(latitude)float3282.0 82.0 82.0 ... -79.0 -79.0array([ 81.99958, 81.99875, 81.99792, ..., -78.99792, -78.99875, -78.99958],\n dtype=float32)longitude(longitude)float32-180.0 -180.0 ... 180.0 180.0array([-179.99959, -179.99875, -179.99791, ..., 179.99791, 179.99875,\n 179.99959], dtype=float32)orbit(orbit)float641.0 2.0 3.0 ... 173.0 174.0 175.0array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.,\n 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.,\n 25., 26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36.,\n 37., 38., 39., 40., 41., 42., 43., 44., 45., 46., 47., 48.,\n 49., 50., 51., 52., 53., 54., 55., 56., 57., 58., 59., 60.,\n 61., 62., 63., 64., 65., 66., 67., 68., 69., 70., 71., 72.,\n 73., 74., 75., 76., 77., 78., 79., 80., 81., 82., 83., 84.,\n 85., 86., 87., 88., 89., 90., 91., 92., 93., 94., 95., 96.,\n 97., 98., 99., 100., 101., 102., 103., 104., 105., 106., 107., 108.,\n 109., 110., 111., 112., 113., 114., 115., 116., 117., 118., 119., 120.,\n 121., 122., 123., 124., 125., 126., 127., 128., 129., 130., 131., 132.,\n 133., 134., 135., 136., 137., 138., 139., 140., 141., 142., 143., 144.,\n 145., 146., 147., 148., 149., 150., 151., 152., 153., 154., 155., 156.,\n 157., 158., 159., 160., 161., 162., 163., 164., 165., 166., 167., 168.,\n 169., 170., 171., 172., 173., 174., 175.])polarization(polarization)object'vv' 'vh' 'hv' 'hh'array(['vv', 'vh', 'hv', 'hh'], dtype=object)season(season)object'winter' 'spring' 'summer' 'fall'array(['winter', 'spring', 'summer', 'fall'], dtype=object)Data variables: (7)AMP(season, polarization, latitude, longitude)float32...[1335398400000 values with dtype=float32]COH(season, polarization, coherence, latitude, longitude)float32...[8012390400000 values with dtype=float32]inc(orbit, flightdirection, latitude, longitude)float32...[29211840000000 values with dtype=float32]lsmap(orbit, flightdirection, latitude, longitude)float32...[29211840000000 values with dtype=float32]rho(season, polarization, latitude, longitude)float32...[1335398400000 values with dtype=float32]rmse(season, polarization, latitude, longitude)float32...[1335398400000 values with dtype=float32]tau(season, polarization, latitude, longitude)float32...[1335398400000 values with dtype=float32]Indexes: (7)coherencePandasIndexPandasIndex(Index([6.0, 12.0, 18.0, 24.0, 36.0, 48.0], dtype='float32', name='coherence'))flightdirectionPandasIndexPandasIndex(Index(['A', 'D'], dtype='object', name='flightdirection'))latitudePandasIndexPandasIndex(Index([ 81.99958038330078, 81.99874877929688, 81.99791717529297,\n 81.99708557128906, 81.99624633789062, 81.99541473388672,\n 81.99458312988281, 81.9937515258789, 81.992919921875,\n 81.99208068847656,\n ...\n -78.99208068847656, -78.992919921875, -78.9937515258789,\n -78.99458312988281, -78.99541473388672, -78.99624633789062,\n -78.99708557128906, -78.99791717529297, -78.99874877929688,\n -78.99958038330078],\n dtype='float32', name='latitude', length=193200))longitudePandasIndexPandasIndex(Index([ -179.9995880126953, -179.99874877929688, -179.99790954589844,\n -179.99708557128906, -179.99624633789062, -179.99542236328125,\n -179.9945831298828, -179.99374389648438, -179.992919921875,\n -179.99208068847656,\n ...\n 179.99208068847656, 179.992919921875, 179.99374389648438,\n 179.9945831298828, 179.99542236328125, 179.99624633789062,\n 179.99708557128906, 179.99790954589844, 179.99874877929688,\n 179.9995880126953],\n dtype='float32', name='longitude', length=432000))orbitPandasIndexPandasIndex(Index([ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,\n ...\n 166.0, 167.0, 168.0, 169.0, 170.0, 171.0, 172.0, 173.0, 174.0, 175.0],\n dtype='float64', name='orbit', length=175))polarizationPandasIndexPandasIndex(Index(['vv', 'vh', 'hv', 'hh'], dtype='object', name='polarization'))seasonPandasIndexPandasIndex(Index(['winter', 'spring', 'summer', 'fall'], dtype='object', name='season'))Attributes: (0)\n\n\nBecause xarray uses fsspec to read data, you can also bypass creating a fsspec object explicitly. Here’s an example using of opening a kerchunk reference generated with pangeo-forge for the NOAA 1/4° daily Optimum Interpolation Sea Surface Temperature (or daily OISST) Climate Data Record (CDR).\n\nurl = \"https://ncsa.osn.xsede.org/Pangeo/pangeo-forge/pangeo-forge/aws-noaa-oisst-feedstock/aws-noaa-oisst-avhrr-only.zarr/reference.json\"\nds = xr.open_dataset(\n \"reference://\",\n engine='zarr',\n backend_kwargs={\n 'consolidated': False,\n 'storage_options': {\n 'fo': url,\n 'remote_options': {'anon': True},\n 'remote_protocol': 's3'}},\n chunks={})\nds\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<xarray.Dataset>\nDimensions: (time: 15044, zlev: 1, lat: 720, lon: 1440)\nCoordinates:\n * lat (lat) float32 -89.88 -89.62 -89.38 -89.12 ... 89.38 89.62 89.88\n * lon (lon) float32 0.125 0.375 0.625 0.875 ... 359.1 359.4 359.6 359.9\n * time (time) datetime64[ns] 1981-09-01T12:00:00 ... 2022-11-08T12:00:00\n * zlev (zlev) float32 0.0\nData variables:\n anom (time, zlev, lat, lon) float32 dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>\n err (time, zlev, lat, lon) float32 dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>\n ice (time, zlev, lat, lon) float32 dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>\n sst (time, zlev, lat, lon) float32 dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>\nAttributes: (12/37)\n Conventions: CF-1.6, ACDD-1.3\n cdm_data_type: Grid\n comment: Data was converted from NetCDF-3 to NetCDF-4 ...\n creator_email: oisst-help@noaa.gov\n creator_url: https://www.ncei.noaa.gov/\n date_created: 2020-05-08T19:05:13Z\n ... ...\n source: ICOADS, NCEP_GTS, GSFC_ICE, NCEP_ICE, Pathfin...\n standard_name_vocabulary: CF Standard Name Table (v40, 25 January 2017)\n summary: NOAAs 1/4-degree Daily Optimum Interpolation ...\n time_coverage_end: 1981-09-01T23:59:59Z\n time_coverage_start: 1981-09-01T00:00:00Z\n title: NOAA/NCEI 1/4 Degree Daily Optimum Interpolat...xarray.DatasetDimensions:time: 15044zlev: 1lat: 720lon: 1440Coordinates: (4)lat(lat)float32-89.88 -89.62 ... 89.62 89.88grids :Uniform grid from -89.875 to 89.875 by 0.25long_name :Latitudeunits :degrees_northarray([-89.875, -89.625, -89.375, ..., 89.375, 89.625, 89.875],\n dtype=float32)lon(lon)float320.125 0.375 0.625 ... 359.6 359.9grids :Uniform grid from 0.125 to 359.875 by 0.25long_name :Longitudeunits :degrees_eastarray([1.25000e-01, 3.75000e-01, 6.25000e-01, ..., 3.59375e+02, 3.59625e+02,\n 3.59875e+02], dtype=float32)time(time)datetime64[ns]1981-09-01T12:00:00 ... 2022-11-...long_name :Center time of the dayarray(['1981-09-01T12:00:00.000000000', '1981-09-02T12:00:00.000000000',\n '1981-09-03T12:00:00.000000000', ..., '2022-11-06T12:00:00.000000000',\n '2022-11-07T12:00:00.000000000', '2022-11-08T12:00:00.000000000'],\n dtype='datetime64[ns]')zlev(zlev)float320.0actual_range :0, 0long_name :Sea surface heightpositive :downunits :metersarray([0.], dtype=float32)Data variables: (4)anom(time, zlev, lat, lon)float32dask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>long_name :Daily sea surface temperature anomaliesunits :Celsiusvalid_max :1200valid_min :-1200\n\n\n\n\n\n\n\n\n\n\n\nArray\nChunk\n\n\n\n\nBytes\n58.11 GiB\n3.96 MiB\n\n\nShape\n(15044, 1, 720, 1440)\n(1, 1, 720, 1440)\n\n\nDask graph\n15044 chunks in 2 graph layers\n\n\nData type\nfloat32 numpy.ndarray\n\n\n\n\n\n\n\n\nerr\n\n\n(time, zlev, lat, lon)\n\n\nfloat32\n\n\ndask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>\n\n\n\n\nlong_name :\n\nEstimated error standard deviation of analysed_sst\n\nunits :\n\nCelsius\n\nvalid_max :\n\n1000\n\nvalid_min :\n\n0\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nArray\nChunk\n\n\n\n\nBytes\n58.11 GiB\n3.96 MiB\n\n\nShape\n(15044, 1, 720, 1440)\n(1, 1, 720, 1440)\n\n\nDask graph\n15044 chunks in 2 graph layers\n\n\nData type\nfloat32 numpy.ndarray\n\n\n\n\n\n\n\n\n\nice\n\n\n(time, zlev, lat, lon)\n\n\nfloat32\n\n\ndask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>\n\n\n\n\nlong_name :\n\nSea ice concentration\n\nunits :\n\n%\n\nvalid_max :\n\n100\n\nvalid_min :\n\n0\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nArray\nChunk\n\n\n\n\nBytes\n58.11 GiB\n3.96 MiB\n\n\nShape\n(15044, 1, 720, 1440)\n(1, 1, 720, 1440)\n\n\nDask graph\n15044 chunks in 2 graph layers\n\n\nData type\nfloat32 numpy.ndarray\n\n\n\n\n\n\n\n\n\nsst\n\n\n(time, zlev, lat, lon)\n\n\nfloat32\n\n\ndask.array<chunksize=(1, 1, 720, 1440), meta=np.ndarray>\n\n\n\n\nlong_name :\n\nDaily sea surface temperature\n\nunits :\n\nCelsius\n\nvalid_max :\n\n4500\n\nvalid_min :\n\n-300\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nArray\nChunk\n\n\n\n\nBytes\n58.11 GiB\n3.96 MiB\n\n\nShape\n(15044, 1, 720, 1440)\n(1, 1, 720, 1440)\n\n\nDask graph\n15044 chunks in 2 graph layers\n\n\nData type\nfloat32 numpy.ndarray\n\n\n\n\n\n\n\n\n\nIndexes: (4)latPandasIndexPandasIndex(Index([-89.875, -89.625, -89.375, -89.125, -88.875, -88.625, -88.375, -88.125,\n -87.875, -87.625,\n ...\n 87.625, 87.875, 88.125, 88.375, 88.625, 88.875, 89.125, 89.375,\n 89.625, 89.875],\n dtype='float32', name='lat', length=720))lonPandasIndexPandasIndex(Index([ 0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875,\n 2.125, 2.375,\n ...\n 357.625, 357.875, 358.125, 358.375, 358.625, 358.875, 359.125, 359.375,\n 359.625, 359.875],\n dtype='float32', name='lon', length=1440))timePandasIndexPandasIndex(DatetimeIndex(['1981-09-01 12:00:00', '1981-09-02 12:00:00',\n '1981-09-03 12:00:00', '1981-09-04 12:00:00',\n '1981-09-05 12:00:00', '1981-09-06 12:00:00',\n '1981-09-07 12:00:00', '1981-09-08 12:00:00',\n '1981-09-09 12:00:00', '1981-09-10 12:00:00',\n ...\n '2022-10-30 12:00:00', '2022-10-31 12:00:00',\n '2022-11-01 12:00:00', '2022-11-02 12:00:00',\n '2022-11-03 12:00:00', '2022-11-04 12:00:00',\n '2022-11-05 12:00:00', '2022-11-06 12:00:00',\n '2022-11-07 12:00:00', '2022-11-08 12:00:00'],\n dtype='datetime64[ns]', name='time', length=15044, freq=None))zlevPandasIndexPandasIndex(Index([0.0], dtype='float32', name='zlev'))Attributes: (37)Conventions :CF-1.6, ACDD-1.3cdm_data_type :Gridcomment :Data was converted from NetCDF-3 to NetCDF-4 format with metadata updates in November 2017.creator_email :oisst-help@noaa.govcreator_url :https://www.ncei.noaa.gov/date_created :2020-05-08T19:05:13Zdate_modified :2020-05-08T19:05:13Zgeospatial_lat_max :90.0geospatial_lat_min :-90.0geospatial_lat_resolution :0.25geospatial_lat_units :degrees_northgeospatial_lon_max :360.0geospatial_lon_min :0.0geospatial_lon_resolution :0.25geospatial_lon_units :degrees_easthistory :Final file created using preliminary as first guess, and 3 days of AVHRR data. Preliminary uses only 1 day of AVHRR data.id :oisst-avhrr-v02r01.19810901.ncinstitution :NOAA/National Centers for Environmental Informationinstrument :Earth Remote Sensing Instruments > Passive Remote Sensing > Spectrometers/Radiometers > Imaging Spectrometers/Radiometers > AVHRR > Advanced Very High Resolution Radiometerinstrument_vocabulary :Global Change Master Directory (GCMD) Instrument Keywordskeywords :Earth Science > Oceans > Ocean Temperature > Sea Surface Temperaturekeywords_vocabulary :Global Change Master Directory (GCMD) Earth Science Keywordsmetadata_link :https://doi.org/10.25921/RE9P-PT57naming_authority :gov.noaa.nceincei_template_version :NCEI_NetCDF_Grid_Template_v2.0platform :Ships, buoys, Argo floats, MetOp-A, MetOp-Bplatform_vocabulary :Global Change Master Directory (GCMD) Platform Keywordsprocessing_level :NOAA Level 4product_version :Version v02r01references :Reynolds, et al.(2007) Daily High-Resolution-Blended Analyses for Sea Surface Temperature (available at https://doi.org/10.1175/2007JCLI1824.1). Banzon, et al.(2016) A long-term record of blended satellite and in situ sea-surface temperature for climate monitoring, modeling and environmental studies (available at https://doi.org/10.5194/essd-8-165-2016). Huang et al. (2020) Improvements of the Daily Optimum Interpolation Sea Surface Temperature (DOISST) Version v02r01, submitted.Climatology is based on 1971-2000 OI.v2 SST. Satellite data: Pathfinder AVHRR SST and Navy AVHRR SST. Ice data: NCEP Ice and GSFC Ice.sensor :Thermometer, AVHRRsource :ICOADS, NCEP_GTS, GSFC_ICE, NCEP_ICE, Pathfinder_AVHRR, Navy_AVHRRstandard_name_vocabulary :CF Standard Name Table (v40, 25 January 2017)summary :NOAAs 1/4-degree Daily Optimum Interpolation Sea Surface Temperature (OISST) (sometimes referred to as Reynolds SST, which however also refers to earlier products at different resolution), currently available as version v02r01, is created by interpolating and extrapolating SST observations from different sources, resulting in a smoothed complete field. The sources of data are satellite (AVHRR) and in situ platforms (i.e., ships and buoys), and the specific datasets employed may change over time. At the marginal ice zone, sea ice concentrations are used to generate proxy SSTs. A preliminary version of this file is produced in near-real time (1-day latency), and then replaced with a final version after 2 weeks. Note that this is the AVHRR-ONLY DOISST, available from Oct 1981, but there is a companion DOISST product that includes microwave satellite data, available from June 2002time_coverage_end :1981-09-01T23:59:59Ztime_coverage_start :1981-09-01T00:00:00Ztitle :NOAA/NCEI 1/4 Degree Daily Optimum Interpolation Sea Surface Temperature (OISST) Analysis, Version 2.1 - Final" + }, + { + "objectID": "kerchunk/kerchunk-in-practice.html#other-examples-of-existing-kerchunk-data", + "href": "kerchunk/kerchunk-in-practice.html#other-examples-of-existing-kerchunk-data", + "title": "Kerchunk in Practice", + "section": "Other examples of existing kerchunk data", + "text": "Other examples of existing kerchunk data\n\nCase Studies on kerchunk Docs page" + }, + { + "objectID": "cloud-optimized-netcdf4-hdf5/index.html", + "href": "cloud-optimized-netcdf4-hdf5/index.html", + "title": "Cloud-Optimized NetCDF4/HDF5", + "section": "", + "text": "Cloud-optimized access to NetCDF4/HDF5 files is possible. However, there are no standards for the metadata, chunking and compression for cloud-optimized access for these file types.\n\n\n\n\n\n\nNote\n\n\n\nNote: NetCDF4 are valid HDF5 files, see Reading and Editing NetCDF-4 Files with HDF5.\n\n\nNetCDF4/HDF5 were designed for disk access and thus moving them to the cloud has borne little fruit. Matt Rocklin describes the issue in HDF in the Cloud: Challenges and Solutions for Scientific Data:\n\nThe HDF format is complex and metadata is strewn throughout the file, so that a complex sequence of reads is required to reach a specific chunk of data. The only pragmatic way to read a chunk of data from an HDF file today is to use the existing HDF C library, which expects to receive a C FILE object, pointing to a normal file system (not a cloud object store) (this is not entirely true, as we’ll see below).\nSo organizations like NASA are dumping large amounts of HDF onto Amazon’s S3 that no one can actually read, except by downloading the entire file to their local hard drive, and then pulling out the particular bits that they need with the HDF library. This is inefficient. It misses out on the potential that cloud-hosted public data can offer to our society.\n\nTo provide cloud-optimized access to these files without an intermediate service like Hyrax or the Highly Scalable Data Service (HSDS), it is recommended to determine if the NetCDF4/HDF5 data you wish to provide can be used with kerchunk. Rich Signell provided some insightful examples and instructions on how to create a kerchunk reference file (aka fsspec.ReferenceFileSystem) for NetCDF4/HDF5 and the things to be aware of in Cloud-Performant NetCDF4/HDF5 with Zarr, Fsspec, and Intake. Note, the post is from 2020, so it’s possible details have changed; however, the approach of using kerchunk for NetCDF4/HDF5 is still recommended.\nStay tuned for more information on cloud-optimized NetCDF4/HDF5 in future releases of this guide." + }, + { + "objectID": "index.html", + "href": "index.html", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "", + "text": "Geospatial data is experiencing exponential growth in both size and complexity. As a result, traditional data access methods, such as file downloads, have become increasingly impractical for achieving scientific objectives. With the limitations of these older methods becoming more apparent, cloud-optimized geospatial formats present a much-needed solution.\nCloud optimization enables efficient, on-the-fly access to geospatial data, offering several advantages:\n\nReduced Latency: Subsets of the raw data can be fetched and processed much faster compared to downloading entire files.\nScalability: Cloud-optimized formats are usually stored on cloud object storage, which is infinitely scalable. Object storage supports many parallel read requests when combined with metadata about where different data bits are stored, making it easier to work with large datasets.\nFlexibility: Cloud-optimized formats allow for high levels of customization, enabling users to tailor data access to their specific needs. Additionally, advanced query capabilities provide the freedom to perform complex operations on the data without downloading and processing entire datasets.\nCost-Effectiveness: Reduced data transfer and storage needs can lower costs. Many of these formats offer compression options, which reduce storage costs.\n\nIf you want to provide optimized access to geospatial data, this guide is designed to help you understand the best practices and tools available for cloud-optimized geospatial formats." + }, + { + "objectID": "index.html#why-cloud-optimize", + "href": "index.html#why-cloud-optimize", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "", + "text": "Geospatial data is experiencing exponential growth in both size and complexity. As a result, traditional data access methods, such as file downloads, have become increasingly impractical for achieving scientific objectives. With the limitations of these older methods becoming more apparent, cloud-optimized geospatial formats present a much-needed solution.\nCloud optimization enables efficient, on-the-fly access to geospatial data, offering several advantages:\n\nReduced Latency: Subsets of the raw data can be fetched and processed much faster compared to downloading entire files.\nScalability: Cloud-optimized formats are usually stored on cloud object storage, which is infinitely scalable. Object storage supports many parallel read requests when combined with metadata about where different data bits are stored, making it easier to work with large datasets.\nFlexibility: Cloud-optimized formats allow for high levels of customization, enabling users to tailor data access to their specific needs. Additionally, advanced query capabilities provide the freedom to perform complex operations on the data without downloading and processing entire datasets.\nCost-Effectiveness: Reduced data transfer and storage needs can lower costs. Many of these formats offer compression options, which reduce storage costs.\n\nIf you want to provide optimized access to geospatial data, this guide is designed to help you understand the best practices and tools available for cloud-optimized geospatial formats." + }, + { + "objectID": "index.html#built-for-the-community-by-the-community.", + "href": "index.html#built-for-the-community-by-the-community.", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "Built for the Community, by the Community.", + "text": "Built for the Community, by the Community.\nThere is no one-size-fits-all approach to cloud-optimized data. Still, the community has developed many tools for creating and assessing geospatial formats that should be organized and shared.\nThis guide provides the landscape of cloud-optimized geospatial formats and the best-known answers to common questions." + }, + { + "objectID": "index.html#how-to-get-involved", + "href": "index.html#how-to-get-involved", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "How to Get Involved", + "text": "How to Get Involved\nIf you want to contribute or modify content, read the Get Involved page.\nIf you have a question or idea for this guide, please start a Github Discussion." + }, + { + "objectID": "index.html#the-opportunity", + "href": "index.html#the-opportunity", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "The Opportunity", + "text": "The Opportunity\nStoring data in the cloud does not on its own solve geospatial’s data problem. Users cannot reasonably wait to download, store, and work with large files on their machines. Large volumes of data must be available via subsetting methods to access data in memory.\nWhile it is possible to provide subsetting as a service, this requires ongoing maintenance of additional servers and as well as extra network latency when accessing data (data has to go to the server where the subsetting service is running and then to the user). With cloud-optimized formats and the appropriate libraries, subsets of data can be accessed directly from an end user’s machine without introducing an additional server.\nRegardless, users will access data over a network, which must be considered when designing the cloud-optimized format. Traditional geospatial formats are optimized for on-disk access via small internal chunks. A network introduces latency, and the number of requests must be considered.\nAs a community, we have arrived at the following cloud-optimized format pattern:\n\nMetadata includes addresses for data blocks.\nMetadata is stored in a consistent format and location.\nMetadata can be read once.\nMetadata can read the underlying file format, which supports subsetted access via addressable chunks, internal tiling, or both.\n\nThese characteristics allow for parallelized and partial reading." + }, + { + "objectID": "index.html#data-type-to-traditional-to-cloud-optimized-geospatial-file-format-table", + "href": "index.html#data-type-to-traditional-to-cloud-optimized-geospatial-file-format-table", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "Data Type to Traditional to Cloud-Optimized Geospatial File Format Table", + "text": "Data Type to Traditional to Cloud-Optimized Geospatial File Format Table\nThe diagram below depicts how some of the cloud-optimized formats discussed in this guide are cloud-optimized formats of traditional geospatial file formats.\n\n\n\nCloud-Optimized Geospatial Formats\n\n\nNotes:\n\nSome data formats cover multiple data types, specifically:\n\nGeoJSON can be used for vector and point cloud data.\nHDF5 can be used for point cloud data or data cubes (or both via groups).\nGeoParquet and FlatGeobuf can be used for vector data or point cloud data.\n\nLAS files are intended for 3D points, not 2D points (since COPC files are compressed LAS files, the same goes for COPC files).\nTopoJSON (an extension of GeoJSON that encodes topology) and newline-delimited GeoJSON are types of GeoJSON worth mentioning but have yet to be explicitly represented in the diagram.\nGeoTIFF and GeoParquet are geospatial versions of the non-geospatial file formats TIFF and Parquet, respectively. FlatGeobuf builds upon the non-geospatial flatbuffers serialization library (though flatbuffers is not a standalone file format)" + }, + { + "objectID": "index.html#table-of-contents", + "href": "index.html#table-of-contents", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "Table of Contents", + "text": "Table of Contents\n\nOverview of Formats (slideshow)\nFormats\n\nCloud-Optimized GeoTIFFs\nZarr\nKerchunk\nCloud-Optimized NetCDF4/HDF5\nGeoParquet\nFlatGeobuf\n\nCookbooks" + }, + { + "objectID": "index.html#running-examples", + "href": "index.html#running-examples", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "Running Examples", + "text": "Running Examples\nMost of the data formats covered in this guide have a Jupyter Notebook example that covers the basics of reading and writing the given format. At the top of each notebook is a link to an environment.yml file describing what libraries need to be installed to run correctly. You can use Conda or Mamba (a successor to Conda with faster package installs) to install the environment needed to run the notebook." + }, + { + "objectID": "index.html#authors", + "href": "index.html#authors", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "Authors", + "text": "Authors\n\nAimee Barciauskas\nAlex Mandel\nKyle Barron\nZac Deziel\nOverview Slide credits: Vincent Sarago, Chris Holmes, Patrick Quinn, Matt Hanson, Ryan Abernathey" + }, + { + "objectID": "index.html#questions-to-ask-when-generating-cloud-optimized-geospatial-data-in-any-format", + "href": "index.html#questions-to-ask-when-generating-cloud-optimized-geospatial-data-in-any-format", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "Questions to Ask When Generating Cloud-Optimized Geospatial Data in Any Format", + "text": "Questions to Ask When Generating Cloud-Optimized Geospatial Data in Any Format\n\nWhat variable(s) should be included in the new data format?\nWill you create copies to optimize for different needs?\nWhat is the intended use case or usage profile? Will this product be used for visualization, analysis, or both?\nWhat is the expected access method?\nHow much of your data is typically rendered or selected at once?" + }, + { + "objectID": "index.html#thank-you-to-our-supporters", + "href": "index.html#thank-you-to-our-supporters", + "title": "Cloud-Optimized Geospatial Formats Guide", + "section": "Thank you to our supporters", + "text": "Thank you to our supporters\nThis guide has been made possible through the support of:" + }, + { + "objectID": "zarr/intro.html", + "href": "zarr/intro.html", + "title": "Zarr", + "section": "", + "text": "Zarr, despite its name, is not a scary format. It’s designed for data that is too big for users’ machines, but Zarr makes data small and organizes it in a way where users can take just the bits they need or distribute the load of processing lots of those bits (stored as chunks) across many machines.\nThe Zarr data format is a community-maintained format for large-scale n-dimensional data. A Zarr store consists of compressed and chunked n-dimensional arrays. Zarr’s flexible indexing and compatibility with object storage lends itself to parallel processing.\nA Zarr chunk is Zarr’s unit of data storage. Each chunk of a Zarr array is an equally-sized block of the array within a larger Zarr store comprised of one or more arrays and array groups. These blocks or chunks of data are stored separately to make reading and updating small chunks more efficient.\nRead more in the official tutorial: Zarr Tutorial\n\n\n\n\n\n\n\n\nImportant\n\n\n\nZarr Version 3 is underway but not released yet, so all the examples in this guide are for Zarr Version 2 data. The concepts in this page are consistent across both Zarr Version 2 and Zarr Version 3, however some metadata field names and organization are changing from Version 2 to version 3.\n\n\nVersion 3 changes from Version 2:\n\ndtype has been renamed to data_type,\nchunks has been replaced with chunk_grid,\ndimension_separator has been replaced with chunk_key_encoding,\norder has been replaced by the transpose codec,\nthe separate filters and compressor fields been combined into the single codecs field.\n\nRead more:\n\nZarr specification version 2\nZarr specification version 3.0\n\n\n\n\n\n\nZarr arrays are similar to numpy arrays, but chunked and compressed. We will add details about chunking and compression to this guide soon.\n\n\n\nZarr supports hierarchical organization via groups. Each node in the Zarr hierarchy is either a group or an array.\n\n\n\nA Zarr array has zero or more dimensions. A Zarr array’s shape is the tuple of the length of the array in each respective dimension.\n\n\n\nZarr indexing supports array subsetting (both reading and writing) without loading the whole array into memory. Advanced indexing operations, such as block indexing, are detailed in the Zarr tutorial: Advanced indexing.\n\n\n\n\n\n\nNote\n\n\n\nThe Zarr format is language-agnostic, but this indexing reference is specific to Python.\n\n\nThe Xarray library provides a rich API for slicing and subselecting data. In addition to providing a positional index to subselect data, xarray supports label-based indexing. Labels, or coordinates, in the case of geospatial data, often include latitude and longitude (or y and x). These coordinates (also called names or labels) can be used to read and write data when the position is unknown.\n\n\n\nEvery Zarr array has its own metadata. When considering cloud storage options, where latency is high so total requests should be limited, it is important to consolidate metadata so all metadata can be read from one object.\nRead more on consolidating metadata.\n\n\n\n\n\n\nZarr can be stored in memory, on disk, in Zip files, and in object storage like S3.\n\n\n\n\n\n\nNote\n\n\n\nAny backend that implements MutableMapping interface from the Python collections module can be used to store Zarr. Learn more and see all the options on the Storage (zarr.storage) documentation page.\n\n\nAs of Zarr version 2.5, Zarr store URLs can be passed to fsspec and it will create a MutableMapping automatically.\n\n\n\nChunking is the process of dividing the data arrays into smaller pieces. This allows for parallel processing and efficient storage.\nOnce data is chunked, applications may read in 1 or many chunks. Because the data is compressed, within-chunk reads are not possible.\n\n\n\nZarr supports compression algorithms to support efficient storage and retrieval.\nTo explore these concepts in practice, see the Zarr in Practice notebook." + }, + { + "objectID": "zarr/intro.html#zarr-version-2-and-version-3", + "href": "zarr/intro.html#zarr-version-2-and-version-3", + "title": "Zarr", + "section": "", + "text": "Important\n\n\n\nZarr Version 3 is underway but not released yet, so all the examples in this guide are for Zarr Version 2 data. The concepts in this page are consistent across both Zarr Version 2 and Zarr Version 3, however some metadata field names and organization are changing from Version 2 to version 3.\n\n\nVersion 3 changes from Version 2:\n\ndtype has been renamed to data_type,\nchunks has been replaced with chunk_grid,\ndimension_separator has been replaced with chunk_key_encoding,\norder has been replaced by the transpose codec,\nthe separate filters and compressor fields been combined into the single codecs field.\n\nRead more:\n\nZarr specification version 2\nZarr specification version 3.0" + }, + { + "objectID": "zarr/intro.html#zarr-data-organization", + "href": "zarr/intro.html#zarr-data-organization", + "title": "Zarr", + "section": "", + "text": "Zarr arrays are similar to numpy arrays, but chunked and compressed. We will add details about chunking and compression to this guide soon.\n\n\n\nZarr supports hierarchical organization via groups. Each node in the Zarr hierarchy is either a group or an array.\n\n\n\nA Zarr array has zero or more dimensions. A Zarr array’s shape is the tuple of the length of the array in each respective dimension.\n\n\n\nZarr indexing supports array subsetting (both reading and writing) without loading the whole array into memory. Advanced indexing operations, such as block indexing, are detailed in the Zarr tutorial: Advanced indexing.\n\n\n\n\n\n\nNote\n\n\n\nThe Zarr format is language-agnostic, but this indexing reference is specific to Python.\n\n\nThe Xarray library provides a rich API for slicing and subselecting data. In addition to providing a positional index to subselect data, xarray supports label-based indexing. Labels, or coordinates, in the case of geospatial data, often include latitude and longitude (or y and x). These coordinates (also called names or labels) can be used to read and write data when the position is unknown.\n\n\n\nEvery Zarr array has its own metadata. When considering cloud storage options, where latency is high so total requests should be limited, it is important to consolidate metadata so all metadata can be read from one object.\nRead more on consolidating metadata." + }, + { + "objectID": "zarr/intro.html#zarr-data-storage", + "href": "zarr/intro.html#zarr-data-storage", + "title": "Zarr", + "section": "", + "text": "Zarr can be stored in memory, on disk, in Zip files, and in object storage like S3.\n\n\n\n\n\n\nNote\n\n\n\nAny backend that implements MutableMapping interface from the Python collections module can be used to store Zarr. Learn more and see all the options on the Storage (zarr.storage) documentation page.\n\n\nAs of Zarr version 2.5, Zarr store URLs can be passed to fsspec and it will create a MutableMapping automatically.\n\n\n\nChunking is the process of dividing the data arrays into smaller pieces. This allows for parallel processing and efficient storage.\nOnce data is chunked, applications may read in 1 or many chunks. Because the data is compressed, within-chunk reads are not possible.\n\n\n\nZarr supports compression algorithms to support efficient storage and retrieval.\nTo explore these concepts in practice, see the Zarr in Practice notebook." + }, + { + "objectID": "zarr/intro.html#what-zarr-is-not", + "href": "zarr/intro.html#what-zarr-is-not", + "title": "Zarr", + "section": "What Zarr is not", + "text": "What Zarr is not\nZarr is not designed for vector, point cloud or sparse data, although there is investigations into supporting a greater variety of data types." + }, + { + "objectID": "zarr/intro.html#zarr-is-in-development", + "href": "zarr/intro.html#zarr-is-in-development", + "title": "Zarr", + "section": "Zarr is in Development", + "text": "Zarr is in Development\nThere are some limitations of Zarr which is why there are Zarr Enhancement Proposals.\nZarr Version 3 was itself a ZEP, which has been accepted.\nDraft ZEPs are recommended reading for anyone considering creating a new Zarr store, since they address common challenges with Zarr data to date." + }, + { + "objectID": "transition-from-rmarkdown.html", + "href": "transition-from-rmarkdown.html", + "title": "Transition from RMarkdown", + "section": "", + "text": "You may already have workflows in RMarkdown and are interested in transitioning to Quarto. There’s no hurry to migrate to Quarto. Keep using Rmarkdown and when you’re ready the migration will be fine.\nHere are some notes as we migrate RMarkdown sites and books.\nTODO: translating R code chunks" + }, + { + "objectID": "transition-from-rmarkdown.html#bookdown-to-quarto", + "href": "transition-from-rmarkdown.html#bookdown-to-quarto", + "title": "Transition from RMarkdown", + "section": "Bookdown to Quarto", + "text": "Bookdown to Quarto\nConverting a Bookdown book to Quarto is slightly more involved than converting a website. A book has chapters whose order must be defined, and likely has citations and cross-refs. Still, conversion is not that hard.\nWe got some practice converting from Bookdown to Quarto by helping Gavin Fay convert his lab’s fantastic onboarding documentation, the Faylab Lab Manual. Here’s the GitHub view before and after.\nOur best first reference material for this was Nick Tierney’s Notes on Changing from Rmarkdown/Bookdown to Quarto. Nick shares some scripts in that post to automate some changes. In our case, the book was small enough that we made all changes manually. Quarto documentation was indispensable.\n\nExperimenting in a low-risk environment\nWe forked a copy of the Faylab Lab manual to the Openscapes organization, and worked in a branch so we could make changes relatively risk-free. We could always fork a new copy of the original if we “broke” something. (Caution: the default when making a pull request from a fork is to push changes to the original upstream repo, not your fork and it does this without warning if you have write-access to that repo.) With local previews it’s easy to test / play with settings to see what they do. We tended to make a change, Preview, then compare the look and functionality of the book to the original. It was helpful to comment out some elements of the configuration file _output.yml after their counterparts had been added to the Quarto configuration file _quarto.yml, or to confirm they were no longer needed, before making the drastic move of deleting them.\n\n\nThe conversion\nHere are the main steps to convert the Faylab Lab manual from Bookdown to Quarto.\nCreate new empty file called _quarto.yml and add book metadata there. The screenshots below\nSet project type as book.\nMove metadata out of index.qmd and into _quarto.yml. Title, author, and publication date were in index.qmd with date set using date: \"Last updated:r Sys.Date()\". Now these are in _quarto.yml with date set using date: last-modified. Note that having R code would require you to adjust code chunk options in the Quarto style (#|). This tripped us up a bit; see GitHub Actions.\nMove chapters listing out of _bookdown.yml and into _quarto.yml.\nAdd page footer to _quarto.yml.\nHere’s what ours looked like when we finished the steps above (_quarto.yml).\n\n\n\n\n\n\n_quarto.yml contents\n\n\n\n\n\n\n\nFaylab Lab Manual\n\n\n\n\n\nChange insertion of images from html style to Quarto style. (Note Quarto calls them “figures”, not “images”.) The following snippet will insert the GitHub octocat logo in a page:\n![](https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png){fig-align=\"left\" width=\"35px\"}\nChange all filename extensions .Rmd -> .qmd (you could Preview after this change and see that the book looks the same). Note that Quarto works with .Rmd files just as well as it does .qmd, so this change is not urgent. In fact, if you have a lot of R code in your .Rmds (unlike the Faylab Lab Manual), there will be additional tinkering needed to make the code chunks happy.\n\n\nCitations\nThe Faylab Lab Manual cited two papers, presenting us with an opportunity to see how easy it is to add references to a Quarto book. Briefly, in the Visual Editor, Insert > Citation > DOI. Pasting the DOI or its full URL, we can insert the citation. This automatically creates a references.bib file and adds the full citations at the bottom of the chapter page (watch demo). In July 2022, we had to manually add a ## References heading, but this may not be necessary in future Quarto updates.\n\n\n\n\n\n\nInsert citation via its DOI using RStudio Visual Editor\n\n\n\n\n\n\n\n\n\n\nPublishing notes\nIf the book’s output is strictly html, there’s no need to specify output-dir in _quarto.yml. The output directory default is _book/, which is what we’d like. If we wanted other types of output like like PDF or EPUB, etc. those single file outputs are also written to the output-dir (Quarto docs).\nIf you currently have a docs/ folder, delete it.\nUpdate .gitignore to ignore _book/. At the same time, we have it ignore caches and a .quarto file:\n/.quarto/\n*_cache/\n_book/\nOnce all is settled, delete _output.yml.\nOnce the Openscapes fork was fully reviewed, we made a pull request from that to the main branch of the book’s repo. Once that was merged, we set up GitHub Actions to render the book. (TODO: instructions for GitHub Actions)\n\n\nGitHub Actions\nThis book was mostly prose and screenshots without any R code. This made the conversion from RMarkdown to Quarto likely more straightforward than if you also needed to adjust code chunk options in the quarto style (#|). Our initial GitHub Action to render the converted Faylab Lab Manual failed because we had a piece of R code - even though the code was commented out! This was resolved when we deleted the line." + }, + { + "objectID": "transition-from-rmarkdown.html#distill-to-quarto", + "href": "transition-from-rmarkdown.html#distill-to-quarto", + "title": "Transition from RMarkdown", + "section": "Distill to quarto", + "text": "Distill to quarto\nWe transitioned our events site from distill to quarto in May 2022 (github view before and after). We followed excellent notes and examples from Nick Tierney and Danielle Navarro.\nAfter we had changed all the files, the Build tab in the RStudio IDE still showed “Build website” rather then “Render Website” and “Preview Website”, and would error when we pushed them (because that button was expecting a distill site, not a quarto site). To fix this, we updated the .Rproj file. Clicking on the .Rproj file in the RStudio IDE will open a dialog box where you can click things you want (you can also open these in a text editor or from the GitHub website to see the actual text). To fix this situation with the Build tab: Project Options > Build Tools > Project Build Tools > None.\nLooking at files /posts/_metadata.yml and _quarto.yml helps see where things are defined. For example, to make event post citations appear, we added citation: true to /posts/_metadata.yml and in _quarto.yml under the website key we set site-url: https://openscapes.github.io/events. We deleted footer.html used with distill because footer is now defined in quarto.yml.\n\nPublishing notes\n\nBackground: Our distill site had been set up to output to a docs folder, and had GitHub Settings > Pages set to look there rather gh-pages branch. (Julie note: this was a new-to-me capability when we set up the events distill site in Spring 2021 so I had forgotten that was an option). We’ve inititally kept this same set-up for now with our events page in _quarto.yml: output-dir: docs. However, this is sub-optimal; better to not have to commit and push these files but to instead have a GitHub Action generate them upon a commit. So the following is what we did -\n\nDon’t specify output-dir in _quarto.yml. The output directory default is _site/, which is what we’d like.\nIf you currently have a docs/ folder (like we did as we were experimenting), delete it.\nUpdate .gitignore to ignore _site/. At the same time, we have it ignore caches and a .quarto file:\n/.quarto/\n*_cache/\n_site/\nPush these changes, merge into main.\nOn GitHub.com, in your repo, set up GitHub publishing\nFollow instructions from the explore and setup chapter." + }, + { + "objectID": "transition-from-rmarkdown.html#troubleshooting", + "href": "transition-from-rmarkdown.html#troubleshooting", + "title": "Transition from RMarkdown", + "section": "Troubleshooting", + "text": "Troubleshooting\n\nGitHub Action fails, says you need RMarkdown but you don’t have R code!\nAnd you changed all .Rmds to .qmds!\nYou likely have a few setup code chunks from RMarkdown, that look like this:\n{r setup, include=FALSE}\nknitr::opts_chunk$set(echo = FALSE)\nYou can find them by opening each of your files and having a look, or use GitHub’s search for the keyword knitr" + }, + { + "objectID": "flatgeobuf/hilbert-r-tree.html", + "href": "flatgeobuf/hilbert-r-tree.html", + "title": "FlatGeobuf Spatial Index", + "section": "", + "text": "FlatGeobuf optionally supports including a spatial index that enables random access for each geometry in the file." + }, + { + "objectID": "flatgeobuf/hilbert-r-tree.html#when-to-use", + "href": "flatgeobuf/hilbert-r-tree.html#when-to-use", + "title": "FlatGeobuf Spatial Index", + "section": "When to use", + "text": "When to use\nWhen writing a FlatGeobuf file, one must decide whether to include a spatial index. A spatial index cannot be added to a FlatGeobuf file after the file has been written.\nA spatial index can enable much more efficient reading from FlatGeobuf, by allowing the reader to skip over portions of the file that fall outside of a qiven spatial query region." + }, + { + "objectID": "flatgeobuf/hilbert-r-tree.html#technical-details", + "href": "flatgeobuf/hilbert-r-tree.html#technical-details", + "title": "FlatGeobuf Spatial Index", + "section": "Technical details", + "text": "Technical details\nIn this section we’ll get into some gory technical details of how FlatGeobuf’s spatial index works. Understanding the below isn’t necessary for using FlatGeobuf, but it may add context for understanding how to create and work with FlatGeobuf files, and why FlatGeobuf is performant.\nFlatGeobuf’s spatial index is a static packed Hilbert R-tree index. That’s a mouthful, so let’s break it down:\n\nR-tree index\nAn R-Tree is a hierarchical collection of bounding boxes. At the lowest level of the tree is a bounding box of every geometry. Then one level above the lowest level exists a collection of bounding boxes, each of which is formed as the union of all child boxes. This means that each box encompasses every child box. There are fewer boxes at this level, because each box contains many child boxes, each of which represents one original geometry. This process continues repeatedly until there’s only one bounding box that indirectly contains the entire dataset.\nThis index allows you to quickly search for features that intersect a given bounding box query. At the top level, compare the bounding box of each node to your query region. If those two don’t intersect, you can discard that node and all of its child nodes from the search, because you know that none of them could possibly fall within your search region.\nContinuing this process allows you to quickly find only the specific items that are candidates for your search query.\n\n\nR-Tree diagram from Wikipedia. From top to bottom, the three levels of this tree are the black, blue, and red boxes. The black boxes contain the most items and encompass the largest area, while the red boxes contain the fewest items and encompass a smaller area.\n\nThe Wikipedia article and this Mapbox blog post are great resources for better understanding how R-Trees work.\n\n\nHilbert\nThe elements of an R-Tree must be sorted before insertion to make the R-Tree useful. This is because the core benefit of an R-Tree is to exclude elements that aren’t within a spatial filter. If elements of each node are randomly drawn from different geographies, then each node’s bounding box will be so large that no nodes can be excluded.\nBut how do you sort geometries? They encompass two dimensions and a range of shapes. If you sort all geometries first on the x coordinate, then you may pair geometries that are far from each other on the y dimension. Instead, it’s ideal to use a space-filling curve. That’s math jargon, but essentially defines a way to sort elements in n dimensions using 1 dimensional numbers.\nA Hilbert R-Tree uses a Hilbert Curve, a special type of space-filling curve, to sort the centers of geometries. This ensures that geometries that are nearby on both the x and y dimensions are placed close to each other in the R-Tree. This ensures that the resulting bounding boxes of the R-Tree are as small as possible, which means that the maximum number of elements can be discarded for any given spatial query.\nThis Crunchy Data blog post has helpful examples for why sorting input is important.\n\n\nStatic\nFlatGeobuf files can’t be modified without rewriting the entire file, so this R-Tree is constructed in such a way that it can’t be modified, which allows for improved tree generation.\n\n\nPacked\nAn R-Tree has a series of nodes at each level, where each node can contain up to n children. If the R-Tree might be updated, not every node will have a total of n children, because some space needs to be reserved for future elements.\nBecause the index is static and immutable, we can construct a packed index, where every node is completely full. This achieves better space utilization, and is more efficient for queries because there are fewer nodes to traverse." + }, + { + "objectID": "flatgeobuf/flatgeobuf-in-js.html", + "href": "flatgeobuf/flatgeobuf-in-js.html", + "title": "FlatGeobuf in JavaScript", + "section": "", + "text": "FlatGeobuf is a cloud-native vector data format because it contains a built-in spatial index that allows reading a specific spatial region from within the file without downloading the entire file’s content.\nThis is very useful for browser-based applications, because it allows them to make use of large files hosted on commodity cloud object storage without maintaining a server.\nThis notebook provides an example of using FlatGeobuf with spatial filtering from JavaScript." + }, + { + "objectID": "flatgeobuf/flatgeobuf-in-js.html#downloading-vs-streaming-vs-range-reads", + "href": "flatgeobuf/flatgeobuf-in-js.html#downloading-vs-streaming-vs-range-reads", + "title": "FlatGeobuf in JavaScript", + "section": "Downloading vs Streaming vs Range reads", + "text": "Downloading vs Streaming vs Range reads\nFlatGeobuf supports a few different ways of loading data into the browser.\nDownloading refers to fetching the entire FlatGeobuf file and parsing it after the full file has finished downloading. This has the downside that the user must wait for the entire download to finish before they see any interaction on the web page. This may lead to a user wondering if the web page is broken if it takes a while to download their data.\nStreaming refers to making use of a file’s contents incrementally as it downloads. This approach still downloads the entire file from beginning to end, but enables e.g. rendering part of the data on a map quickly, before waiting for the full file to finish downloading. This has the benefit of increased responsiveness, but the downside that a large file will be loaded in full. FlatGeobuf supports streaming because the file’s metadata is located at the beginning. A good example of this in action is “Streaming FlatGeobuf” by Björn Harrtell.\nRange reads refers to fetching only specific parts of the file that are required by the user. In the context of FlatGeobuf, this usually means a spatial query. FlatGeobuf enables this through its spatial index at the beginning of the file. Web clients can read the header, and then make requests only for data in a specific location. This has the benefit that very large files can be used in situations where downloading them in full would be impractical. A downside is that it takes more individual HTTP requests to understand which byte range in the file contains the desired data, leading to a longer latency before data starts to display." + }, + { + "objectID": "flatgeobuf/flatgeobuf-in-js.html#example", + "href": "flatgeobuf/flatgeobuf-in-js.html#example", + "title": "FlatGeobuf in JavaScript", + "section": "Example", + "text": "Example\nThis example uses slightly-modified JavaScript syntax used in Observable notebooks.\nLoad the FlatGeobuf JavaScript library:\n\nflatgeobuf = require(\"flatgeobuf@3.26.2/dist/flatgeobuf-geojson.min.js\")\n\n\n\n\n\n\nThis library has two functions: deserialize to fetch a remote file and parse it to GeoJSON, and serialize, which converts GeoJSON to FlatGeobuf.\n\nflatgeobuf\n\n\n\n\n\n\nFor this demo, we’ll use the same data source as in the FlatGeobuf leaflet example. This data file represents every census block in the USA.\n\nurl = 'https://flatgeobuf.septima.dk/population_areas.fgb'\n\n\n\n\n\n\nThe above is a really big file at almost 12GB total size, so we don’t want to fetch the entire file. In this demo, we’ll choose a small bounding box representing an area over Manhattan in New York City.\nBeware: if you make this bounding box too big, FlatGeobuf will try to download a large amount of data into your browser and maybe crash the tab!\n\nbbox = {\n return {\n minX: -74.003802,\n minY: 40.725756,\n maxX: -73.981481,\n maxY: 40.744008,\n }\n}\n\n\n\n\n\n\nThe above bbox object represents a bounding box in the format required by the FlatGeobuf API, but Leaflet’s API requires an array-formatted bounding box, so we’ll define a function to convert between the two:\n\n// leaflet uses lat-lon ordering\nbboxObjectToArray = (obj) => [\n [obj.minY, obj.minX],\n [obj.maxY, obj.maxX],\n];\n\n\n\n\n\n\nNext we’ll fetch all the data from the FlatGeobuf file within this bounding box. Notice how we pass the bbox argument into deserialize.\n\nfeatures = {\n const iter = flatgeobuf.deserialize(url, bbox);\n const features = [];\n for await (const feature of iter) {\n features.push(feature);\n }\n return features;\n}\n\n\n\n\n\n\nThere are 354 individual features that match this query:\n\nfeatures\n\n\n\n\n\n\nAs in the FlatGeobuf example, we’ll define a color scale based on how many people live in the census block.\n\ncolorScale = (d) => {\n return d > 750\n ? \"#800026\"\n : d > 500\n ? \"#BD0026\"\n : d > 250\n ? \"#E31A1C\"\n : d > 100\n ? \"#FC4E2A\"\n : d > 50\n ? \"#FD8D3C\"\n : d > 25\n ? \"#FEB24C\"\n : d > 10\n ? \"#FED976\"\n : \"#FFEDA0\";\n};\n\n\n\n\n\n\nNext we load the Leaflet JavaScript library and fetch its CSS styling defintions if needed.\n\nL = {\n const L = await require(\"leaflet@1/dist/leaflet.js\");\n if (!L._style) {\n const href = await require.resolve(\"leaflet@1/dist/leaflet.css\");\n document.head.appendChild(L._style = html`<link href=${href} rel=stylesheet>`);\n }\n return L;\n}\n\n\n\n\n\n\nNext we instantiate the Leaflet map and include multiple layers:\n\nAn L.tileLayer to show basemap tiles on the map for context.\nAn L.rectangle to show the bounding box of our FlatGeobuf query.\nAn L.layerGroup to group all the FlatGeobuf features into a single layer.\nAn L.geoJSON item for each feature in the FlatGeobuf response.\n\n\nmap = {\n const container = html`<div style=\"height:600px;\"></div>`;\n yield container;\n const map = L.map(container).setView([40.7299, -73.9923], 13);\n L.tileLayer(\"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\", {\n attribution:\n \"© <a href=https://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors\",\n }).addTo(map);\n\n // Render the bounding box rectangle\n L.rectangle(bboxObjectToArray(bbox), {\n interactive: false,\n color: \"blue\",\n fillOpacity: 0.0,\n opacity: 1.0,\n }).addTo(map);\n\n const results = L.layerGroup().addTo(map);\n for (const feature of features) {\n // Leaflet styling\n const defaultStyle = {\n color: colorScale(feature.properties[\"population\"]),\n weight: 1,\n fillOpacity: 0.4,\n };\n L.geoJSON(feature, {\n style: defaultStyle,\n })\n .on({\n mouseover: function (e) {\n const layer = e.target;\n layer.setStyle({\n weight: 4,\n fillOpacity: 0.8,\n });\n },\n mouseout: function (e) {\n const layer = e.target;\n layer.setStyle(defaultStyle);\n },\n })\n .bindPopup(\n `${feature.properties[\"population\"]} people live in this census block.</h1>`\n )\n .addTo(results);\n }\n}\n\n\n\n\n\n\nVoilà! We just fetched data directly from a massive FlatGeobuf file, directly from the client, without a server in between.\n\nReferences\nThis notebook was created with help from several resources\n\nFlatGeobuf Leaflet example (and its source code)\n@bjornharrtell/streaming-flatgeobuf is a useful related resource for an example of a streaming load of FlatGeobuf.\n@observablehq/hello-leaflet for an example of loading and rendering a Leaflet map using Observable." + }, + { + "objectID": "geoparquet/index.html", + "href": "geoparquet/index.html", + "title": "GeoParquet", + "section": "", + "text": "GeoParquet is an encoding for how to store geospatial vector data (point, lines, polygons) in Apache Parquet, a popular columnar storage format for tabular data.\nParquet has a wide ecosystem of tools and support; GeoParquet builds on this success by defining how to store geometries in the Parquet format. Because GeoParquet is not a separate format, any program that can read Parquet is able to load GeoParquet as well, even if it can’t make sense of the geometry information. This is very similar to how GeoTIFF layers geospatial information on top of the existing TIFF image standard.\nThe two main things that GeoParquet defines on top of Parquet are how to encode geometries in the geometry column and how to include metadata like the geometries’ Coordinate Reference System (CRS).\nGeoParquet is a relatively young format, and the specification has not yet reached a 1.0 release (as of August 2023, it’s at 1.0.0-rc.1). However, reading and writing GeoParquet has been supported in GDAL since version 3.5, and thus can be used in programs like GeoPandas and QGIS.\n\n\n\n\n\n\nWarning\n\n\n\nIn GeoPandas use read_parquet and to_parquet to read and write GeoParquet, not read_file and to_file as one would use with most other formats. 1\n\n\nBecause GeoParquet stores geometries in standard Well-Known Binary (WKB), it supports any vector geometry type defined in the OGC Simple Features specification. This includes the standard building blocks of Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, and GeometryCollection. A best practice is to store only geometries with the same type, as that allows readers to know which geometry type is stored without scanning the entire file.\nSome of the sections below will discuss strengths of Parquet in general. Keep in mind that because GeoParquet is built on top of Parquet, GeoParquet inherits all of these strengths.\n\n\nParquet files are laid out differently than other tabular formats like CSV or FlatGeobuf, so it’s helpful to see a diagram:\n\n\n\nSchematic of Parquet file layout\n\n\nA Parquet file consists of a sequence of chunks called row groups. These are logical groups of columns with the same number of rows. A row group consists of multiple columns, each of which is called a column chunk. These are sequences of raw column values that are guaranteed to be contiguous in the file. All row groups in the file must have the same schema, meaning that the data type of each column must be the same for every row group.\nA Parquet file includes metadata describing the internal chunking. This metadata includes the byte range of every column chunk in the dataset. This allows a Parquet reader to fetch any given column chunk once they have the file metadata.\nThe Parquet metadata also includes column statistics (the minimum and maximum value) for each column chunk. This means that if a user is interested in data where column “A” has values greater than 100, the Parquet reader can skip loading and parsing any column chunks where the maximum is known to be less than 100.\nIn Parquet, the metadata is located at the end of the file rather than at the beginning. This makes it much easier to write, as you don’t need to know how many total rows you have at the beginning, but makes it slightly harder to read. In practice, this is not too much more difficult to read: a Parquet reader first reads the end of the file, then makes reads for select columns.\n\n\nThe bytes of each column are contiguous, instead of each row. This means that it’s easy to filter on columns — fetching all rows of a single column — but not possible to filter on individual rows.\n\n\n\nBecause Parquet is column-oriented, a Parquet reader can fetch only specific columns that the user is interested in.\n\n\n\nBecause Parquet is internally chunked, Parquet can fetch only specific row groups that meet a specific filtering condition.\nNote that row group filtering on a specific column tends to only work well if the Parquet file was sorted on that column when saved. Non-sorted columns tend to have random values, and so the column statistics won’t tend to filter out many row groups.\n\n\n\n\n\n\nNote\n\n\n\nIn general it’s only possible to optimize filtering row groups by one column. This is the biggest difference between file formats and databases. Databases can have multiple indexes on whatever columns you want, and then when you run a query, and it will use all of the indexes. But that’s why it’s hard to make databases work as cloud-native files, because if you have high latency, you don’t want to make lots of tiny fetches.\n\n\n\n\n\nParquet is internally compressed by default and Parquet compression is more efficient compared to other formats.\nCompression algorithms are more effective when nearby bytes are more similar to each other. Data within a column tends to be much more similar than data across a row. Since Parquet is column-oriented, compression algorithms work better and result in smaller file sizes than a comparable row-based format.\nIt’s possible to have random access to one of the internal chunks inside the file at large, even though that chunk is compressed. Note that it isn’t possible to fetch partial data inside one chunk without loading and decompressing the entire chunk.\n\n\n\nFor maximum compatibility with existing systems, geometries are stored as ISO-standard WKB. Most geospatial programs are able to read and write WKB.\n\n\n\nGeoParquet is a young specification, and spatial indices are not yet part of the standard. Future revisions of GeoParquet are expected to add support for spatial indexes.\nOne way around this is to store multiple GeoParquet files according to some region identifier, cataloging each file with the SpatioTemporal Asset Catalog (STAC) specification.\n\n\n\nIn a streaming download, you read bytes starting at the beginning of the file, progressing towards the end. In Parquet, this is not helpful because the metadata is in the footer of the file instead of the header.\nInstead, we can replicate something similar to streaming by first fetching only the metadata region at the end of the file, and then making multiple requests for each internal chunk.\n\n\n\nOnce written, a Parquet file is immutable. No modification or appending can happen to that Parquet file. Instead, create a new Parquet file.\n\n\n\nWhile at medium data sizes GeoParquet is most easily distributed as a single file, at large data sizes a single dataset is often split into multiple files. Sometimes multiple files can be easier to write, such as if the data is output from a distributed system.\nA best practice when writing multiple files is to store a top-level metadata file, often named _metadata, with the metadata of all Parquet files in the directory. Without a top-level metadata file, a reader must read the Parquet footer of every individual file in the directory before reading any data. With a metadata file, a Parquet reader can read just that one metadata file, and then read the relevant chunks in the directory. For more information on this, read the “Partitioned Datasets” and “Writing _metadata and _common_metadata files” of the pyarrow documentation. As of August 2023, GeoPandas has no way to write multiple GeoParquet files out of the box, though you may be able to pass a * glob with multiple paths into geopandas.read_parquet.\nStoring Parquet data in multiple files makes it possible to in effect append to the dataset by adding a new file to the directory, but you must be careful to ensure that the new file has the exact same data schema as the existing files, and if a top-level metadata file exists, it must be rewritten to reflect the new file.\nSome elements of how to store GeoParquet-specific metadata in a multi-file layout have not yet been standardized.\n\n\n\nParquet supports a very extensive type system, including nested types such as lists and maps (i.e. like a Python dict). This means that you can store a key-value mapping or a multi-dimensional array within an attribute column of a GeoParquet dataset.\n\n\n\n\n\nDemystifying the Parquet File Format" + }, + { + "objectID": "geoparquet/index.html#file-layout", + "href": "geoparquet/index.html#file-layout", + "title": "GeoParquet", + "section": "", + "text": "Parquet files are laid out differently than other tabular formats like CSV or FlatGeobuf, so it’s helpful to see a diagram:\n\n\n\nSchematic of Parquet file layout\n\n\nA Parquet file consists of a sequence of chunks called row groups. These are logical groups of columns with the same number of rows. A row group consists of multiple columns, each of which is called a column chunk. These are sequences of raw column values that are guaranteed to be contiguous in the file. All row groups in the file must have the same schema, meaning that the data type of each column must be the same for every row group.\nA Parquet file includes metadata describing the internal chunking. This metadata includes the byte range of every column chunk in the dataset. This allows a Parquet reader to fetch any given column chunk once they have the file metadata.\nThe Parquet metadata also includes column statistics (the minimum and maximum value) for each column chunk. This means that if a user is interested in data where column “A” has values greater than 100, the Parquet reader can skip loading and parsing any column chunks where the maximum is known to be less than 100.\nIn Parquet, the metadata is located at the end of the file rather than at the beginning. This makes it much easier to write, as you don’t need to know how many total rows you have at the beginning, but makes it slightly harder to read. In practice, this is not too much more difficult to read: a Parquet reader first reads the end of the file, then makes reads for select columns.\n\n\nThe bytes of each column are contiguous, instead of each row. This means that it’s easy to filter on columns — fetching all rows of a single column — but not possible to filter on individual rows.\n\n\n\nBecause Parquet is column-oriented, a Parquet reader can fetch only specific columns that the user is interested in.\n\n\n\nBecause Parquet is internally chunked, Parquet can fetch only specific row groups that meet a specific filtering condition.\nNote that row group filtering on a specific column tends to only work well if the Parquet file was sorted on that column when saved. Non-sorted columns tend to have random values, and so the column statistics won’t tend to filter out many row groups.\n\n\n\n\n\n\nNote\n\n\n\nIn general it’s only possible to optimize filtering row groups by one column. This is the biggest difference between file formats and databases. Databases can have multiple indexes on whatever columns you want, and then when you run a query, and it will use all of the indexes. But that’s why it’s hard to make databases work as cloud-native files, because if you have high latency, you don’t want to make lots of tiny fetches.\n\n\n\n\n\nParquet is internally compressed by default and Parquet compression is more efficient compared to other formats.\nCompression algorithms are more effective when nearby bytes are more similar to each other. Data within a column tends to be much more similar than data across a row. Since Parquet is column-oriented, compression algorithms work better and result in smaller file sizes than a comparable row-based format.\nIt’s possible to have random access to one of the internal chunks inside the file at large, even though that chunk is compressed. Note that it isn’t possible to fetch partial data inside one chunk without loading and decompressing the entire chunk.\n\n\n\nFor maximum compatibility with existing systems, geometries are stored as ISO-standard WKB. Most geospatial programs are able to read and write WKB.\n\n\n\nGeoParquet is a young specification, and spatial indices are not yet part of the standard. Future revisions of GeoParquet are expected to add support for spatial indexes.\nOne way around this is to store multiple GeoParquet files according to some region identifier, cataloging each file with the SpatioTemporal Asset Catalog (STAC) specification.\n\n\n\nIn a streaming download, you read bytes starting at the beginning of the file, progressing towards the end. In Parquet, this is not helpful because the metadata is in the footer of the file instead of the header.\nInstead, we can replicate something similar to streaming by first fetching only the metadata region at the end of the file, and then making multiple requests for each internal chunk.\n\n\n\nOnce written, a Parquet file is immutable. No modification or appending can happen to that Parquet file. Instead, create a new Parquet file.\n\n\n\nWhile at medium data sizes GeoParquet is most easily distributed as a single file, at large data sizes a single dataset is often split into multiple files. Sometimes multiple files can be easier to write, such as if the data is output from a distributed system.\nA best practice when writing multiple files is to store a top-level metadata file, often named _metadata, with the metadata of all Parquet files in the directory. Without a top-level metadata file, a reader must read the Parquet footer of every individual file in the directory before reading any data. With a metadata file, a Parquet reader can read just that one metadata file, and then read the relevant chunks in the directory. For more information on this, read the “Partitioned Datasets” and “Writing _metadata and _common_metadata files” of the pyarrow documentation. As of August 2023, GeoPandas has no way to write multiple GeoParquet files out of the box, though you may be able to pass a * glob with multiple paths into geopandas.read_parquet.\nStoring Parquet data in multiple files makes it possible to in effect append to the dataset by adding a new file to the directory, but you must be careful to ensure that the new file has the exact same data schema as the existing files, and if a top-level metadata file exists, it must be rewritten to reflect the new file.\nSome elements of how to store GeoParquet-specific metadata in a multi-file layout have not yet been standardized.\n\n\n\nParquet supports a very extensive type system, including nested types such as lists and maps (i.e. like a Python dict). This means that you can store a key-value mapping or a multi-dimensional array within an attribute column of a GeoParquet dataset." + }, + { + "objectID": "geoparquet/index.html#references", + "href": "geoparquet/index.html#references", + "title": "GeoParquet", + "section": "", + "text": "Demystifying the Parquet File Format" + }, + { + "objectID": "geoparquet/index.html#footnotes", + "href": "geoparquet/index.html#footnotes", + "title": "GeoParquet", + "section": "Footnotes", + "text": "Footnotes\n\n\nAs pointed out by GDAL developer Even Rouault, reading GeoParquet through GDAL is just as fast as reading through the geopandas.read_parquet function if you’re using GDAL’s Arrow API. As of September 2023, this is not the default, so you need to opt into the pyogrio engine and opt into the Arrow API:\nimport geopandas as gpd\ngpd.read_file(\"file.parquet\", engine=\"pyogrio\", use_arrow=True)\nIt’s also necessary to note that the Python wheels distributed by pyogrio do not include the Arrow and Parquet drivers by default. In order to use the pyogrio driver for a GeoParquet file, you need to compile from source when installing. You’ll need to have a GDAL installation version 3.6 or later (and built with Arrow and Parquet support, as seen by ogrinfo --formats) on your computer already, and then you can build pyogrio from source with:\npip install pyogrio --no-binary pyogrio\n↩︎" + }, + { + "objectID": "cloud-optimized-geotiffs/intro.html", + "href": "cloud-optimized-geotiffs/intro.html", + "title": "Cloud-Optimized GeoTIFFs", + "section": "", + "text": "Cloud-Optimized GeoTIFF (COG), a raster format, is a variant of the TIFF image format that specifies a particular layout of internal data in the GeoTIFF specification to allow for optimized (subsetted or aggregated) access over a network for display or data reading. All COG files are valid GeoTIFF files, but not all GeoTIFF files are valid COG files. The key components that differ between GeoTIFF and COG are overviews and internal tiling.\nFor more details see https://www.cogeo.org/\n\n\n\nDimensions are the number of bands, rows and columns stored in a GeoTIFF. There is a tradeoff between storing lots of data in one GeoTIFF and storing less data in many GeoTIFFs. The larger a single file, the larger the GeoTIFF header and the multiple requests may be required just to read the spatial index before data retrieval. The opposite problem occurs if you make too many small files, then it takes many reads to retrieve data, and when rendering a combined visualization can greatly impact load time.\nIf you plan to pan and zoom a large amount of data through a tiling service in a web browser, there is a tradeoff between 1 large file, or many smaller files. The current recommendation is to meet somewhere in the middle, a moderate amount of medium files.\n\n\n\n\nThis attribute is also sometimes called chunks or internal tiles.\n\nInternal blocks are required if the dimensions of data are over 512x512. However you can control the size of the internal blocks. 256x256 or 512x512 are recommended. When displaying data at full resolution, or doing partial reading of data this size will impact the number of reads required. A size of 256 will take less time to read, and read less data outside the desired bounding box, however for reading large parts of a file, it may take more total read requests. Some clients will aggregate neighboring block reads to reduce the total number of requests.\n\n\n\nOverviews are downsampled (aggregated) data intended for visualization. The best resampling algorithm depends on the range, type, and distribution of the data.\nThe smallest size overview should match the tiling components’ fetch size, typically 256x256. Due to aspect ratio variation just aim to have at least one dimension at or slightly less than 256. The COG driver in GDAL, or rio cogeo tools should do this.\nThere are many resampling algorithms for generating overviews. When creating overviews several options should be compared before deciding which resampling method to apply.\n\n\n\n\nAdditional COG details that can be helpful.\nMaking and using COG examples." + }, + { + "objectID": "cloud-optimized-geotiffs/intro.html#dimensions", + "href": "cloud-optimized-geotiffs/intro.html#dimensions", + "title": "Cloud-Optimized GeoTIFFs", + "section": "", + "text": "Dimensions are the number of bands, rows and columns stored in a GeoTIFF. There is a tradeoff between storing lots of data in one GeoTIFF and storing less data in many GeoTIFFs. The larger a single file, the larger the GeoTIFF header and the multiple requests may be required just to read the spatial index before data retrieval. The opposite problem occurs if you make too many small files, then it takes many reads to retrieve data, and when rendering a combined visualization can greatly impact load time.\nIf you plan to pan and zoom a large amount of data through a tiling service in a web browser, there is a tradeoff between 1 large file, or many smaller files. The current recommendation is to meet somewhere in the middle, a moderate amount of medium files." + }, + { + "objectID": "cloud-optimized-geotiffs/intro.html#internal-blocks", + "href": "cloud-optimized-geotiffs/intro.html#internal-blocks", + "title": "Cloud-Optimized GeoTIFFs", + "section": "", + "text": "This attribute is also sometimes called chunks or internal tiles.\n\nInternal blocks are required if the dimensions of data are over 512x512. However you can control the size of the internal blocks. 256x256 or 512x512 are recommended. When displaying data at full resolution, or doing partial reading of data this size will impact the number of reads required. A size of 256 will take less time to read, and read less data outside the desired bounding box, however for reading large parts of a file, it may take more total read requests. Some clients will aggregate neighboring block reads to reduce the total number of requests." + }, + { + "objectID": "cloud-optimized-geotiffs/intro.html#overviews", + "href": "cloud-optimized-geotiffs/intro.html#overviews", + "title": "Cloud-Optimized GeoTIFFs", + "section": "", + "text": "Overviews are downsampled (aggregated) data intended for visualization. The best resampling algorithm depends on the range, type, and distribution of the data.\nThe smallest size overview should match the tiling components’ fetch size, typically 256x256. Due to aspect ratio variation just aim to have at least one dimension at or slightly less than 256. The COG driver in GDAL, or rio cogeo tools should do this.\nThere are many resampling algorithms for generating overviews. When creating overviews several options should be compared before deciding which resampling method to apply." + }, + { + "objectID": "cloud-optimized-geotiffs/intro.html#see-more", + "href": "cloud-optimized-geotiffs/intro.html#see-more", + "title": "Cloud-Optimized GeoTIFFs", + "section": "", + "text": "Additional COG details that can be helpful.\nMaking and using COG examples." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-details.html", + "href": "cloud-optimized-geotiffs/cogs-details.html", + "title": "Advanced COG/GeoTIFF Details", + "section": "", + "text": "The COG Intro page describes what makes a Cloud-Optimized GeoTIFF different from a plain, non-optimized GeoTIFF. The rest of this page details additional useful information (applicable to both COGs and plain GeoTIFF files) that can be relevant for making your files as useful and efficient as possible. Any reference to “GeoTIFF” below applies both to plain GeoTIFF files and to COG files.\n\n\nRecommendation The smallest possible data type that still represents the data appropriately should be used. It is not generally recommended to shift or quantize data from float to integer by multiplying, a space saving technique, as end users then need to undo this step to use the data. Data compression is preferred, see also Compression.\nThe GeoTIFF format supports many data types. The key is that all bands must be of the same data type. Unlike some other formats, you cannot mix and match integer (whole number) and float (decimal number) data types in the same file. If you have this use case consider splitting files by data type and using a catalog like STAC to keep track of them, or look at other formats like Zarr.\nScenario: If the COG is intended only for visualization, conversion to 3 band byte will improve performance.\n\nGDAL supported Data Types list\n\n\n\n\nThe compression used in a GeoTIFF is the greatest determinator of the file’s size. If storing a large amount of data, the right compression choice can lead to much smaller file sizes on disk, leading to lower costs.\n\n\nGeoTIFFs have compression internal to the file, meaning that the internal blocks in a GeoTIFF are already compressed. This internal compression is especially useful for COGs, compared to external compression (such as saving a COG inside a ZIP file), since a COG reader can decompress only the specific portion of the file requested, instead of needing to decompress the entire file.\nThe internal compression of a GeoTIFF also means that it does not need additional compression, and indeed that additional compression will decrease performance. Gzip or ZIP compression applied to a GeoTIFF with internal compression will not make the file smaller.\nIt is possible but not recommended to create COGs or GeoTIFFs with no internal compression.\n\n\n\nThere are a variety of compression codecs supported by GeoTIFF. Compression codecs tend to be split into two camps: lossy compression where the exact original values cannot be recovered or lossless compression which does not lose any information through the compression and decompression process. For most cases, a lossless compression is recommended, but in some cases a lossy compression can be useful and lead to smaller file sizes, such as if the COG is intended to be used only for visualization.\nDeflate or LZW are both lossless compression codecs and are the recommended algorithms for general use.\nJPEG is a lossy compression codec useful for true-color GeoTIFFs intended to be used only for visualization. Because it’s lossy, it tends to produce smaller file sizes than deflate or LZW. JPEG should only be used with RGB Byte data.\nLERC (Limited Error Raster Compression) is a lossy but very efficient compression algorithm for floating point data. This compression rounds values to a precision provided by the user and tends to be useful e.g. for elevation data where the source data is known to not have precision beyond a known value. But note, this compression is not lossless. Additionally, LERC is a relatively new algorithm and may not be supported everywhere. GDAL needs to be compiled with the LERC driver in order to load a GeoTIFF with LERC compression.\nSome other compression algorithms may be preferred depending on the data type and distribution, and if the goal is maximum compression or not. Codecs that produce the smallest file sizes tend to take longer to read into memory. If the network bandwidth to load the file is slow, then a very efficient compression algorithm may be most efficient, even if it takes longer to decompress when loaded. Alternatively, if the network speed is very fast, or if reading from a local disk, a slightly less efficient compression codec that decompresses faster may be preferred.\nThere are many posts on the internet exploring GeoTIFF compression and performance:\n\nGuide to GeoTIFF compression and optimization with GDAL\nGeoTiff Compression for Dummies\nGeoTiff compression comparison\n\n\n\n\n\nSetting a no data value makes it clear to users and visualization tools what pixels are not actually data. For visualization this allows these pixels to be easily hidden (transparent). Historically many values have been used, 0, -9999, etc… The key is to make sure the GDAL flag for no data is set. It is also suggested that the smallest negative value be used instead of a random value. For byte and unsigned integers data types this will be 0. For float data, setting NaN as the no data value is suggested. Make sure to use a no data value that does not have meaning in your data; otherwise use a different value (like the max possible value). Having the right nodata flag set is important for overview generation.\n\n\n\nRead performance can be greatly impacted by the choice of projection and the particular applications used for dynamic tile serving. Using a known CRS defined in the PROJ database (typically EPSG code) is preferred over custom projections. Load times can be 5-20 times greater when using a custom projection. Whenever applying projections make sure to use WKT2 representation. If using a database of known projections, i.e. EPSG codes, this should be fine, there are known issues around manually setting proj-strings.\n\n\n\nUp to this point, we’ve mentioned that a COG has internal tiling, but the exact layout of those internal tiles has been unspecified. A web-optimized COG exploits that internal tiling to enforce the same tiling as used in web maps. Additionally, overviews will also be aligned to the Web Mercator grid. Thus, a web-optimized COG is especially useful for relaying tiled image data to a browser. Because the internal tile layout exactly matches the tiling structure required in web mapping libraries, only one HTTP range request needs to be performed to access any tile.\nDownsides of web-optimized COGs include the fact that they must be in Web Mercator projection and that the file most likely will not line up exactly with the bounds of the original image data. This means that the COG will have a “collar” of invalid data around the edges of the file.\nWeb-Optimized COGs can be created via GDAL by using the COG driver with the creation option TILING_SCHEME=GoogleMapsCompatible or with rio-cogeo with the --web-optimized flag.\n\n\n\n\nThe optimum size of data at which splitting across files improves performance as a multi-file dataset instead of a single file.\nWhen to recommend particular internal tile sizes\nCompression impacts on http transfer rates.\nSupport for COG creation in all common geospatial tools varies.\n\n\n\n\n\nAn Introduction to Cloud Optimized GeoTIFFS (COGs) Part 1: Overview\nDo you really want people using your data?" + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-details.html#data-type", + "href": "cloud-optimized-geotiffs/cogs-details.html#data-type", + "title": "Advanced COG/GeoTIFF Details", + "section": "", + "text": "Recommendation The smallest possible data type that still represents the data appropriately should be used. It is not generally recommended to shift or quantize data from float to integer by multiplying, a space saving technique, as end users then need to undo this step to use the data. Data compression is preferred, see also Compression.\nThe GeoTIFF format supports many data types. The key is that all bands must be of the same data type. Unlike some other formats, you cannot mix and match integer (whole number) and float (decimal number) data types in the same file. If you have this use case consider splitting files by data type and using a catalog like STAC to keep track of them, or look at other formats like Zarr.\nScenario: If the COG is intended only for visualization, conversion to 3 band byte will improve performance.\n\nGDAL supported Data Types list" + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-details.html#compression", + "href": "cloud-optimized-geotiffs/cogs-details.html#compression", + "title": "Advanced COG/GeoTIFF Details", + "section": "", + "text": "The compression used in a GeoTIFF is the greatest determinator of the file’s size. If storing a large amount of data, the right compression choice can lead to much smaller file sizes on disk, leading to lower costs.\n\n\nGeoTIFFs have compression internal to the file, meaning that the internal blocks in a GeoTIFF are already compressed. This internal compression is especially useful for COGs, compared to external compression (such as saving a COG inside a ZIP file), since a COG reader can decompress only the specific portion of the file requested, instead of needing to decompress the entire file.\nThe internal compression of a GeoTIFF also means that it does not need additional compression, and indeed that additional compression will decrease performance. Gzip or ZIP compression applied to a GeoTIFF with internal compression will not make the file smaller.\nIt is possible but not recommended to create COGs or GeoTIFFs with no internal compression.\n\n\n\nThere are a variety of compression codecs supported by GeoTIFF. Compression codecs tend to be split into two camps: lossy compression where the exact original values cannot be recovered or lossless compression which does not lose any information through the compression and decompression process. For most cases, a lossless compression is recommended, but in some cases a lossy compression can be useful and lead to smaller file sizes, such as if the COG is intended to be used only for visualization.\nDeflate or LZW are both lossless compression codecs and are the recommended algorithms for general use.\nJPEG is a lossy compression codec useful for true-color GeoTIFFs intended to be used only for visualization. Because it’s lossy, it tends to produce smaller file sizes than deflate or LZW. JPEG should only be used with RGB Byte data.\nLERC (Limited Error Raster Compression) is a lossy but very efficient compression algorithm for floating point data. This compression rounds values to a precision provided by the user and tends to be useful e.g. for elevation data where the source data is known to not have precision beyond a known value. But note, this compression is not lossless. Additionally, LERC is a relatively new algorithm and may not be supported everywhere. GDAL needs to be compiled with the LERC driver in order to load a GeoTIFF with LERC compression.\nSome other compression algorithms may be preferred depending on the data type and distribution, and if the goal is maximum compression or not. Codecs that produce the smallest file sizes tend to take longer to read into memory. If the network bandwidth to load the file is slow, then a very efficient compression algorithm may be most efficient, even if it takes longer to decompress when loaded. Alternatively, if the network speed is very fast, or if reading from a local disk, a slightly less efficient compression codec that decompresses faster may be preferred.\nThere are many posts on the internet exploring GeoTIFF compression and performance:\n\nGuide to GeoTIFF compression and optimization with GDAL\nGeoTiff Compression for Dummies\nGeoTiff compression comparison" + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-details.html#no-data", + "href": "cloud-optimized-geotiffs/cogs-details.html#no-data", + "title": "Advanced COG/GeoTIFF Details", + "section": "", + "text": "Setting a no data value makes it clear to users and visualization tools what pixels are not actually data. For visualization this allows these pixels to be easily hidden (transparent). Historically many values have been used, 0, -9999, etc… The key is to make sure the GDAL flag for no data is set. It is also suggested that the smallest negative value be used instead of a random value. For byte and unsigned integers data types this will be 0. For float data, setting NaN as the no data value is suggested. Make sure to use a no data value that does not have meaning in your data; otherwise use a different value (like the max possible value). Having the right nodata flag set is important for overview generation." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-details.html#projection", + "href": "cloud-optimized-geotiffs/cogs-details.html#projection", + "title": "Advanced COG/GeoTIFF Details", + "section": "", + "text": "Read performance can be greatly impacted by the choice of projection and the particular applications used for dynamic tile serving. Using a known CRS defined in the PROJ database (typically EPSG code) is preferred over custom projections. Load times can be 5-20 times greater when using a custom projection. Whenever applying projections make sure to use WKT2 representation. If using a database of known projections, i.e. EPSG codes, this should be fine, there are known issues around manually setting proj-strings." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-details.html#web-optimized-cog", + "href": "cloud-optimized-geotiffs/cogs-details.html#web-optimized-cog", + "title": "Advanced COG/GeoTIFF Details", + "section": "", + "text": "Up to this point, we’ve mentioned that a COG has internal tiling, but the exact layout of those internal tiles has been unspecified. A web-optimized COG exploits that internal tiling to enforce the same tiling as used in web maps. Additionally, overviews will also be aligned to the Web Mercator grid. Thus, a web-optimized COG is especially useful for relaying tiled image data to a browser. Because the internal tile layout exactly matches the tiling structure required in web mapping libraries, only one HTTP range request needs to be performed to access any tile.\nDownsides of web-optimized COGs include the fact that they must be in Web Mercator projection and that the file most likely will not line up exactly with the bounds of the original image data. This means that the COG will have a “collar” of invalid data around the edges of the file.\nWeb-Optimized COGs can be created via GDAL by using the COG driver with the creation option TILING_SCHEME=GoogleMapsCompatible or with rio-cogeo with the --web-optimized flag." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-details.html#what-we-dont-know-areas-of-research", + "href": "cloud-optimized-geotiffs/cogs-details.html#what-we-dont-know-areas-of-research", + "title": "Advanced COG/GeoTIFF Details", + "section": "", + "text": "The optimum size of data at which splitting across files improves performance as a multi-file dataset instead of a single file.\nWhen to recommend particular internal tile sizes\nCompression impacts on http transfer rates.\nSupport for COG creation in all common geospatial tools varies." + }, + { + "objectID": "cloud-optimized-geotiffs/cogs-details.html#additional-resources", + "href": "cloud-optimized-geotiffs/cogs-details.html#additional-resources", + "title": "Advanced COG/GeoTIFF Details", + "section": "", + "text": "An Introduction to Cloud Optimized GeoTIFFS (COGs) Part 1: Overview\nDo you really want people using your data?" + }, + { + "objectID": "copc/index.html", + "href": "copc/index.html", + "title": "Cloud-Optimized Point Clouds (COPC)", + "section": "", + "text": "The LASER (LAS) file format is designed to store 3-dimensional (x,y,z) point cloud data typically collected from LiDAR. An LAZ file is a compressed LAS file and a Cloud-Optimized Point Cloud (COPC) file is a valid LAZ file.\nCOPC files are similar to COGs for GeoTIFFs: Both are valid versions of the original file format but with additional requirements to support cloud-optimized data access. In the case of COGs, there are additional requirements for tiling and overviews. For COPC, data must be organized into a clustered octree with a variable-length record (VLR) describing the octree structure.\nRead more at https://copc.io/.\nStay tuned for more information on COPC in future releases of this guide." + }, + { + "objectID": "pmtiles/intro.html", + "href": "pmtiles/intro.html", + "title": "PMTiles", + "section": "", + "text": "PMTiles is a single-file archive format for tiled data, usually used for visualization.\nAs an “archive format”, PMTiles is similar to a ZIP file: it contains the contents of many individual files inside of one PMTiles file. A single file is often much easier to use and keep track of than many very small files.\nPMTiles is designed for tiled data. That is, data where one inner file represents a small square somewhere on a map, usually representing the Web Mercator grid. PMTiles can be used for any format of tiled data. PMTiles is used most often with vector data, where each tile data contained within the archive is encoded as a Mapbox Vector Tile (MVT), but can also be used with e.g. raster data or terrain mesh data.\n\n\nTo understand PMTiles, it’s important to understand the difference between “analytical” data and “tiled” data. Analytical data refers to data in its original form, without any modifications to geometry. Tiled data formats apply a variety of modifications to geometries, including clipping and simplification, to save space and make it faster to visualize.\n\nConsider the above diagram. In an analytical format, every coordinate of the complex polygon would be included in one single file. In a tiled format, there are predefined tile sets (or grids) and the geometry would be split into one or more files, where each file represents one cell of the grid.\nThe analytical format is more useful for operations like a spatial join, because the entire geometry is available. It’s harder to perform such analyses on tiled data because given any one tile, it’s impossible to know whether the data contained in that tile represents the full geometry or not.\n\nKnow which other tiles contain part of this polygon (This is hard! It requires some other pre-generated attribute other than the geometry itself.)\nFetch each of those neighboring tiles\nAssemble the dissected geometries back into a single geometry\nApply the desired operation\n\nThe tiled format is more useful for visualization because a user who wants to visualize a small area only needs to download a few tiles. Additionally loading the data is faster because of simplification. It’s slower to visualize analytical data because the entire shape with all coordinates must be loaded, even if visualizing only a small area.\nThus analytical and visualization formats strive for different goals.\n\n\n\nPMTiles is designed to be a cloud-native file format: used directly from a client over a network via HTTP range requests, without having a server in the middle.\n\n\n\nPMTiles has a file header, one or more metadata regions, and a region of tile data.\nThe header is fixed length, located at the beginning of the file, and includes necessary information to decode the rest of the file accurately.\nPMTiles includes directories, or regions of bytes with metadata about tiles. It’s important for each directory to remain small, so while there will always be at least one directory, larger PMTiles archives with many tiles may include more than one directory.\nAt the end of the file is the tile data. This includes all data for all the tiles in the archive.\nThe full specification is defined here.\n\n\nInterally, tiles are oriented along a Hilbert Curve. This means that tiles that are spatially near each other are also located near each other in the file structure.\nThis is especially appropriate for PMTiles because visualization purposes most often request data within a specific geographic area. Because spatially-nearby tiles are likely to be nearby in the file as well, this allows the PMTiles client to merge multiple requests for tiles into one larger request, rather than needing to fetch a different area of the file for each tile.\n\n\n\n\nPMTiles archives support storing a full XYZ pyramid of tile data. This means that you can store multiple zoom levels of data inside a single file.\n\n\n\nPMTiles allows tiles to be stored in the file with compression.\n\n\n\n\n\nThe easiest way to generate PMTiles for vector data is through the tippecanoe tool. This will generate vector tiles that are ideal for visualization, removing small features at low zoom levels to keep tiles a manageable size.\n\n\n\nPMTiles has a command-line program for creating PMTiles if you already have an MBTiles file or a directory of tiles.\n\n\n\n\n\n\nIf you have an existing PMTiles archive, either as a local file or hosted on cloud storage, you can use the PMTiles Viewer to inspect the tiles hosted within the file.\n\n\n\nPMTiles doesn’t have a standalone JavaScript library, but rather is designed to be used in conjunction with a JavaScript map rendering library.\nSee the docs on viewing PMTiles in Leaflet, MapLibre GL JS and OpenLayers.\n\n\n\nPMTiles has a Python package, which allows reading and writing PMTiles archives from Python.\n\n\n\n\n\n\nThe most common alternative for PMTiles is MBTiles, which was in many ways the precursor to PMTiles. MBTiles stores the included vector tiles in a table in a SQLite database. MBTiles has the benefit of being much easier to use than manually managing millions of tiny, individual files, but MBTiles is not serverless. In general, it’s impossible to read from a SQLite database without fetching the entire file’s content. This means that frontend clients like a web browser couldn’t fetch tiles directly using range requests, but rather a server has to be running to fetch tiles from the MBTiles file.\n\n\n\nIt’s also possible to upload the bare tiled data directly to cloud storage as individual files.\nThis has significant downsides of needing to manage many millions of tiny individual files. Uploading millions of files to a cloud storage provider such as S3 takes time and money. For example, AWS charges $5 per million files added to an S3 bucket. So a 10 million PMTiles archive would cost $50, compared to 5-millionths of a cent to upload the PMTiles file." + }, + { + "objectID": "pmtiles/intro.html#analytical-vs-tiled-data-formats", + "href": "pmtiles/intro.html#analytical-vs-tiled-data-formats", + "title": "PMTiles", + "section": "", + "text": "To understand PMTiles, it’s important to understand the difference between “analytical” data and “tiled” data. Analytical data refers to data in its original form, without any modifications to geometry. Tiled data formats apply a variety of modifications to geometries, including clipping and simplification, to save space and make it faster to visualize.\n\nConsider the above diagram. In an analytical format, every coordinate of the complex polygon would be included in one single file. In a tiled format, there are predefined tile sets (or grids) and the geometry would be split into one or more files, where each file represents one cell of the grid.\nThe analytical format is more useful for operations like a spatial join, because the entire geometry is available. It’s harder to perform such analyses on tiled data because given any one tile, it’s impossible to know whether the data contained in that tile represents the full geometry or not.\n\nKnow which other tiles contain part of this polygon (This is hard! It requires some other pre-generated attribute other than the geometry itself.)\nFetch each of those neighboring tiles\nAssemble the dissected geometries back into a single geometry\nApply the desired operation\n\nThe tiled format is more useful for visualization because a user who wants to visualize a small area only needs to download a few tiles. Additionally loading the data is faster because of simplification. It’s slower to visualize analytical data because the entire shape with all coordinates must be loaded, even if visualizing only a small area.\nThus analytical and visualization formats strive for different goals." + }, + { + "objectID": "pmtiles/intro.html#cloud-native", + "href": "pmtiles/intro.html#cloud-native", + "title": "PMTiles", + "section": "", + "text": "PMTiles is designed to be a cloud-native file format: used directly from a client over a network via HTTP range requests, without having a server in the middle." + }, + { + "objectID": "pmtiles/intro.html#internal-format", + "href": "pmtiles/intro.html#internal-format", + "title": "PMTiles", + "section": "", + "text": "PMTiles has a file header, one or more metadata regions, and a region of tile data.\nThe header is fixed length, located at the beginning of the file, and includes necessary information to decode the rest of the file accurately.\nPMTiles includes directories, or regions of bytes with metadata about tiles. It’s important for each directory to remain small, so while there will always be at least one directory, larger PMTiles archives with many tiles may include more than one directory.\nAt the end of the file is the tile data. This includes all data for all the tiles in the archive.\nThe full specification is defined here.\n\n\nInterally, tiles are oriented along a Hilbert Curve. This means that tiles that are spatially near each other are also located near each other in the file structure.\nThis is especially appropriate for PMTiles because visualization purposes most often request data within a specific geographic area. Because spatially-nearby tiles are likely to be nearby in the file as well, this allows the PMTiles client to merge multiple requests for tiles into one larger request, rather than needing to fetch a different area of the file for each tile." + }, + { + "objectID": "pmtiles/intro.html#multiple-resolution", + "href": "pmtiles/intro.html#multiple-resolution", + "title": "PMTiles", + "section": "", + "text": "PMTiles archives support storing a full XYZ pyramid of tile data. This means that you can store multiple zoom levels of data inside a single file." + }, + { + "objectID": "pmtiles/intro.html#internal-compression", + "href": "pmtiles/intro.html#internal-compression", + "title": "PMTiles", + "section": "", + "text": "PMTiles allows tiles to be stored in the file with compression." + }, + { + "objectID": "pmtiles/intro.html#generating-pmtiles", + "href": "pmtiles/intro.html#generating-pmtiles", + "title": "PMTiles", + "section": "", + "text": "The easiest way to generate PMTiles for vector data is through the tippecanoe tool. This will generate vector tiles that are ideal for visualization, removing small features at low zoom levels to keep tiles a manageable size.\n\n\n\nPMTiles has a command-line program for creating PMTiles if you already have an MBTiles file or a directory of tiles." + }, + { + "objectID": "pmtiles/intro.html#using-pmtiles", + "href": "pmtiles/intro.html#using-pmtiles", + "title": "PMTiles", + "section": "", + "text": "If you have an existing PMTiles archive, either as a local file or hosted on cloud storage, you can use the PMTiles Viewer to inspect the tiles hosted within the file.\n\n\n\nPMTiles doesn’t have a standalone JavaScript library, but rather is designed to be used in conjunction with a JavaScript map rendering library.\nSee the docs on viewing PMTiles in Leaflet, MapLibre GL JS and OpenLayers.\n\n\n\nPMTiles has a Python package, which allows reading and writing PMTiles archives from Python." + }, + { + "objectID": "pmtiles/intro.html#alternatives", + "href": "pmtiles/intro.html#alternatives", + "title": "PMTiles", + "section": "", + "text": "The most common alternative for PMTiles is MBTiles, which was in many ways the precursor to PMTiles. MBTiles stores the included vector tiles in a table in a SQLite database. MBTiles has the benefit of being much easier to use than manually managing millions of tiny, individual files, but MBTiles is not serverless. In general, it’s impossible to read from a SQLite database without fetching the entire file’s content. This means that frontend clients like a web browser couldn’t fetch tiles directly using range requests, but rather a server has to be running to fetch tiles from the MBTiles file.\n\n\n\nIt’s also possible to upload the bare tiled data directly to cloud storage as individual files.\nThis has significant downsides of needing to manage many millions of tiny individual files. Uploading millions of files to a cloud storage provider such as S3 takes time and money. For example, AWS charges $5 per million files added to an S3 bucket. So a 10 million PMTiles archive would cost $50, compared to 5-millionths of a cent to upload the PMTiles file." + } +] \ No newline at end of file diff --git a/pr-preview/pr-68/site_libs/bootstrap/bootstrap-dark.min.css b/pr-preview/pr-68/site_libs/bootstrap/bootstrap-dark.min.css new file mode 100644 index 0000000..16e83c4 --- /dev/null +++ b/pr-preview/pr-68/site_libs/bootstrap/bootstrap-dark.min.css @@ -0,0 +1,10 @@ +@import'https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible&display=swap';/*! + * Bootstrap v5.1.3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */@import"https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@300;400;700&display=swap";:root{--bs-blue: #2780e3;--bs-indigo: #6610f2;--bs-purple: #613d7c;--bs-pink: #e83e8c;--bs-red: #ff0039;--bs-orange: #f0ad4e;--bs-yellow: #ff7518;--bs-green: #3fb618;--bs-teal: #20c997;--bs-cyan: #9954bb;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #373a3c;--bs-gray-100: #f8f9fa;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #495057;--bs-gray-800: #373a3c;--bs-gray-900: #212529;--bs-default: #373a3c;--bs-primary: #2780e3;--bs-secondary: #373a3c;--bs-success: #3fb618;--bs-info: #9954bb;--bs-warning: #ff7518;--bs-danger: #ff0039;--bs-light: #525252;--bs-dark: #373a3c;--bs-default-rgb: 55, 58, 60;--bs-primary-rgb: 39, 128, 227;--bs-secondary-rgb: 55, 58, 60;--bs-success-rgb: 63, 182, 24;--bs-info-rgb: 153, 84, 187;--bs-warning-rgb: 255, 117, 24;--bs-danger-rgb: 255, 0, 57;--bs-light-rgb: 82, 82, 82;--bs-dark-rgb: 55, 58, 60;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-body-color-rgb: 255, 255, 255;--bs-body-bg-rgb: 24, 24, 24;--bs-font-sans-serif: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-root-font-size: 17px;--bs-body-font-family: var(--bs-font-sans-serif);--bs-body-font-size: 1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: white;--bs-body-bg: #181818}*,*::before,*::after{box-sizing:border-box}:root{font-size:var(--bs-root-font-size)}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:400;line-height:1.2}h1,.h1{font-size:calc(1.325rem + 0.9vw)}@media(min-width: 1200px){h1,.h1{font-size:2rem}}h2,.h2{font-size:calc(1.29rem + 0.48vw)}@media(min-width: 1200px){h2,.h2{font-size:1.65rem}}h3,.h3{font-size:calc(1.27rem + 0.24vw)}@media(min-width: 1200px){h3,.h3{font-size:1.45rem}}h4,.h4{font-size:1.25rem}h5,.h5{font-size:1.1rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-bs-original-title]{text-decoration:underline dotted;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;-ms-text-decoration:underline dotted;-o-text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem;padding:.625rem 1.25rem;border-left:.25rem solid #e9ecef}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}b,strong{font-weight:bolder}small,.small{font-size:0.875em}mark,.mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:0.75em;line-height:0;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}a{color:#75aadb;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}a:hover{color:#5e88af}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr /* rtl:ignore */;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:0.875em;color:#fff;background-color:#212121;padding:.5rem;border:1px solid #dee2e6}pre code{background-color:rgba(0,0,0,0);font-size:inherit;color:inherit;word-break:normal}code{font-size:0.875em;color:#9753b8;background-color:#212121;padding:.125rem .25rem;word-wrap:break-word}a>code{color:inherit}kbd{padding:.4rem .4rem;font-size:0.875em;color:#fff;background-color:#212529}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + 0.3vw);line-height:inherit}@media(min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:0.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:0.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#181818;border:1px solid #dee2e6;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:0.875em;color:#6c757d}.grid{display:grid;grid-template-rows:repeat(var(--bs-rows, 1), 1fr);grid-template-columns:repeat(var(--bs-columns, 12), 1fr);gap:var(--bs-gap, 1.5rem)}.grid .g-col-1{grid-column:auto/span 1}.grid .g-col-2{grid-column:auto/span 2}.grid .g-col-3{grid-column:auto/span 3}.grid .g-col-4{grid-column:auto/span 4}.grid .g-col-5{grid-column:auto/span 5}.grid .g-col-6{grid-column:auto/span 6}.grid .g-col-7{grid-column:auto/span 7}.grid .g-col-8{grid-column:auto/span 8}.grid .g-col-9{grid-column:auto/span 9}.grid .g-col-10{grid-column:auto/span 10}.grid .g-col-11{grid-column:auto/span 11}.grid .g-col-12{grid-column:auto/span 12}.grid .g-start-1{grid-column-start:1}.grid .g-start-2{grid-column-start:2}.grid .g-start-3{grid-column-start:3}.grid .g-start-4{grid-column-start:4}.grid .g-start-5{grid-column-start:5}.grid .g-start-6{grid-column-start:6}.grid .g-start-7{grid-column-start:7}.grid .g-start-8{grid-column-start:8}.grid .g-start-9{grid-column-start:9}.grid .g-start-10{grid-column-start:10}.grid .g-start-11{grid-column-start:11}@media(min-width: 576px){.grid .g-col-sm-1{grid-column:auto/span 1}.grid .g-col-sm-2{grid-column:auto/span 2}.grid .g-col-sm-3{grid-column:auto/span 3}.grid .g-col-sm-4{grid-column:auto/span 4}.grid .g-col-sm-5{grid-column:auto/span 5}.grid .g-col-sm-6{grid-column:auto/span 6}.grid .g-col-sm-7{grid-column:auto/span 7}.grid .g-col-sm-8{grid-column:auto/span 8}.grid .g-col-sm-9{grid-column:auto/span 9}.grid .g-col-sm-10{grid-column:auto/span 10}.grid .g-col-sm-11{grid-column:auto/span 11}.grid .g-col-sm-12{grid-column:auto/span 12}.grid .g-start-sm-1{grid-column-start:1}.grid .g-start-sm-2{grid-column-start:2}.grid .g-start-sm-3{grid-column-start:3}.grid .g-start-sm-4{grid-column-start:4}.grid .g-start-sm-5{grid-column-start:5}.grid .g-start-sm-6{grid-column-start:6}.grid .g-start-sm-7{grid-column-start:7}.grid .g-start-sm-8{grid-column-start:8}.grid .g-start-sm-9{grid-column-start:9}.grid .g-start-sm-10{grid-column-start:10}.grid .g-start-sm-11{grid-column-start:11}}@media(min-width: 768px){.grid .g-col-md-1{grid-column:auto/span 1}.grid .g-col-md-2{grid-column:auto/span 2}.grid .g-col-md-3{grid-column:auto/span 3}.grid .g-col-md-4{grid-column:auto/span 4}.grid .g-col-md-5{grid-column:auto/span 5}.grid .g-col-md-6{grid-column:auto/span 6}.grid .g-col-md-7{grid-column:auto/span 7}.grid .g-col-md-8{grid-column:auto/span 8}.grid .g-col-md-9{grid-column:auto/span 9}.grid .g-col-md-10{grid-column:auto/span 10}.grid .g-col-md-11{grid-column:auto/span 11}.grid .g-col-md-12{grid-column:auto/span 12}.grid .g-start-md-1{grid-column-start:1}.grid .g-start-md-2{grid-column-start:2}.grid .g-start-md-3{grid-column-start:3}.grid .g-start-md-4{grid-column-start:4}.grid .g-start-md-5{grid-column-start:5}.grid .g-start-md-6{grid-column-start:6}.grid .g-start-md-7{grid-column-start:7}.grid .g-start-md-8{grid-column-start:8}.grid .g-start-md-9{grid-column-start:9}.grid .g-start-md-10{grid-column-start:10}.grid .g-start-md-11{grid-column-start:11}}@media(min-width: 992px){.grid .g-col-lg-1{grid-column:auto/span 1}.grid .g-col-lg-2{grid-column:auto/span 2}.grid .g-col-lg-3{grid-column:auto/span 3}.grid .g-col-lg-4{grid-column:auto/span 4}.grid .g-col-lg-5{grid-column:auto/span 5}.grid .g-col-lg-6{grid-column:auto/span 6}.grid .g-col-lg-7{grid-column:auto/span 7}.grid .g-col-lg-8{grid-column:auto/span 8}.grid .g-col-lg-9{grid-column:auto/span 9}.grid .g-col-lg-10{grid-column:auto/span 10}.grid .g-col-lg-11{grid-column:auto/span 11}.grid .g-col-lg-12{grid-column:auto/span 12}.grid .g-start-lg-1{grid-column-start:1}.grid .g-start-lg-2{grid-column-start:2}.grid .g-start-lg-3{grid-column-start:3}.grid .g-start-lg-4{grid-column-start:4}.grid .g-start-lg-5{grid-column-start:5}.grid .g-start-lg-6{grid-column-start:6}.grid .g-start-lg-7{grid-column-start:7}.grid .g-start-lg-8{grid-column-start:8}.grid .g-start-lg-9{grid-column-start:9}.grid .g-start-lg-10{grid-column-start:10}.grid .g-start-lg-11{grid-column-start:11}}@media(min-width: 1200px){.grid .g-col-xl-1{grid-column:auto/span 1}.grid .g-col-xl-2{grid-column:auto/span 2}.grid .g-col-xl-3{grid-column:auto/span 3}.grid .g-col-xl-4{grid-column:auto/span 4}.grid .g-col-xl-5{grid-column:auto/span 5}.grid .g-col-xl-6{grid-column:auto/span 6}.grid .g-col-xl-7{grid-column:auto/span 7}.grid .g-col-xl-8{grid-column:auto/span 8}.grid .g-col-xl-9{grid-column:auto/span 9}.grid .g-col-xl-10{grid-column:auto/span 10}.grid .g-col-xl-11{grid-column:auto/span 11}.grid .g-col-xl-12{grid-column:auto/span 12}.grid .g-start-xl-1{grid-column-start:1}.grid .g-start-xl-2{grid-column-start:2}.grid .g-start-xl-3{grid-column-start:3}.grid .g-start-xl-4{grid-column-start:4}.grid .g-start-xl-5{grid-column-start:5}.grid .g-start-xl-6{grid-column-start:6}.grid .g-start-xl-7{grid-column-start:7}.grid .g-start-xl-8{grid-column-start:8}.grid .g-start-xl-9{grid-column-start:9}.grid .g-start-xl-10{grid-column-start:10}.grid .g-start-xl-11{grid-column-start:11}}@media(min-width: 1400px){.grid .g-col-xxl-1{grid-column:auto/span 1}.grid .g-col-xxl-2{grid-column:auto/span 2}.grid .g-col-xxl-3{grid-column:auto/span 3}.grid .g-col-xxl-4{grid-column:auto/span 4}.grid .g-col-xxl-5{grid-column:auto/span 5}.grid .g-col-xxl-6{grid-column:auto/span 6}.grid .g-col-xxl-7{grid-column:auto/span 7}.grid .g-col-xxl-8{grid-column:auto/span 8}.grid .g-col-xxl-9{grid-column:auto/span 9}.grid .g-col-xxl-10{grid-column:auto/span 10}.grid .g-col-xxl-11{grid-column:auto/span 11}.grid .g-col-xxl-12{grid-column:auto/span 12}.grid .g-start-xxl-1{grid-column-start:1}.grid .g-start-xxl-2{grid-column-start:2}.grid .g-start-xxl-3{grid-column-start:3}.grid .g-start-xxl-4{grid-column-start:4}.grid .g-start-xxl-5{grid-column-start:5}.grid .g-start-xxl-6{grid-column-start:6}.grid .g-start-xxl-7{grid-column-start:7}.grid .g-start-xxl-8{grid-column-start:8}.grid .g-start-xxl-9{grid-column-start:9}.grid .g-start-xxl-10{grid-column-start:10}.grid .g-start-xxl-11{grid-column-start:11}}.table{--bs-table-bg: transparent;--bs-table-accent-bg: transparent;--bs-table-striped-color: white;--bs-table-striped-bg: rgba(0, 0, 0, 0.05);--bs-table-active-color: white;--bs-table-active-bg: rgba(0, 0, 0, 0.1);--bs-table-hover-color: white;--bs-table-hover-bg: rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;color:#fff;vertical-align:top;border-color:#dee2e6}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table>:not(:first-child){border-top:2px solid #fff}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-accent-bg: var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg: var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover>*{--bs-table-accent-bg: var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg: #d4e6f9;--bs-table-striped-bg: #c9dbed;--bs-table-striped-color: #000;--bs-table-active-bg: #bfcfe0;--bs-table-active-color: #000;--bs-table-hover-bg: #c4d5e6;--bs-table-hover-color: #000;color:#000;border-color:#bfcfe0}.table-secondary{--bs-table-bg: #d7d8d8;--bs-table-striped-bg: #cccdcd;--bs-table-striped-color: #000;--bs-table-active-bg: #c2c2c2;--bs-table-active-color: #000;--bs-table-hover-bg: #c7c8c8;--bs-table-hover-color: #000;color:#000;border-color:#c2c2c2}.table-success{--bs-table-bg: #d9f0d1;--bs-table-striped-bg: #cee4c7;--bs-table-striped-color: #000;--bs-table-active-bg: #c3d8bc;--bs-table-active-color: #000;--bs-table-hover-bg: #c9dec1;--bs-table-hover-color: #000;color:#000;border-color:#c3d8bc}.table-info{--bs-table-bg: #ebddf1;--bs-table-striped-bg: #dfd2e5;--bs-table-striped-color: #000;--bs-table-active-bg: #d4c7d9;--bs-table-active-color: #000;--bs-table-hover-bg: #d9ccdf;--bs-table-hover-color: #000;color:#000;border-color:#d4c7d9}.table-warning{--bs-table-bg: #ffe3d1;--bs-table-striped-bg: #f2d8c7;--bs-table-striped-color: #000;--bs-table-active-bg: #e6ccbc;--bs-table-active-color: #000;--bs-table-hover-bg: #ecd2c1;--bs-table-hover-color: #000;color:#000;border-color:#e6ccbc}.table-danger{--bs-table-bg: #ffccd7;--bs-table-striped-bg: #f2c2cc;--bs-table-striped-color: #000;--bs-table-active-bg: #e6b8c2;--bs-table-active-color: #000;--bs-table-hover-bg: #ecbdc7;--bs-table-hover-color: #000;color:#000;border-color:#e6b8c2}.table-light{--bs-table-bg: #525252;--bs-table-striped-bg: #5b5b5b;--bs-table-striped-color: #fff;--bs-table-active-bg: #636363;--bs-table-active-color: #fff;--bs-table-hover-bg: #5f5f5f;--bs-table-hover-color: #fff;color:#fff;border-color:#636363}.table-dark{--bs-table-bg: #373a3c;--bs-table-striped-bg: #414446;--bs-table-striped-color: #fff;--bs-table-active-bg: #4b4e50;--bs-table-active-color: #fff;--bs-table-hover-bg: #46494b;--bs-table-hover-color: #fff;color:#fff;border-color:#4b4e50}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width: 575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label,.shiny-input-container .control-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.875rem}.form-text{margin-top:.25rem;font-size:0.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#fff;background-color:#242424;background-clip:padding-box;border:1px solid #ced4da;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;border-radius:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#fff;background-color:#242424;border-color:#93c0f1;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-0.375rem -0.75rem;margin-inline-end:.75rem;color:#000;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-0.375rem -0.75rem;margin-inline-end:.75rem;color:#000;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control::-webkit-file-upload-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#fff;background-color:rgba(0,0,0,0);border:solid rgba(0,0,0,0);border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + 0.5rem + 2px);padding:.25rem .5rem;font-size:0.875rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-0.25rem -0.5rem;margin-inline-end:.5rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-0.25rem -0.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-0.5rem -1rem;margin-inline-end:1rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-0.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + 0.75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + 0.5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{width:3rem;height:auto;padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{height:1.5em}.form-control-color::-webkit-color-swatch{height:1.5em}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;-moz-padding-start:calc(0.75rem - 3px);font-size:1rem;font-weight:400;line-height:1.5;color:#fff;background-color:#242424;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23373a3c' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media(prefers-reduced-motion: reduce){.form-select{transition:none}}.form-select:focus{border-color:#93c0f1;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:rgba(0,0,0,0);text-shadow:0 0 0 #fff}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:0.875rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check,.shiny-input-container .checkbox,.shiny-input-container .radio{display:block;min-height:1.5rem;padding-left:0;margin-bottom:.125rem}.form-check .form-check-input,.form-check .shiny-input-container .checkbox input,.form-check .shiny-input-container .radio input,.shiny-input-container .checkbox .form-check-input,.shiny-input-container .checkbox .shiny-input-container .checkbox input,.shiny-input-container .checkbox .shiny-input-container .radio input,.shiny-input-container .radio .form-check-input,.shiny-input-container .radio .shiny-input-container .checkbox input,.shiny-input-container .radio .shiny-input-container .radio input{float:left;margin-left:0}.form-check-input,.shiny-input-container .checkbox input,.shiny-input-container .checkbox-inline input,.shiny-input-container .radio input,.shiny-input-container .radio-inline input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#242424;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;color-adjust:exact;-webkit-print-color-adjust:exact}.form-check-input[type=radio],.shiny-input-container .checkbox input[type=radio],.shiny-input-container .checkbox-inline input[type=radio],.shiny-input-container .radio input[type=radio],.shiny-input-container .radio-inline input[type=radio]{border-radius:50%}.form-check-input:active,.shiny-input-container .checkbox input:active,.shiny-input-container .checkbox-inline input:active,.shiny-input-container .radio input:active,.shiny-input-container .radio-inline input:active{filter:brightness(90%)}.form-check-input:focus,.shiny-input-container .checkbox input:focus,.shiny-input-container .checkbox-inline input:focus,.shiny-input-container .radio input:focus,.shiny-input-container .radio-inline input:focus{border-color:#93c0f1;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.form-check-input:checked,.shiny-input-container .checkbox input:checked,.shiny-input-container .checkbox-inline input:checked,.shiny-input-container .radio input:checked,.shiny-input-container .radio-inline input:checked{background-color:#2780e3;border-color:#2780e3}.form-check-input:checked[type=checkbox],.shiny-input-container .checkbox input:checked[type=checkbox],.shiny-input-container .checkbox-inline input:checked[type=checkbox],.shiny-input-container .radio input:checked[type=checkbox],.shiny-input-container .radio-inline input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio],.shiny-input-container .checkbox input:checked[type=radio],.shiny-input-container .checkbox-inline input:checked[type=radio],.shiny-input-container .radio input:checked[type=radio],.shiny-input-container .radio-inline input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate,.shiny-input-container .checkbox input[type=checkbox]:indeterminate,.shiny-input-container .checkbox-inline input[type=checkbox]:indeterminate,.shiny-input-container .radio input[type=checkbox]:indeterminate,.shiny-input-container .radio-inline input[type=checkbox]:indeterminate{background-color:#2780e3;border-color:#2780e3;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled,.shiny-input-container .checkbox input:disabled,.shiny-input-container .checkbox-inline input:disabled,.shiny-input-container .radio input:disabled,.shiny-input-container .radio-inline input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input[disabled]~span,.form-check-input:disabled~.form-check-label,.form-check-input:disabled~span,.shiny-input-container .checkbox input[disabled]~.form-check-label,.shiny-input-container .checkbox input[disabled]~span,.shiny-input-container .checkbox input:disabled~.form-check-label,.shiny-input-container .checkbox input:disabled~span,.shiny-input-container .checkbox-inline input[disabled]~.form-check-label,.shiny-input-container .checkbox-inline input[disabled]~span,.shiny-input-container .checkbox-inline input:disabled~.form-check-label,.shiny-input-container .checkbox-inline input:disabled~span,.shiny-input-container .radio input[disabled]~.form-check-label,.shiny-input-container .radio input[disabled]~span,.shiny-input-container .radio input:disabled~.form-check-label,.shiny-input-container .radio input:disabled~span,.shiny-input-container .radio-inline input[disabled]~.form-check-label,.shiny-input-container .radio-inline input[disabled]~span,.shiny-input-container .radio-inline input:disabled~.form-check-label,.shiny-input-container .radio-inline input:disabled~span{opacity:.5}.form-check-label,.shiny-input-container .checkbox label,.shiny-input-container .checkbox-inline label,.shiny-input-container .radio label,.shiny-input-container .radio-inline label{cursor:pointer}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:left center;transition:background-position .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2393c0f1'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline,.shiny-input-container .checkbox-inline,.shiny-input-container .radio-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.btn-check[disabled]+.btn,.btn-check:disabled+.btn{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:rgba(0,0,0,0);appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #181818,0 0 0 .25rem rgba(39,128,227,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #181818,0 0 0 .25rem rgba(39,128,227,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-0.25rem;background-color:#2780e3;border:0;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media(prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#bed9f7}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#dee2e6;border-color:rgba(0,0,0,0)}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#2780e3;border:0;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media(prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#bed9f7}.form-range::-moz-range-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#dee2e6;border-color:rgba(0,0,0,0)}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-select{height:calc(3.5rem + 2px);line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;height:100%;padding:1rem .75rem;pointer-events:none;border:1px solid rgba(0,0,0,0);transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media(prefers-reduced-motion: reduce){.form-floating>label{transition:none}}.form-floating>.form-control{padding:1rem .75rem}.form-floating>.form-control::placeholder{color:rgba(0,0,0,0)}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.input-group{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:stretch;-webkit-align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#000;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.25rem .5rem;font-size:0.875rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#3fb618}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:rgba(63,182,24,.9)}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#3fb618;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%233fb618' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#3fb618;box-shadow:0 0 0 .25rem rgba(63,182,24,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#3fb618}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23373a3c' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%233fb618' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#3fb618;box-shadow:0 0 0 .25rem rgba(63,182,24,.25)}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#3fb618}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#3fb618}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(63,182,24,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#3fb618}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group .form-control:valid,.input-group .form-control.is-valid,.was-validated .input-group .form-select:valid,.input-group .form-select.is-valid{z-index:1}.was-validated .input-group .form-control:valid:focus,.input-group .form-control.is-valid:focus,.was-validated .input-group .form-select:valid:focus,.input-group .form-select.is-valid:focus{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#ff0039}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:rgba(255,0,57,.9)}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#ff0039;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23ff0039'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ff0039' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#ff0039;box-shadow:0 0 0 .25rem rgba(255,0,57,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#ff0039}.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"],.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23373a3c' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23ff0039'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ff0039' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#ff0039;box-shadow:0 0 0 .25rem rgba(255,0,57,.25)}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#ff0039}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#ff0039}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(255,0,57,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#ff0039}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group .form-control:invalid,.input-group .form-control.is-invalid,.was-validated .input-group .form-select:invalid,.input-group .form-select.is-invalid{z-index:2}.was-validated .input-group .form-control:invalid:focus,.input-group .form-control.is-invalid:focus,.was-validated .input-group .form-select:invalid:focus,.input-group .form-select.is-invalid:focus{z-index:3}.btn{display:inline-block;font-weight:400;line-height:1.5;color:#fff;text-align:center;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;vertical-align:middle;cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;background-color:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);padding:.375rem .75rem;font-size:1rem;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:#fff}.btn-check:focus+.btn,.btn:focus{outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{pointer-events:none;opacity:.65}.btn-default{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-default:hover{color:#fff;background-color:#2f3133;border-color:#2c2e30}.btn-check:focus+.btn-default,.btn-default:focus{color:#fff;background-color:#2f3133;border-color:#2c2e30;box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-check:checked+.btn-default,.btn-check:active+.btn-default,.btn-default:active,.btn-default.active,.show>.btn-default.dropdown-toggle{color:#fff;background-color:#2c2e30;border-color:#292c2d}.btn-check:checked+.btn-default:focus,.btn-check:active+.btn-default:focus,.btn-default:active:focus,.btn-default.active:focus,.show>.btn-default.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-default:disabled,.btn-default.disabled{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-primary{color:#fff;background-color:#2780e3;border-color:#2780e3}.btn-primary:hover{color:#fff;background-color:#216dc1;border-color:#1f66b6}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#216dc1;border-color:#1f66b6;box-shadow:0 0 0 .25rem rgba(71,147,231,.5)}.btn-check:checked+.btn-primary,.btn-check:active+.btn-primary,.btn-primary:active,.btn-primary.active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#1f66b6;border-color:#1d60aa}.btn-check:checked+.btn-primary:focus,.btn-check:active+.btn-primary:focus,.btn-primary:active:focus,.btn-primary.active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(71,147,231,.5)}.btn-primary:disabled,.btn-primary.disabled{color:#fff;background-color:#2780e3;border-color:#2780e3}.btn-secondary{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-secondary:hover{color:#fff;background-color:#2f3133;border-color:#2c2e30}.btn-check:focus+.btn-secondary,.btn-secondary:focus{color:#fff;background-color:#2f3133;border-color:#2c2e30;box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-check:checked+.btn-secondary,.btn-check:active+.btn-secondary,.btn-secondary:active,.btn-secondary.active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#2c2e30;border-color:#292c2d}.btn-check:checked+.btn-secondary:focus,.btn-check:active+.btn-secondary:focus,.btn-secondary:active:focus,.btn-secondary.active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-secondary:disabled,.btn-secondary.disabled{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-success{color:#fff;background-color:#3fb618;border-color:#3fb618}.btn-success:hover{color:#fff;background-color:#369b14;border-color:#329213}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#369b14;border-color:#329213;box-shadow:0 0 0 .25rem rgba(92,193,59,.5)}.btn-check:checked+.btn-success,.btn-check:active+.btn-success,.btn-success:active,.btn-success.active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#329213;border-color:#2f8912}.btn-check:checked+.btn-success:focus,.btn-check:active+.btn-success:focus,.btn-success:active:focus,.btn-success.active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(92,193,59,.5)}.btn-success:disabled,.btn-success.disabled{color:#fff;background-color:#3fb618;border-color:#3fb618}.btn-info{color:#fff;background-color:#9954bb;border-color:#9954bb}.btn-info:hover{color:#fff;background-color:#82479f;border-color:#7a4396}.btn-check:focus+.btn-info,.btn-info:focus{color:#fff;background-color:#82479f;border-color:#7a4396;box-shadow:0 0 0 .25rem rgba(168,110,197,.5)}.btn-check:checked+.btn-info,.btn-check:active+.btn-info,.btn-info:active,.btn-info.active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#7a4396;border-color:#733f8c}.btn-check:checked+.btn-info:focus,.btn-check:active+.btn-info:focus,.btn-info:active:focus,.btn-info.active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(168,110,197,.5)}.btn-info:disabled,.btn-info.disabled{color:#fff;background-color:#9954bb;border-color:#9954bb}.btn-warning{color:#fff;background-color:#ff7518;border-color:#ff7518}.btn-warning:hover{color:#fff;background-color:#d96314;border-color:#cc5e13}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#fff;background-color:#d96314;border-color:#cc5e13;box-shadow:0 0 0 .25rem rgba(255,138,59,.5)}.btn-check:checked+.btn-warning,.btn-check:active+.btn-warning,.btn-warning:active,.btn-warning.active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#cc5e13;border-color:#bf5812}.btn-check:checked+.btn-warning:focus,.btn-check:active+.btn-warning:focus,.btn-warning:active:focus,.btn-warning.active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(255,138,59,.5)}.btn-warning:disabled,.btn-warning.disabled{color:#fff;background-color:#ff7518;border-color:#ff7518}.btn-danger{color:#fff;background-color:#ff0039;border-color:#ff0039}.btn-danger:hover{color:#fff;background-color:#d90030;border-color:#cc002e}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#d90030;border-color:#cc002e;box-shadow:0 0 0 .25rem rgba(255,38,87,.5)}.btn-check:checked+.btn-danger,.btn-check:active+.btn-danger,.btn-danger:active,.btn-danger.active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#cc002e;border-color:#bf002b}.btn-check:checked+.btn-danger:focus,.btn-check:active+.btn-danger:focus,.btn-danger:active:focus,.btn-danger.active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(255,38,87,.5)}.btn-danger:disabled,.btn-danger.disabled{color:#fff;background-color:#ff0039;border-color:#ff0039}.btn-light{color:#fff;background-color:#525252;border-color:#525252}.btn-light:hover{color:#fff;background-color:#464646;border-color:#424242}.btn-check:focus+.btn-light,.btn-light:focus{color:#fff;background-color:#464646;border-color:#424242;box-shadow:0 0 0 .25rem rgba(108,108,108,.5)}.btn-check:checked+.btn-light,.btn-check:active+.btn-light,.btn-light:active,.btn-light.active,.show>.btn-light.dropdown-toggle{color:#fff;background-color:#424242;border-color:#3e3e3e}.btn-check:checked+.btn-light:focus,.btn-check:active+.btn-light:focus,.btn-light:active:focus,.btn-light.active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(108,108,108,.5)}.btn-light:disabled,.btn-light.disabled{color:#fff;background-color:#525252;border-color:#525252}.btn-dark{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-dark:hover{color:#fff;background-color:#2f3133;border-color:#2c2e30}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#2f3133;border-color:#2c2e30;box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-check:checked+.btn-dark,.btn-check:active+.btn-dark,.btn-dark:active,.btn-dark.active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#2c2e30;border-color:#292c2d}.btn-check:checked+.btn-dark:focus,.btn-check:active+.btn-dark:focus,.btn-dark:active:focus,.btn-dark.active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-dark:disabled,.btn-dark.disabled{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-outline-default{color:#373a3c;border-color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-default:hover{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:focus+.btn-outline-default,.btn-outline-default:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-check:checked+.btn-outline-default,.btn-check:active+.btn-outline-default,.btn-outline-default:active,.btn-outline-default.active,.btn-outline-default.dropdown-toggle.show{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:checked+.btn-outline-default:focus,.btn-check:active+.btn-outline-default:focus,.btn-outline-default:active:focus,.btn-outline-default.active:focus,.btn-outline-default.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-outline-default:disabled,.btn-outline-default.disabled{color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-primary{color:#2780e3;border-color:#2780e3;background-color:rgba(0,0,0,0)}.btn-outline-primary:hover{color:#fff;background-color:#2780e3;border-color:#2780e3}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(39,128,227,.5)}.btn-check:checked+.btn-outline-primary,.btn-check:active+.btn-outline-primary,.btn-outline-primary:active,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show{color:#fff;background-color:#2780e3;border-color:#2780e3}.btn-check:checked+.btn-outline-primary:focus,.btn-check:active+.btn-outline-primary:focus,.btn-outline-primary:active:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(39,128,227,.5)}.btn-outline-primary:disabled,.btn-outline-primary.disabled{color:#2780e3;background-color:rgba(0,0,0,0)}.btn-outline-secondary{color:#373a3c;border-color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-secondary:hover{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-check:checked+.btn-outline-secondary,.btn-check:active+.btn-outline-secondary,.btn-outline-secondary:active,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:checked+.btn-outline-secondary:focus,.btn-check:active+.btn-outline-secondary:focus,.btn-outline-secondary:active:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-outline-secondary:disabled,.btn-outline-secondary.disabled{color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-success{color:#3fb618;border-color:#3fb618;background-color:rgba(0,0,0,0)}.btn-outline-success:hover{color:#fff;background-color:#3fb618;border-color:#3fb618}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(63,182,24,.5)}.btn-check:checked+.btn-outline-success,.btn-check:active+.btn-outline-success,.btn-outline-success:active,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show{color:#fff;background-color:#3fb618;border-color:#3fb618}.btn-check:checked+.btn-outline-success:focus,.btn-check:active+.btn-outline-success:focus,.btn-outline-success:active:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(63,182,24,.5)}.btn-outline-success:disabled,.btn-outline-success.disabled{color:#3fb618;background-color:rgba(0,0,0,0)}.btn-outline-info{color:#9954bb;border-color:#9954bb;background-color:rgba(0,0,0,0)}.btn-outline-info:hover{color:#fff;background-color:#9954bb;border-color:#9954bb}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(153,84,187,.5)}.btn-check:checked+.btn-outline-info,.btn-check:active+.btn-outline-info,.btn-outline-info:active,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show{color:#fff;background-color:#9954bb;border-color:#9954bb}.btn-check:checked+.btn-outline-info:focus,.btn-check:active+.btn-outline-info:focus,.btn-outline-info:active:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(153,84,187,.5)}.btn-outline-info:disabled,.btn-outline-info.disabled{color:#9954bb;background-color:rgba(0,0,0,0)}.btn-outline-warning{color:#ff7518;border-color:#ff7518;background-color:rgba(0,0,0,0)}.btn-outline-warning:hover{color:#fff;background-color:#ff7518;border-color:#ff7518}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,117,24,.5)}.btn-check:checked+.btn-outline-warning,.btn-check:active+.btn-outline-warning,.btn-outline-warning:active,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show{color:#fff;background-color:#ff7518;border-color:#ff7518}.btn-check:checked+.btn-outline-warning:focus,.btn-check:active+.btn-outline-warning:focus,.btn-outline-warning:active:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(255,117,24,.5)}.btn-outline-warning:disabled,.btn-outline-warning.disabled{color:#ff7518;background-color:rgba(0,0,0,0)}.btn-outline-danger{color:#ff0039;border-color:#ff0039;background-color:rgba(0,0,0,0)}.btn-outline-danger:hover{color:#fff;background-color:#ff0039;border-color:#ff0039}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(255,0,57,.5)}.btn-check:checked+.btn-outline-danger,.btn-check:active+.btn-outline-danger,.btn-outline-danger:active,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show{color:#fff;background-color:#ff0039;border-color:#ff0039}.btn-check:checked+.btn-outline-danger:focus,.btn-check:active+.btn-outline-danger:focus,.btn-outline-danger:active:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(255,0,57,.5)}.btn-outline-danger:disabled,.btn-outline-danger.disabled{color:#ff0039;background-color:rgba(0,0,0,0)}.btn-outline-light{color:#525252;border-color:#525252;background-color:rgba(0,0,0,0)}.btn-outline-light:hover{color:#fff;background-color:#525252;border-color:#525252}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(82,82,82,.5)}.btn-check:checked+.btn-outline-light,.btn-check:active+.btn-outline-light,.btn-outline-light:active,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show{color:#fff;background-color:#525252;border-color:#525252}.btn-check:checked+.btn-outline-light:focus,.btn-check:active+.btn-outline-light:focus,.btn-outline-light:active:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(82,82,82,.5)}.btn-outline-light:disabled,.btn-outline-light.disabled{color:#525252;background-color:rgba(0,0,0,0)}.btn-outline-dark{color:#373a3c;border-color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-dark:hover{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-check:checked+.btn-outline-dark,.btn-check:active+.btn-outline-dark,.btn-outline-dark:active,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:checked+.btn-outline-dark:focus,.btn-check:active+.btn-outline-dark:focus,.btn-outline-dark:active:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-outline-dark:disabled,.btn-outline-dark.disabled{color:#373a3c;background-color:rgba(0,0,0,0)}.btn-link{font-weight:400;color:#75aadb;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:hover{color:#5e88af}.btn-link:disabled,.btn-link.disabled{color:#6c757d}.btn-lg,.btn-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:0}.btn-sm,.btn-group-sm>.btn{padding:.25rem .5rem;font-size:0.875rem;border-radius:0}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .2s ease}@media(prefers-reduced-motion: reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media(prefers-reduced-motion: reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid rgba(0,0,0,0);border-bottom:0;border-left:.3em solid rgba(0,0,0,0)}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:0;font-size:1rem;color:#fff;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:.125rem}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media(min-width: 576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid rgba(0,0,0,0);border-bottom:.3em solid;border-left:.3em solid rgba(0,0,0,0)}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:0;border-bottom:.3em solid rgba(0,0,0,0);border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:.3em solid;border-bottom:.3em solid rgba(0,0,0,0)}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,.15)}.dropdown-item{display:block;width:100%;padding:.25rem 1rem;clear:both;font-weight:400;color:#212529;text-align:inherit;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap;background-color:rgba(0,0,0,0);border:0}.dropdown-item:hover,.dropdown-item:focus{color:#1e2125;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#2780e3}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:rgba(0,0,0,0)}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:0.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1rem;color:#212529}.dropdown-menu-dark{color:#dee2e6;background-color:#373a3c;border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:hover,.dropdown-menu-dark .dropdown-item:focus{color:#fff;background-color:rgba(255,255,255,.15)}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{color:#fff;background-color:#2780e3}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;justify-content:flex-start;-webkit-justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child){margin-left:-1px}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;-webkit-flex-direction:column;align-items:flex-start;-webkit-align-items:flex-start;justify-content:center;-webkit-justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.nav{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem;color:#75aadb;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media(prefers-reduced-motion: reduce){.nav-link{transition:none}}.nav-link:hover,.nav-link:focus{color:#5e88af}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background:none;border:1px solid rgba(0,0,0,0)}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:rgba(0,0,0,0);border-color:rgba(0,0,0,0)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#495057;background-color:#181818;border-color:#dee2e6 #dee2e6 #181818}.nav-tabs .dropdown-menu{margin-top:-1px}.nav-pills .nav-link{background:none;border:0}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#2780e3}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;-webkit-flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar>.container-xxl,.navbar>.container-xl,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container,.navbar>.container-fluid{display:flex;display:-webkit-flex;flex-wrap:inherit;-webkit-flex-wrap:inherit;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap}.navbar-nav{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;-webkit-flex-basis:100%;flex-grow:1;-webkit-flex-grow:1;align-items:center;-webkit-align-items:center}.navbar-toggler{padding:.25 0;font-size:1.25rem;line-height:1;background-color:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);transition:box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 .25rem}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height, 75vh);overflow-y:auto}@media(min-width: 576px){.navbar-expand-sm{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas-header{display:none}.navbar-expand-sm .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-sm .offcanvas-top,.navbar-expand-sm .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-sm .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 768px){.navbar-expand-md{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas-header{display:none}.navbar-expand-md .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-md .offcanvas-top,.navbar-expand-md .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-md .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 992px){.navbar-expand-lg{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas-header{display:none}.navbar-expand-lg .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-lg .offcanvas-top,.navbar-expand-lg .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-lg .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1200px){.navbar-expand-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas-header{display:none}.navbar-expand-xl .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-xl .offcanvas-top,.navbar-expand-xl .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-xl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1400px){.navbar-expand-xxl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-xxl .offcanvas-top,.navbar-expand-xxl .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-xxl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas-header{display:none}.navbar-expand .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand .offcanvas-top,.navbar-expand .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}.navbar-light{background-color:#303030}.navbar-light .navbar-brand{color:#bdbdbd}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:#9cc2e5}.navbar-light .navbar-nav .nav-link{color:#bdbdbd}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:rgba(156,194,229,.8)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(189,189,189,.75)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .nav-link.active{color:#9cc2e5}.navbar-light .navbar-toggler{color:#bdbdbd;border-color:rgba(189,189,189,0)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23bdbdbd' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:#bdbdbd}.navbar-light .navbar-text a,.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:#9cc2e5}.navbar-dark{background-color:#303030}.navbar-dark .navbar-brand{color:#bdbdbd}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#9cc2e5}.navbar-dark .navbar-nav .nav-link{color:#bdbdbd}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:rgba(156,194,229,.8)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(189,189,189,.75)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active{color:#9cc2e5}.navbar-dark .navbar-toggler{color:#bdbdbd;border-color:rgba(189,189,189,0)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23bdbdbd' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:#bdbdbd}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#9cc2e5}.card{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0}.card>.list-group:last-child{border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;-webkit-flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-0.25rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:1rem}.card-header{padding:.5rem 1rem;margin-bottom:0;background-color:#adb5bd;border-bottom:1px solid rgba(0,0,0,.125)}.card-footer{padding:.5rem 1rem;background-color:#adb5bd;border-top:1px solid rgba(0,0,0,.125)}.card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.card-header-tabs .nav-link.active{background-color:#fff;border-bottom-color:#fff}.card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-group>.card{margin-bottom:.75rem}@media(min-width: 576px){.card-group{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap}.card-group>.card{flex:1 0 0%;-webkit-flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}}.accordion-button{position:relative;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;width:100%;padding:1rem 1.25rem;font-size:1rem;color:#fff;text-align:left;background-color:#181818;border:0;overflow-anchor:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease}@media(prefers-reduced-motion: reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:#2373cc;background-color:#e9f2fc;box-shadow:inset 0 -1px 0 rgba(0,0,0,.125)}.accordion-button:not(.collapsed)::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%232373cc'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");transform:rotate(-180deg)}.accordion-button::after{flex-shrink:0;-webkit-flex-shrink:0;width:1.25rem;height:1.25rem;margin-left:auto;content:"";background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-size:1.25rem;transition:transform .2s ease-in-out}@media(prefers-reduced-motion: reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:#93c0f1;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.accordion-header{margin-bottom:0}.accordion-item{background-color:#181818;border:1px solid rgba(0,0,0,.125)}.accordion-item:not(:first-of-type){border-top:0}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.breadcrumb{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding:0 0;margin-bottom:1rem;list-style:none}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:var(--bs-breadcrumb-divider, ">") /* rtl: var(--bs-breadcrumb-divider, ">") */}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;display:-webkit-flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;color:#75aadb;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:#fff;border:1px solid #dee2e6;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:#5e88af;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;color:#5e88af;background-color:#e9ecef;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{z-index:3;color:#fff;background-color:#2780e3;border-color:#2780e3}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;background-color:#fff;border-color:#dee2e6}.page-link{padding:.375rem .75rem}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:0.875rem}.badge{display:inline-block;padding:.35em .65em;font-size:0.75em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{position:relative;padding:1rem 1rem;margin-bottom:1rem;border:0 solid rgba(0,0,0,0)}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-default{color:#212324;background-color:#d7d8d8;border-color:#c3c4c5}.alert-default .alert-link{color:#1a1c1d}.alert-primary{color:#174d88;background-color:#d4e6f9;border-color:#bed9f7}.alert-primary .alert-link{color:#123e6d}.alert-secondary{color:#212324;background-color:#d7d8d8;border-color:#c3c4c5}.alert-secondary .alert-link{color:#1a1c1d}.alert-success{color:#266d0e;background-color:#d9f0d1;border-color:#c5e9ba}.alert-success .alert-link{color:#1e570b}.alert-info{color:#5c3270;background-color:#ebddf1;border-color:#e0cceb}.alert-info .alert-link{color:#4a285a}.alert-warning{color:#99460e;background-color:#ffe3d1;border-color:#ffd6ba}.alert-warning .alert-link{color:#7a380b}.alert-danger{color:#902;background-color:#ffccd7;border-color:#ffb3c4}.alert-danger .alert-link{color:#7a001b}.alert-light{color:#313131;background-color:#dcdcdc;border-color:#cbcbcb}.alert-light .alert-link{color:#272727}.alert-dark{color:#212324;background-color:#d7d8d8;border-color:#c3c4c5}.alert-dark .alert-link{color:#1a1c1d}@keyframes progress-bar-stripes{0%{background-position-x:.5rem}}.progress{display:flex;display:-webkit-flex;height:.5rem;overflow:hidden;font-size:0.75rem;background-color:#e9ecef}.progress-bar{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#2780e3;transition:width .6s ease}@media(prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-size:.5rem .5rem}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media(prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.list-group{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>li::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#fff;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.5rem 1rem;color:#212529;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#2780e3;border-color:#2780e3}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media(min-width: 576px){.list-group-horizontal-sm{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media(min-width: 768px){.list-group-horizontal-md{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media(min-width: 992px){.list-group-horizontal-lg{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media(min-width: 1200px){.list-group-horizontal-xl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media(min-width: 1400px){.list-group-horizontal-xxl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-default{color:#212324;background-color:#d7d8d8}.list-group-item-default.list-group-item-action:hover,.list-group-item-default.list-group-item-action:focus{color:#212324;background-color:#c2c2c2}.list-group-item-default.list-group-item-action.active{color:#fff;background-color:#212324;border-color:#212324}.list-group-item-primary{color:#174d88;background-color:#d4e6f9}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#174d88;background-color:#bfcfe0}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#174d88;border-color:#174d88}.list-group-item-secondary{color:#212324;background-color:#d7d8d8}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#212324;background-color:#c2c2c2}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#212324;border-color:#212324}.list-group-item-success{color:#266d0e;background-color:#d9f0d1}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#266d0e;background-color:#c3d8bc}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#266d0e;border-color:#266d0e}.list-group-item-info{color:#5c3270;background-color:#ebddf1}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#5c3270;background-color:#d4c7d9}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#5c3270;border-color:#5c3270}.list-group-item-warning{color:#99460e;background-color:#ffe3d1}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#99460e;background-color:#e6ccbc}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#99460e;border-color:#99460e}.list-group-item-danger{color:#902;background-color:#ffccd7}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#902;background-color:#e6b8c2}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#902;border-color:#902}.list-group-item-light{color:#313131;background-color:#dcdcdc}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#313131;background-color:#c6c6c6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#313131;border-color:#313131}.list-group-item-dark{color:#212324;background-color:#d7d8d8}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#212324;background-color:#c2c2c2}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#212324;border-color:#212324}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#000;background:rgba(0,0,0,0) url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25);opacity:1}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{width:350px;max-width:100%;font-size:0.875rem;pointer-events:auto;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .5rem 1rem rgba(0,0,0,.15)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{width:max-content;width:-webkit-max-content;width:-moz-max-content;width:-ms-max-content;width:-o-max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:.75rem}.toast-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.5rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-header .btn-close{margin-right:-0.375rem;margin-left:.75rem}.toast-body{padding:.75rem;word-wrap:break-word}.modal{position:fixed;top:0;left:0;z-index:1055;display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0, -50px)}@media(prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1050;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;display:-webkit-flex;flex-shrink:0;-webkit-flex-shrink:0;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6}.modal-header .btn-close{padding:.5rem .5rem;margin:-0.5rem -0.5rem -0.5rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;padding:1rem}.modal-footer{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-shrink:0;-webkit-flex-shrink:0;align-items:center;-webkit-align-items:center;justify-content:flex-end;-webkit-justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6}.modal-footer>*{margin:.25rem}@media(min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media(min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media(min-width: 1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0}.modal-fullscreen .modal-body{overflow-y:auto}@media(max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media(max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media(max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media(max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media(max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{position:absolute;z-index:1080;display:block;margin:0;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[data-popper-placement^=top]{padding:.4rem 0}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:0}.bs-tooltip-top .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before{top:-1px;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-end,.bs-tooltip-auto[data-popper-placement^=right]{padding:0 .4rem}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-end .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before{right:-1px;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[data-popper-placement^=bottom]{padding:.4rem 0}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:0}.bs-tooltip-bottom .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before{bottom:-1px;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-start,.bs-tooltip-auto[data-popper-placement^=left]{padding:0 .4rem}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-start .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before{left:-1px;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000}.popover{position:absolute;top:0;left:0 /* rtl:ignore */;z-index:1070;display:block;max-width:276px;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.875rem;word-wrap:break-word;background-color:#242424;background-clip:padding-box;border:1px solid rgba(0,0,0,.2)}.popover .popover-arrow{position:absolute;display:block;width:1rem;height:.5rem}.popover .popover-arrow::before,.popover .popover-arrow::after{position:absolute;display:block;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-0.5rem - 1px)}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#242424}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-0.5rem - 1px);width:.5rem;height:1rem}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#242424}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-0.5rem - 1px)}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#242424}.bs-popover-bottom .popover-header::before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-0.5rem;content:"";border-bottom:1px solid #222}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-0.5rem - 1px);width:.5rem;height:1rem}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#242424}.popover-header{padding:.5rem 1rem;margin-bottom:0;font-size:1rem;background-color:#222;border-bottom:1px solid rgba(0,0,0,.2)}.popover-header:empty{display:none}.popover-body{padding:1rem 1rem;color:#fff}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y;-webkit-touch-action:pan-y;-moz-touch-action:pan-y;-ms-touch-action:pan-y;-o-touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden;transition:transform .6s ease-in-out}@media(prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media(prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;border:0;opacity:.5;transition:opacity .15s ease}@media(prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;display:-webkit-flex;justify-content:center;-webkit-justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;-webkit-flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid rgba(0,0,0,0);border-bottom:10px solid rgba(0,0,0,0);opacity:.5;transition:opacity .6s ease}@media(prefers-reduced-motion: reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-prev-icon,.carousel-dark .carousel-control-next-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}@keyframes spinner-border{to{transform:rotate(360deg) /* rtl:ignore */}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-0.125em;border:.25em solid currentColor;border-right-color:rgba(0,0,0,0);border-radius:50%;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-0.125em;background-color:currentColor;border-radius:50%;opacity:0;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media(prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{animation-duration:1.5s;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s}}.offcanvas{position:fixed;bottom:0;z-index:1045;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;visibility:hidden;background-color:#fff;background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}@media(prefers-reduced-motion: reduce){.offcanvas{transition:none}}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:1rem 1rem}.offcanvas-header .btn-close{padding:.5rem .5rem;margin-top:-0.5rem;margin-right:-0.5rem;margin-bottom:-0.5rem}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;-webkit-flex-grow:1;padding:1rem 1rem;overflow-y:auto}.offcanvas-start{top:0;left:0;width:400px;border-right:1px solid rgba(0,0,0,.2);transform:translateX(-100%)}.offcanvas-end{top:0;right:0;width:400px;border-left:1px solid rgba(0,0,0,.2);transform:translateX(100%)}.offcanvas-top{top:0;right:0;left:0;height:30vh;max-height:100%;border-bottom:1px solid rgba(0,0,0,.2);transform:translateY(-100%)}.offcanvas-bottom{right:0;left:0;height:30vh;max-height:100%;border-top:1px solid rgba(0,0,0,.2);transform:translateY(100%)}.offcanvas.show{transform:none}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentColor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);-webkit-mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);mask-size:200% 100%;-webkit-mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{mask-position:-200% 0%;-webkit-mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.link-default{color:#373a3c}.link-default:hover,.link-default:focus{color:#2c2e30}.link-primary{color:#2780e3}.link-primary:hover,.link-primary:focus{color:#1f66b6}.link-secondary{color:#373a3c}.link-secondary:hover,.link-secondary:focus{color:#2c2e30}.link-success{color:#3fb618}.link-success:hover,.link-success:focus{color:#329213}.link-info{color:#9954bb}.link-info:hover,.link-info:focus{color:#7a4396}.link-warning{color:#ff7518}.link-warning:hover,.link-warning:focus{color:#cc5e13}.link-danger{color:#ff0039}.link-danger:hover,.link-danger:focus{color:#cc002e}.link-light{color:#525252}.link-light:hover,.link-light:focus{color:#424242}.link-dark{color:#373a3c}.link-dark:hover,.link-dark:focus{color:#2c2e30}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}@media(min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}}@media(min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}}@media(min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}}@media(min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}}@media(min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}}.hstack{display:flex;display:-webkit-flex;flex-direction:row;-webkit-flex-direction:row;align-items:center;-webkit-align-items:center;align-self:stretch;-webkit-align-self:stretch}.vstack{display:flex;display:-webkit-flex;flex:1 1 auto;-webkit-flex:1 1 auto;flex-direction:column;-webkit-flex-direction:column;align-self:stretch;-webkit-align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;-webkit-align-self:stretch;width:1px;min-height:1em;background-color:currentColor;opacity:.25}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-start{float:left !important}.float-end{float:right !important}.float-none{float:none !important}.opacity-0{opacity:0 !important}.opacity-25{opacity:.25 !important}.opacity-50{opacity:.5 !important}.opacity-75{opacity:.75 !important}.opacity-100{opacity:1 !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.overflow-visible{overflow:visible !important}.overflow-scroll{overflow:scroll !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15) !important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175) !important}.shadow-none{box-shadow:none !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.top-0{top:0 !important}.top-50{top:50% !important}.top-100{top:100% !important}.bottom-0{bottom:0 !important}.bottom-50{bottom:50% !important}.bottom-100{bottom:100% !important}.start-0{left:0 !important}.start-50{left:50% !important}.start-100{left:100% !important}.end-0{right:0 !important}.end-50{right:50% !important}.end-100{right:100% !important}.translate-middle{transform:translate(-50%, -50%) !important}.translate-middle-x{transform:translateX(-50%) !important}.translate-middle-y{transform:translateY(-50%) !important}.border{border:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-top-0{border-top:0 !important}.border-end{border-right:1px solid #dee2e6 !important}.border-end-0{border-right:0 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-bottom-0{border-bottom:0 !important}.border-start{border-left:1px solid #dee2e6 !important}.border-start-0{border-left:0 !important}.border-default{border-color:#373a3c !important}.border-primary{border-color:#2780e3 !important}.border-secondary{border-color:#373a3c !important}.border-success{border-color:#3fb618 !important}.border-info{border-color:#9954bb !important}.border-warning{border-color:#ff7518 !important}.border-danger{border-color:#ff0039 !important}.border-light{border-color:#525252 !important}.border-dark{border-color:#373a3c !important}.border-white{border-color:#fff !important}.border-1{border-width:1px !important}.border-2{border-width:2px !important}.border-3{border-width:3px !important}.border-4{border-width:4px !important}.border-5{border-width:5px !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-0{gap:0 !important}.gap-1{gap:.25rem !important}.gap-2{gap:.5rem !important}.gap-3{gap:1rem !important}.gap-4{gap:1.5rem !important}.gap-5{gap:3rem !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.fs-1{font-size:calc(1.325rem + 0.9vw) !important}.fs-2{font-size:calc(1.29rem + 0.48vw) !important}.fs-3{font-size:calc(1.27rem + 0.24vw) !important}.fs-4{font-size:1.25rem !important}.fs-5{font-size:1.1rem !important}.fs-6{font-size:1rem !important}.fst-italic{font-style:italic !important}.fst-normal{font-style:normal !important}.fw-light{font-weight:300 !important}.fw-lighter{font-weight:lighter !important}.fw-normal{font-weight:400 !important}.fw-bold{font-weight:700 !important}.fw-bolder{font-weight:bolder !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.text-start{text-align:left !important}.text-end{text-align:right !important}.text-center{text-align:center !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.text-default{--bs-text-opacity: 1;color:rgba(var(--bs-default-rgb), var(--bs-text-opacity)) !important}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important}.text-secondary{--bs-text-opacity: 1;color:rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important}.text-success{--bs-text-opacity: 1;color:rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important}.text-info{--bs-text-opacity: 1;color:rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important}.text-warning{--bs-text-opacity: 1;color:rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important}.text-danger{--bs-text-opacity: 1;color:rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important}.text-light{--bs-text-opacity: 1;color:rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important}.text-dark{--bs-text-opacity: 1;color:rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important}.text-black{--bs-text-opacity: 1;color:rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important}.text-white{--bs-text-opacity: 1;color:rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important}.text-body{--bs-text-opacity: 1;color:rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important}.text-muted{--bs-text-opacity: 1;color:#6c757d !important}.text-black-50{--bs-text-opacity: 1;color:rgba(0,0,0,.5) !important}.text-white-50{--bs-text-opacity: 1;color:rgba(255,255,255,.5) !important}.text-reset{--bs-text-opacity: 1;color:inherit !important}.text-opacity-25{--bs-text-opacity: 0.25}.text-opacity-50{--bs-text-opacity: 0.5}.text-opacity-75{--bs-text-opacity: 0.75}.text-opacity-100{--bs-text-opacity: 1}.bg-default{--bs-bg-opacity: 1;background-color:rgba(var(--bs-default-rgb), var(--bs-bg-opacity)) !important}.bg-primary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important}.bg-secondary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important}.bg-success{--bs-bg-opacity: 1;background-color:rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important}.bg-info{--bs-bg-opacity: 1;background-color:rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important}.bg-warning{--bs-bg-opacity: 1;background-color:rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important}.bg-danger{--bs-bg-opacity: 1;background-color:rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important}.bg-light{--bs-bg-opacity: 1;background-color:rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important}.bg-dark{--bs-bg-opacity: 1;background-color:rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important}.bg-black{--bs-bg-opacity: 1;background-color:rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important}.bg-white{--bs-bg-opacity: 1;background-color:rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important}.bg-body{--bs-bg-opacity: 1;background-color:rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important}.bg-transparent{--bs-bg-opacity: 1;background-color:rgba(0,0,0,0) !important}.bg-opacity-10{--bs-bg-opacity: 0.1}.bg-opacity-25{--bs-bg-opacity: 0.25}.bg-opacity-50{--bs-bg-opacity: 0.5}.bg-opacity-75{--bs-bg-opacity: 0.75}.bg-opacity-100{--bs-bg-opacity: 1}.bg-gradient{background-image:var(--bs-gradient) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:.25rem !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:.2em !important}.rounded-2{border-radius:.25rem !important}.rounded-3{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-top{border-top-left-radius:.25rem !important;border-top-right-radius:.25rem !important}.rounded-end{border-top-right-radius:.25rem !important;border-bottom-right-radius:.25rem !important}.rounded-bottom{border-bottom-right-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-start{border-bottom-left-radius:.25rem !important;border-top-left-radius:.25rem !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media(min-width: 576px){.float-sm-start{float:left !important}.float-sm-end{float:right !important}.float-sm-none{float:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-sm-0{gap:0 !important}.gap-sm-1{gap:.25rem !important}.gap-sm-2{gap:.5rem !important}.gap-sm-3{gap:1rem !important}.gap-sm-4{gap:1.5rem !important}.gap-sm-5{gap:3rem !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}.text-sm-start{text-align:left !important}.text-sm-end{text-align:right !important}.text-sm-center{text-align:center !important}}@media(min-width: 768px){.float-md-start{float:left !important}.float-md-end{float:right !important}.float-md-none{float:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-md-0{gap:0 !important}.gap-md-1{gap:.25rem !important}.gap-md-2{gap:.5rem !important}.gap-md-3{gap:1rem !important}.gap-md-4{gap:1.5rem !important}.gap-md-5{gap:3rem !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}.text-md-start{text-align:left !important}.text-md-end{text-align:right !important}.text-md-center{text-align:center !important}}@media(min-width: 992px){.float-lg-start{float:left !important}.float-lg-end{float:right !important}.float-lg-none{float:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-lg-0{gap:0 !important}.gap-lg-1{gap:.25rem !important}.gap-lg-2{gap:.5rem !important}.gap-lg-3{gap:1rem !important}.gap-lg-4{gap:1.5rem !important}.gap-lg-5{gap:3rem !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}.text-lg-start{text-align:left !important}.text-lg-end{text-align:right !important}.text-lg-center{text-align:center !important}}@media(min-width: 1200px){.float-xl-start{float:left !important}.float-xl-end{float:right !important}.float-xl-none{float:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xl-0{gap:0 !important}.gap-xl-1{gap:.25rem !important}.gap-xl-2{gap:.5rem !important}.gap-xl-3{gap:1rem !important}.gap-xl-4{gap:1.5rem !important}.gap-xl-5{gap:3rem !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}.text-xl-start{text-align:left !important}.text-xl-end{text-align:right !important}.text-xl-center{text-align:center !important}}@media(min-width: 1400px){.float-xxl-start{float:left !important}.float-xxl-end{float:right !important}.float-xxl-none{float:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xxl-0{gap:0 !important}.gap-xxl-1{gap:.25rem !important}.gap-xxl-2{gap:.5rem !important}.gap-xxl-3{gap:1rem !important}.gap-xxl-4{gap:1.5rem !important}.gap-xxl-5{gap:3rem !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}.text-xxl-start{text-align:left !important}.text-xxl-end{text-align:right !important}.text-xxl-center{text-align:center !important}}.bg-default{color:#fff}.bg-primary{color:#fff}.bg-secondary{color:#fff}.bg-success{color:#fff}.bg-info{color:#fff}.bg-warning{color:#fff}.bg-danger{color:#fff}.bg-light{color:#fff}.bg-dark{color:#fff}@media(min-width: 1200px){.fs-1{font-size:2rem !important}.fs-2{font-size:1.65rem !important}.fs-3{font-size:1.45rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}}.quarto-container{min-height:calc(100vh - 132px)}footer.footer .nav-footer,#quarto-header>nav{padding-left:1em;padding-right:1em}nav[role=doc-toc]{padding-left:.5em}#quarto-content>*{padding-top:14px}@media(max-width: 991.98px){#quarto-content>*{padding-top:0}#quarto-content .subtitle{padding-top:14px}#quarto-content section:first-of-type h2:first-of-type,#quarto-content section:first-of-type .h2:first-of-type{margin-top:1rem}}.headroom-target,header.headroom{will-change:transform;transition:position 200ms linear;transition:all 200ms linear}header.headroom--pinned{transform:translateY(0%)}header.headroom--unpinned{transform:translateY(-100%)}.navbar-container{width:100%}.navbar-brand{overflow:hidden;text-overflow:ellipsis}.navbar-brand-container{max-width:calc(100% - 115px);min-width:0;display:flex;align-items:center}@media(min-width: 992px){.navbar-brand-container{margin-right:1em}}.navbar-brand.navbar-brand-logo{margin-right:4px;display:inline-flex}.navbar-toggler{flex-basis:content;flex-shrink:0}.navbar .navbar-toggler{order:-1;margin-right:.5em}.navbar-logo{max-height:24px;width:auto;padding-right:4px}nav .nav-item:not(.compact){padding-top:1px}nav .nav-link i,nav .dropdown-item i{padding-right:1px}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.6rem;padding-right:.6rem}nav .nav-item.compact .nav-link{padding-left:.5rem;padding-right:.5rem;font-size:1.1rem}.navbar .quarto-navbar-tools div.dropdown{display:inline-block}.navbar .quarto-navbar-tools .quarto-navigation-tool{color:#bdbdbd}.navbar .quarto-navbar-tools .quarto-navigation-tool:hover{color:#9cc2e5}@media(max-width: 991.98px){.navbar .quarto-navbar-tools{margin-top:.25em;padding-top:.75em;display:block;color:solid #3e3e3e 1px;text-align:center;vertical-align:middle;margin-right:auto}}.navbar-nav .dropdown-menu{min-width:220px;font-size:.9rem}.navbar .navbar-nav .nav-link.dropdown-toggle::after{opacity:.75;vertical-align:.175em}.navbar ul.dropdown-menu{padding-top:0;padding-bottom:0}.navbar .dropdown-header{text-transform:uppercase;font-size:.8rem;padding:0 .5rem}.navbar .dropdown-item{padding:.4rem .5rem}.navbar .dropdown-item>i.bi{margin-left:.1rem;margin-right:.25em}.sidebar #quarto-search{margin-top:-1px}.sidebar #quarto-search svg.aa-SubmitIcon{width:16px;height:16px}.sidebar-navigation a{color:inherit}.sidebar-title{margin-top:.25rem;padding-bottom:.5rem;font-size:1.3rem;line-height:1.6rem;visibility:visible}.sidebar-title>a{font-size:inherit;text-decoration:none}.sidebar-title .sidebar-tools-main{margin-top:-6px}@media(max-width: 991.98px){#quarto-sidebar div.sidebar-header{padding-top:.2em}}.sidebar-header-stacked .sidebar-title{margin-top:.6rem}.sidebar-logo{max-width:90%;padding-bottom:.5rem}.sidebar-logo-link{text-decoration:none}.sidebar-navigation li a{text-decoration:none}.sidebar-navigation .quarto-navigation-tool{opacity:.7;font-size:.875rem}#quarto-sidebar>nav>.sidebar-tools-main{margin-left:14px}.sidebar-tools-main{display:inline-flex;margin-left:0px;order:2}.sidebar-tools-main:not(.tools-wide){vertical-align:middle}.sidebar-navigation .quarto-navigation-tool.dropdown-toggle::after{display:none}.sidebar.sidebar-navigation>*{padding-top:1em}.sidebar-item{margin-bottom:.2em}.sidebar-section{margin-top:.2em;padding-left:.5em;padding-bottom:.2em}.sidebar-item .sidebar-item-container{display:flex;justify-content:space-between}.sidebar-item-toggle:hover{cursor:pointer}.sidebar-item .sidebar-item-toggle .bi{font-size:.7rem;text-align:center}.sidebar-item .sidebar-item-toggle .bi-chevron-right::before{transition:transform 200ms ease}.sidebar-item .sidebar-item-toggle[aria-expanded=false] .bi-chevron-right::before{transform:none}.sidebar-item .sidebar-item-toggle[aria-expanded=true] .bi-chevron-right::before{transform:rotate(90deg)}.sidebar-navigation .sidebar-divider{margin-left:0;margin-right:0;margin-top:.5rem;margin-bottom:.5rem}@media(max-width: 991.98px){.quarto-secondary-nav{display:block}.quarto-secondary-nav button.quarto-search-button{padding-right:0em;padding-left:2em}.quarto-secondary-nav button.quarto-btn-toggle{margin-left:-0.75rem;margin-right:.15rem}.quarto-secondary-nav nav.quarto-page-breadcrumbs{display:flex;align-items:center;padding-right:1em;margin-left:-0.25em}.quarto-secondary-nav nav.quarto-page-breadcrumbs a{text-decoration:none}.quarto-secondary-nav nav.quarto-page-breadcrumbs ol.breadcrumb{margin-bottom:0}}@media(min-width: 992px){.quarto-secondary-nav{display:none}}.quarto-secondary-nav .quarto-btn-toggle{color:#bdbdbd}.quarto-secondary-nav[aria-expanded=false] .quarto-btn-toggle .bi-chevron-right::before{transform:none}.quarto-secondary-nav[aria-expanded=true] .quarto-btn-toggle .bi-chevron-right::before{transform:rotate(90deg)}.quarto-secondary-nav .quarto-btn-toggle .bi-chevron-right::before{transition:transform 200ms ease}.quarto-secondary-nav{cursor:pointer}.quarto-secondary-nav-title{margin-top:.3em;color:#bdbdbd;padding-top:4px}.quarto-secondary-nav nav.quarto-page-breadcrumbs{color:#bdbdbd}.quarto-secondary-nav nav.quarto-page-breadcrumbs a{color:#bdbdbd}.quarto-secondary-nav nav.quarto-page-breadcrumbs a:hover{color:rgba(156,194,229,.8)}.quarto-secondary-nav nav.quarto-page-breadcrumbs .breadcrumb-item::before{color:#8a8a8a}div.sidebar-item-container{color:#bdbdbd}div.sidebar-item-container:hover,div.sidebar-item-container:focus{color:rgba(156,194,229,.8)}div.sidebar-item-container.disabled{color:rgba(189,189,189,.75)}div.sidebar-item-container .active,div.sidebar-item-container .show>.nav-link,div.sidebar-item-container .sidebar-link>code{color:#9cc2e5}div.sidebar.sidebar-navigation.rollup.quarto-sidebar-toggle-contents,nav.sidebar.sidebar-navigation:not(.rollup){background-color:#303030}.sidebar.sidebar-navigation:not(.rollup){border-right:1px solid #dee2e6 !important}@media(max-width: 991.98px){.sidebar-navigation .sidebar-item a,.nav-page .nav-page-text,.sidebar-navigation{font-size:1rem}.sidebar-navigation ul.sidebar-section.depth1 .sidebar-section-item{font-size:1.1rem}.sidebar-logo{display:none}.sidebar.sidebar-navigation{position:static;border-bottom:1px solid #dee2e6}.sidebar.sidebar-navigation.collapsing{position:fixed;z-index:1000}.sidebar.sidebar-navigation.show{position:fixed;z-index:1000}.sidebar.sidebar-navigation{min-height:100%}nav.quarto-secondary-nav{background-color:#303030;border-bottom:1px solid #dee2e6}.sidebar .sidebar-footer{visibility:visible;padding-top:1rem;position:inherit}.sidebar-tools-collapse{display:block}}#quarto-sidebar{transition:width .15s ease-in}#quarto-sidebar>*{padding-right:1em}@media(max-width: 991.98px){#quarto-sidebar .sidebar-menu-container{white-space:nowrap;min-width:225px}#quarto-sidebar.show{transition:width .15s ease-out}}@media(min-width: 992px){#quarto-sidebar{display:flex;flex-direction:column}.nav-page .nav-page-text,.sidebar-navigation .sidebar-section .sidebar-item{font-size:.875rem}.sidebar-navigation .sidebar-item{font-size:.925rem}.sidebar.sidebar-navigation{display:block;position:sticky}.sidebar-search{width:100%}.sidebar .sidebar-footer{visibility:visible}}@media(max-width: 991.98px){#quarto-sidebar-glass{position:fixed;top:0;bottom:0;left:0;right:0;background-color:rgba(255,255,255,0);transition:background-color .15s ease-in;z-index:-1}#quarto-sidebar-glass.collapsing{z-index:1000}#quarto-sidebar-glass.show{transition:background-color .15s ease-out;background-color:rgba(102,102,102,.4);z-index:1000}}.sidebar .sidebar-footer{padding:.5rem 1rem;align-self:flex-end;color:#6c757d;width:100%}.quarto-page-breadcrumbs .breadcrumb-item+.breadcrumb-item,.quarto-page-breadcrumbs .breadcrumb-item{padding-right:.33em;padding-left:0}.quarto-page-breadcrumbs .breadcrumb-item::before{padding-right:.33em}.quarto-sidebar-footer{font-size:.875em}.sidebar-section .bi-chevron-right{vertical-align:middle}.sidebar-section .bi-chevron-right::before{font-size:.9em}.notransition{-webkit-transition:none !important;-moz-transition:none !important;-o-transition:none !important;transition:none !important}.btn:focus:not(:focus-visible){box-shadow:none}.page-navigation{display:flex;justify-content:space-between}.nav-page{padding-bottom:.75em}.nav-page .bi{font-size:1.8rem;vertical-align:middle}.nav-page .nav-page-text{padding-left:.25em;padding-right:.25em}.nav-page a{color:#6c757d;text-decoration:none;display:flex;align-items:center}.nav-page a:hover{color:#5e88af}.toc-actions{display:flex}.toc-actions p{margin-block-start:0;margin-block-end:0}.toc-actions a{text-decoration:none;color:inherit;font-weight:400}.toc-actions a:hover{color:#5e88af}.toc-actions .action-links{margin-left:4px}.sidebar nav[role=doc-toc] .toc-actions .bi{margin-left:-4px;font-size:.7rem;color:#6c757d}.sidebar nav[role=doc-toc] .toc-actions .bi:before{padding-top:3px}#quarto-margin-sidebar .toc-actions .bi:before{margin-top:.3rem;font-size:.7rem;color:#6c757d;vertical-align:top}.sidebar nav[role=doc-toc] .toc-actions>div:first-of-type{margin-top:-3px}#quarto-margin-sidebar .toc-actions p,.sidebar nav[role=doc-toc] .toc-actions p{font-size:.875rem}.nav-footer .toc-actions{padding-bottom:.5em;padding-top:.5em}.nav-footer .toc-actions :first-child{margin-left:auto}.nav-footer .toc-actions :last-child{margin-right:auto}.nav-footer .toc-actions .action-links{display:flex}.nav-footer .toc-actions .action-links p{padding-right:1.5em}.nav-footer .toc-actions .action-links p:last-of-type{padding-right:0}.nav-footer{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;align-items:baseline;text-align:center;padding-top:.5rem;padding-bottom:.5rem;background-color:#181818}body.nav-fixed{padding-top:64px}body .nav-footer{border-top:1px solid #dee2e6}.nav-footer-contents{color:#6c757d;margin-top:.25rem}.nav-footer{min-height:3.5em;color:#828282}.nav-footer a{color:#828282}.nav-footer .nav-footer-left{font-size:.825em}.nav-footer .nav-footer-center{font-size:.825em}.nav-footer .nav-footer-right{font-size:.825em}.nav-footer-left .footer-items,.nav-footer-center .footer-items,.nav-footer-right .footer-items{display:inline-flex;padding-top:.3em;padding-bottom:.3em;margin-bottom:0em}.nav-footer-left .footer-items .nav-link,.nav-footer-center .footer-items .nav-link,.nav-footer-right .footer-items .nav-link{padding-left:.6em;padding-right:.6em}.nav-footer-left{flex:1 1 0px;text-align:left}.nav-footer-right{flex:1 1 0px;text-align:right}.nav-footer-center{flex:1 1 0px;min-height:3em;text-align:center}.nav-footer-center .footer-items{justify-content:center}@media(max-width: 767.98px){.nav-footer-center{margin-top:3em}}.navbar .quarto-reader-toggle.reader .quarto-reader-toggle-btn{background-color:#bdbdbd;border-radius:3px}.quarto-reader-toggle.reader.quarto-navigation-tool .quarto-reader-toggle-btn{background-color:#bdbdbd;border-radius:3px}.quarto-reader-toggle .quarto-reader-toggle-btn{display:inline-flex;padding-left:.2em;padding-right:.2em;margin-left:-0.2em;margin-right:-0.2em;text-align:center}.navbar .quarto-reader-toggle:not(.reader) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-reader-toggle.reader .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-reader-toggle:not(.reader) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-reader-toggle.reader .bi::before{background-image:url('data:image/svg+xml,')}#quarto-back-to-top{display:none;position:fixed;bottom:50px;background-color:#181818;border-radius:.25rem;box-shadow:0 .2rem .5rem #6c757d,0 0 .05rem #6c757d;color:#6c757d;text-decoration:none;font-size:.9em;text-align:center;left:50%;padding:.4rem .8rem;transform:translate(-50%, 0)}.aa-DetachedOverlay ul.aa-List,#quarto-search-results ul.aa-List{list-style:none;padding-left:0}.aa-DetachedOverlay .aa-Panel,#quarto-search-results .aa-Panel{background-color:#181818;position:absolute;z-index:2000}#quarto-search-results .aa-Panel{max-width:400px}#quarto-search input{font-size:.925rem}@media(min-width: 992px){.navbar #quarto-search{margin-left:.25rem;order:999}}@media(max-width: 991.98px){#quarto-sidebar .sidebar-search{display:none}}#quarto-sidebar .sidebar-search .aa-Autocomplete{width:100%}.navbar .aa-Autocomplete .aa-Form{width:180px}.navbar #quarto-search.type-overlay .aa-Autocomplete{width:40px}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form{background-color:inherit;border:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form:focus-within{box-shadow:none;outline:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-InputWrapper{display:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-InputWrapper:focus-within{display:inherit}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-Label svg,.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-LoadingIndicator svg{width:26px;height:26px;color:#bdbdbd;opacity:1}.navbar #quarto-search.type-overlay .aa-Autocomplete svg.aa-SubmitIcon{width:26px;height:26px;color:#bdbdbd;opacity:1}.aa-Autocomplete .aa-Form,.aa-DetachedFormContainer .aa-Form{align-items:center;background-color:#242424;border:1px solid #ced4da;border-radius:.25rem;color:#fff;display:flex;line-height:1em;margin:0;position:relative;width:100%}.aa-Autocomplete .aa-Form:focus-within,.aa-DetachedFormContainer .aa-Form:focus-within{box-shadow:rgba(39,128,227,.6) 0 0 0 1px;outline:currentColor none medium}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix{align-items:center;display:flex;flex-shrink:0;order:1}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-Label,.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-Label,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator{cursor:initial;flex-shrink:0;padding:0;text-align:left}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-Label svg,.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-Label svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator svg{color:#fff;opacity:.5}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-SubmitButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-SubmitButton{appearance:none;background:none;border:0;margin:0}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator{align-items:center;display:flex;justify-content:center}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator[hidden]{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapper,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper{order:3;position:relative;width:100%}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input{appearance:none;background:none;border:0;color:#fff;font:inherit;height:calc(1.5em + .1rem + 2px);padding:0;width:100%}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::placeholder,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::placeholder{color:#fff;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input:focus{border-color:none;box-shadow:none;outline:none}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-decoration,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-cancel-button,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-button,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-decoration,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-decoration,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-cancel-button,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-button,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-decoration{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix{align-items:center;display:flex;order:4}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton{align-items:center;background:none;border:0;color:#fff;opacity:.8;cursor:pointer;display:flex;margin:0;width:calc(1.5em + .1rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:hover,.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:hover,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:focus{color:#fff;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton[hidden]{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton svg{width:calc(1.5em + 0.75rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton{border:none;align-items:center;background:none;color:#fff;opacity:.4;font-size:.7rem;cursor:pointer;display:none;margin:0;width:calc(1em + .1rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:hover,.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:hover,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:focus{color:#fff;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton[hidden]{display:none}.aa-PanelLayout:empty{display:none}.quarto-search-no-results.no-query{display:none}.aa-Source:has(.no-query){display:none}#quarto-search-results .aa-Panel{border:solid #ced4da 1px}#quarto-search-results .aa-SourceNoResults{width:398px}.aa-DetachedOverlay .aa-Panel,#quarto-search-results .aa-Panel{max-height:65vh;overflow-y:auto;font-size:.925rem}.aa-DetachedOverlay .aa-SourceNoResults,#quarto-search-results .aa-SourceNoResults{height:60px;display:flex;justify-content:center;align-items:center}.aa-DetachedOverlay .search-error,#quarto-search-results .search-error{padding-top:10px;padding-left:20px;padding-right:20px;cursor:default}.aa-DetachedOverlay .search-error .search-error-title,#quarto-search-results .search-error .search-error-title{font-size:1.1rem;margin-bottom:.5rem}.aa-DetachedOverlay .search-error .search-error-title .search-error-icon,#quarto-search-results .search-error .search-error-title .search-error-icon{margin-right:8px}.aa-DetachedOverlay .search-error .search-error-text,#quarto-search-results .search-error .search-error-text{font-weight:300}.aa-DetachedOverlay .search-result-text,#quarto-search-results .search-result-text{font-weight:300;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.2rem;max-height:2.4rem}.aa-DetachedOverlay .aa-SourceHeader .search-result-header,#quarto-search-results .aa-SourceHeader .search-result-header{font-size:.875rem;background-color:#252525;padding-left:14px;padding-bottom:4px;padding-top:4px}.aa-DetachedOverlay .aa-SourceHeader .search-result-header-no-results,#quarto-search-results .aa-SourceHeader .search-result-header-no-results{display:none}.aa-DetachedOverlay .aa-SourceFooter .algolia-search-logo,#quarto-search-results .aa-SourceFooter .algolia-search-logo{width:110px;opacity:.85;margin:8px;float:right}.aa-DetachedOverlay .search-result-section,#quarto-search-results .search-result-section{font-size:.925em}.aa-DetachedOverlay a.search-result-link,#quarto-search-results a.search-result-link{color:inherit;text-decoration:none}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item,#quarto-search-results li.aa-Item[aria-selected=true] .search-item{background-color:#2780e3}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item.search-result-more,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-section,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-text,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-title-container,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-text-container,#quarto-search-results li.aa-Item[aria-selected=true] .search-item.search-result-more,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-section,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-text,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-title-container,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-text-container{color:#fff;background-color:#2780e3}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item mark.search-match,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-match.mark,#quarto-search-results li.aa-Item[aria-selected=true] .search-item mark.search-match,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-match.mark{color:#fff;background-color:#1a6cc7}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item,#quarto-search-results li.aa-Item[aria-selected=false] .search-item{background-color:#242424}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item.search-result-more,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-section,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-text,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-title-container,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-text-container,#quarto-search-results li.aa-Item[aria-selected=false] .search-item.search-result-more,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-section,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-text,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-title-container,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-text-container{color:#fff}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item mark.search-match,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-match.mark,#quarto-search-results li.aa-Item[aria-selected=false] .search-item mark.search-match,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-match.mark{color:inherit;background-color:#06192e}.aa-DetachedOverlay .aa-Item .search-result-doc:not(.document-selectable) .search-result-title-container,#quarto-search-results .aa-Item .search-result-doc:not(.document-selectable) .search-result-title-container{background-color:#242424;color:#fff}.aa-DetachedOverlay .aa-Item .search-result-doc:not(.document-selectable) .search-result-text-container,#quarto-search-results .aa-Item .search-result-doc:not(.document-selectable) .search-result-text-container{padding-top:0px}.aa-DetachedOverlay li.aa-Item .search-result-doc.document-selectable .search-result-text-container,#quarto-search-results li.aa-Item .search-result-doc.document-selectable .search-result-text-container{margin-top:-4px}.aa-DetachedOverlay .aa-Item,#quarto-search-results .aa-Item{cursor:pointer}.aa-DetachedOverlay .aa-Item .search-item,#quarto-search-results .aa-Item .search-item{border-left:none;border-right:none;border-top:none;background-color:#242424;border-color:#ced4da;color:#fff}.aa-DetachedOverlay .aa-Item .search-item p,#quarto-search-results .aa-Item .search-item p{margin-top:0;margin-bottom:0}.aa-DetachedOverlay .aa-Item .search-item i.bi,#quarto-search-results .aa-Item .search-item i.bi{padding-left:8px;padding-right:8px;font-size:1.3em}.aa-DetachedOverlay .aa-Item .search-item .search-result-title,#quarto-search-results .aa-Item .search-item .search-result-title{margin-top:.3em;margin-bottom:.1rem}.aa-DetachedOverlay .aa-Item .search-result-title-container,#quarto-search-results .aa-Item .search-result-title-container{font-size:1em;display:flex;padding:6px 4px 6px 4px}.aa-DetachedOverlay .aa-Item .search-result-text-container,#quarto-search-results .aa-Item .search-result-text-container{padding-bottom:8px;padding-right:8px;margin-left:44px}.aa-DetachedOverlay .aa-Item .search-result-doc-section,.aa-DetachedOverlay .aa-Item .search-result-more,#quarto-search-results .aa-Item .search-result-doc-section,#quarto-search-results .aa-Item .search-result-more{padding-top:8px;padding-bottom:8px;padding-left:44px}.aa-DetachedOverlay .aa-Item .search-result-more,#quarto-search-results .aa-Item .search-result-more{font-size:.8em;font-weight:400}.aa-DetachedOverlay .aa-Item .search-result-doc,#quarto-search-results .aa-Item .search-result-doc{border-top:1px solid #ced4da}.aa-DetachedSearchButton{background:none;border:none}.aa-DetachedSearchButton .aa-DetachedSearchButtonPlaceholder{display:none}.navbar .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon{color:#bdbdbd}.sidebar-tools-collapse #quarto-search,.sidebar-tools-main #quarto-search{display:inline}.sidebar-tools-collapse #quarto-search .aa-Autocomplete,.sidebar-tools-main #quarto-search .aa-Autocomplete{display:inline}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton{padding-left:4px;padding-right:4px}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon{color:#bdbdbd}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon .aa-SubmitIcon,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon .aa-SubmitIcon{margin-top:-3px}.aa-DetachedContainer{background:rgba(24,24,24,.65);width:90%;bottom:0;box-shadow:rgba(206,212,218,.6) 0 0 0 1px;outline:currentColor none medium;display:flex;flex-direction:column;left:0;margin:0;overflow:hidden;padding:0;position:fixed;right:0;top:0;z-index:1101}.aa-DetachedContainer::after{height:32px}.aa-DetachedContainer .aa-SourceHeader{margin:var(--aa-spacing-half) 0 var(--aa-spacing-half) 2px}.aa-DetachedContainer .aa-Panel{background-color:#181818;border-radius:0;box-shadow:none;flex-grow:1;margin:0;padding:0;position:relative}.aa-DetachedContainer .aa-PanelLayout{bottom:0;box-shadow:none;left:0;margin:0;max-height:none;overflow-y:auto;position:absolute;right:0;top:0;width:100%}.aa-DetachedFormContainer{background-color:#181818;border-bottom:1px solid #ced4da;display:flex;flex-direction:row;justify-content:space-between;margin:0;padding:.5em}.aa-DetachedCancelButton{background:none;font-size:.8em;border:0;border-radius:3px;color:#fff;cursor:pointer;margin:0 0 0 .5em;padding:0 .5em}.aa-DetachedCancelButton:hover,.aa-DetachedCancelButton:focus{box-shadow:rgba(39,128,227,.6) 0 0 0 1px;outline:currentColor none medium}.aa-DetachedContainer--modal{bottom:inherit;height:auto;margin:0 auto;position:absolute;top:100px;border-radius:6px;max-width:850px}@media(max-width: 575.98px){.aa-DetachedContainer--modal{width:100%;top:0px;border-radius:0px;border:none}}.aa-DetachedContainer--modal .aa-PanelLayout{max-height:var(--aa-detached-modal-max-height);padding-bottom:var(--aa-spacing-half);position:static}.aa-Detached{height:100vh;overflow:hidden}.aa-DetachedOverlay{background-color:rgba(255,255,255,.4);position:fixed;left:0;right:0;top:0;margin:0;padding:0;height:100vh;z-index:1100}.quarto-listing{padding-bottom:1em}.listing-pagination{padding-top:.5em}ul.pagination{float:right;padding-left:8px;padding-top:.5em}ul.pagination li{padding-right:.75em}ul.pagination li.disabled a,ul.pagination li.active a{color:#fff;text-decoration:none}ul.pagination li:last-of-type{padding-right:0}.listing-actions-group{display:flex}.quarto-listing-filter{margin-bottom:1em;width:200px;margin-left:auto}.quarto-listing-sort{margin-bottom:1em;margin-right:auto;width:auto}.quarto-listing-sort .input-group-text{font-size:.8em}.input-group-text{border-right:none}.quarto-listing-sort select.form-select{font-size:.8em}.listing-no-matching{text-align:center;padding-top:2em;padding-bottom:3em;font-size:1em}#quarto-margin-sidebar .quarto-listing-category{padding-top:0;font-size:1rem}#quarto-margin-sidebar .quarto-listing-category-title{cursor:pointer;font-weight:600;font-size:1rem}.quarto-listing-category .category{cursor:pointer}.quarto-listing-category .category.active{font-weight:600}.quarto-listing-category.category-cloud{display:flex;flex-wrap:wrap;align-items:baseline}.quarto-listing-category.category-cloud .category{padding-right:5px}.quarto-listing-category.category-cloud .category-cloud-1{font-size:.75em}.quarto-listing-category.category-cloud .category-cloud-2{font-size:.95em}.quarto-listing-category.category-cloud .category-cloud-3{font-size:1.15em}.quarto-listing-category.category-cloud .category-cloud-4{font-size:1.35em}.quarto-listing-category.category-cloud .category-cloud-5{font-size:1.55em}.quarto-listing-category.category-cloud .category-cloud-6{font-size:1.75em}.quarto-listing-category.category-cloud .category-cloud-7{font-size:1.95em}.quarto-listing-category.category-cloud .category-cloud-8{font-size:2.15em}.quarto-listing-category.category-cloud .category-cloud-9{font-size:2.35em}.quarto-listing-category.category-cloud .category-cloud-10{font-size:2.55em}.quarto-listing-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-1{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-2{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-3{grid-template-columns:repeat(3, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-3{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-3{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-4{grid-template-columns:repeat(4, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-4{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-4{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-5{grid-template-columns:repeat(5, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-5{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-5{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-6{grid-template-columns:repeat(6, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-6{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-6{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-7{grid-template-columns:repeat(7, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-7{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-7{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-8{grid-template-columns:repeat(8, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-8{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-8{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-9{grid-template-columns:repeat(9, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-9{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-9{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-10{grid-template-columns:repeat(10, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-10{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-10{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-11{grid-template-columns:repeat(11, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-11{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-11{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-12{grid-template-columns:repeat(12, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-12{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-12{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-grid{gap:1.5em}.quarto-grid-item.borderless{border:none}.quarto-grid-item.borderless .listing-categories .listing-category:last-of-type,.quarto-grid-item.borderless .listing-categories .listing-category:first-of-type{padding-left:0}.quarto-grid-item.borderless .listing-categories .listing-category{border:0}.quarto-grid-link{text-decoration:none;color:inherit}.quarto-grid-link:hover{text-decoration:none;color:inherit}.quarto-grid-item h5.title,.quarto-grid-item .title.h5{margin-top:0;margin-bottom:0}.quarto-grid-item .card-footer{display:flex;justify-content:space-between;font-size:.8em}.quarto-grid-item .card-footer p{margin-bottom:0}.quarto-grid-item p.card-img-top{margin-bottom:0}.quarto-grid-item p.card-img-top>img{object-fit:cover}.quarto-grid-item .card-other-values{margin-top:.5em;font-size:.8em}.quarto-grid-item .card-other-values tr{margin-bottom:.5em}.quarto-grid-item .card-other-values tr>td:first-of-type{font-weight:600;padding-right:1em;padding-left:1em;vertical-align:top}.quarto-grid-item div.post-contents{display:flex;flex-direction:column;text-decoration:none;height:100%}.quarto-grid-item .listing-item-img-placeholder{background-color:#adb5bd;flex-shrink:0}.quarto-grid-item .card-attribution{padding-top:1em;display:flex;gap:1em;text-transform:uppercase;color:#6c757d;font-weight:500;flex-grow:10;align-items:flex-end}.quarto-grid-item .description{padding-bottom:1em}.quarto-grid-item .card-attribution .date{align-self:flex-end}.quarto-grid-item .card-attribution.justify{justify-content:space-between}.quarto-grid-item .card-attribution.start{justify-content:flex-start}.quarto-grid-item .card-attribution.end{justify-content:flex-end}.quarto-grid-item .card-title{margin-bottom:.1em}.quarto-grid-item .card-subtitle{padding-top:.25em}.quarto-grid-item .card-text{font-size:.9em}.quarto-grid-item .listing-reading-time{padding-bottom:.25em}.quarto-grid-item .card-text-small{font-size:.8em}.quarto-grid-item .card-subtitle.subtitle{font-size:.9em;font-weight:600;padding-bottom:.5em}.quarto-grid-item .listing-categories{display:flex;flex-wrap:wrap;padding-bottom:5px}.quarto-grid-item .listing-categories .listing-category{color:#6c757d;border:solid 1px #dee2e6;border-radius:.25rem;text-transform:uppercase;font-size:.65em;padding-left:.5em;padding-right:.5em;padding-top:.15em;padding-bottom:.15em;cursor:pointer;margin-right:4px;margin-bottom:4px}.quarto-grid-item.card-right{text-align:right}.quarto-grid-item.card-right .listing-categories{justify-content:flex-end}.quarto-grid-item.card-left{text-align:left}.quarto-grid-item.card-center{text-align:center}.quarto-grid-item.card-center .listing-description{text-align:justify}.quarto-grid-item.card-center .listing-categories{justify-content:center}table.quarto-listing-table td.image{padding:0px}table.quarto-listing-table td.image img{width:100%;max-width:50px;object-fit:contain}table.quarto-listing-table a{text-decoration:none}table.quarto-listing-table th a{color:inherit}table.quarto-listing-table th a.asc:after{margin-bottom:-2px;margin-left:5px;display:inline-block;height:1rem;width:1rem;background-repeat:no-repeat;background-size:1rem 1rem;background-image:url('data:image/svg+xml,');content:""}table.quarto-listing-table th a.desc:after{margin-bottom:-2px;margin-left:5px;display:inline-block;height:1rem;width:1rem;background-repeat:no-repeat;background-size:1rem 1rem;background-image:url('data:image/svg+xml,');content:""}table.quarto-listing-table.table-hover td{cursor:pointer}.quarto-post.image-left{flex-direction:row}.quarto-post.image-right{flex-direction:row-reverse}@media(max-width: 767.98px){.quarto-post.image-right,.quarto-post.image-left{gap:0em;flex-direction:column}.quarto-post .metadata{padding-bottom:1em;order:2}.quarto-post .body{order:1}.quarto-post .thumbnail{order:3}}.list.quarto-listing-default div:last-of-type{border-bottom:none}@media(min-width: 992px){.quarto-listing-container-default{margin-right:2em}}div.quarto-post{display:flex;gap:2em;margin-bottom:1.5em;border-bottom:1px solid #dee2e6}@media(max-width: 767.98px){div.quarto-post{padding-bottom:1em}}div.quarto-post .metadata{flex-basis:20%;flex-grow:0;margin-top:.2em;flex-shrink:10}div.quarto-post .thumbnail{flex-basis:30%;flex-grow:0;flex-shrink:0}div.quarto-post .thumbnail img{margin-top:.4em;width:100%;object-fit:cover}div.quarto-post .body{flex-basis:45%;flex-grow:1;flex-shrink:0}div.quarto-post .body h3.listing-title,div.quarto-post .body .listing-title.h3{margin-top:0px;margin-bottom:0px;border-bottom:none}div.quarto-post .body .listing-subtitle{font-size:.875em;margin-bottom:.5em;margin-top:.2em}div.quarto-post .body .description{font-size:.9em}div.quarto-post a{color:#fff;display:flex;flex-direction:column;text-decoration:none}div.quarto-post a div.description{flex-shrink:0}div.quarto-post .metadata{display:flex;flex-direction:column;font-size:.8em;font-family:var(--bs-font-sans-serif);flex-basis:33%}div.quarto-post .listing-categories{display:flex;flex-wrap:wrap;padding-bottom:5px}div.quarto-post .listing-categories .listing-category{color:#6c757d;border:solid 1px #dee2e6;border-radius:.25rem;text-transform:uppercase;font-size:.65em;padding-left:.5em;padding-right:.5em;padding-top:.15em;padding-bottom:.15em;cursor:pointer;margin-right:4px;margin-bottom:4px}div.quarto-post .listing-description{margin-bottom:.5em}div.quarto-about-jolla{display:flex !important;flex-direction:column;align-items:center;margin-top:10%;padding-bottom:1em}div.quarto-about-jolla .about-image{object-fit:cover;margin-left:auto;margin-right:auto;margin-bottom:1.5em}div.quarto-about-jolla img.round{border-radius:50%}div.quarto-about-jolla img.rounded{border-radius:10px}div.quarto-about-jolla .quarto-title h1.title,div.quarto-about-jolla .quarto-title .title.h1{text-align:center}div.quarto-about-jolla .quarto-title .description{text-align:center}div.quarto-about-jolla h2,div.quarto-about-jolla .h2{border-bottom:none}div.quarto-about-jolla .about-sep{width:60%}div.quarto-about-jolla main{text-align:center}div.quarto-about-jolla .about-links{display:flex}@media(min-width: 992px){div.quarto-about-jolla .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-jolla .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-jolla .about-link{color:#fff;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-jolla .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-jolla .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-jolla .about-link:hover{color:#75aadb}div.quarto-about-jolla .about-link i.bi{margin-right:.15em}div.quarto-about-solana{display:flex !important;flex-direction:column;padding-top:3em !important;padding-bottom:1em}div.quarto-about-solana .about-entity{display:flex !important;align-items:start;justify-content:space-between}@media(min-width: 992px){div.quarto-about-solana .about-entity{flex-direction:row}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity{flex-direction:column-reverse;align-items:center;text-align:center}}div.quarto-about-solana .about-entity .entity-contents{display:flex;flex-direction:column}@media(max-width: 767.98px){div.quarto-about-solana .about-entity .entity-contents{width:100%}}div.quarto-about-solana .about-entity .about-image{object-fit:cover}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-image{margin-bottom:1.5em}}div.quarto-about-solana .about-entity img.round{border-radius:50%}div.quarto-about-solana .about-entity img.rounded{border-radius:10px}div.quarto-about-solana .about-entity .about-links{display:flex;justify-content:left;padding-bottom:1.2em}@media(min-width: 992px){div.quarto-about-solana .about-entity .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-solana .about-entity .about-link{color:#fff;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-solana .about-entity .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-solana .about-entity .about-link:hover{color:#75aadb}div.quarto-about-solana .about-entity .about-link i.bi{margin-right:.15em}div.quarto-about-solana .about-contents{padding-right:1.5em;flex-basis:0;flex-grow:1}div.quarto-about-solana .about-contents main.content{margin-top:0}div.quarto-about-solana .about-contents h2,div.quarto-about-solana .about-contents .h2{border-bottom:none}div.quarto-about-trestles{display:flex !important;flex-direction:row;padding-top:3em !important;padding-bottom:1em}@media(max-width: 991.98px){div.quarto-about-trestles{flex-direction:column;padding-top:0em !important}}div.quarto-about-trestles .about-entity{display:flex !important;flex-direction:column;align-items:center;text-align:center;padding-right:1em}@media(min-width: 992px){div.quarto-about-trestles .about-entity{flex:0 0 42%}}div.quarto-about-trestles .about-entity .about-image{object-fit:cover;margin-bottom:1.5em}div.quarto-about-trestles .about-entity img.round{border-radius:50%}div.quarto-about-trestles .about-entity img.rounded{border-radius:10px}div.quarto-about-trestles .about-entity .about-links{display:flex;justify-content:center}@media(min-width: 992px){div.quarto-about-trestles .about-entity .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-trestles .about-entity .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-trestles .about-entity .about-link{color:#fff;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-trestles .about-entity .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-trestles .about-entity .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-trestles .about-entity .about-link:hover{color:#75aadb}div.quarto-about-trestles .about-entity .about-link i.bi{margin-right:.15em}div.quarto-about-trestles .about-contents{flex-basis:0;flex-grow:1}div.quarto-about-trestles .about-contents h2,div.quarto-about-trestles .about-contents .h2{border-bottom:none}@media(min-width: 992px){div.quarto-about-trestles .about-contents{border-left:solid 1px #dee2e6;padding-left:1.5em}}div.quarto-about-trestles .about-contents main.content{margin-top:0}div.quarto-about-marquee{padding-bottom:1em}div.quarto-about-marquee .about-contents{display:flex;flex-direction:column}div.quarto-about-marquee .about-image{max-height:550px;margin-bottom:1.5em;object-fit:cover}div.quarto-about-marquee img.round{border-radius:50%}div.quarto-about-marquee img.rounded{border-radius:10px}div.quarto-about-marquee h2,div.quarto-about-marquee .h2{border-bottom:none}div.quarto-about-marquee .about-links{display:flex;justify-content:center;padding-top:1.5em}@media(min-width: 992px){div.quarto-about-marquee .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-marquee .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-marquee .about-link{color:#fff;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-marquee .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-marquee .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-marquee .about-link:hover{color:#75aadb}div.quarto-about-marquee .about-link i.bi{margin-right:.15em}@media(min-width: 992px){div.quarto-about-marquee .about-link{border:none}}div.quarto-about-broadside{display:flex;flex-direction:column;padding-bottom:1em}div.quarto-about-broadside .about-main{display:flex !important;padding-top:0 !important}@media(min-width: 992px){div.quarto-about-broadside .about-main{flex-direction:row;align-items:flex-start}}@media(max-width: 991.98px){div.quarto-about-broadside .about-main{flex-direction:column}}@media(max-width: 991.98px){div.quarto-about-broadside .about-main .about-entity{flex-shrink:0;width:100%;height:450px;margin-bottom:1.5em;background-size:cover;background-repeat:no-repeat}}@media(min-width: 992px){div.quarto-about-broadside .about-main .about-entity{flex:0 10 50%;margin-right:1.5em;width:100%;height:100%;background-size:100%;background-repeat:no-repeat}}div.quarto-about-broadside .about-main .about-contents{padding-top:14px;flex:0 0 50%}div.quarto-about-broadside h2,div.quarto-about-broadside .h2{border-bottom:none}div.quarto-about-broadside .about-sep{margin-top:1.5em;width:60%;align-self:center}div.quarto-about-broadside .about-links{display:flex;justify-content:center;column-gap:20px;padding-top:1.5em}@media(min-width: 992px){div.quarto-about-broadside .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-broadside .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-broadside .about-link{color:#fff;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-broadside .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-broadside .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-broadside .about-link:hover{color:#75aadb}div.quarto-about-broadside .about-link i.bi{margin-right:.15em}@media(min-width: 992px){div.quarto-about-broadside .about-link{border:none}}.tippy-box[data-theme~=quarto]{background-color:#181818;border:solid 1px #dee2e6;border-radius:.25rem;color:#fff;font-size:.875rem}.tippy-box[data-theme~=quarto]>.tippy-backdrop{background-color:#181818}.tippy-box[data-theme~=quarto]>.tippy-arrow:after,.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{content:"";position:absolute;z-index:-1}.tippy-box[data-theme~=quarto]>.tippy-arrow:after{border-color:rgba(0,0,0,0);border-style:solid}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-6px}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-6px}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-6px}.tippy-box[data-placement^=left]>.tippy-arrow:before{right:-6px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:before{border-top-color:#181818}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:after{border-top-color:#dee2e6;border-width:7px 7px 0;top:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow>svg{top:16px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow:after{top:17px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#181818;bottom:16px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:after{border-bottom-color:#dee2e6;border-width:0 7px 7px;bottom:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow>svg{bottom:15px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow:after{bottom:17px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:before{border-left-color:#181818}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:after{border-left-color:#dee2e6;border-width:7px 0 7px 7px;left:17px;top:1px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow>svg{left:11px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow:after{left:12px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:before{border-right-color:#181818;right:16px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:after{border-width:7px 7px 7px 0;right:17px;top:1px;border-right-color:#dee2e6}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow>svg{right:11px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow:after{right:12px}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow{fill:#fff}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCA2czEuNzk2LS4wMTMgNC42Ny0zLjYxNUM1Ljg1MS45IDYuOTMuMDA2IDggMGMxLjA3LS4wMDYgMi4xNDguODg3IDMuMzQzIDIuMzg1QzE0LjIzMyA2LjAwNSAxNiA2IDE2IDZIMHoiIGZpbGw9InJnYmEoMCwgOCwgMTYsIDAuMikiLz48L3N2Zz4=);background-size:16px 6px;width:16px;height:6px}.top-right{position:absolute;top:1em;right:1em}.hidden{display:none !important}.zindex-bottom{z-index:-1 !important}.quarto-layout-panel{margin-bottom:1em}.quarto-layout-panel>figure{width:100%}.quarto-layout-panel>figure>figcaption,.quarto-layout-panel>.panel-caption{margin-top:10pt}.quarto-layout-panel>.table-caption{margin-top:0px}.table-caption p{margin-bottom:.5em}.quarto-layout-row{display:flex;flex-direction:row;align-items:flex-start}.quarto-layout-valign-top{align-items:flex-start}.quarto-layout-valign-bottom{align-items:flex-end}.quarto-layout-valign-center{align-items:center}.quarto-layout-cell{position:relative;margin-right:20px}.quarto-layout-cell:last-child{margin-right:0}.quarto-layout-cell figure,.quarto-layout-cell>p{margin:.2em}.quarto-layout-cell img{max-width:100%}.quarto-layout-cell .html-widget{width:100% !important}.quarto-layout-cell div figure p{margin:0}.quarto-layout-cell figure{display:inline-block;margin-inline-start:0;margin-inline-end:0}.quarto-layout-cell table{display:inline-table}.quarto-layout-cell-subref figcaption,figure .quarto-layout-row figure figcaption{text-align:center;font-style:italic}.quarto-figure{position:relative;margin-bottom:1em}.quarto-figure>figure{width:100%;margin-bottom:0}.quarto-figure-left>figure>p,.quarto-figure-left>figure>div{text-align:left}.quarto-figure-center>figure>p,.quarto-figure-center>figure>div{text-align:center}.quarto-figure-right>figure>p,.quarto-figure-right>figure>div{text-align:right}figure>p:empty{display:none}figure>p:first-child{margin-top:0;margin-bottom:0}figure>figcaption{margin-top:.5em}div[id^=tbl-]{position:relative}.quarto-figure>.anchorjs-link{position:absolute;top:.6em;right:.5em}div[id^=tbl-]>.anchorjs-link{position:absolute;top:.7em;right:.3em}.quarto-figure:hover>.anchorjs-link,div[id^=tbl-]:hover>.anchorjs-link,h2:hover>.anchorjs-link,.h2:hover>.anchorjs-link,h3:hover>.anchorjs-link,.h3:hover>.anchorjs-link,h4:hover>.anchorjs-link,.h4:hover>.anchorjs-link,h5:hover>.anchorjs-link,.h5:hover>.anchorjs-link,h6:hover>.anchorjs-link,.h6:hover>.anchorjs-link,.reveal-anchorjs-link>.anchorjs-link{opacity:1}#title-block-header{margin-block-end:1rem;position:relative;margin-top:-1px}#title-block-header .abstract{margin-block-start:1rem}#title-block-header .abstract .abstract-title{font-weight:600}#title-block-header a{text-decoration:none}#title-block-header .author,#title-block-header .date,#title-block-header .doi{margin-block-end:.2rem}#title-block-header .quarto-title-block>div{display:flex}#title-block-header .quarto-title-block>div>h1,#title-block-header .quarto-title-block>div>.h1{flex-grow:1}#title-block-header .quarto-title-block>div>button{flex-shrink:0;height:2.25rem;margin-top:0}@media(min-width: 992px){#title-block-header .quarto-title-block>div>button{margin-top:5px}}tr.header>th>p:last-of-type{margin-bottom:0px}table,.table{caption-side:top;margin-bottom:1.5rem}caption,.table-caption{padding-top:.5rem;padding-bottom:.5rem;text-align:center}.utterances{max-width:none;margin-left:-8px}iframe{margin-bottom:1em}details{margin-bottom:1em}details[show]{margin-bottom:0}details>summary{color:#6c757d}details>summary>p:only-child{display:inline}pre.sourceCode,code.sourceCode{position:relative}p code:not(.sourceCode){white-space:pre-wrap}code{white-space:pre}@media print{code{white-space:pre-wrap}}pre>code{display:block}pre>code.sourceCode{white-space:pre-wrap}pre>code.sourceCode>span>a:first-child::before{text-decoration:none}pre.code-overflow-wrap>code.sourceCode{white-space:pre-wrap}pre.code-overflow-scroll>code.sourceCode{white-space:pre}code a:any-link{color:inherit;text-decoration:none}code a:hover{color:inherit;text-decoration:underline}ul.task-list{padding-left:1em}[data-tippy-root]{display:inline-block}.tippy-content .footnote-back{display:none}.quarto-embedded-source-code{display:none}.quarto-unresolved-ref{font-weight:600}.quarto-cover-image{max-width:35%;float:right;margin-left:30px}.cell-output-display .widget-subarea{margin-bottom:1em}.cell-output-display:not(.no-overflow-x),.knitsql-table:not(.no-overflow-x){overflow-x:auto}.panel-input{margin-bottom:1em}.panel-input>div,.panel-input>div>div{display:inline-block;vertical-align:top;padding-right:12px}.panel-input>p:last-child{margin-bottom:0}.layout-sidebar{margin-bottom:1em}.layout-sidebar .tab-content{border:none}.tab-content>.page-columns.active{display:grid}div.sourceCode>iframe{width:100%;height:300px;margin-bottom:-0.5em}div.ansi-escaped-output{font-family:monospace;display:block}/*! +* +* ansi colors from IPython notebook's +* +*/.ansi-black-fg{color:#3e424d}.ansi-black-bg{background-color:#3e424d}.ansi-black-intense-fg{color:#282c36}.ansi-black-intense-bg{background-color:#282c36}.ansi-red-fg{color:#e75c58}.ansi-red-bg{background-color:#e75c58}.ansi-red-intense-fg{color:#b22b31}.ansi-red-intense-bg{background-color:#b22b31}.ansi-green-fg{color:#00a250}.ansi-green-bg{background-color:#00a250}.ansi-green-intense-fg{color:#007427}.ansi-green-intense-bg{background-color:#007427}.ansi-yellow-fg{color:#ddb62b}.ansi-yellow-bg{background-color:#ddb62b}.ansi-yellow-intense-fg{color:#b27d12}.ansi-yellow-intense-bg{background-color:#b27d12}.ansi-blue-fg{color:#208ffb}.ansi-blue-bg{background-color:#208ffb}.ansi-blue-intense-fg{color:#0065ca}.ansi-blue-intense-bg{background-color:#0065ca}.ansi-magenta-fg{color:#d160c4}.ansi-magenta-bg{background-color:#d160c4}.ansi-magenta-intense-fg{color:#a03196}.ansi-magenta-intense-bg{background-color:#a03196}.ansi-cyan-fg{color:#60c6c8}.ansi-cyan-bg{background-color:#60c6c8}.ansi-cyan-intense-fg{color:#258f8f}.ansi-cyan-intense-bg{background-color:#258f8f}.ansi-white-fg{color:#c5c1b4}.ansi-white-bg{background-color:#c5c1b4}.ansi-white-intense-fg{color:#a1a6b2}.ansi-white-intense-bg{background-color:#a1a6b2}.ansi-default-inverse-fg{color:#fff}.ansi-default-inverse-bg{background-color:#000}.ansi-bold{font-weight:bold}.ansi-underline{text-decoration:underline}:root{--quarto-body-bg: #181818;--quarto-body-color: white;--quarto-text-muted: #6c757d;--quarto-border-color: #dee2e6;--quarto-border-width: 1px;--quarto-border-radius: 0.25rem}table.gt_table{color:var(--quarto-body-color);font-size:1em;width:100%;background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_column_spanner_outer{color:var(--quarto-body-color);background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_col_heading{color:var(--quarto-body-color);font-weight:bold;background-color:rgba(0,0,0,0)}table.gt_table thead.gt_col_headings{border-bottom:1px solid currentColor;border-top-width:inherit;border-top-color:var(--quarto-border-color)}table.gt_table thead.gt_col_headings:not(:first-child){border-top-width:1px;border-top-color:var(--quarto-border-color)}table.gt_table td.gt_row{border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-width:0px}table.gt_table tbody.gt_table_body{border-top-width:1px;border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-color:currentColor}div.columns{display:initial;gap:initial}div.column{display:inline-block;overflow-x:initial;vertical-align:top;width:50%}.code-annotation-tip-content{word-wrap:break-word}.code-annotation-container-hidden{display:none !important}dl.code-annotation-container-grid{display:grid;grid-template-columns:min-content auto}dl.code-annotation-container-grid dt{grid-column:1}dl.code-annotation-container-grid dd{grid-column:2}pre.sourceCode.code-annotation-code{padding-right:0}code.sourceCode .code-annotation-anchor{z-index:100;position:absolute;right:.5em;left:inherit;background-color:rgba(0,0,0,0)}:root{--mermaid-bg-color: #181818;--mermaid-edge-color: #373a3c;--mermaid-node-fg-color: white;--mermaid-fg-color: white;--mermaid-fg-color--lighter: white;--mermaid-fg-color--lightest: white;--mermaid-font-family: Source Sans Pro, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;--mermaid-label-bg-color: #181818;--mermaid-label-fg-color: #2780e3;--mermaid-node-bg-color: rgba(39, 128, 227, 0.1);--mermaid-node-fg-color: white}@media print{:root{font-size:11pt}#quarto-sidebar,#TOC,.nav-page{display:none}.page-columns .content{grid-column-start:page-start}.fixed-top{position:relative}.panel-caption,.figure-caption,figcaption{color:#666}}.code-copy-button{position:absolute;top:0;right:0;border:0;margin-top:5px;margin-right:5px;background-color:rgba(0,0,0,0);z-index:3}.code-copy-button:focus{outline:none}.code-copy-button-tooltip{font-size:.75em}.code-copy-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}.code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}.code-copy-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}.code-copy-button-checked:hover>.bi::before{background-image:url('data:image/svg+xml,')}main ol ol,main ul ul,main ol ul,main ul ol{margin-bottom:1em}ul>li:not(:has(>p))>ul,ol>li:not(:has(>p))>ul,ul>li:not(:has(>p))>ol,ol>li:not(:has(>p))>ol{margin-bottom:0}ul>li:not(:has(>p))>ul>li:has(>p),ol>li:not(:has(>p))>ul>li:has(>p),ul>li:not(:has(>p))>ol>li:has(>p),ol>li:not(:has(>p))>ol>li:has(>p){margin-top:1rem}body{margin:0}main.page-columns>header>h1.title,main.page-columns>header>.title.h1{margin-bottom:0}@media(min-width: 992px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 56px [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(500px, calc( 850px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 56px [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(500px, calc( 850px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] 35px [page-end-inset page-end] 5fr [screen-end-inset] 1.5em}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 56px [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(500px, calc( 850px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 56px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 850px - 3em )) [body-content-end] 3em [body-end] 80px [body-end-outset] minmax(0px, 250px) [page-end-inset] minmax(80px, 160px) [page-end] 1fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 56px [page-start-inset] minmax(0px, 280px) [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(450px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 56px [page-start-inset] minmax(0px, 280px) [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(450px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(40px, 80px) [page-start-inset] minmax(80px, 240px) [body-start-outset] minmax(40px, 80px) [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 1000px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 100px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 1000px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 80px [page-start-inset] minmax(80px, 240px) [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(450px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 1000px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 80px [page-start-inset] minmax(80px, 240px) [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(450px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 150px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(40px, 80px) [page-start-inset] minmax(80px, 240px) [body-start-outset] minmax(40px, 80px) [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 991.98px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc( 1250px - 3em )) [body-content-end body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 56px [page-start-inset] minmax(0px, 232px) [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(450px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 56px [page-start-inset] minmax(0px, 232px) [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(450px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1.5em [body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc( 1000px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 767.98px){body .page-columns,body.fullcontent:not(.floating):not(.docked) .page-columns,body.slimcontent:not(.floating):not(.docked) .page-columns,body.docked .page-columns,body.docked.slimcontent .page-columns,body.docked.fullcontent .page-columns,body.floating .page-columns,body.floating.slimcontent .page-columns,body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}nav[role=doc-toc]{display:none}}body,.page-row-navigation{grid-template-rows:[page-top] max-content [contents-top] max-content [contents-bottom] max-content [page-bottom]}.page-rows-contents{grid-template-rows:[content-top] minmax(max-content, 1fr) [content-bottom] minmax(60px, max-content) [page-bottom]}.page-full{grid-column:screen-start/screen-end !important}.page-columns>*{grid-column:body-content-start/body-content-end}.page-columns.column-page>*{grid-column:page-start/page-end}.page-columns.column-page-left>*{grid-column:page-start/body-content-end}.page-columns.column-page-right>*{grid-column:body-content-start/page-end}.page-rows{grid-auto-rows:auto}.header{grid-column:screen-start/screen-end;grid-row:page-top/contents-top}#quarto-content{padding:0;grid-column:screen-start/screen-end;grid-row:contents-top/contents-bottom}body.floating .sidebar.sidebar-navigation{grid-column:page-start/body-start;grid-row:content-top/page-bottom}body.docked .sidebar.sidebar-navigation{grid-column:screen-start/body-start;grid-row:content-top/page-bottom}.sidebar.toc-left{grid-column:page-start/body-start;grid-row:content-top/page-bottom}.sidebar.margin-sidebar{grid-column:body-end/page-end;grid-row:content-top/page-bottom}.page-columns .content{grid-column:body-content-start/body-content-end;grid-row:content-top/content-bottom;align-content:flex-start}.page-columns .page-navigation{grid-column:body-content-start/body-content-end;grid-row:content-bottom/page-bottom}.page-columns .footer{grid-column:screen-start/screen-end;grid-row:contents-bottom/page-bottom}.page-columns .column-body{grid-column:body-content-start/body-content-end}.page-columns .column-body-fullbleed{grid-column:body-start/body-end}.page-columns .column-body-outset{grid-column:body-start-outset/body-end-outset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-body-outset table{background:#181818}.page-columns .column-body-outset-left{grid-column:body-start-outset/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-body-outset-left table{background:#181818}.page-columns .column-body-outset-right{grid-column:body-content-start/body-end-outset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-body-outset-right table{background:#181818}.page-columns .column-page{grid-column:page-start/page-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page table{background:#181818}.page-columns .column-page-inset{grid-column:page-start-inset/page-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-inset table{background:#181818}.page-columns .column-page-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-inset-left table{background:#181818}.page-columns .column-page-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-inset-right figcaption table{background:#181818}.page-columns .column-page-left{grid-column:page-start/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-left table{background:#181818}.page-columns .column-page-right{grid-column:body-content-start/page-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-right figcaption table{background:#181818}#quarto-content.page-columns #quarto-margin-sidebar,#quarto-content.page-columns #quarto-sidebar{z-index:1}@media(max-width: 991.98px){#quarto-content.page-columns #quarto-margin-sidebar.collapse,#quarto-content.page-columns #quarto-sidebar.collapse,#quarto-content.page-columns #quarto-margin-sidebar.collapsing,#quarto-content.page-columns #quarto-sidebar.collapsing{z-index:1055}}#quarto-content.page-columns main.column-page,#quarto-content.page-columns main.column-page-right,#quarto-content.page-columns main.column-page-left{z-index:0}.page-columns .column-screen-inset{grid-column:screen-start-inset/screen-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset table{background:#181818}.page-columns .column-screen-inset-left{grid-column:screen-start-inset/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset-left table{background:#181818}.page-columns .column-screen-inset-right{grid-column:body-content-start/screen-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset-right table{background:#181818}.page-columns .column-screen{grid-column:screen-start/screen-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen table{background:#181818}.page-columns .column-screen-left{grid-column:screen-start/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-left table{background:#181818}.page-columns .column-screen-right{grid-column:body-content-start/screen-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-right table{background:#181818}.page-columns .column-screen-inset-shaded{grid-column:screen-start/screen-end;padding:1em;background:#525252;z-index:998;transform:translate3d(0, 0, 0);margin-bottom:1em}.zindex-content{z-index:998;transform:translate3d(0, 0, 0)}.zindex-modal{z-index:1055;transform:translate3d(0, 0, 0)}.zindex-over-content{z-index:999;transform:translate3d(0, 0, 0)}img.img-fluid.column-screen,img.img-fluid.column-screen-inset-shaded,img.img-fluid.column-screen-inset,img.img-fluid.column-screen-inset-left,img.img-fluid.column-screen-inset-right,img.img-fluid.column-screen-left,img.img-fluid.column-screen-right{width:100%}@media(min-width: 992px){.margin-caption,div.aside,aside,.column-margin{grid-column:body-end/page-end !important;z-index:998}.column-sidebar{grid-column:page-start/body-start !important;z-index:998}.column-leftmargin{grid-column:screen-start-inset/body-start !important;z-index:998}.no-row-height{height:1em;overflow:visible}}@media(max-width: 991.98px){.margin-caption,div.aside,aside,.column-margin{grid-column:body-end/page-end !important;z-index:998}.no-row-height{height:1em;overflow:visible}.page-columns.page-full{overflow:visible}.page-columns.toc-left .margin-caption,.page-columns.toc-left div.aside,.page-columns.toc-left aside,.page-columns.toc-left .column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;transform:translate3d(0, 0, 0)}.page-columns.toc-left .no-row-height{height:initial;overflow:initial}}@media(max-width: 767.98px){.margin-caption,div.aside,aside,.column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;transform:translate3d(0, 0, 0)}.no-row-height{height:initial;overflow:initial}#quarto-margin-sidebar{display:none}#quarto-sidebar-toc-left{display:none}.hidden-sm{display:none}}.panel-grid{display:grid;grid-template-rows:repeat(1, 1fr);grid-template-columns:repeat(24, 1fr);gap:1em}.panel-grid .g-col-1{grid-column:auto/span 1}.panel-grid .g-col-2{grid-column:auto/span 2}.panel-grid .g-col-3{grid-column:auto/span 3}.panel-grid .g-col-4{grid-column:auto/span 4}.panel-grid .g-col-5{grid-column:auto/span 5}.panel-grid .g-col-6{grid-column:auto/span 6}.panel-grid .g-col-7{grid-column:auto/span 7}.panel-grid .g-col-8{grid-column:auto/span 8}.panel-grid .g-col-9{grid-column:auto/span 9}.panel-grid .g-col-10{grid-column:auto/span 10}.panel-grid .g-col-11{grid-column:auto/span 11}.panel-grid .g-col-12{grid-column:auto/span 12}.panel-grid .g-col-13{grid-column:auto/span 13}.panel-grid .g-col-14{grid-column:auto/span 14}.panel-grid .g-col-15{grid-column:auto/span 15}.panel-grid .g-col-16{grid-column:auto/span 16}.panel-grid .g-col-17{grid-column:auto/span 17}.panel-grid .g-col-18{grid-column:auto/span 18}.panel-grid .g-col-19{grid-column:auto/span 19}.panel-grid .g-col-20{grid-column:auto/span 20}.panel-grid .g-col-21{grid-column:auto/span 21}.panel-grid .g-col-22{grid-column:auto/span 22}.panel-grid .g-col-23{grid-column:auto/span 23}.panel-grid .g-col-24{grid-column:auto/span 24}.panel-grid .g-start-1{grid-column-start:1}.panel-grid .g-start-2{grid-column-start:2}.panel-grid .g-start-3{grid-column-start:3}.panel-grid .g-start-4{grid-column-start:4}.panel-grid .g-start-5{grid-column-start:5}.panel-grid .g-start-6{grid-column-start:6}.panel-grid .g-start-7{grid-column-start:7}.panel-grid .g-start-8{grid-column-start:8}.panel-grid .g-start-9{grid-column-start:9}.panel-grid .g-start-10{grid-column-start:10}.panel-grid .g-start-11{grid-column-start:11}.panel-grid .g-start-12{grid-column-start:12}.panel-grid .g-start-13{grid-column-start:13}.panel-grid .g-start-14{grid-column-start:14}.panel-grid .g-start-15{grid-column-start:15}.panel-grid .g-start-16{grid-column-start:16}.panel-grid .g-start-17{grid-column-start:17}.panel-grid .g-start-18{grid-column-start:18}.panel-grid .g-start-19{grid-column-start:19}.panel-grid .g-start-20{grid-column-start:20}.panel-grid .g-start-21{grid-column-start:21}.panel-grid .g-start-22{grid-column-start:22}.panel-grid .g-start-23{grid-column-start:23}@media(min-width: 576px){.panel-grid .g-col-sm-1{grid-column:auto/span 1}.panel-grid .g-col-sm-2{grid-column:auto/span 2}.panel-grid .g-col-sm-3{grid-column:auto/span 3}.panel-grid .g-col-sm-4{grid-column:auto/span 4}.panel-grid .g-col-sm-5{grid-column:auto/span 5}.panel-grid .g-col-sm-6{grid-column:auto/span 6}.panel-grid .g-col-sm-7{grid-column:auto/span 7}.panel-grid .g-col-sm-8{grid-column:auto/span 8}.panel-grid .g-col-sm-9{grid-column:auto/span 9}.panel-grid .g-col-sm-10{grid-column:auto/span 10}.panel-grid .g-col-sm-11{grid-column:auto/span 11}.panel-grid .g-col-sm-12{grid-column:auto/span 12}.panel-grid .g-col-sm-13{grid-column:auto/span 13}.panel-grid .g-col-sm-14{grid-column:auto/span 14}.panel-grid .g-col-sm-15{grid-column:auto/span 15}.panel-grid .g-col-sm-16{grid-column:auto/span 16}.panel-grid .g-col-sm-17{grid-column:auto/span 17}.panel-grid .g-col-sm-18{grid-column:auto/span 18}.panel-grid .g-col-sm-19{grid-column:auto/span 19}.panel-grid .g-col-sm-20{grid-column:auto/span 20}.panel-grid .g-col-sm-21{grid-column:auto/span 21}.panel-grid .g-col-sm-22{grid-column:auto/span 22}.panel-grid .g-col-sm-23{grid-column:auto/span 23}.panel-grid .g-col-sm-24{grid-column:auto/span 24}.panel-grid .g-start-sm-1{grid-column-start:1}.panel-grid .g-start-sm-2{grid-column-start:2}.panel-grid .g-start-sm-3{grid-column-start:3}.panel-grid .g-start-sm-4{grid-column-start:4}.panel-grid .g-start-sm-5{grid-column-start:5}.panel-grid .g-start-sm-6{grid-column-start:6}.panel-grid .g-start-sm-7{grid-column-start:7}.panel-grid .g-start-sm-8{grid-column-start:8}.panel-grid .g-start-sm-9{grid-column-start:9}.panel-grid .g-start-sm-10{grid-column-start:10}.panel-grid .g-start-sm-11{grid-column-start:11}.panel-grid .g-start-sm-12{grid-column-start:12}.panel-grid .g-start-sm-13{grid-column-start:13}.panel-grid .g-start-sm-14{grid-column-start:14}.panel-grid .g-start-sm-15{grid-column-start:15}.panel-grid .g-start-sm-16{grid-column-start:16}.panel-grid .g-start-sm-17{grid-column-start:17}.panel-grid .g-start-sm-18{grid-column-start:18}.panel-grid .g-start-sm-19{grid-column-start:19}.panel-grid .g-start-sm-20{grid-column-start:20}.panel-grid .g-start-sm-21{grid-column-start:21}.panel-grid .g-start-sm-22{grid-column-start:22}.panel-grid .g-start-sm-23{grid-column-start:23}}@media(min-width: 768px){.panel-grid .g-col-md-1{grid-column:auto/span 1}.panel-grid .g-col-md-2{grid-column:auto/span 2}.panel-grid .g-col-md-3{grid-column:auto/span 3}.panel-grid .g-col-md-4{grid-column:auto/span 4}.panel-grid .g-col-md-5{grid-column:auto/span 5}.panel-grid .g-col-md-6{grid-column:auto/span 6}.panel-grid .g-col-md-7{grid-column:auto/span 7}.panel-grid .g-col-md-8{grid-column:auto/span 8}.panel-grid .g-col-md-9{grid-column:auto/span 9}.panel-grid .g-col-md-10{grid-column:auto/span 10}.panel-grid .g-col-md-11{grid-column:auto/span 11}.panel-grid .g-col-md-12{grid-column:auto/span 12}.panel-grid .g-col-md-13{grid-column:auto/span 13}.panel-grid .g-col-md-14{grid-column:auto/span 14}.panel-grid .g-col-md-15{grid-column:auto/span 15}.panel-grid .g-col-md-16{grid-column:auto/span 16}.panel-grid .g-col-md-17{grid-column:auto/span 17}.panel-grid .g-col-md-18{grid-column:auto/span 18}.panel-grid .g-col-md-19{grid-column:auto/span 19}.panel-grid .g-col-md-20{grid-column:auto/span 20}.panel-grid .g-col-md-21{grid-column:auto/span 21}.panel-grid .g-col-md-22{grid-column:auto/span 22}.panel-grid .g-col-md-23{grid-column:auto/span 23}.panel-grid .g-col-md-24{grid-column:auto/span 24}.panel-grid .g-start-md-1{grid-column-start:1}.panel-grid .g-start-md-2{grid-column-start:2}.panel-grid .g-start-md-3{grid-column-start:3}.panel-grid .g-start-md-4{grid-column-start:4}.panel-grid .g-start-md-5{grid-column-start:5}.panel-grid .g-start-md-6{grid-column-start:6}.panel-grid .g-start-md-7{grid-column-start:7}.panel-grid .g-start-md-8{grid-column-start:8}.panel-grid .g-start-md-9{grid-column-start:9}.panel-grid .g-start-md-10{grid-column-start:10}.panel-grid .g-start-md-11{grid-column-start:11}.panel-grid .g-start-md-12{grid-column-start:12}.panel-grid .g-start-md-13{grid-column-start:13}.panel-grid .g-start-md-14{grid-column-start:14}.panel-grid .g-start-md-15{grid-column-start:15}.panel-grid .g-start-md-16{grid-column-start:16}.panel-grid .g-start-md-17{grid-column-start:17}.panel-grid .g-start-md-18{grid-column-start:18}.panel-grid .g-start-md-19{grid-column-start:19}.panel-grid .g-start-md-20{grid-column-start:20}.panel-grid .g-start-md-21{grid-column-start:21}.panel-grid .g-start-md-22{grid-column-start:22}.panel-grid .g-start-md-23{grid-column-start:23}}@media(min-width: 992px){.panel-grid .g-col-lg-1{grid-column:auto/span 1}.panel-grid .g-col-lg-2{grid-column:auto/span 2}.panel-grid .g-col-lg-3{grid-column:auto/span 3}.panel-grid .g-col-lg-4{grid-column:auto/span 4}.panel-grid .g-col-lg-5{grid-column:auto/span 5}.panel-grid .g-col-lg-6{grid-column:auto/span 6}.panel-grid .g-col-lg-7{grid-column:auto/span 7}.panel-grid .g-col-lg-8{grid-column:auto/span 8}.panel-grid .g-col-lg-9{grid-column:auto/span 9}.panel-grid .g-col-lg-10{grid-column:auto/span 10}.panel-grid .g-col-lg-11{grid-column:auto/span 11}.panel-grid .g-col-lg-12{grid-column:auto/span 12}.panel-grid .g-col-lg-13{grid-column:auto/span 13}.panel-grid .g-col-lg-14{grid-column:auto/span 14}.panel-grid .g-col-lg-15{grid-column:auto/span 15}.panel-grid .g-col-lg-16{grid-column:auto/span 16}.panel-grid .g-col-lg-17{grid-column:auto/span 17}.panel-grid .g-col-lg-18{grid-column:auto/span 18}.panel-grid .g-col-lg-19{grid-column:auto/span 19}.panel-grid .g-col-lg-20{grid-column:auto/span 20}.panel-grid .g-col-lg-21{grid-column:auto/span 21}.panel-grid .g-col-lg-22{grid-column:auto/span 22}.panel-grid .g-col-lg-23{grid-column:auto/span 23}.panel-grid .g-col-lg-24{grid-column:auto/span 24}.panel-grid .g-start-lg-1{grid-column-start:1}.panel-grid .g-start-lg-2{grid-column-start:2}.panel-grid .g-start-lg-3{grid-column-start:3}.panel-grid .g-start-lg-4{grid-column-start:4}.panel-grid .g-start-lg-5{grid-column-start:5}.panel-grid .g-start-lg-6{grid-column-start:6}.panel-grid .g-start-lg-7{grid-column-start:7}.panel-grid .g-start-lg-8{grid-column-start:8}.panel-grid .g-start-lg-9{grid-column-start:9}.panel-grid .g-start-lg-10{grid-column-start:10}.panel-grid .g-start-lg-11{grid-column-start:11}.panel-grid .g-start-lg-12{grid-column-start:12}.panel-grid .g-start-lg-13{grid-column-start:13}.panel-grid .g-start-lg-14{grid-column-start:14}.panel-grid .g-start-lg-15{grid-column-start:15}.panel-grid .g-start-lg-16{grid-column-start:16}.panel-grid .g-start-lg-17{grid-column-start:17}.panel-grid .g-start-lg-18{grid-column-start:18}.panel-grid .g-start-lg-19{grid-column-start:19}.panel-grid .g-start-lg-20{grid-column-start:20}.panel-grid .g-start-lg-21{grid-column-start:21}.panel-grid .g-start-lg-22{grid-column-start:22}.panel-grid .g-start-lg-23{grid-column-start:23}}@media(min-width: 1200px){.panel-grid .g-col-xl-1{grid-column:auto/span 1}.panel-grid .g-col-xl-2{grid-column:auto/span 2}.panel-grid .g-col-xl-3{grid-column:auto/span 3}.panel-grid .g-col-xl-4{grid-column:auto/span 4}.panel-grid .g-col-xl-5{grid-column:auto/span 5}.panel-grid .g-col-xl-6{grid-column:auto/span 6}.panel-grid .g-col-xl-7{grid-column:auto/span 7}.panel-grid .g-col-xl-8{grid-column:auto/span 8}.panel-grid .g-col-xl-9{grid-column:auto/span 9}.panel-grid .g-col-xl-10{grid-column:auto/span 10}.panel-grid .g-col-xl-11{grid-column:auto/span 11}.panel-grid .g-col-xl-12{grid-column:auto/span 12}.panel-grid .g-col-xl-13{grid-column:auto/span 13}.panel-grid .g-col-xl-14{grid-column:auto/span 14}.panel-grid .g-col-xl-15{grid-column:auto/span 15}.panel-grid .g-col-xl-16{grid-column:auto/span 16}.panel-grid .g-col-xl-17{grid-column:auto/span 17}.panel-grid .g-col-xl-18{grid-column:auto/span 18}.panel-grid .g-col-xl-19{grid-column:auto/span 19}.panel-grid .g-col-xl-20{grid-column:auto/span 20}.panel-grid .g-col-xl-21{grid-column:auto/span 21}.panel-grid .g-col-xl-22{grid-column:auto/span 22}.panel-grid .g-col-xl-23{grid-column:auto/span 23}.panel-grid .g-col-xl-24{grid-column:auto/span 24}.panel-grid .g-start-xl-1{grid-column-start:1}.panel-grid .g-start-xl-2{grid-column-start:2}.panel-grid .g-start-xl-3{grid-column-start:3}.panel-grid .g-start-xl-4{grid-column-start:4}.panel-grid .g-start-xl-5{grid-column-start:5}.panel-grid .g-start-xl-6{grid-column-start:6}.panel-grid .g-start-xl-7{grid-column-start:7}.panel-grid .g-start-xl-8{grid-column-start:8}.panel-grid .g-start-xl-9{grid-column-start:9}.panel-grid .g-start-xl-10{grid-column-start:10}.panel-grid .g-start-xl-11{grid-column-start:11}.panel-grid .g-start-xl-12{grid-column-start:12}.panel-grid .g-start-xl-13{grid-column-start:13}.panel-grid .g-start-xl-14{grid-column-start:14}.panel-grid .g-start-xl-15{grid-column-start:15}.panel-grid .g-start-xl-16{grid-column-start:16}.panel-grid .g-start-xl-17{grid-column-start:17}.panel-grid .g-start-xl-18{grid-column-start:18}.panel-grid .g-start-xl-19{grid-column-start:19}.panel-grid .g-start-xl-20{grid-column-start:20}.panel-grid .g-start-xl-21{grid-column-start:21}.panel-grid .g-start-xl-22{grid-column-start:22}.panel-grid .g-start-xl-23{grid-column-start:23}}@media(min-width: 1400px){.panel-grid .g-col-xxl-1{grid-column:auto/span 1}.panel-grid .g-col-xxl-2{grid-column:auto/span 2}.panel-grid .g-col-xxl-3{grid-column:auto/span 3}.panel-grid .g-col-xxl-4{grid-column:auto/span 4}.panel-grid .g-col-xxl-5{grid-column:auto/span 5}.panel-grid .g-col-xxl-6{grid-column:auto/span 6}.panel-grid .g-col-xxl-7{grid-column:auto/span 7}.panel-grid .g-col-xxl-8{grid-column:auto/span 8}.panel-grid .g-col-xxl-9{grid-column:auto/span 9}.panel-grid .g-col-xxl-10{grid-column:auto/span 10}.panel-grid .g-col-xxl-11{grid-column:auto/span 11}.panel-grid .g-col-xxl-12{grid-column:auto/span 12}.panel-grid .g-col-xxl-13{grid-column:auto/span 13}.panel-grid .g-col-xxl-14{grid-column:auto/span 14}.panel-grid .g-col-xxl-15{grid-column:auto/span 15}.panel-grid .g-col-xxl-16{grid-column:auto/span 16}.panel-grid .g-col-xxl-17{grid-column:auto/span 17}.panel-grid .g-col-xxl-18{grid-column:auto/span 18}.panel-grid .g-col-xxl-19{grid-column:auto/span 19}.panel-grid .g-col-xxl-20{grid-column:auto/span 20}.panel-grid .g-col-xxl-21{grid-column:auto/span 21}.panel-grid .g-col-xxl-22{grid-column:auto/span 22}.panel-grid .g-col-xxl-23{grid-column:auto/span 23}.panel-grid .g-col-xxl-24{grid-column:auto/span 24}.panel-grid .g-start-xxl-1{grid-column-start:1}.panel-grid .g-start-xxl-2{grid-column-start:2}.panel-grid .g-start-xxl-3{grid-column-start:3}.panel-grid .g-start-xxl-4{grid-column-start:4}.panel-grid .g-start-xxl-5{grid-column-start:5}.panel-grid .g-start-xxl-6{grid-column-start:6}.panel-grid .g-start-xxl-7{grid-column-start:7}.panel-grid .g-start-xxl-8{grid-column-start:8}.panel-grid .g-start-xxl-9{grid-column-start:9}.panel-grid .g-start-xxl-10{grid-column-start:10}.panel-grid .g-start-xxl-11{grid-column-start:11}.panel-grid .g-start-xxl-12{grid-column-start:12}.panel-grid .g-start-xxl-13{grid-column-start:13}.panel-grid .g-start-xxl-14{grid-column-start:14}.panel-grid .g-start-xxl-15{grid-column-start:15}.panel-grid .g-start-xxl-16{grid-column-start:16}.panel-grid .g-start-xxl-17{grid-column-start:17}.panel-grid .g-start-xxl-18{grid-column-start:18}.panel-grid .g-start-xxl-19{grid-column-start:19}.panel-grid .g-start-xxl-20{grid-column-start:20}.panel-grid .g-start-xxl-21{grid-column-start:21}.panel-grid .g-start-xxl-22{grid-column-start:22}.panel-grid .g-start-xxl-23{grid-column-start:23}}main{margin-top:1em;margin-bottom:1em}h1,.h1,h2,.h2{opacity:.9;margin-top:2rem;margin-bottom:1rem;font-weight:600}h1.title,.title.h1{margin-top:0}h2,.h2{border-bottom:1px solid #dee2e6;padding-bottom:.5rem}h3,.h3{font-weight:600}h3,.h3,h4,.h4{opacity:.9;margin-top:1.5rem}h5,.h5,h6,.h6{opacity:.9}.header-section-number{color:#bfbfbf}.nav-link.active .header-section-number{color:inherit}mark,.mark{padding:0em}.panel-caption,caption,.figure-caption{font-size:.9rem}.panel-caption,.figure-caption,figcaption{color:#bfbfbf}.table-caption,caption{color:#fff}.quarto-layout-cell[data-ref-parent] caption{color:#bfbfbf}.column-margin figcaption,.margin-caption,div.aside,aside,.column-margin{color:#bfbfbf;font-size:.825rem}.panel-caption.margin-caption{text-align:inherit}.column-margin.column-container p{margin-bottom:0}.column-margin.column-container>*:not(.collapse){padding-top:.5em;padding-bottom:.5em;display:block}.column-margin.column-container>*.collapse:not(.show){display:none}@media(min-width: 768px){.column-margin.column-container .callout-margin-content:first-child{margin-top:4.5em}.column-margin.column-container .callout-margin-content-simple:first-child{margin-top:3.5em}}.margin-caption>*{padding-top:.5em;padding-bottom:.5em}@media(max-width: 767.98px){.quarto-layout-row{flex-direction:column}}.nav-tabs .nav-item{margin-top:1px;cursor:pointer}.tab-content{margin-top:0px;border-left:#dee2e6 1px solid;border-right:#dee2e6 1px solid;border-bottom:#dee2e6 1px solid;margin-left:0;padding:1em;margin-bottom:1em}@media(max-width: 767.98px){.layout-sidebar{margin-left:0;margin-right:0}}.panel-sidebar,.panel-sidebar .form-control,.panel-input,.panel-input .form-control,.selectize-dropdown{font-size:.9rem}.panel-sidebar .form-control,.panel-input .form-control{padding-top:.1rem}.tab-pane div.sourceCode{margin-top:0px}.tab-pane>p{padding-top:1em}.tab-content>.tab-pane:not(.active){display:none !important}div.sourceCode{background-color:rgba(233,236,239,.2);border:1px solid rgba(233,236,239,.2);border-radius:.25rem}pre.sourceCode{background-color:rgba(0,0,0,0)}pre.sourceCode{border:none;font-size:.875em;overflow:visible !important;padding:.4em}.callout pre.sourceCode{padding-left:0}div.sourceCode{overflow-y:hidden}.callout div.sourceCode{margin-left:initial}.blockquote{font-size:inherit;padding-left:1rem;padding-right:1.5rem;color:#bfbfbf}.blockquote h1:first-child,.blockquote .h1:first-child,.blockquote h2:first-child,.blockquote .h2:first-child,.blockquote h3:first-child,.blockquote .h3:first-child,.blockquote h4:first-child,.blockquote .h4:first-child,.blockquote h5:first-child,.blockquote .h5:first-child{margin-top:0}pre{background-color:initial;padding:initial;border:initial}p code:not(.sourceCode),li code:not(.sourceCode),td code:not(.sourceCode){background-color:#212121;padding:.2em}nav p code:not(.sourceCode),nav li code:not(.sourceCode),nav td code:not(.sourceCode){background-color:rgba(0,0,0,0);padding:0}td code:not(.sourceCode){white-space:pre-wrap}#quarto-embedded-source-code-modal>.modal-dialog{max-width:1000px;padding-left:1.75rem;padding-right:1.75rem}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body{padding:0}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body div.sourceCode{margin:0;padding:.2rem .2rem;border-radius:0px;border:none}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-header{padding:.7rem}.code-tools-button{font-size:1rem;padding:.15rem .15rem;margin-left:5px;color:#6c757d;background-color:rgba(0,0,0,0);transition:initial;cursor:pointer}.code-tools-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}.code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}.sidebar{will-change:top;transition:top 200ms linear;position:sticky;overflow-y:auto;padding-top:1.2em;max-height:100vh}.sidebar.toc-left,.sidebar.margin-sidebar{top:0px;padding-top:1em}.sidebar.toc-left>*,.sidebar.margin-sidebar>*{padding-top:.5em}.sidebar.quarto-banner-title-block-sidebar>*{padding-top:1.65em}figure .quarto-notebook-link{margin-top:.5em}.quarto-notebook-link{font-size:.75em;color:#6c757d;margin-bottom:1em;text-decoration:none;display:block}.quarto-notebook-link:hover{text-decoration:underline;color:#75aadb}.quarto-notebook-link::before{display:inline-block;height:.75rem;width:.75rem;margin-bottom:0em;margin-right:.25em;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:.75rem .75rem}.quarto-alternate-notebooks i.bi,.quarto-alternate-formats i.bi{margin-right:.4em}.quarto-notebook .cell-container{display:flex}.quarto-notebook .cell-container .cell{flex-grow:4}.quarto-notebook .cell-container .cell-decorator{padding-top:1.5em;padding-right:1em;text-align:right}.quarto-notebook h2,.quarto-notebook .h2{border-bottom:none}.sidebar .quarto-alternate-formats a,.sidebar .quarto-alternate-notebooks a{text-decoration:none}.sidebar .quarto-alternate-formats a:hover,.sidebar .quarto-alternate-notebooks a:hover{color:#75aadb}.sidebar .quarto-alternate-notebooks h2,.sidebar .quarto-alternate-notebooks .h2,.sidebar .quarto-alternate-formats h2,.sidebar .quarto-alternate-formats .h2,.sidebar nav[role=doc-toc]>h2,.sidebar nav[role=doc-toc]>.h2{font-size:.875rem;font-weight:400;margin-bottom:.5rem;margin-top:.3rem;font-family:inherit;border-bottom:0;padding-bottom:0;padding-top:0px}.sidebar .quarto-alternate-notebooks h2,.sidebar .quarto-alternate-notebooks .h2,.sidebar .quarto-alternate-formats h2,.sidebar .quarto-alternate-formats .h2{margin-top:1rem}.sidebar nav[role=doc-toc]>ul a{border-left:1px solid #e9ecef;padding-left:.6rem}.sidebar .quarto-alternate-notebooks h2>ul a,.sidebar .quarto-alternate-notebooks .h2>ul a,.sidebar .quarto-alternate-formats h2>ul a,.sidebar .quarto-alternate-formats .h2>ul a{border-left:none;padding-left:.6rem}.sidebar .quarto-alternate-notebooks ul a:empty,.sidebar .quarto-alternate-formats ul a:empty,.sidebar nav[role=doc-toc]>ul a:empty{display:none}.sidebar .quarto-alternate-notebooks ul,.sidebar .quarto-alternate-formats ul,.sidebar nav[role=doc-toc] ul{padding-left:0;list-style:none;font-size:.875rem;font-weight:300}.sidebar .quarto-alternate-notebooks ul li a,.sidebar .quarto-alternate-formats ul li a,.sidebar nav[role=doc-toc]>ul li a{line-height:1.1rem;padding-bottom:.2rem;padding-top:.2rem;color:inherit}.sidebar nav[role=doc-toc] ul>li>ul>li>a{padding-left:1.2em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>a{padding-left:2.4em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>a{padding-left:3.6em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:4.8em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:6em}.sidebar nav[role=doc-toc] ul>li>a.active,.sidebar nav[role=doc-toc] ul>li>ul>li>a.active{border-left:1px solid #75aadb;color:#75aadb !important}.sidebar nav[role=doc-toc] ul>li>a:hover,.sidebar nav[role=doc-toc] ul>li>ul>li>a:hover{color:#75aadb !important}kbd,.kbd{color:#fff;background-color:#f8f9fa;border:1px solid;border-radius:5px;border-color:#dee2e6}div.hanging-indent{margin-left:1em;text-indent:-1em}.citation a,.footnote-ref{text-decoration:none}.footnotes ol{padding-left:1em}.tippy-content>*{margin-bottom:.7em}.tippy-content>*:last-child{margin-bottom:0}.table a{word-break:break-word}.table>thead{border-top-width:1px;border-top-color:#dee2e6;border-bottom:1px solid #fff}.callout{margin-top:1.25rem;margin-bottom:1.25rem;border-radius:.25rem;overflow-wrap:break-word}.callout .callout-title-container{overflow-wrap:anywhere}.callout.callout-style-simple{padding:.4em .7em;border-left:5px solid;border-right:1px solid #dee2e6;border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.callout.callout-style-default{border-left:5px solid;border-right:1px solid #dee2e6;border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.callout .callout-body-container{flex-grow:1}.callout.callout-style-simple .callout-body{font-size:.9rem;font-weight:400}.callout.callout-style-default .callout-body{font-size:.9rem;font-weight:400}.callout.callout-titled .callout-body{margin-top:.2em}.callout:not(.no-icon).callout-titled.callout-style-simple .callout-body{padding-left:1.6em}.callout.callout-titled>.callout-header{padding-top:.2em;margin-bottom:-0.2em}.callout.callout-style-simple>div.callout-header{border-bottom:none;font-size:.9rem;font-weight:600;opacity:75%}.callout.callout-style-default>div.callout-header{border-bottom:none;font-weight:600;opacity:85%;font-size:.9rem;padding-left:.5em;padding-right:.5em}.callout.callout-style-default div.callout-body{padding-left:.5em;padding-right:.5em}.callout.callout-style-default div.callout-body>:first-child{margin-top:.5em}.callout>div.callout-header[data-bs-toggle=collapse]{cursor:pointer}.callout.callout-style-default .callout-header[aria-expanded=false],.callout.callout-style-default .callout-header[aria-expanded=true]{padding-top:0px;margin-bottom:0px;align-items:center}.callout.callout-titled .callout-body>:last-child:not(.sourceCode),.callout.callout-titled .callout-body>div>:last-child:not(.sourceCode){margin-bottom:.5rem}.callout:not(.callout-titled) .callout-body>:first-child,.callout:not(.callout-titled) .callout-body>div>:first-child{margin-top:.25rem}.callout:not(.callout-titled) .callout-body>:last-child,.callout:not(.callout-titled) .callout-body>div>:last-child{margin-bottom:.2rem}.callout.callout-style-simple .callout-icon::before,.callout.callout-style-simple .callout-toggle::before{height:1rem;width:1rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.callout.callout-style-default .callout-icon::before,.callout.callout-style-default .callout-toggle::before{height:.9rem;width:.9rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:.9rem .9rem}.callout.callout-style-default .callout-toggle::before{margin-top:5px}.callout .callout-btn-toggle .callout-toggle::before{transition:transform .2s linear}.callout .callout-header[aria-expanded=false] .callout-toggle::before{transform:rotate(-90deg)}.callout .callout-header[aria-expanded=true] .callout-toggle::before{transform:none}.callout.callout-style-simple:not(.no-icon) div.callout-icon-container{padding-top:.2em;padding-right:.55em}.callout.callout-style-default:not(.no-icon) div.callout-icon-container{padding-top:.1em;padding-right:.35em}.callout.callout-style-default:not(.no-icon) div.callout-title-container{margin-top:-1px}.callout.callout-style-default.callout-caution:not(.no-icon) div.callout-icon-container{padding-top:.3em;padding-right:.35em}.callout>.callout-body>.callout-icon-container>.no-icon,.callout>.callout-header>.callout-icon-container>.no-icon{display:none}div.callout.callout{border-left-color:#6c757d}div.callout.callout-style-default>.callout-header{background-color:#6c757d}div.callout-note.callout{border-left-color:#2780e3}div.callout-note.callout-style-default>.callout-header{background-color:#0c2644}div.callout-note:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-tip.callout{border-left-color:#3fb618}div.callout-tip.callout-style-default>.callout-header{background-color:#133707}div.callout-tip:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-warning.callout{border-left-color:#ff7518}div.callout-warning.callout-style-default>.callout-header{background-color:#4d2307}div.callout-warning:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-caution.callout{border-left-color:#f0ad4e}div.callout-caution.callout-style-default>.callout-header{background-color:#483417}div.callout-caution:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-important.callout{border-left-color:#ff0039}div.callout-important.callout-style-default>.callout-header{background-color:#4d0011}div.callout-important:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important .callout-toggle::before{background-image:url('data:image/svg+xml,')}.quarto-toggle-container{display:flex;align-items:center}.quarto-reader-toggle .bi::before,.quarto-color-scheme-toggle .bi::before{display:inline-block;height:1rem;width:1rem;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.sidebar-navigation{padding-left:20px}.navbar .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.quarto-sidebar-toggle{border-color:#dee2e6;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;border-style:solid;border-width:1px;overflow:hidden;border-top-width:0px;padding-top:0px !important}.quarto-sidebar-toggle-title{cursor:pointer;padding-bottom:2px;margin-left:.25em;text-align:center;font-weight:400;font-size:.775em}#quarto-content .quarto-sidebar-toggle{background:#1d1d1d}#quarto-content .quarto-sidebar-toggle-title{color:#fff}.quarto-sidebar-toggle-icon{color:#dee2e6;margin-right:.5em;float:right;transition:transform .2s ease}.quarto-sidebar-toggle-icon::before{padding-top:5px}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-icon{transform:rotate(-180deg)}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-title{border-bottom:solid #dee2e6 1px}.quarto-sidebar-toggle-contents{background-color:#181818;padding-right:10px;padding-left:10px;margin-top:0px !important;transition:max-height .5s ease}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-contents{padding-top:1em;padding-bottom:10px}.quarto-sidebar-toggle:not(.expanded) .quarto-sidebar-toggle-contents{padding-top:0px !important;padding-bottom:0px}nav[role=doc-toc]{z-index:1020}#quarto-sidebar>*,nav[role=doc-toc]>*{transition:opacity .1s ease,border .1s ease}#quarto-sidebar.slow>*,nav[role=doc-toc].slow>*{transition:opacity .4s ease,border .4s ease}.quarto-color-scheme-toggle:not(.alternate).top-right .bi::before{background-image:url('data:image/svg+xml,')}.quarto-color-scheme-toggle.alternate.top-right .bi::before{background-image:url('data:image/svg+xml,')}#quarto-appendix.default{border-top:1px solid #dee2e6}#quarto-appendix.default{background-color:#181818;padding-top:1.5em;margin-top:2em;z-index:998}#quarto-appendix.default .quarto-appendix-heading{margin-top:0;line-height:1.4em;font-weight:600;opacity:.9;border-bottom:none;margin-bottom:0}#quarto-appendix.default .footnotes ol,#quarto-appendix.default .footnotes ol li>p:last-of-type,#quarto-appendix.default .quarto-appendix-contents>p:last-of-type{margin-bottom:0}#quarto-appendix.default .quarto-appendix-secondary-label{margin-bottom:.4em}#quarto-appendix.default .quarto-appendix-bibtex{font-size:.7em;padding:1em;border:solid 1px #dee2e6;margin-bottom:1em}#quarto-appendix.default .quarto-appendix-bibtex code.sourceCode{white-space:pre-wrap}#quarto-appendix.default .quarto-appendix-citeas{font-size:.9em;padding:1em;border:solid 1px #dee2e6;margin-bottom:1em}#quarto-appendix.default .quarto-appendix-heading{font-size:1em !important}#quarto-appendix.default *[role=doc-endnotes]>ol,#quarto-appendix.default .quarto-appendix-contents>*:not(h2):not(.h2){font-size:.9em}#quarto-appendix.default section{padding-bottom:1.5em}#quarto-appendix.default section *[role=doc-endnotes],#quarto-appendix.default section>*:not(a){opacity:.9;word-wrap:break-word}.btn.btn-quarto,div.cell-output-display .btn-quarto{color:#cbcccc;background-color:#373a3c;border-color:#373a3c}.btn.btn-quarto:hover,div.cell-output-display .btn-quarto:hover{color:#cbcccc;background-color:#555859;border-color:#4b4e50}.btn-check:focus+.btn.btn-quarto,.btn.btn-quarto:focus,.btn-check:focus+div.cell-output-display .btn-quarto,div.cell-output-display .btn-quarto:focus{color:#cbcccc;background-color:#555859;border-color:#4b4e50;box-shadow:0 0 0 .25rem rgba(77,80,82,.5)}.btn-check:checked+.btn.btn-quarto,.btn-check:active+.btn.btn-quarto,.btn.btn-quarto:active,.btn.btn-quarto.active,.show>.btn.btn-quarto.dropdown-toggle,.btn-check:checked+div.cell-output-display .btn-quarto,.btn-check:active+div.cell-output-display .btn-quarto,div.cell-output-display .btn-quarto:active,div.cell-output-display .btn-quarto.active,.show>div.cell-output-display .btn-quarto.dropdown-toggle{color:#fff;background-color:#5f6163;border-color:#4b4e50}.btn-check:checked+.btn.btn-quarto:focus,.btn-check:active+.btn.btn-quarto:focus,.btn.btn-quarto:active:focus,.btn.btn-quarto.active:focus,.show>.btn.btn-quarto.dropdown-toggle:focus,.btn-check:checked+div.cell-output-display .btn-quarto:focus,.btn-check:active+div.cell-output-display .btn-quarto:focus,div.cell-output-display .btn-quarto:active:focus,div.cell-output-display .btn-quarto.active:focus,.show>div.cell-output-display .btn-quarto.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(77,80,82,.5)}.btn.btn-quarto:disabled,.btn.btn-quarto.disabled,div.cell-output-display .btn-quarto:disabled,div.cell-output-display .btn-quarto.disabled{color:#fff;background-color:#373a3c;border-color:#373a3c}nav.quarto-secondary-nav.color-navbar{background-color:#303030;color:#bdbdbd}nav.quarto-secondary-nav.color-navbar h1,nav.quarto-secondary-nav.color-navbar .h1,nav.quarto-secondary-nav.color-navbar .quarto-btn-toggle{color:#bdbdbd}@media(max-width: 991.98px){body.nav-sidebar .quarto-title-banner{margin-bottom:0;padding-bottom:0}body.nav-sidebar #title-block-header{margin-block-end:0}}p.subtitle{margin-top:.25em;margin-bottom:.5em}code a:any-link{color:inherit;text-decoration-color:#6c757d}/*! dark */div.observablehq table thead tr th{background-color:var(--bs-body-bg)}input,button,select,optgroup,textarea{background-color:var(--bs-body-bg)}.code-annotated .code-copy-button{margin-right:1.25em;margin-top:0;padding-bottom:0;padding-top:3px}.code-annotation-gutter-bg{background-color:#181818}.code-annotation-gutter{background-color:rgba(233,236,239,.2)}.code-annotation-gutter,.code-annotation-gutter-bg{height:100%;width:calc(20px + .5em);position:absolute;top:0;right:0}dl.code-annotation-container-grid dt{margin-right:1em;margin-top:.25rem}dl.code-annotation-container-grid dt{font-family:var(--bs-font-monospace);color:#e6e6e6;border:solid #e6e6e6 1px;border-radius:50%;height:22px;width:22px;line-height:22px;font-size:11px;text-align:center;vertical-align:middle;text-decoration:none}dl.code-annotation-container-grid dt[data-target-cell]{cursor:pointer}dl.code-annotation-container-grid dt[data-target-cell].code-annotation-active{color:#181818;border:solid #aaa 1px;background-color:#aaa}pre.code-annotation-code{padding-top:0;padding-bottom:0}pre.code-annotation-code code{z-index:3}#code-annotation-line-highlight-gutter{width:100%;border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}#code-annotation-line-highlight{margin-left:-4em;width:calc(100% + 4em);border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}code.sourceCode .code-annotation-anchor.code-annotation-active{background-color:var(--quarto-hl-normal-color, #aaaaaa);border:solid var(--quarto-hl-normal-color, #aaaaaa) 1px;color:#e9ecef;font-weight:bolder}code.sourceCode .code-annotation-anchor{font-family:var(--bs-font-monospace);color:var(--quarto-hl-co-color);border:solid var(--quarto-hl-co-color) 1px;border-radius:50%;height:18px;width:18px;font-size:9px;margin-top:2px}code.sourceCode button.code-annotation-anchor{padding:2px}code.sourceCode a.code-annotation-anchor{line-height:18px;text-align:center;vertical-align:middle;cursor:default;text-decoration:none}@media print{.page-columns .column-screen-inset{grid-column:page-start-inset/page-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset table{background:#181818}.page-columns .column-screen-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset-left table{background:#181818}.page-columns .column-screen-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset-right table{background:#181818}.page-columns .column-screen{grid-column:page-start/page-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen table{background:#181818}.page-columns .column-screen-left{grid-column:page-start/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-left table{background:#181818}.page-columns .column-screen-right{grid-column:body-content-start/page-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-right table{background:#181818}.page-columns .column-screen-inset-shaded{grid-column:page-start-inset/page-end-inset;padding:1em;background:#525252;z-index:998;transform:translate3d(0, 0, 0);margin-bottom:1em}}.quarto-video{margin-bottom:1em}.table>thead{border-top-width:0}.table>:not(caption)>*:not(:last-child)>*{border-bottom-color:#fff;border-bottom-style:solid;border-bottom-width:1px}.table>:not(:first-child){border-top:1px solid #fff;border-bottom:1px solid inherit}.table tbody{border-bottom-color:#fff}a.external:after{display:inline-block;height:.75rem;width:.75rem;margin-bottom:.15em;margin-left:.25em;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:.75rem .75rem}div.sourceCode code a.external:after{content:none}a.external:after:hover{cursor:pointer}.quarto-ext-icon{display:inline-block;font-size:.75em;padding-left:.3em}.code-with-filename .code-with-filename-file{margin-bottom:0;padding-bottom:2px;padding-top:2px;padding-left:.7em;border:var(--quarto-border-width) solid var(--quarto-border-color);border-radius:var(--quarto-border-radius);border-bottom:0;border-bottom-left-radius:0%;border-bottom-right-radius:0%}.code-with-filename div.sourceCode,.reveal .code-with-filename div.sourceCode{margin-top:0;border-top-left-radius:0%;border-top-right-radius:0%}.code-with-filename .code-with-filename-file pre{margin-bottom:0}.code-with-filename .code-with-filename-file,.code-with-filename .code-with-filename-file pre{background-color:rgba(219,219,219,.8)}.quarto-dark .code-with-filename .code-with-filename-file,.quarto-dark .code-with-filename .code-with-filename-file pre{background-color:#555}.code-with-filename .code-with-filename-file strong{font-weight:400}body{-webkit-font-smoothing:antialiased}.badge.bg-light{color:#373a3c}.progress .progress-bar{font-size:8px;line-height:8px}.layout-example{background:#495057}.quarto-title-banner{margin-bottom:1em;color:#bdbdbd;background:#303030}.quarto-title-banner .code-tools-button{color:#8a8a8a}.quarto-title-banner .code-tools-button:hover{color:#bdbdbd}.quarto-title-banner .code-tools-button>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .quarto-title .title{font-weight:600}.quarto-title-banner .quarto-categories{margin-top:.75em}@media(min-width: 992px){.quarto-title-banner{padding-top:2.5em;padding-bottom:2.5em}}@media(max-width: 991.98px){.quarto-title-banner{padding-top:1em;padding-bottom:1em}}main.quarto-banner-title-block>section:first-child>h2,main.quarto-banner-title-block>section:first-child>.h2,main.quarto-banner-title-block>section:first-child>h3,main.quarto-banner-title-block>section:first-child>.h3,main.quarto-banner-title-block>section:first-child>h4,main.quarto-banner-title-block>section:first-child>.h4{margin-top:0}.quarto-title .quarto-categories{display:flex;flex-wrap:wrap;row-gap:.5em;column-gap:.4em;padding-bottom:.5em;margin-top:.75em}.quarto-title .quarto-categories .quarto-category{padding:.25em .75em;font-size:.65em;text-transform:uppercase;border:solid 1px;border-radius:.25rem;opacity:.6}.quarto-title .quarto-categories .quarto-category a{color:inherit}#title-block-header.quarto-title-block.default .quarto-title-meta{display:grid;grid-template-columns:repeat(2, 1fr)}#title-block-header.quarto-title-block.default .quarto-title .title{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-author-orcid img{margin-top:-5px}#title-block-header.quarto-title-block.default .quarto-description p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p,#title-block-header.quarto-title-block.default .quarto-title-authors p,#title-block-header.quarto-title-block.default .quarto-title-affiliations p{margin-bottom:.1em}#title-block-header.quarto-title-block.default .quarto-title-meta-heading{text-transform:uppercase;margin-top:1em;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-contents{font-size:.9em}#title-block-header.quarto-title-block.default .quarto-title-meta-contents a{color:#fff}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p.affiliation:last-of-type{margin-bottom:.7em}#title-block-header.quarto-title-block.default p.affiliation{margin-bottom:.1em}#title-block-header.quarto-title-block.default .description,#title-block-header.quarto-title-block.default .abstract{margin-top:0}#title-block-header.quarto-title-block.default .description>p,#title-block-header.quarto-title-block.default .abstract>p{font-size:.9em}#title-block-header.quarto-title-block.default .description>p:last-of-type,#title-block-header.quarto-title-block.default .abstract>p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .description .abstract-title,#title-block-header.quarto-title-block.default .abstract .abstract-title{margin-top:1em;text-transform:uppercase;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-author{display:grid;grid-template-columns:1fr 1fr}.quarto-title-tools-only{display:flex;justify-content:right}/*# sourceMappingURL=945575463e70190d99eb671cb8520afc.css.map */ diff --git a/pr-preview/pr-68/site_libs/bootstrap/bootstrap-icons.css b/pr-preview/pr-68/site_libs/bootstrap/bootstrap-icons.css new file mode 100644 index 0000000..94f1940 --- /dev/null +++ b/pr-preview/pr-68/site_libs/bootstrap/bootstrap-icons.css @@ -0,0 +1,2018 @@ +@font-face { + font-display: block; + font-family: "bootstrap-icons"; + src: +url("./bootstrap-icons.woff?2ab2cbbe07fcebb53bdaa7313bb290f2") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-1::before { content: "\f2a5"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-1::before { content: "\f68a"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-1::before { content: "\f68d"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-1::before { content: "\f690"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-1::before { content: "\f695"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-1::before { content: "\f698"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-mortorboard-fill::before { content: "\f6a2"; } +.bi-mortorboard::before { content: "\f6a3"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-1::before { content: "\f6b6"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash-1::before { content: "\f6c2"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport-1::before { content: "\f6e0"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-ssd-fill::before { content: "\f6ed"; } +.bi-ssd::before { content: "\f6ee"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt-1::before { content: "\f759"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls-1::before { content: "\f769"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } +.bi-1-circle-1::before { content: "\f794"; } +.bi-1-circle-fill-1::before { content: "\f795"; } +.bi-1-circle-fill::before { content: "\f796"; } +.bi-1-circle::before { content: "\f797"; } +.bi-1-square-fill::before { content: "\f798"; } +.bi-1-square::before { content: "\f799"; } +.bi-2-circle-1::before { content: "\f79a"; } +.bi-2-circle-fill-1::before { content: "\f79b"; } +.bi-2-circle-fill::before { content: "\f79c"; } +.bi-2-circle::before { content: "\f79d"; } +.bi-2-square-fill::before { content: "\f79e"; } +.bi-2-square::before { content: "\f79f"; } +.bi-3-circle-1::before { content: "\f7a0"; } +.bi-3-circle-fill-1::before { content: "\f7a1"; } +.bi-3-circle-fill::before { content: "\f7a2"; } +.bi-3-circle::before { content: "\f7a3"; } +.bi-3-square-fill::before { content: "\f7a4"; } +.bi-3-square::before { content: "\f7a5"; } +.bi-4-circle-1::before { content: "\f7a6"; } +.bi-4-circle-fill-1::before { content: "\f7a7"; } +.bi-4-circle-fill::before { content: "\f7a8"; } +.bi-4-circle::before { content: "\f7a9"; } +.bi-4-square-fill::before { content: "\f7aa"; } +.bi-4-square::before { content: "\f7ab"; } +.bi-5-circle-1::before { content: "\f7ac"; } +.bi-5-circle-fill-1::before { content: "\f7ad"; } +.bi-5-circle-fill::before { content: "\f7ae"; } +.bi-5-circle::before { content: "\f7af"; } +.bi-5-square-fill::before { content: "\f7b0"; } +.bi-5-square::before { content: "\f7b1"; } +.bi-6-circle-1::before { content: "\f7b2"; } +.bi-6-circle-fill-1::before { content: "\f7b3"; } +.bi-6-circle-fill::before { content: "\f7b4"; } +.bi-6-circle::before { content: "\f7b5"; } +.bi-6-square-fill::before { content: "\f7b6"; } +.bi-6-square::before { content: "\f7b7"; } +.bi-7-circle-1::before { content: "\f7b8"; } +.bi-7-circle-fill-1::before { content: "\f7b9"; } +.bi-7-circle-fill::before { content: "\f7ba"; } +.bi-7-circle::before { content: "\f7bb"; } +.bi-7-square-fill::before { content: "\f7bc"; } +.bi-7-square::before { content: "\f7bd"; } +.bi-8-circle-1::before { content: "\f7be"; } +.bi-8-circle-fill-1::before { content: "\f7bf"; } +.bi-8-circle-fill::before { content: "\f7c0"; } +.bi-8-circle::before { content: "\f7c1"; } +.bi-8-square-fill::before { content: "\f7c2"; } +.bi-8-square::before { content: "\f7c3"; } +.bi-9-circle-1::before { content: "\f7c4"; } +.bi-9-circle-fill-1::before { content: "\f7c5"; } +.bi-9-circle-fill::before { content: "\f7c6"; } +.bi-9-circle::before { content: "\f7c7"; } +.bi-9-square-fill::before { content: "\f7c8"; } +.bi-9-square::before { content: "\f7c9"; } +.bi-airplane-engines-fill::before { content: "\f7ca"; } +.bi-airplane-engines::before { content: "\f7cb"; } +.bi-airplane-fill::before { content: "\f7cc"; } +.bi-airplane::before { content: "\f7cd"; } +.bi-alexa::before { content: "\f7ce"; } +.bi-alipay::before { content: "\f7cf"; } +.bi-android::before { content: "\f7d0"; } +.bi-android2::before { content: "\f7d1"; } +.bi-box-fill::before { content: "\f7d2"; } +.bi-box-seam-fill::before { content: "\f7d3"; } +.bi-browser-chrome::before { content: "\f7d4"; } +.bi-browser-edge::before { content: "\f7d5"; } +.bi-browser-firefox::before { content: "\f7d6"; } +.bi-browser-safari::before { content: "\f7d7"; } +.bi-c-circle-1::before { content: "\f7d8"; } +.bi-c-circle-fill-1::before { content: "\f7d9"; } +.bi-c-circle-fill::before { content: "\f7da"; } +.bi-c-circle::before { content: "\f7db"; } +.bi-c-square-fill::before { content: "\f7dc"; } +.bi-c-square::before { content: "\f7dd"; } +.bi-capsule-pill::before { content: "\f7de"; } +.bi-capsule::before { content: "\f7df"; } +.bi-car-front-fill::before { content: "\f7e0"; } +.bi-car-front::before { content: "\f7e1"; } +.bi-cassette-fill::before { content: "\f7e2"; } +.bi-cassette::before { content: "\f7e3"; } +.bi-cc-circle-1::before { content: "\f7e4"; } +.bi-cc-circle-fill-1::before { content: "\f7e5"; } +.bi-cc-circle-fill::before { content: "\f7e6"; } +.bi-cc-circle::before { content: "\f7e7"; } +.bi-cc-square-fill::before { content: "\f7e8"; } +.bi-cc-square::before { content: "\f7e9"; } +.bi-cup-hot-fill::before { content: "\f7ea"; } +.bi-cup-hot::before { content: "\f7eb"; } +.bi-currency-rupee::before { content: "\f7ec"; } +.bi-dropbox::before { content: "\f7ed"; } +.bi-escape::before { content: "\f7ee"; } +.bi-fast-forward-btn-fill::before { content: "\f7ef"; } +.bi-fast-forward-btn::before { content: "\f7f0"; } +.bi-fast-forward-circle-fill::before { content: "\f7f1"; } +.bi-fast-forward-circle::before { content: "\f7f2"; } +.bi-fast-forward-fill::before { content: "\f7f3"; } +.bi-fast-forward::before { content: "\f7f4"; } +.bi-filetype-sql::before { content: "\f7f5"; } +.bi-fire::before { content: "\f7f6"; } +.bi-google-play::before { content: "\f7f7"; } +.bi-h-circle-1::before { content: "\f7f8"; } +.bi-h-circle-fill-1::before { content: "\f7f9"; } +.bi-h-circle-fill::before { content: "\f7fa"; } +.bi-h-circle::before { content: "\f7fb"; } +.bi-h-square-fill::before { content: "\f7fc"; } +.bi-h-square::before { content: "\f7fd"; } +.bi-indent::before { content: "\f7fe"; } +.bi-lungs-fill::before { content: "\f7ff"; } +.bi-lungs::before { content: "\f800"; } +.bi-microsoft-teams::before { content: "\f801"; } +.bi-p-circle-1::before { content: "\f802"; } +.bi-p-circle-fill-1::before { content: "\f803"; } +.bi-p-circle-fill::before { content: "\f804"; } +.bi-p-circle::before { content: "\f805"; } +.bi-p-square-fill::before { content: "\f806"; } +.bi-p-square::before { content: "\f807"; } +.bi-pass-fill::before { content: "\f808"; } +.bi-pass::before { content: "\f809"; } +.bi-prescription::before { content: "\f80a"; } +.bi-prescription2::before { content: "\f80b"; } +.bi-r-circle-1::before { content: "\f80c"; } +.bi-r-circle-fill-1::before { content: "\f80d"; } +.bi-r-circle-fill::before { content: "\f80e"; } +.bi-r-circle::before { content: "\f80f"; } +.bi-r-square-fill::before { content: "\f810"; } +.bi-r-square::before { content: "\f811"; } +.bi-repeat-1::before { content: "\f812"; } +.bi-repeat::before { content: "\f813"; } +.bi-rewind-btn-fill::before { content: "\f814"; } +.bi-rewind-btn::before { content: "\f815"; } +.bi-rewind-circle-fill::before { content: "\f816"; } +.bi-rewind-circle::before { content: "\f817"; } +.bi-rewind-fill::before { content: "\f818"; } +.bi-rewind::before { content: "\f819"; } +.bi-train-freight-front-fill::before { content: "\f81a"; } +.bi-train-freight-front::before { content: "\f81b"; } +.bi-train-front-fill::before { content: "\f81c"; } +.bi-train-front::before { content: "\f81d"; } +.bi-train-lightrail-front-fill::before { content: "\f81e"; } +.bi-train-lightrail-front::before { content: "\f81f"; } +.bi-truck-front-fill::before { content: "\f820"; } +.bi-truck-front::before { content: "\f821"; } +.bi-ubuntu::before { content: "\f822"; } +.bi-unindent::before { content: "\f823"; } +.bi-unity::before { content: "\f824"; } +.bi-universal-access-circle::before { content: "\f825"; } +.bi-universal-access::before { content: "\f826"; } +.bi-virus::before { content: "\f827"; } +.bi-virus2::before { content: "\f828"; } +.bi-wechat::before { content: "\f829"; } +.bi-yelp::before { content: "\f82a"; } +.bi-sign-stop-fill::before { content: "\f82b"; } +.bi-sign-stop-lights-fill::before { content: "\f82c"; } +.bi-sign-stop-lights::before { content: "\f82d"; } +.bi-sign-stop::before { content: "\f82e"; } +.bi-sign-turn-left-fill::before { content: "\f82f"; } +.bi-sign-turn-left::before { content: "\f830"; } +.bi-sign-turn-right-fill::before { content: "\f831"; } +.bi-sign-turn-right::before { content: "\f832"; } +.bi-sign-turn-slight-left-fill::before { content: "\f833"; } +.bi-sign-turn-slight-left::before { content: "\f834"; } +.bi-sign-turn-slight-right-fill::before { content: "\f835"; } +.bi-sign-turn-slight-right::before { content: "\f836"; } +.bi-sign-yield-fill::before { content: "\f837"; } +.bi-sign-yield::before { content: "\f838"; } +.bi-ev-station-fill::before { content: "\f839"; } +.bi-ev-station::before { content: "\f83a"; } +.bi-fuel-pump-diesel-fill::before { content: "\f83b"; } +.bi-fuel-pump-diesel::before { content: "\f83c"; } +.bi-fuel-pump-fill::before { content: "\f83d"; } +.bi-fuel-pump::before { content: "\f83e"; } +.bi-0-circle-fill::before { content: "\f83f"; } +.bi-0-circle::before { content: "\f840"; } +.bi-0-square-fill::before { content: "\f841"; } +.bi-0-square::before { content: "\f842"; } +.bi-rocket-fill::before { content: "\f843"; } +.bi-rocket-takeoff-fill::before { content: "\f844"; } +.bi-rocket-takeoff::before { content: "\f845"; } +.bi-rocket::before { content: "\f846"; } +.bi-stripe::before { content: "\f847"; } +.bi-subscript::before { content: "\f848"; } +.bi-superscript::before { content: "\f849"; } +.bi-trello::before { content: "\f84a"; } +.bi-envelope-at-fill::before { content: "\f84b"; } +.bi-envelope-at::before { content: "\f84c"; } +.bi-regex::before { content: "\f84d"; } +.bi-text-wrap::before { content: "\f84e"; } +.bi-sign-dead-end-fill::before { content: "\f84f"; } +.bi-sign-dead-end::before { content: "\f850"; } +.bi-sign-do-not-enter-fill::before { content: "\f851"; } +.bi-sign-do-not-enter::before { content: "\f852"; } +.bi-sign-intersection-fill::before { content: "\f853"; } +.bi-sign-intersection-side-fill::before { content: "\f854"; } +.bi-sign-intersection-side::before { content: "\f855"; } +.bi-sign-intersection-t-fill::before { content: "\f856"; } +.bi-sign-intersection-t::before { content: "\f857"; } +.bi-sign-intersection-y-fill::before { content: "\f858"; } +.bi-sign-intersection-y::before { content: "\f859"; } +.bi-sign-intersection::before { content: "\f85a"; } +.bi-sign-merge-left-fill::before { content: "\f85b"; } +.bi-sign-merge-left::before { content: "\f85c"; } +.bi-sign-merge-right-fill::before { content: "\f85d"; } +.bi-sign-merge-right::before { content: "\f85e"; } +.bi-sign-no-left-turn-fill::before { content: "\f85f"; } +.bi-sign-no-left-turn::before { content: "\f860"; } +.bi-sign-no-parking-fill::before { content: "\f861"; } +.bi-sign-no-parking::before { content: "\f862"; } +.bi-sign-no-right-turn-fill::before { content: "\f863"; } +.bi-sign-no-right-turn::before { content: "\f864"; } +.bi-sign-railroad-fill::before { content: "\f865"; } +.bi-sign-railroad::before { content: "\f866"; } +.bi-building-add::before { content: "\f867"; } +.bi-building-check::before { content: "\f868"; } +.bi-building-dash::before { content: "\f869"; } +.bi-building-down::before { content: "\f86a"; } +.bi-building-exclamation::before { content: "\f86b"; } +.bi-building-fill-add::before { content: "\f86c"; } +.bi-building-fill-check::before { content: "\f86d"; } +.bi-building-fill-dash::before { content: "\f86e"; } +.bi-building-fill-down::before { content: "\f86f"; } +.bi-building-fill-exclamation::before { content: "\f870"; } +.bi-building-fill-gear::before { content: "\f871"; } +.bi-building-fill-lock::before { content: "\f872"; } +.bi-building-fill-slash::before { content: "\f873"; } +.bi-building-fill-up::before { content: "\f874"; } +.bi-building-fill-x::before { content: "\f875"; } +.bi-building-fill::before { content: "\f876"; } +.bi-building-gear::before { content: "\f877"; } +.bi-building-lock::before { content: "\f878"; } +.bi-building-slash::before { content: "\f879"; } +.bi-building-up::before { content: "\f87a"; } +.bi-building-x::before { content: "\f87b"; } +.bi-buildings-fill::before { content: "\f87c"; } +.bi-buildings::before { content: "\f87d"; } +.bi-bus-front-fill::before { content: "\f87e"; } +.bi-bus-front::before { content: "\f87f"; } +.bi-ev-front-fill::before { content: "\f880"; } +.bi-ev-front::before { content: "\f881"; } +.bi-globe-americas::before { content: "\f882"; } +.bi-globe-asia-australia::before { content: "\f883"; } +.bi-globe-central-south-asia::before { content: "\f884"; } +.bi-globe-europe-africa::before { content: "\f885"; } +.bi-house-add-fill::before { content: "\f886"; } +.bi-house-add::before { content: "\f887"; } +.bi-house-check-fill::before { content: "\f888"; } +.bi-house-check::before { content: "\f889"; } +.bi-house-dash-fill::before { content: "\f88a"; } +.bi-house-dash::before { content: "\f88b"; } +.bi-house-down-fill::before { content: "\f88c"; } +.bi-house-down::before { content: "\f88d"; } +.bi-house-exclamation-fill::before { content: "\f88e"; } +.bi-house-exclamation::before { content: "\f88f"; } +.bi-house-gear-fill::before { content: "\f890"; } +.bi-house-gear::before { content: "\f891"; } +.bi-house-lock-fill::before { content: "\f892"; } +.bi-house-lock::before { content: "\f893"; } +.bi-house-slash-fill::before { content: "\f894"; } +.bi-house-slash::before { content: "\f895"; } +.bi-house-up-fill::before { content: "\f896"; } +.bi-house-up::before { content: "\f897"; } +.bi-house-x-fill::before { content: "\f898"; } +.bi-house-x::before { content: "\f899"; } +.bi-person-add::before { content: "\f89a"; } +.bi-person-down::before { content: "\f89b"; } +.bi-person-exclamation::before { content: "\f89c"; } +.bi-person-fill-add::before { content: "\f89d"; } +.bi-person-fill-check::before { content: "\f89e"; } +.bi-person-fill-dash::before { content: "\f89f"; } +.bi-person-fill-down::before { content: "\f8a0"; } +.bi-person-fill-exclamation::before { content: "\f8a1"; } +.bi-person-fill-gear::before { content: "\f8a2"; } +.bi-person-fill-lock::before { content: "\f8a3"; } +.bi-person-fill-slash::before { content: "\f8a4"; } +.bi-person-fill-up::before { content: "\f8a5"; } +.bi-person-fill-x::before { content: "\f8a6"; } +.bi-person-gear::before { content: "\f8a7"; } +.bi-person-lock::before { content: "\f8a8"; } +.bi-person-slash::before { content: "\f8a9"; } +.bi-person-up::before { content: "\f8aa"; } +.bi-scooter::before { content: "\f8ab"; } +.bi-taxi-front-fill::before { content: "\f8ac"; } +.bi-taxi-front::before { content: "\f8ad"; } +.bi-amd::before { content: "\f8ae"; } +.bi-database-add::before { content: "\f8af"; } +.bi-database-check::before { content: "\f8b0"; } +.bi-database-dash::before { content: "\f8b1"; } +.bi-database-down::before { content: "\f8b2"; } +.bi-database-exclamation::before { content: "\f8b3"; } +.bi-database-fill-add::before { content: "\f8b4"; } +.bi-database-fill-check::before { content: "\f8b5"; } +.bi-database-fill-dash::before { content: "\f8b6"; } +.bi-database-fill-down::before { content: "\f8b7"; } +.bi-database-fill-exclamation::before { content: "\f8b8"; } +.bi-database-fill-gear::before { content: "\f8b9"; } +.bi-database-fill-lock::before { content: "\f8ba"; } +.bi-database-fill-slash::before { content: "\f8bb"; } +.bi-database-fill-up::before { content: "\f8bc"; } +.bi-database-fill-x::before { content: "\f8bd"; } +.bi-database-fill::before { content: "\f8be"; } +.bi-database-gear::before { content: "\f8bf"; } +.bi-database-lock::before { content: "\f8c0"; } +.bi-database-slash::before { content: "\f8c1"; } +.bi-database-up::before { content: "\f8c2"; } +.bi-database-x::before { content: "\f8c3"; } +.bi-database::before { content: "\f8c4"; } +.bi-houses-fill::before { content: "\f8c5"; } +.bi-houses::before { content: "\f8c6"; } +.bi-nvidia::before { content: "\f8c7"; } +.bi-person-vcard-fill::before { content: "\f8c8"; } +.bi-person-vcard::before { content: "\f8c9"; } +.bi-sina-weibo::before { content: "\f8ca"; } +.bi-tencent-qq::before { content: "\f8cb"; } +.bi-wikipedia::before { content: "\f8cc"; } diff --git a/pr-preview/pr-68/site_libs/bootstrap/bootstrap-icons.woff b/pr-preview/pr-68/site_libs/bootstrap/bootstrap-icons.woff new file mode 100644 index 0000000..18d21d4 Binary files /dev/null and b/pr-preview/pr-68/site_libs/bootstrap/bootstrap-icons.woff differ diff --git a/pr-preview/pr-68/site_libs/bootstrap/bootstrap.min.css b/pr-preview/pr-68/site_libs/bootstrap/bootstrap.min.css new file mode 100644 index 0000000..8a75a25 --- /dev/null +++ b/pr-preview/pr-68/site_libs/bootstrap/bootstrap.min.css @@ -0,0 +1,10 @@ +/*! + * Bootstrap v5.1.3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */@import"https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@300;400;700&display=swap";:root{--bs-blue: #2780e3;--bs-indigo: #6610f2;--bs-purple: #613d7c;--bs-pink: #e83e8c;--bs-red: #ff0039;--bs-orange: #f0ad4e;--bs-yellow: #ff7518;--bs-green: #3fb618;--bs-teal: #20c997;--bs-cyan: #9954bb;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #373a3c;--bs-gray-100: #f8f9fa;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #495057;--bs-gray-800: #373a3c;--bs-gray-900: #212529;--bs-default: #373a3c;--bs-primary: #2780e3;--bs-secondary: #373a3c;--bs-success: #3fb618;--bs-info: #9954bb;--bs-warning: #ff7518;--bs-danger: #ff0039;--bs-light: #f8f9fa;--bs-dark: #373a3c;--bs-default-rgb: 55, 58, 60;--bs-primary-rgb: 39, 128, 227;--bs-secondary-rgb: 55, 58, 60;--bs-success-rgb: 63, 182, 24;--bs-info-rgb: 153, 84, 187;--bs-warning-rgb: 255, 117, 24;--bs-danger-rgb: 255, 0, 57;--bs-light-rgb: 248, 249, 250;--bs-dark-rgb: 55, 58, 60;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-body-color-rgb: 55, 58, 60;--bs-body-bg-rgb: 255, 255, 255;--bs-font-sans-serif: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-root-font-size: 17px;--bs-body-font-family: var(--bs-font-sans-serif);--bs-body-font-size: 1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #373a3c;--bs-body-bg: #fff}*,*::before,*::after{box-sizing:border-box}:root{font-size:var(--bs-root-font-size)}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:400;line-height:1.2}h1,.h1{font-size:calc(1.325rem + 0.9vw)}@media(min-width: 1200px){h1,.h1{font-size:2rem}}h2,.h2{font-size:calc(1.29rem + 0.48vw)}@media(min-width: 1200px){h2,.h2{font-size:1.65rem}}h3,.h3{font-size:calc(1.27rem + 0.24vw)}@media(min-width: 1200px){h3,.h3{font-size:1.45rem}}h4,.h4{font-size:1.25rem}h5,.h5{font-size:1.1rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-bs-original-title]{text-decoration:underline dotted;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;-ms-text-decoration:underline dotted;-o-text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem;padding:.625rem 1.25rem;border-left:.25rem solid #e9ecef}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}b,strong{font-weight:bolder}small,.small{font-size:0.875em}mark,.mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:0.75em;line-height:0;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}a{color:#2780e3;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}a:hover{color:#1f66b6}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr /* rtl:ignore */;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:0.875em;color:#000;background-color:#f7f7f7;padding:.5rem;border:1px solid #dee2e6}pre code{background-color:rgba(0,0,0,0);font-size:inherit;color:inherit;word-break:normal}code{font-size:0.875em;color:#9753b8;background-color:#f7f7f7;padding:.125rem .25rem;word-wrap:break-word}a>code{color:inherit}kbd{padding:.4rem .4rem;font-size:0.875em;color:#fff;background-color:#212529}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + 0.3vw);line-height:inherit}@media(min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:0.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:0.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:0.875em;color:#6c757d}.grid{display:grid;grid-template-rows:repeat(var(--bs-rows, 1), 1fr);grid-template-columns:repeat(var(--bs-columns, 12), 1fr);gap:var(--bs-gap, 1.5rem)}.grid .g-col-1{grid-column:auto/span 1}.grid .g-col-2{grid-column:auto/span 2}.grid .g-col-3{grid-column:auto/span 3}.grid .g-col-4{grid-column:auto/span 4}.grid .g-col-5{grid-column:auto/span 5}.grid .g-col-6{grid-column:auto/span 6}.grid .g-col-7{grid-column:auto/span 7}.grid .g-col-8{grid-column:auto/span 8}.grid .g-col-9{grid-column:auto/span 9}.grid .g-col-10{grid-column:auto/span 10}.grid .g-col-11{grid-column:auto/span 11}.grid .g-col-12{grid-column:auto/span 12}.grid .g-start-1{grid-column-start:1}.grid .g-start-2{grid-column-start:2}.grid .g-start-3{grid-column-start:3}.grid .g-start-4{grid-column-start:4}.grid .g-start-5{grid-column-start:5}.grid .g-start-6{grid-column-start:6}.grid .g-start-7{grid-column-start:7}.grid .g-start-8{grid-column-start:8}.grid .g-start-9{grid-column-start:9}.grid .g-start-10{grid-column-start:10}.grid .g-start-11{grid-column-start:11}@media(min-width: 576px){.grid .g-col-sm-1{grid-column:auto/span 1}.grid .g-col-sm-2{grid-column:auto/span 2}.grid .g-col-sm-3{grid-column:auto/span 3}.grid .g-col-sm-4{grid-column:auto/span 4}.grid .g-col-sm-5{grid-column:auto/span 5}.grid .g-col-sm-6{grid-column:auto/span 6}.grid .g-col-sm-7{grid-column:auto/span 7}.grid .g-col-sm-8{grid-column:auto/span 8}.grid .g-col-sm-9{grid-column:auto/span 9}.grid .g-col-sm-10{grid-column:auto/span 10}.grid .g-col-sm-11{grid-column:auto/span 11}.grid .g-col-sm-12{grid-column:auto/span 12}.grid .g-start-sm-1{grid-column-start:1}.grid .g-start-sm-2{grid-column-start:2}.grid .g-start-sm-3{grid-column-start:3}.grid .g-start-sm-4{grid-column-start:4}.grid .g-start-sm-5{grid-column-start:5}.grid .g-start-sm-6{grid-column-start:6}.grid .g-start-sm-7{grid-column-start:7}.grid .g-start-sm-8{grid-column-start:8}.grid .g-start-sm-9{grid-column-start:9}.grid .g-start-sm-10{grid-column-start:10}.grid .g-start-sm-11{grid-column-start:11}}@media(min-width: 768px){.grid .g-col-md-1{grid-column:auto/span 1}.grid .g-col-md-2{grid-column:auto/span 2}.grid .g-col-md-3{grid-column:auto/span 3}.grid .g-col-md-4{grid-column:auto/span 4}.grid .g-col-md-5{grid-column:auto/span 5}.grid .g-col-md-6{grid-column:auto/span 6}.grid .g-col-md-7{grid-column:auto/span 7}.grid .g-col-md-8{grid-column:auto/span 8}.grid .g-col-md-9{grid-column:auto/span 9}.grid .g-col-md-10{grid-column:auto/span 10}.grid .g-col-md-11{grid-column:auto/span 11}.grid .g-col-md-12{grid-column:auto/span 12}.grid .g-start-md-1{grid-column-start:1}.grid .g-start-md-2{grid-column-start:2}.grid .g-start-md-3{grid-column-start:3}.grid .g-start-md-4{grid-column-start:4}.grid .g-start-md-5{grid-column-start:5}.grid .g-start-md-6{grid-column-start:6}.grid .g-start-md-7{grid-column-start:7}.grid .g-start-md-8{grid-column-start:8}.grid .g-start-md-9{grid-column-start:9}.grid .g-start-md-10{grid-column-start:10}.grid .g-start-md-11{grid-column-start:11}}@media(min-width: 992px){.grid .g-col-lg-1{grid-column:auto/span 1}.grid .g-col-lg-2{grid-column:auto/span 2}.grid .g-col-lg-3{grid-column:auto/span 3}.grid .g-col-lg-4{grid-column:auto/span 4}.grid .g-col-lg-5{grid-column:auto/span 5}.grid .g-col-lg-6{grid-column:auto/span 6}.grid .g-col-lg-7{grid-column:auto/span 7}.grid .g-col-lg-8{grid-column:auto/span 8}.grid .g-col-lg-9{grid-column:auto/span 9}.grid .g-col-lg-10{grid-column:auto/span 10}.grid .g-col-lg-11{grid-column:auto/span 11}.grid .g-col-lg-12{grid-column:auto/span 12}.grid .g-start-lg-1{grid-column-start:1}.grid .g-start-lg-2{grid-column-start:2}.grid .g-start-lg-3{grid-column-start:3}.grid .g-start-lg-4{grid-column-start:4}.grid .g-start-lg-5{grid-column-start:5}.grid .g-start-lg-6{grid-column-start:6}.grid .g-start-lg-7{grid-column-start:7}.grid .g-start-lg-8{grid-column-start:8}.grid .g-start-lg-9{grid-column-start:9}.grid .g-start-lg-10{grid-column-start:10}.grid .g-start-lg-11{grid-column-start:11}}@media(min-width: 1200px){.grid .g-col-xl-1{grid-column:auto/span 1}.grid .g-col-xl-2{grid-column:auto/span 2}.grid .g-col-xl-3{grid-column:auto/span 3}.grid .g-col-xl-4{grid-column:auto/span 4}.grid .g-col-xl-5{grid-column:auto/span 5}.grid .g-col-xl-6{grid-column:auto/span 6}.grid .g-col-xl-7{grid-column:auto/span 7}.grid .g-col-xl-8{grid-column:auto/span 8}.grid .g-col-xl-9{grid-column:auto/span 9}.grid .g-col-xl-10{grid-column:auto/span 10}.grid .g-col-xl-11{grid-column:auto/span 11}.grid .g-col-xl-12{grid-column:auto/span 12}.grid .g-start-xl-1{grid-column-start:1}.grid .g-start-xl-2{grid-column-start:2}.grid .g-start-xl-3{grid-column-start:3}.grid .g-start-xl-4{grid-column-start:4}.grid .g-start-xl-5{grid-column-start:5}.grid .g-start-xl-6{grid-column-start:6}.grid .g-start-xl-7{grid-column-start:7}.grid .g-start-xl-8{grid-column-start:8}.grid .g-start-xl-9{grid-column-start:9}.grid .g-start-xl-10{grid-column-start:10}.grid .g-start-xl-11{grid-column-start:11}}@media(min-width: 1400px){.grid .g-col-xxl-1{grid-column:auto/span 1}.grid .g-col-xxl-2{grid-column:auto/span 2}.grid .g-col-xxl-3{grid-column:auto/span 3}.grid .g-col-xxl-4{grid-column:auto/span 4}.grid .g-col-xxl-5{grid-column:auto/span 5}.grid .g-col-xxl-6{grid-column:auto/span 6}.grid .g-col-xxl-7{grid-column:auto/span 7}.grid .g-col-xxl-8{grid-column:auto/span 8}.grid .g-col-xxl-9{grid-column:auto/span 9}.grid .g-col-xxl-10{grid-column:auto/span 10}.grid .g-col-xxl-11{grid-column:auto/span 11}.grid .g-col-xxl-12{grid-column:auto/span 12}.grid .g-start-xxl-1{grid-column-start:1}.grid .g-start-xxl-2{grid-column-start:2}.grid .g-start-xxl-3{grid-column-start:3}.grid .g-start-xxl-4{grid-column-start:4}.grid .g-start-xxl-5{grid-column-start:5}.grid .g-start-xxl-6{grid-column-start:6}.grid .g-start-xxl-7{grid-column-start:7}.grid .g-start-xxl-8{grid-column-start:8}.grid .g-start-xxl-9{grid-column-start:9}.grid .g-start-xxl-10{grid-column-start:10}.grid .g-start-xxl-11{grid-column-start:11}}.table{--bs-table-bg: transparent;--bs-table-accent-bg: transparent;--bs-table-striped-color: #373a3c;--bs-table-striped-bg: rgba(0, 0, 0, 0.05);--bs-table-active-color: #373a3c;--bs-table-active-bg: rgba(0, 0, 0, 0.1);--bs-table-hover-color: #373a3c;--bs-table-hover-bg: rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;color:#373a3c;vertical-align:top;border-color:#dee2e6}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table>:not(:first-child){border-top:2px solid #b6babc}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-accent-bg: var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg: var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover>*{--bs-table-accent-bg: var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-bg: #d4e6f9;--bs-table-striped-bg: #c9dbed;--bs-table-striped-color: #000;--bs-table-active-bg: #bfcfe0;--bs-table-active-color: #000;--bs-table-hover-bg: #c4d5e6;--bs-table-hover-color: #000;color:#000;border-color:#bfcfe0}.table-secondary{--bs-table-bg: #d7d8d8;--bs-table-striped-bg: #cccdcd;--bs-table-striped-color: #000;--bs-table-active-bg: #c2c2c2;--bs-table-active-color: #000;--bs-table-hover-bg: #c7c8c8;--bs-table-hover-color: #000;color:#000;border-color:#c2c2c2}.table-success{--bs-table-bg: #d9f0d1;--bs-table-striped-bg: #cee4c7;--bs-table-striped-color: #000;--bs-table-active-bg: #c3d8bc;--bs-table-active-color: #000;--bs-table-hover-bg: #c9dec1;--bs-table-hover-color: #000;color:#000;border-color:#c3d8bc}.table-info{--bs-table-bg: #ebddf1;--bs-table-striped-bg: #dfd2e5;--bs-table-striped-color: #000;--bs-table-active-bg: #d4c7d9;--bs-table-active-color: #000;--bs-table-hover-bg: #d9ccdf;--bs-table-hover-color: #000;color:#000;border-color:#d4c7d9}.table-warning{--bs-table-bg: #ffe3d1;--bs-table-striped-bg: #f2d8c7;--bs-table-striped-color: #000;--bs-table-active-bg: #e6ccbc;--bs-table-active-color: #000;--bs-table-hover-bg: #ecd2c1;--bs-table-hover-color: #000;color:#000;border-color:#e6ccbc}.table-danger{--bs-table-bg: #ffccd7;--bs-table-striped-bg: #f2c2cc;--bs-table-striped-color: #000;--bs-table-active-bg: #e6b8c2;--bs-table-active-color: #000;--bs-table-hover-bg: #ecbdc7;--bs-table-hover-color: #000;color:#000;border-color:#e6b8c2}.table-light{--bs-table-bg: #f8f9fa;--bs-table-striped-bg: #ecedee;--bs-table-striped-color: #000;--bs-table-active-bg: #dfe0e1;--bs-table-active-color: #000;--bs-table-hover-bg: #e5e6e7;--bs-table-hover-color: #000;color:#000;border-color:#dfe0e1}.table-dark{--bs-table-bg: #373a3c;--bs-table-striped-bg: #414446;--bs-table-striped-color: #fff;--bs-table-active-bg: #4b4e50;--bs-table-active-color: #fff;--bs-table-hover-bg: #46494b;--bs-table-hover-color: #fff;color:#fff;border-color:#4b4e50}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width: 575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label,.shiny-input-container .control-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.875rem}.form-text{margin-top:.25rem;font-size:0.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#373a3c;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;border-radius:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#373a3c;background-color:#fff;border-color:#93c0f1;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-0.375rem -0.75rem;margin-inline-end:.75rem;color:#373a3c;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-0.375rem -0.75rem;margin-inline-end:.75rem;color:#373a3c;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control::-webkit-file-upload-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#373a3c;background-color:rgba(0,0,0,0);border:solid rgba(0,0,0,0);border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + 0.5rem + 2px);padding:.25rem .5rem;font-size:0.875rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-0.25rem -0.5rem;margin-inline-end:.5rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-0.25rem -0.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-0.5rem -1rem;margin-inline-end:1rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-0.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + 0.75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + 0.5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{width:3rem;height:auto;padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{height:1.5em}.form-control-color::-webkit-color-swatch{height:1.5em}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;-moz-padding-start:calc(0.75rem - 3px);font-size:1rem;font-weight:400;line-height:1.5;color:#373a3c;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23373a3c' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:0;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media(prefers-reduced-motion: reduce){.form-select{transition:none}}.form-select:focus{border-color:#93c0f1;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:rgba(0,0,0,0);text-shadow:0 0 0 #373a3c}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:0.875rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.form-check,.shiny-input-container .checkbox,.shiny-input-container .radio{display:block;min-height:1.5rem;padding-left:0;margin-bottom:.125rem}.form-check .form-check-input,.form-check .shiny-input-container .checkbox input,.form-check .shiny-input-container .radio input,.shiny-input-container .checkbox .form-check-input,.shiny-input-container .checkbox .shiny-input-container .checkbox input,.shiny-input-container .checkbox .shiny-input-container .radio input,.shiny-input-container .radio .form-check-input,.shiny-input-container .radio .shiny-input-container .checkbox input,.shiny-input-container .radio .shiny-input-container .radio input{float:left;margin-left:0}.form-check-input,.shiny-input-container .checkbox input,.shiny-input-container .checkbox-inline input,.shiny-input-container .radio input,.shiny-input-container .radio-inline input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;color-adjust:exact;-webkit-print-color-adjust:exact}.form-check-input[type=radio],.shiny-input-container .checkbox input[type=radio],.shiny-input-container .checkbox-inline input[type=radio],.shiny-input-container .radio input[type=radio],.shiny-input-container .radio-inline input[type=radio]{border-radius:50%}.form-check-input:active,.shiny-input-container .checkbox input:active,.shiny-input-container .checkbox-inline input:active,.shiny-input-container .radio input:active,.shiny-input-container .radio-inline input:active{filter:brightness(90%)}.form-check-input:focus,.shiny-input-container .checkbox input:focus,.shiny-input-container .checkbox-inline input:focus,.shiny-input-container .radio input:focus,.shiny-input-container .radio-inline input:focus{border-color:#93c0f1;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.form-check-input:checked,.shiny-input-container .checkbox input:checked,.shiny-input-container .checkbox-inline input:checked,.shiny-input-container .radio input:checked,.shiny-input-container .radio-inline input:checked{background-color:#2780e3;border-color:#2780e3}.form-check-input:checked[type=checkbox],.shiny-input-container .checkbox input:checked[type=checkbox],.shiny-input-container .checkbox-inline input:checked[type=checkbox],.shiny-input-container .radio input:checked[type=checkbox],.shiny-input-container .radio-inline input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio],.shiny-input-container .checkbox input:checked[type=radio],.shiny-input-container .checkbox-inline input:checked[type=radio],.shiny-input-container .radio input:checked[type=radio],.shiny-input-container .radio-inline input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate,.shiny-input-container .checkbox input[type=checkbox]:indeterminate,.shiny-input-container .checkbox-inline input[type=checkbox]:indeterminate,.shiny-input-container .radio input[type=checkbox]:indeterminate,.shiny-input-container .radio-inline input[type=checkbox]:indeterminate{background-color:#2780e3;border-color:#2780e3;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled,.shiny-input-container .checkbox input:disabled,.shiny-input-container .checkbox-inline input:disabled,.shiny-input-container .radio input:disabled,.shiny-input-container .radio-inline input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input[disabled]~span,.form-check-input:disabled~.form-check-label,.form-check-input:disabled~span,.shiny-input-container .checkbox input[disabled]~.form-check-label,.shiny-input-container .checkbox input[disabled]~span,.shiny-input-container .checkbox input:disabled~.form-check-label,.shiny-input-container .checkbox input:disabled~span,.shiny-input-container .checkbox-inline input[disabled]~.form-check-label,.shiny-input-container .checkbox-inline input[disabled]~span,.shiny-input-container .checkbox-inline input:disabled~.form-check-label,.shiny-input-container .checkbox-inline input:disabled~span,.shiny-input-container .radio input[disabled]~.form-check-label,.shiny-input-container .radio input[disabled]~span,.shiny-input-container .radio input:disabled~.form-check-label,.shiny-input-container .radio input:disabled~span,.shiny-input-container .radio-inline input[disabled]~.form-check-label,.shiny-input-container .radio-inline input[disabled]~span,.shiny-input-container .radio-inline input:disabled~.form-check-label,.shiny-input-container .radio-inline input:disabled~span{opacity:.5}.form-check-label,.shiny-input-container .checkbox label,.shiny-input-container .checkbox-inline label,.shiny-input-container .radio label,.shiny-input-container .radio-inline label{cursor:pointer}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:left center;transition:background-position .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2393c0f1'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-check-inline,.shiny-input-container .checkbox-inline,.shiny-input-container .radio-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.btn-check[disabled]+.btn,.btn-check:disabled+.btn{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:rgba(0,0,0,0);appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(39,128,227,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(39,128,227,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-0.25rem;background-color:#2780e3;border:0;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media(prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#bed9f7}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#dee2e6;border-color:rgba(0,0,0,0)}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#2780e3;border:0;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media(prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#bed9f7}.form-range::-moz-range-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#dee2e6;border-color:rgba(0,0,0,0)}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-select{height:calc(3.5rem + 2px);line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;height:100%;padding:1rem .75rem;pointer-events:none;border:1px solid rgba(0,0,0,0);transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media(prefers-reduced-motion: reduce){.form-floating>label{transition:none}}.form-floating>.form-control{padding:1rem .75rem}.form-floating>.form-control::placeholder{color:rgba(0,0,0,0)}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.input-group{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:stretch;-webkit-align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus{z-index:3}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:3}.input-group-text{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#373a3c;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.25rem .5rem;font-size:0.875rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#3fb618}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:rgba(63,182,24,.9)}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#3fb618;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%233fb618' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#3fb618;box-shadow:0 0 0 .25rem rgba(63,182,24,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#3fb618}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23373a3c' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%233fb618' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#3fb618;box-shadow:0 0 0 .25rem rgba(63,182,24,.25)}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#3fb618}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#3fb618}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(63,182,24,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#3fb618}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group .form-control:valid,.input-group .form-control.is-valid,.was-validated .input-group .form-select:valid,.input-group .form-select.is-valid{z-index:1}.was-validated .input-group .form-control:valid:focus,.input-group .form-control.is-valid:focus,.was-validated .input-group .form-select:valid:focus,.input-group .form-select.is-valid:focus{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#ff0039}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:rgba(255,0,57,.9)}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#ff0039;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23ff0039'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ff0039' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#ff0039;box-shadow:0 0 0 .25rem rgba(255,0,57,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#ff0039}.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"],.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23373a3c' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23ff0039'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ff0039' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#ff0039;box-shadow:0 0 0 .25rem rgba(255,0,57,.25)}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#ff0039}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#ff0039}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(255,0,57,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#ff0039}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group .form-control:invalid,.input-group .form-control.is-invalid,.was-validated .input-group .form-select:invalid,.input-group .form-select.is-invalid{z-index:2}.was-validated .input-group .form-control:invalid:focus,.input-group .form-control.is-invalid:focus,.was-validated .input-group .form-select:invalid:focus,.input-group .form-select.is-invalid:focus{z-index:3}.btn{display:inline-block;font-weight:400;line-height:1.5;color:#373a3c;text-align:center;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;vertical-align:middle;cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;background-color:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);padding:.375rem .75rem;font-size:1rem;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:#373a3c}.btn-check:focus+.btn,.btn:focus{outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{pointer-events:none;opacity:.65}.btn-default{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-default:hover{color:#fff;background-color:#2f3133;border-color:#2c2e30}.btn-check:focus+.btn-default,.btn-default:focus{color:#fff;background-color:#2f3133;border-color:#2c2e30;box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-check:checked+.btn-default,.btn-check:active+.btn-default,.btn-default:active,.btn-default.active,.show>.btn-default.dropdown-toggle{color:#fff;background-color:#2c2e30;border-color:#292c2d}.btn-check:checked+.btn-default:focus,.btn-check:active+.btn-default:focus,.btn-default:active:focus,.btn-default.active:focus,.show>.btn-default.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-default:disabled,.btn-default.disabled{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-primary{color:#fff;background-color:#2780e3;border-color:#2780e3}.btn-primary:hover{color:#fff;background-color:#216dc1;border-color:#1f66b6}.btn-check:focus+.btn-primary,.btn-primary:focus{color:#fff;background-color:#216dc1;border-color:#1f66b6;box-shadow:0 0 0 .25rem rgba(71,147,231,.5)}.btn-check:checked+.btn-primary,.btn-check:active+.btn-primary,.btn-primary:active,.btn-primary.active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#1f66b6;border-color:#1d60aa}.btn-check:checked+.btn-primary:focus,.btn-check:active+.btn-primary:focus,.btn-primary:active:focus,.btn-primary.active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(71,147,231,.5)}.btn-primary:disabled,.btn-primary.disabled{color:#fff;background-color:#2780e3;border-color:#2780e3}.btn-secondary{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-secondary:hover{color:#fff;background-color:#2f3133;border-color:#2c2e30}.btn-check:focus+.btn-secondary,.btn-secondary:focus{color:#fff;background-color:#2f3133;border-color:#2c2e30;box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-check:checked+.btn-secondary,.btn-check:active+.btn-secondary,.btn-secondary:active,.btn-secondary.active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#2c2e30;border-color:#292c2d}.btn-check:checked+.btn-secondary:focus,.btn-check:active+.btn-secondary:focus,.btn-secondary:active:focus,.btn-secondary.active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-secondary:disabled,.btn-secondary.disabled{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-success{color:#fff;background-color:#3fb618;border-color:#3fb618}.btn-success:hover{color:#fff;background-color:#369b14;border-color:#329213}.btn-check:focus+.btn-success,.btn-success:focus{color:#fff;background-color:#369b14;border-color:#329213;box-shadow:0 0 0 .25rem rgba(92,193,59,.5)}.btn-check:checked+.btn-success,.btn-check:active+.btn-success,.btn-success:active,.btn-success.active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#329213;border-color:#2f8912}.btn-check:checked+.btn-success:focus,.btn-check:active+.btn-success:focus,.btn-success:active:focus,.btn-success.active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(92,193,59,.5)}.btn-success:disabled,.btn-success.disabled{color:#fff;background-color:#3fb618;border-color:#3fb618}.btn-info{color:#fff;background-color:#9954bb;border-color:#9954bb}.btn-info:hover{color:#fff;background-color:#82479f;border-color:#7a4396}.btn-check:focus+.btn-info,.btn-info:focus{color:#fff;background-color:#82479f;border-color:#7a4396;box-shadow:0 0 0 .25rem rgba(168,110,197,.5)}.btn-check:checked+.btn-info,.btn-check:active+.btn-info,.btn-info:active,.btn-info.active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#7a4396;border-color:#733f8c}.btn-check:checked+.btn-info:focus,.btn-check:active+.btn-info:focus,.btn-info:active:focus,.btn-info.active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(168,110,197,.5)}.btn-info:disabled,.btn-info.disabled{color:#fff;background-color:#9954bb;border-color:#9954bb}.btn-warning{color:#fff;background-color:#ff7518;border-color:#ff7518}.btn-warning:hover{color:#fff;background-color:#d96314;border-color:#cc5e13}.btn-check:focus+.btn-warning,.btn-warning:focus{color:#fff;background-color:#d96314;border-color:#cc5e13;box-shadow:0 0 0 .25rem rgba(255,138,59,.5)}.btn-check:checked+.btn-warning,.btn-check:active+.btn-warning,.btn-warning:active,.btn-warning.active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#cc5e13;border-color:#bf5812}.btn-check:checked+.btn-warning:focus,.btn-check:active+.btn-warning:focus,.btn-warning:active:focus,.btn-warning.active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(255,138,59,.5)}.btn-warning:disabled,.btn-warning.disabled{color:#fff;background-color:#ff7518;border-color:#ff7518}.btn-danger{color:#fff;background-color:#ff0039;border-color:#ff0039}.btn-danger:hover{color:#fff;background-color:#d90030;border-color:#cc002e}.btn-check:focus+.btn-danger,.btn-danger:focus{color:#fff;background-color:#d90030;border-color:#cc002e;box-shadow:0 0 0 .25rem rgba(255,38,87,.5)}.btn-check:checked+.btn-danger,.btn-check:active+.btn-danger,.btn-danger:active,.btn-danger.active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#cc002e;border-color:#bf002b}.btn-check:checked+.btn-danger:focus,.btn-check:active+.btn-danger:focus,.btn-danger:active:focus,.btn-danger.active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(255,38,87,.5)}.btn-danger:disabled,.btn-danger.disabled{color:#fff;background-color:#ff0039;border-color:#ff0039}.btn-light{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:focus+.btn-light,.btn-light:focus{color:#000;background-color:#f9fafb;border-color:#f9fafb;box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-check:checked+.btn-light,.btn-check:active+.btn-light,.btn-light:active,.btn-light.active,.show>.btn-light.dropdown-toggle{color:#000;background-color:#f9fafb;border-color:#f9fafb}.btn-check:checked+.btn-light:focus,.btn-check:active+.btn-light:focus,.btn-light:active:focus,.btn-light.active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(211,212,213,.5)}.btn-light:disabled,.btn-light.disabled{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-dark{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-dark:hover{color:#fff;background-color:#2f3133;border-color:#2c2e30}.btn-check:focus+.btn-dark,.btn-dark:focus{color:#fff;background-color:#2f3133;border-color:#2c2e30;box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-check:checked+.btn-dark,.btn-check:active+.btn-dark,.btn-dark:active,.btn-dark.active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#2c2e30;border-color:#292c2d}.btn-check:checked+.btn-dark:focus,.btn-check:active+.btn-dark:focus,.btn-dark:active:focus,.btn-dark.active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(85,88,89,.5)}.btn-dark:disabled,.btn-dark.disabled{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-outline-default{color:#373a3c;border-color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-default:hover{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:focus+.btn-outline-default,.btn-outline-default:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-check:checked+.btn-outline-default,.btn-check:active+.btn-outline-default,.btn-outline-default:active,.btn-outline-default.active,.btn-outline-default.dropdown-toggle.show{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:checked+.btn-outline-default:focus,.btn-check:active+.btn-outline-default:focus,.btn-outline-default:active:focus,.btn-outline-default.active:focus,.btn-outline-default.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-outline-default:disabled,.btn-outline-default.disabled{color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-primary{color:#2780e3;border-color:#2780e3;background-color:rgba(0,0,0,0)}.btn-outline-primary:hover{color:#fff;background-color:#2780e3;border-color:#2780e3}.btn-check:focus+.btn-outline-primary,.btn-outline-primary:focus{box-shadow:0 0 0 .25rem rgba(39,128,227,.5)}.btn-check:checked+.btn-outline-primary,.btn-check:active+.btn-outline-primary,.btn-outline-primary:active,.btn-outline-primary.active,.btn-outline-primary.dropdown-toggle.show{color:#fff;background-color:#2780e3;border-color:#2780e3}.btn-check:checked+.btn-outline-primary:focus,.btn-check:active+.btn-outline-primary:focus,.btn-outline-primary:active:focus,.btn-outline-primary.active:focus,.btn-outline-primary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(39,128,227,.5)}.btn-outline-primary:disabled,.btn-outline-primary.disabled{color:#2780e3;background-color:rgba(0,0,0,0)}.btn-outline-secondary{color:#373a3c;border-color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-secondary:hover{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:focus+.btn-outline-secondary,.btn-outline-secondary:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-check:checked+.btn-outline-secondary,.btn-check:active+.btn-outline-secondary,.btn-outline-secondary:active,.btn-outline-secondary.active,.btn-outline-secondary.dropdown-toggle.show{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:checked+.btn-outline-secondary:focus,.btn-check:active+.btn-outline-secondary:focus,.btn-outline-secondary:active:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-outline-secondary:disabled,.btn-outline-secondary.disabled{color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-success{color:#3fb618;border-color:#3fb618;background-color:rgba(0,0,0,0)}.btn-outline-success:hover{color:#fff;background-color:#3fb618;border-color:#3fb618}.btn-check:focus+.btn-outline-success,.btn-outline-success:focus{box-shadow:0 0 0 .25rem rgba(63,182,24,.5)}.btn-check:checked+.btn-outline-success,.btn-check:active+.btn-outline-success,.btn-outline-success:active,.btn-outline-success.active,.btn-outline-success.dropdown-toggle.show{color:#fff;background-color:#3fb618;border-color:#3fb618}.btn-check:checked+.btn-outline-success:focus,.btn-check:active+.btn-outline-success:focus,.btn-outline-success:active:focus,.btn-outline-success.active:focus,.btn-outline-success.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(63,182,24,.5)}.btn-outline-success:disabled,.btn-outline-success.disabled{color:#3fb618;background-color:rgba(0,0,0,0)}.btn-outline-info{color:#9954bb;border-color:#9954bb;background-color:rgba(0,0,0,0)}.btn-outline-info:hover{color:#fff;background-color:#9954bb;border-color:#9954bb}.btn-check:focus+.btn-outline-info,.btn-outline-info:focus{box-shadow:0 0 0 .25rem rgba(153,84,187,.5)}.btn-check:checked+.btn-outline-info,.btn-check:active+.btn-outline-info,.btn-outline-info:active,.btn-outline-info.active,.btn-outline-info.dropdown-toggle.show{color:#fff;background-color:#9954bb;border-color:#9954bb}.btn-check:checked+.btn-outline-info:focus,.btn-check:active+.btn-outline-info:focus,.btn-outline-info:active:focus,.btn-outline-info.active:focus,.btn-outline-info.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(153,84,187,.5)}.btn-outline-info:disabled,.btn-outline-info.disabled{color:#9954bb;background-color:rgba(0,0,0,0)}.btn-outline-warning{color:#ff7518;border-color:#ff7518;background-color:rgba(0,0,0,0)}.btn-outline-warning:hover{color:#fff;background-color:#ff7518;border-color:#ff7518}.btn-check:focus+.btn-outline-warning,.btn-outline-warning:focus{box-shadow:0 0 0 .25rem rgba(255,117,24,.5)}.btn-check:checked+.btn-outline-warning,.btn-check:active+.btn-outline-warning,.btn-outline-warning:active,.btn-outline-warning.active,.btn-outline-warning.dropdown-toggle.show{color:#fff;background-color:#ff7518;border-color:#ff7518}.btn-check:checked+.btn-outline-warning:focus,.btn-check:active+.btn-outline-warning:focus,.btn-outline-warning:active:focus,.btn-outline-warning.active:focus,.btn-outline-warning.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(255,117,24,.5)}.btn-outline-warning:disabled,.btn-outline-warning.disabled{color:#ff7518;background-color:rgba(0,0,0,0)}.btn-outline-danger{color:#ff0039;border-color:#ff0039;background-color:rgba(0,0,0,0)}.btn-outline-danger:hover{color:#fff;background-color:#ff0039;border-color:#ff0039}.btn-check:focus+.btn-outline-danger,.btn-outline-danger:focus{box-shadow:0 0 0 .25rem rgba(255,0,57,.5)}.btn-check:checked+.btn-outline-danger,.btn-check:active+.btn-outline-danger,.btn-outline-danger:active,.btn-outline-danger.active,.btn-outline-danger.dropdown-toggle.show{color:#fff;background-color:#ff0039;border-color:#ff0039}.btn-check:checked+.btn-outline-danger:focus,.btn-check:active+.btn-outline-danger:focus,.btn-outline-danger:active:focus,.btn-outline-danger.active:focus,.btn-outline-danger.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(255,0,57,.5)}.btn-outline-danger:disabled,.btn-outline-danger.disabled{color:#ff0039;background-color:rgba(0,0,0,0)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa;background-color:rgba(0,0,0,0)}.btn-outline-light:hover{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:focus+.btn-outline-light,.btn-outline-light:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-check:checked+.btn-outline-light,.btn-check:active+.btn-outline-light,.btn-outline-light:active,.btn-outline-light.active,.btn-outline-light.dropdown-toggle.show{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-check:checked+.btn-outline-light:focus,.btn-check:active+.btn-outline-light:focus,.btn-outline-light:active:focus,.btn-outline-light.active:focus,.btn-outline-light.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(248,249,250,.5)}.btn-outline-light:disabled,.btn-outline-light.disabled{color:#f8f9fa;background-color:rgba(0,0,0,0)}.btn-outline-dark{color:#373a3c;border-color:#373a3c;background-color:rgba(0,0,0,0)}.btn-outline-dark:hover{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:focus+.btn-outline-dark,.btn-outline-dark:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-check:checked+.btn-outline-dark,.btn-check:active+.btn-outline-dark,.btn-outline-dark:active,.btn-outline-dark.active,.btn-outline-dark.dropdown-toggle.show{color:#fff;background-color:#373a3c;border-color:#373a3c}.btn-check:checked+.btn-outline-dark:focus,.btn-check:active+.btn-outline-dark:focus,.btn-outline-dark:active:focus,.btn-outline-dark.active:focus,.btn-outline-dark.dropdown-toggle.show:focus{box-shadow:0 0 0 .25rem rgba(55,58,60,.5)}.btn-outline-dark:disabled,.btn-outline-dark.disabled{color:#373a3c;background-color:rgba(0,0,0,0)}.btn-link{font-weight:400;color:#2780e3;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:hover{color:#1f66b6}.btn-link:disabled,.btn-link.disabled{color:#6c757d}.btn-lg,.btn-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:0}.btn-sm,.btn-group-sm>.btn{padding:.25rem .5rem;font-size:0.875rem;border-radius:0}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .2s ease}@media(prefers-reduced-motion: reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media(prefers-reduced-motion: reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid rgba(0,0,0,0);border-bottom:0;border-left:.3em solid rgba(0,0,0,0)}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;z-index:1000;display:none;min-width:10rem;padding:.5rem 0;margin:0;font-size:1rem;color:#373a3c;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:.125rem}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media(min-width: 576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid rgba(0,0,0,0);border-bottom:.3em solid;border-left:.3em solid rgba(0,0,0,0)}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:0;border-bottom:.3em solid rgba(0,0,0,0);border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:.3em solid;border-bottom:.3em solid rgba(0,0,0,0)}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid rgba(0,0,0,.15)}.dropdown-item{display:block;width:100%;padding:.25rem 1rem;clear:both;font-weight:400;color:#212529;text-align:inherit;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap;background-color:rgba(0,0,0,0);border:0}.dropdown-item:hover,.dropdown-item:focus{color:#1e2125;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#2780e3}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:rgba(0,0,0,0)}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1rem;margin-bottom:0;font-size:0.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1rem;color:#212529}.dropdown-menu-dark{color:#dee2e6;background-color:#373a3c;border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item{color:#dee2e6}.dropdown-menu-dark .dropdown-item:hover,.dropdown-menu-dark .dropdown-item:focus{color:#fff;background-color:rgba(255,255,255,.15)}.dropdown-menu-dark .dropdown-item.active,.dropdown-menu-dark .dropdown-item:active{color:#fff;background-color:#2780e3}.dropdown-menu-dark .dropdown-item.disabled,.dropdown-menu-dark .dropdown-item:disabled{color:#adb5bd}.dropdown-menu-dark .dropdown-divider{border-color:rgba(0,0,0,.15)}.dropdown-menu-dark .dropdown-item-text{color:#dee2e6}.dropdown-menu-dark .dropdown-header{color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;justify-content:flex-start;-webkit-justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child){margin-left:-1px}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;-webkit-flex-direction:column;align-items:flex-start;-webkit-align-items:flex-start;justify-content:center;-webkit-justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.nav{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem;color:#2780e3;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media(prefers-reduced-motion: reduce){.nav-link{transition:none}}.nav-link:hover,.nav-link:focus{color:#1f66b6}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background:none;border:1px solid rgba(0,0,0,0)}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:rgba(0,0,0,0);border-color:rgba(0,0,0,0)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px}.nav-pills .nav-link{background:none;border:0}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#2780e3}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;-webkit-flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar>.container-xxl,.navbar>.container-xl,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container,.navbar>.container-fluid{display:flex;display:-webkit-flex;flex-wrap:inherit;-webkit-flex-wrap:inherit;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap}.navbar-nav{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;-webkit-flex-basis:100%;flex-grow:1;-webkit-flex-grow:1;align-items:center;-webkit-align-items:center}.navbar-toggler{padding:.25 0;font-size:1.25rem;line-height:1;background-color:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);transition:box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 .25rem}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height, 75vh);overflow-y:auto}@media(min-width: 576px){.navbar-expand-sm{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas-header{display:none}.navbar-expand-sm .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-sm .offcanvas-top,.navbar-expand-sm .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-sm .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 768px){.navbar-expand-md{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas-header{display:none}.navbar-expand-md .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-md .offcanvas-top,.navbar-expand-md .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-md .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 992px){.navbar-expand-lg{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas-header{display:none}.navbar-expand-lg .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-lg .offcanvas-top,.navbar-expand-lg .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-lg .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1200px){.navbar-expand-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas-header{display:none}.navbar-expand-xl .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-xl .offcanvas-top,.navbar-expand-xl .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-xl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1400px){.navbar-expand-xxl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand-xxl .offcanvas-top,.navbar-expand-xxl .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand-xxl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas-header{display:none}.navbar-expand .offcanvas{position:inherit;bottom:0;z-index:1000;flex-grow:1;-webkit-flex-grow:1;visibility:visible !important;background-color:rgba(0,0,0,0);border-right:0;border-left:0;transition:none;transform:none}.navbar-expand .offcanvas-top,.navbar-expand .offcanvas-bottom{height:auto;border-top:0;border-bottom:0}.navbar-expand .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}.navbar-light{background-color:#f8f9fa}.navbar-light .navbar-brand{color:#545555}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:#1a5698}.navbar-light .navbar-nav .nav-link{color:#545555}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:rgba(26,86,152,.8)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(84,85,85,.75)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .nav-link.active{color:#1a5698}.navbar-light .navbar-toggler{color:#545555;border-color:rgba(84,85,85,0)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23545555' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:#545555}.navbar-light .navbar-text a,.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:#1a5698}.navbar-dark{background-color:#f8f9fa}.navbar-dark .navbar-brand{color:#545555}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#1a5698}.navbar-dark .navbar-nav .nav-link{color:#545555}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:rgba(26,86,152,.8)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(84,85,85,.75)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active{color:#1a5698}.navbar-dark .navbar-toggler{color:#545555;border-color:rgba(84,85,85,0)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23545555' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:#545555}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#1a5698}.card{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0}.card>.list-group:last-child{border-bottom-width:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;-webkit-flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-subtitle{margin-top:-0.25rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:1rem}.card-header{padding:.5rem 1rem;margin-bottom:0;background-color:#adb5bd;border-bottom:1px solid rgba(0,0,0,.125)}.card-footer{padding:.5rem 1rem;background-color:#adb5bd;border-top:1px solid rgba(0,0,0,.125)}.card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-group>.card{margin-bottom:.75rem}@media(min-width: 576px){.card-group{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap}.card-group>.card{flex:1 0 0%;-webkit-flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}}.accordion-button{position:relative;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;width:100%;padding:1rem 1.25rem;font-size:1rem;color:#373a3c;text-align:left;background-color:#fff;border:0;overflow-anchor:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease}@media(prefers-reduced-motion: reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:#2373cc;background-color:#e9f2fc;box-shadow:inset 0 -1px 0 rgba(0,0,0,.125)}.accordion-button:not(.collapsed)::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%232373cc'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");transform:rotate(-180deg)}.accordion-button::after{flex-shrink:0;-webkit-flex-shrink:0;width:1.25rem;height:1.25rem;margin-left:auto;content:"";background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23373a3c'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-size:1.25rem;transition:transform .2s ease-in-out}@media(prefers-reduced-motion: reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:#93c0f1;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.accordion-header{margin-bottom:0}.accordion-item{background-color:#fff;border:1px solid rgba(0,0,0,.125)}.accordion-item:not(:first-of-type){border-top:0}.accordion-body{padding:1rem 1.25rem}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.breadcrumb{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding:0 0;margin-bottom:1rem;list-style:none}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:var(--bs-breadcrumb-divider, ">") /* rtl: var(--bs-breadcrumb-divider, ">") */}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;display:-webkit-flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;color:#2780e3;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:#fff;border:1px solid #dee2e6;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:#1f66b6;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;color:#1f66b6;background-color:#e9ecef;outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item.active .page-link{z-index:3;color:#fff;background-color:#2780e3;border-color:#2780e3}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;background-color:#fff;border-color:#dee2e6}.page-link{padding:.375rem .75rem}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:0.875rem}.badge{display:inline-block;padding:.35em .65em;font-size:0.75em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{position:relative;padding:1rem 1rem;margin-bottom:1rem;border:0 solid rgba(0,0,0,0)}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-default{color:#212324;background-color:#d7d8d8;border-color:#c3c4c5}.alert-default .alert-link{color:#1a1c1d}.alert-primary{color:#174d88;background-color:#d4e6f9;border-color:#bed9f7}.alert-primary .alert-link{color:#123e6d}.alert-secondary{color:#212324;background-color:#d7d8d8;border-color:#c3c4c5}.alert-secondary .alert-link{color:#1a1c1d}.alert-success{color:#266d0e;background-color:#d9f0d1;border-color:#c5e9ba}.alert-success .alert-link{color:#1e570b}.alert-info{color:#5c3270;background-color:#ebddf1;border-color:#e0cceb}.alert-info .alert-link{color:#4a285a}.alert-warning{color:#99460e;background-color:#ffe3d1;border-color:#ffd6ba}.alert-warning .alert-link{color:#7a380b}.alert-danger{color:#902;background-color:#ffccd7;border-color:#ffb3c4}.alert-danger .alert-link{color:#7a001b}.alert-light{color:#959596;background-color:#fefefe;border-color:#fdfdfe}.alert-light .alert-link{color:#777778}.alert-dark{color:#212324;background-color:#d7d8d8;border-color:#c3c4c5}.alert-dark .alert-link{color:#1a1c1d}@keyframes progress-bar-stripes{0%{background-position-x:.5rem}}.progress{display:flex;display:-webkit-flex;height:.5rem;overflow:hidden;font-size:0.75rem;background-color:#e9ecef}.progress-bar{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#2780e3;transition:width .6s ease}@media(prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-size:.5rem .5rem}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media(prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.list-group{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>li::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#373a3c;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.5rem 1rem;color:#212529;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#2780e3;border-color:#2780e3}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media(min-width: 576px){.list-group-horizontal-sm{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media(min-width: 768px){.list-group-horizontal-md{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media(min-width: 992px){.list-group-horizontal-lg{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media(min-width: 1200px){.list-group-horizontal-xl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media(min-width: 1400px){.list-group-horizontal-xxl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-default{color:#212324;background-color:#d7d8d8}.list-group-item-default.list-group-item-action:hover,.list-group-item-default.list-group-item-action:focus{color:#212324;background-color:#c2c2c2}.list-group-item-default.list-group-item-action.active{color:#fff;background-color:#212324;border-color:#212324}.list-group-item-primary{color:#174d88;background-color:#d4e6f9}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#174d88;background-color:#bfcfe0}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#174d88;border-color:#174d88}.list-group-item-secondary{color:#212324;background-color:#d7d8d8}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#212324;background-color:#c2c2c2}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#212324;border-color:#212324}.list-group-item-success{color:#266d0e;background-color:#d9f0d1}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#266d0e;background-color:#c3d8bc}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#266d0e;border-color:#266d0e}.list-group-item-info{color:#5c3270;background-color:#ebddf1}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#5c3270;background-color:#d4c7d9}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#5c3270;border-color:#5c3270}.list-group-item-warning{color:#99460e;background-color:#ffe3d1}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#99460e;background-color:#e6ccbc}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#99460e;border-color:#99460e}.list-group-item-danger{color:#902;background-color:#ffccd7}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#902;background-color:#e6b8c2}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#902;border-color:#902}.list-group-item-light{color:#959596;background-color:#fefefe}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#959596;background-color:#e5e5e5}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#959596;border-color:#959596}.list-group-item-dark{color:#212324;background-color:#d7d8d8}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#212324;background-color:#c2c2c2}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#212324;border-color:#212324}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#000;background:rgba(0,0,0,0) url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(39,128,227,.25);opacity:1}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{width:350px;max-width:100%;font-size:0.875rem;pointer-events:auto;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .5rem 1rem rgba(0,0,0,.15)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{width:max-content;width:-webkit-max-content;width:-moz-max-content;width:-ms-max-content;width:-o-max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:.75rem}.toast-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.5rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-header .btn-close{margin-right:-0.375rem;margin-left:.75rem}.toast-body{padding:.75rem;word-wrap:break-word}.modal{position:fixed;top:0;left:0;z-index:1055;display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0, -50px)}@media(prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;min-height:calc(100% - 1rem)}.modal-content{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1050;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;display:-webkit-flex;flex-shrink:0;-webkit-flex-shrink:0;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6}.modal-header .btn-close{padding:.5rem .5rem;margin:-0.5rem -0.5rem -0.5rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;padding:1rem}.modal-footer{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-shrink:0;-webkit-flex-shrink:0;align-items:center;-webkit-align-items:center;justify-content:flex-end;-webkit-justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6}.modal-footer>*{margin:.25rem}@media(min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{height:calc(100% - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-sm{max-width:300px}}@media(min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media(min-width: 1200px){.modal-xl{max-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0}.modal-fullscreen .modal-body{overflow-y:auto}@media(max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media(max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media(max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media(max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media(max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{position:absolute;z-index:1080;display:block;margin:0;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .tooltip-arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[data-popper-placement^=top]{padding:.4rem 0}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:0}.bs-tooltip-top .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before{top:-1px;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-end,.bs-tooltip-auto[data-popper-placement^=right]{padding:0 .4rem}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-end .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before{right:-1px;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[data-popper-placement^=bottom]{padding:.4rem 0}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:0}.bs-tooltip-bottom .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before{bottom:-1px;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-start,.bs-tooltip-auto[data-popper-placement^=left]{padding:0 .4rem}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-start .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before{left:-1px;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000}.popover{position:absolute;top:0;left:0 /* rtl:ignore */;z-index:1070;display:block;max-width:276px;font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2)}.popover .popover-arrow{position:absolute;display:block;width:1rem;height:.5rem}.popover .popover-arrow::before,.popover .popover-arrow::after{position:absolute;display:block;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-0.5rem - 1px)}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-0.5rem - 1px);width:.5rem;height:1rem}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-0.5rem - 1px)}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-0.5rem;content:"";border-bottom:1px solid #f0f0f0}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-0.5rem - 1px);width:.5rem;height:1rem}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem 1rem;margin-bottom:0;font-size:1rem;background-color:#f0f0f0;border-bottom:1px solid rgba(0,0,0,.2)}.popover-header:empty{display:none}.popover-body{padding:1rem 1rem;color:#373a3c}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y;-webkit-touch-action:pan-y;-moz-touch-action:pan-y;-ms-touch-action:pan-y;-o-touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden;transition:transform .6s ease-in-out}@media(prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media(prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;border:0;opacity:.5;transition:opacity .15s ease}@media(prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;display:-webkit-flex;justify-content:center;-webkit-justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;-webkit-flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid rgba(0,0,0,0);border-bottom:10px solid rgba(0,0,0,0);opacity:.5;transition:opacity .6s ease}@media(prefers-reduced-motion: reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-prev-icon,.carousel-dark .carousel-control-next-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}@keyframes spinner-border{to{transform:rotate(360deg) /* rtl:ignore */}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-0.125em;border:.25em solid currentColor;border-right-color:rgba(0,0,0,0);border-radius:50%;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-0.125em;background-color:currentColor;border-radius:50%;opacity:0;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media(prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{animation-duration:1.5s;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s}}.offcanvas{position:fixed;bottom:0;z-index:1045;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;visibility:hidden;background-color:#fff;background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}@media(prefers-reduced-motion: reduce){.offcanvas{transition:none}}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:1rem 1rem}.offcanvas-header .btn-close{padding:.5rem .5rem;margin-top:-0.5rem;margin-right:-0.5rem;margin-bottom:-0.5rem}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;-webkit-flex-grow:1;padding:1rem 1rem;overflow-y:auto}.offcanvas-start{top:0;left:0;width:400px;border-right:1px solid rgba(0,0,0,.2);transform:translateX(-100%)}.offcanvas-end{top:0;right:0;width:400px;border-left:1px solid rgba(0,0,0,.2);transform:translateX(100%)}.offcanvas-top{top:0;right:0;left:0;height:30vh;max-height:100%;border-bottom:1px solid rgba(0,0,0,.2);transform:translateY(-100%)}.offcanvas-bottom{right:0;left:0;height:30vh;max-height:100%;border-top:1px solid rgba(0,0,0,.2);transform:translateY(100%)}.offcanvas.show{transform:none}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentColor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);-webkit-mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);mask-size:200% 100%;-webkit-mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{mask-position:-200% 0%;-webkit-mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.link-default{color:#373a3c}.link-default:hover,.link-default:focus{color:#2c2e30}.link-primary{color:#2780e3}.link-primary:hover,.link-primary:focus{color:#1f66b6}.link-secondary{color:#373a3c}.link-secondary:hover,.link-secondary:focus{color:#2c2e30}.link-success{color:#3fb618}.link-success:hover,.link-success:focus{color:#329213}.link-info{color:#9954bb}.link-info:hover,.link-info:focus{color:#7a4396}.link-warning{color:#ff7518}.link-warning:hover,.link-warning:focus{color:#cc5e13}.link-danger{color:#ff0039}.link-danger:hover,.link-danger:focus{color:#cc002e}.link-light{color:#f8f9fa}.link-light:hover,.link-light:focus{color:#f9fafb}.link-dark{color:#373a3c}.link-dark:hover,.link-dark:focus{color:#2c2e30}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}@media(min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}}@media(min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}}@media(min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}}@media(min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}}@media(min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}}.hstack{display:flex;display:-webkit-flex;flex-direction:row;-webkit-flex-direction:row;align-items:center;-webkit-align-items:center;align-self:stretch;-webkit-align-self:stretch}.vstack{display:flex;display:-webkit-flex;flex:1 1 auto;-webkit-flex:1 1 auto;flex-direction:column;-webkit-flex-direction:column;align-self:stretch;-webkit-align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;-webkit-align-self:stretch;width:1px;min-height:1em;background-color:currentColor;opacity:.25}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-start{float:left !important}.float-end{float:right !important}.float-none{float:none !important}.opacity-0{opacity:0 !important}.opacity-25{opacity:.25 !important}.opacity-50{opacity:.5 !important}.opacity-75{opacity:.75 !important}.opacity-100{opacity:1 !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.overflow-visible{overflow:visible !important}.overflow-scroll{overflow:scroll !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15) !important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175) !important}.shadow-none{box-shadow:none !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.top-0{top:0 !important}.top-50{top:50% !important}.top-100{top:100% !important}.bottom-0{bottom:0 !important}.bottom-50{bottom:50% !important}.bottom-100{bottom:100% !important}.start-0{left:0 !important}.start-50{left:50% !important}.start-100{left:100% !important}.end-0{right:0 !important}.end-50{right:50% !important}.end-100{right:100% !important}.translate-middle{transform:translate(-50%, -50%) !important}.translate-middle-x{transform:translateX(-50%) !important}.translate-middle-y{transform:translateY(-50%) !important}.border{border:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-top-0{border-top:0 !important}.border-end{border-right:1px solid #dee2e6 !important}.border-end-0{border-right:0 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-bottom-0{border-bottom:0 !important}.border-start{border-left:1px solid #dee2e6 !important}.border-start-0{border-left:0 !important}.border-default{border-color:#373a3c !important}.border-primary{border-color:#2780e3 !important}.border-secondary{border-color:#373a3c !important}.border-success{border-color:#3fb618 !important}.border-info{border-color:#9954bb !important}.border-warning{border-color:#ff7518 !important}.border-danger{border-color:#ff0039 !important}.border-light{border-color:#f8f9fa !important}.border-dark{border-color:#373a3c !important}.border-white{border-color:#fff !important}.border-1{border-width:1px !important}.border-2{border-width:2px !important}.border-3{border-width:3px !important}.border-4{border-width:4px !important}.border-5{border-width:5px !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-0{gap:0 !important}.gap-1{gap:.25rem !important}.gap-2{gap:.5rem !important}.gap-3{gap:1rem !important}.gap-4{gap:1.5rem !important}.gap-5{gap:3rem !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.fs-1{font-size:calc(1.325rem + 0.9vw) !important}.fs-2{font-size:calc(1.29rem + 0.48vw) !important}.fs-3{font-size:calc(1.27rem + 0.24vw) !important}.fs-4{font-size:1.25rem !important}.fs-5{font-size:1.1rem !important}.fs-6{font-size:1rem !important}.fst-italic{font-style:italic !important}.fst-normal{font-style:normal !important}.fw-light{font-weight:300 !important}.fw-lighter{font-weight:lighter !important}.fw-normal{font-weight:400 !important}.fw-bold{font-weight:700 !important}.fw-bolder{font-weight:bolder !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.text-start{text-align:left !important}.text-end{text-align:right !important}.text-center{text-align:center !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.text-default{--bs-text-opacity: 1;color:rgba(var(--bs-default-rgb), var(--bs-text-opacity)) !important}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important}.text-secondary{--bs-text-opacity: 1;color:rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important}.text-success{--bs-text-opacity: 1;color:rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important}.text-info{--bs-text-opacity: 1;color:rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important}.text-warning{--bs-text-opacity: 1;color:rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important}.text-danger{--bs-text-opacity: 1;color:rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important}.text-light{--bs-text-opacity: 1;color:rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important}.text-dark{--bs-text-opacity: 1;color:rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important}.text-black{--bs-text-opacity: 1;color:rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important}.text-white{--bs-text-opacity: 1;color:rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important}.text-body{--bs-text-opacity: 1;color:rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important}.text-muted{--bs-text-opacity: 1;color:#6c757d !important}.text-black-50{--bs-text-opacity: 1;color:rgba(0,0,0,.5) !important}.text-white-50{--bs-text-opacity: 1;color:rgba(255,255,255,.5) !important}.text-reset{--bs-text-opacity: 1;color:inherit !important}.text-opacity-25{--bs-text-opacity: 0.25}.text-opacity-50{--bs-text-opacity: 0.5}.text-opacity-75{--bs-text-opacity: 0.75}.text-opacity-100{--bs-text-opacity: 1}.bg-default{--bs-bg-opacity: 1;background-color:rgba(var(--bs-default-rgb), var(--bs-bg-opacity)) !important}.bg-primary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important}.bg-secondary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important}.bg-success{--bs-bg-opacity: 1;background-color:rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important}.bg-info{--bs-bg-opacity: 1;background-color:rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important}.bg-warning{--bs-bg-opacity: 1;background-color:rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important}.bg-danger{--bs-bg-opacity: 1;background-color:rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important}.bg-light{--bs-bg-opacity: 1;background-color:rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important}.bg-dark{--bs-bg-opacity: 1;background-color:rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important}.bg-black{--bs-bg-opacity: 1;background-color:rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important}.bg-white{--bs-bg-opacity: 1;background-color:rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important}.bg-body{--bs-bg-opacity: 1;background-color:rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important}.bg-transparent{--bs-bg-opacity: 1;background-color:rgba(0,0,0,0) !important}.bg-opacity-10{--bs-bg-opacity: 0.1}.bg-opacity-25{--bs-bg-opacity: 0.25}.bg-opacity-50{--bs-bg-opacity: 0.5}.bg-opacity-75{--bs-bg-opacity: 0.75}.bg-opacity-100{--bs-bg-opacity: 1}.bg-gradient{background-image:var(--bs-gradient) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:.25rem !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:.2em !important}.rounded-2{border-radius:.25rem !important}.rounded-3{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-top{border-top-left-radius:.25rem !important;border-top-right-radius:.25rem !important}.rounded-end{border-top-right-radius:.25rem !important;border-bottom-right-radius:.25rem !important}.rounded-bottom{border-bottom-right-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-start{border-bottom-left-radius:.25rem !important;border-top-left-radius:.25rem !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media(min-width: 576px){.float-sm-start{float:left !important}.float-sm-end{float:right !important}.float-sm-none{float:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-sm-0{gap:0 !important}.gap-sm-1{gap:.25rem !important}.gap-sm-2{gap:.5rem !important}.gap-sm-3{gap:1rem !important}.gap-sm-4{gap:1.5rem !important}.gap-sm-5{gap:3rem !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}.text-sm-start{text-align:left !important}.text-sm-end{text-align:right !important}.text-sm-center{text-align:center !important}}@media(min-width: 768px){.float-md-start{float:left !important}.float-md-end{float:right !important}.float-md-none{float:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-md-0{gap:0 !important}.gap-md-1{gap:.25rem !important}.gap-md-2{gap:.5rem !important}.gap-md-3{gap:1rem !important}.gap-md-4{gap:1.5rem !important}.gap-md-5{gap:3rem !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}.text-md-start{text-align:left !important}.text-md-end{text-align:right !important}.text-md-center{text-align:center !important}}@media(min-width: 992px){.float-lg-start{float:left !important}.float-lg-end{float:right !important}.float-lg-none{float:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-lg-0{gap:0 !important}.gap-lg-1{gap:.25rem !important}.gap-lg-2{gap:.5rem !important}.gap-lg-3{gap:1rem !important}.gap-lg-4{gap:1.5rem !important}.gap-lg-5{gap:3rem !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}.text-lg-start{text-align:left !important}.text-lg-end{text-align:right !important}.text-lg-center{text-align:center !important}}@media(min-width: 1200px){.float-xl-start{float:left !important}.float-xl-end{float:right !important}.float-xl-none{float:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xl-0{gap:0 !important}.gap-xl-1{gap:.25rem !important}.gap-xl-2{gap:.5rem !important}.gap-xl-3{gap:1rem !important}.gap-xl-4{gap:1.5rem !important}.gap-xl-5{gap:3rem !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}.text-xl-start{text-align:left !important}.text-xl-end{text-align:right !important}.text-xl-center{text-align:center !important}}@media(min-width: 1400px){.float-xxl-start{float:left !important}.float-xxl-end{float:right !important}.float-xxl-none{float:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.gap-xxl-0{gap:0 !important}.gap-xxl-1{gap:.25rem !important}.gap-xxl-2{gap:.5rem !important}.gap-xxl-3{gap:1rem !important}.gap-xxl-4{gap:1.5rem !important}.gap-xxl-5{gap:3rem !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}.text-xxl-start{text-align:left !important}.text-xxl-end{text-align:right !important}.text-xxl-center{text-align:center !important}}.bg-default{color:#fff}.bg-primary{color:#fff}.bg-secondary{color:#fff}.bg-success{color:#fff}.bg-info{color:#fff}.bg-warning{color:#fff}.bg-danger{color:#fff}.bg-light{color:#000}.bg-dark{color:#fff}@media(min-width: 1200px){.fs-1{font-size:2rem !important}.fs-2{font-size:1.65rem !important}.fs-3{font-size:1.45rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}}.quarto-container{min-height:calc(100vh - 132px)}footer.footer .nav-footer,#quarto-header>nav{padding-left:1em;padding-right:1em}nav[role=doc-toc]{padding-left:.5em}#quarto-content>*{padding-top:14px}@media(max-width: 991.98px){#quarto-content>*{padding-top:0}#quarto-content .subtitle{padding-top:14px}#quarto-content section:first-of-type h2:first-of-type,#quarto-content section:first-of-type .h2:first-of-type{margin-top:1rem}}.headroom-target,header.headroom{will-change:transform;transition:position 200ms linear;transition:all 200ms linear}header.headroom--pinned{transform:translateY(0%)}header.headroom--unpinned{transform:translateY(-100%)}.navbar-container{width:100%}.navbar-brand{overflow:hidden;text-overflow:ellipsis}.navbar-brand-container{max-width:calc(100% - 115px);min-width:0;display:flex;align-items:center}@media(min-width: 992px){.navbar-brand-container{margin-right:1em}}.navbar-brand.navbar-brand-logo{margin-right:4px;display:inline-flex}.navbar-toggler{flex-basis:content;flex-shrink:0}.navbar .navbar-toggler{order:-1;margin-right:.5em}.navbar-logo{max-height:24px;width:auto;padding-right:4px}nav .nav-item:not(.compact){padding-top:1px}nav .nav-link i,nav .dropdown-item i{padding-right:1px}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.6rem;padding-right:.6rem}nav .nav-item.compact .nav-link{padding-left:.5rem;padding-right:.5rem;font-size:1.1rem}.navbar .quarto-navbar-tools div.dropdown{display:inline-block}.navbar .quarto-navbar-tools .quarto-navigation-tool{color:#545555}.navbar .quarto-navbar-tools .quarto-navigation-tool:hover{color:#1a5698}@media(max-width: 991.98px){.navbar .quarto-navbar-tools{margin-top:.25em;padding-top:.75em;display:block;color:solid #d4d4d4 1px;text-align:center;vertical-align:middle;margin-right:auto}}.navbar-nav .dropdown-menu{min-width:220px;font-size:.9rem}.navbar .navbar-nav .nav-link.dropdown-toggle::after{opacity:.75;vertical-align:.175em}.navbar ul.dropdown-menu{padding-top:0;padding-bottom:0}.navbar .dropdown-header{text-transform:uppercase;font-size:.8rem;padding:0 .5rem}.navbar .dropdown-item{padding:.4rem .5rem}.navbar .dropdown-item>i.bi{margin-left:.1rem;margin-right:.25em}.sidebar #quarto-search{margin-top:-1px}.sidebar #quarto-search svg.aa-SubmitIcon{width:16px;height:16px}.sidebar-navigation a{color:inherit}.sidebar-title{margin-top:.25rem;padding-bottom:.5rem;font-size:1.3rem;line-height:1.6rem;visibility:visible}.sidebar-title>a{font-size:inherit;text-decoration:none}.sidebar-title .sidebar-tools-main{margin-top:-6px}@media(max-width: 991.98px){#quarto-sidebar div.sidebar-header{padding-top:.2em}}.sidebar-header-stacked .sidebar-title{margin-top:.6rem}.sidebar-logo{max-width:90%;padding-bottom:.5rem}.sidebar-logo-link{text-decoration:none}.sidebar-navigation li a{text-decoration:none}.sidebar-navigation .quarto-navigation-tool{opacity:.7;font-size:.875rem}#quarto-sidebar>nav>.sidebar-tools-main{margin-left:14px}.sidebar-tools-main{display:inline-flex;margin-left:0px;order:2}.sidebar-tools-main:not(.tools-wide){vertical-align:middle}.sidebar-navigation .quarto-navigation-tool.dropdown-toggle::after{display:none}.sidebar.sidebar-navigation>*{padding-top:1em}.sidebar-item{margin-bottom:.2em}.sidebar-section{margin-top:.2em;padding-left:.5em;padding-bottom:.2em}.sidebar-item .sidebar-item-container{display:flex;justify-content:space-between}.sidebar-item-toggle:hover{cursor:pointer}.sidebar-item .sidebar-item-toggle .bi{font-size:.7rem;text-align:center}.sidebar-item .sidebar-item-toggle .bi-chevron-right::before{transition:transform 200ms ease}.sidebar-item .sidebar-item-toggle[aria-expanded=false] .bi-chevron-right::before{transform:none}.sidebar-item .sidebar-item-toggle[aria-expanded=true] .bi-chevron-right::before{transform:rotate(90deg)}.sidebar-navigation .sidebar-divider{margin-left:0;margin-right:0;margin-top:.5rem;margin-bottom:.5rem}@media(max-width: 991.98px){.quarto-secondary-nav{display:block}.quarto-secondary-nav button.quarto-search-button{padding-right:0em;padding-left:2em}.quarto-secondary-nav button.quarto-btn-toggle{margin-left:-0.75rem;margin-right:.15rem}.quarto-secondary-nav nav.quarto-page-breadcrumbs{display:flex;align-items:center;padding-right:1em;margin-left:-0.25em}.quarto-secondary-nav nav.quarto-page-breadcrumbs a{text-decoration:none}.quarto-secondary-nav nav.quarto-page-breadcrumbs ol.breadcrumb{margin-bottom:0}}@media(min-width: 992px){.quarto-secondary-nav{display:none}}.quarto-secondary-nav .quarto-btn-toggle{color:#545555}.quarto-secondary-nav[aria-expanded=false] .quarto-btn-toggle .bi-chevron-right::before{transform:none}.quarto-secondary-nav[aria-expanded=true] .quarto-btn-toggle .bi-chevron-right::before{transform:rotate(90deg)}.quarto-secondary-nav .quarto-btn-toggle .bi-chevron-right::before{transition:transform 200ms ease}.quarto-secondary-nav{cursor:pointer}.quarto-secondary-nav-title{margin-top:.3em;color:#545555;padding-top:4px}.quarto-secondary-nav nav.quarto-page-breadcrumbs{color:#545555}.quarto-secondary-nav nav.quarto-page-breadcrumbs a{color:#545555}.quarto-secondary-nav nav.quarto-page-breadcrumbs a:hover{color:rgba(26,86,152,.8)}.quarto-secondary-nav nav.quarto-page-breadcrumbs .breadcrumb-item::before{color:#878888}div.sidebar-item-container{color:#545555}div.sidebar-item-container:hover,div.sidebar-item-container:focus{color:rgba(26,86,152,.8)}div.sidebar-item-container.disabled{color:rgba(84,85,85,.75)}div.sidebar-item-container .active,div.sidebar-item-container .show>.nav-link,div.sidebar-item-container .sidebar-link>code{color:#1a5698}div.sidebar.sidebar-navigation.rollup.quarto-sidebar-toggle-contents,nav.sidebar.sidebar-navigation:not(.rollup){background-color:#f8f9fa}.sidebar.sidebar-navigation:not(.rollup){border-right:1px solid #dee2e6 !important}@media(max-width: 991.98px){.sidebar-navigation .sidebar-item a,.nav-page .nav-page-text,.sidebar-navigation{font-size:1rem}.sidebar-navigation ul.sidebar-section.depth1 .sidebar-section-item{font-size:1.1rem}.sidebar-logo{display:none}.sidebar.sidebar-navigation{position:static;border-bottom:1px solid #dee2e6}.sidebar.sidebar-navigation.collapsing{position:fixed;z-index:1000}.sidebar.sidebar-navigation.show{position:fixed;z-index:1000}.sidebar.sidebar-navigation{min-height:100%}nav.quarto-secondary-nav{background-color:#f8f9fa;border-bottom:1px solid #dee2e6}.sidebar .sidebar-footer{visibility:visible;padding-top:1rem;position:inherit}.sidebar-tools-collapse{display:block}}#quarto-sidebar{transition:width .15s ease-in}#quarto-sidebar>*{padding-right:1em}@media(max-width: 991.98px){#quarto-sidebar .sidebar-menu-container{white-space:nowrap;min-width:225px}#quarto-sidebar.show{transition:width .15s ease-out}}@media(min-width: 992px){#quarto-sidebar{display:flex;flex-direction:column}.nav-page .nav-page-text,.sidebar-navigation .sidebar-section .sidebar-item{font-size:.875rem}.sidebar-navigation .sidebar-item{font-size:.925rem}.sidebar.sidebar-navigation{display:block;position:sticky}.sidebar-search{width:100%}.sidebar .sidebar-footer{visibility:visible}}@media(max-width: 991.98px){#quarto-sidebar-glass{position:fixed;top:0;bottom:0;left:0;right:0;background-color:rgba(255,255,255,0);transition:background-color .15s ease-in;z-index:-1}#quarto-sidebar-glass.collapsing{z-index:1000}#quarto-sidebar-glass.show{transition:background-color .15s ease-out;background-color:rgba(102,102,102,.4);z-index:1000}}.sidebar .sidebar-footer{padding:.5rem 1rem;align-self:flex-end;color:#6c757d;width:100%}.quarto-page-breadcrumbs .breadcrumb-item+.breadcrumb-item,.quarto-page-breadcrumbs .breadcrumb-item{padding-right:.33em;padding-left:0}.quarto-page-breadcrumbs .breadcrumb-item::before{padding-right:.33em}.quarto-sidebar-footer{font-size:.875em}.sidebar-section .bi-chevron-right{vertical-align:middle}.sidebar-section .bi-chevron-right::before{font-size:.9em}.notransition{-webkit-transition:none !important;-moz-transition:none !important;-o-transition:none !important;transition:none !important}.btn:focus:not(:focus-visible){box-shadow:none}.page-navigation{display:flex;justify-content:space-between}.nav-page{padding-bottom:.75em}.nav-page .bi{font-size:1.8rem;vertical-align:middle}.nav-page .nav-page-text{padding-left:.25em;padding-right:.25em}.nav-page a{color:#6c757d;text-decoration:none;display:flex;align-items:center}.nav-page a:hover{color:#1f66b6}.toc-actions{display:flex}.toc-actions p{margin-block-start:0;margin-block-end:0}.toc-actions a{text-decoration:none;color:inherit;font-weight:400}.toc-actions a:hover{color:#1f66b6}.toc-actions .action-links{margin-left:4px}.sidebar nav[role=doc-toc] .toc-actions .bi{margin-left:-4px;font-size:.7rem;color:#6c757d}.sidebar nav[role=doc-toc] .toc-actions .bi:before{padding-top:3px}#quarto-margin-sidebar .toc-actions .bi:before{margin-top:.3rem;font-size:.7rem;color:#6c757d;vertical-align:top}.sidebar nav[role=doc-toc] .toc-actions>div:first-of-type{margin-top:-3px}#quarto-margin-sidebar .toc-actions p,.sidebar nav[role=doc-toc] .toc-actions p{font-size:.875rem}.nav-footer .toc-actions{padding-bottom:.5em;padding-top:.5em}.nav-footer .toc-actions :first-child{margin-left:auto}.nav-footer .toc-actions :last-child{margin-right:auto}.nav-footer .toc-actions .action-links{display:flex}.nav-footer .toc-actions .action-links p{padding-right:1.5em}.nav-footer .toc-actions .action-links p:last-of-type{padding-right:0}.nav-footer{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;align-items:baseline;text-align:center;padding-top:.5rem;padding-bottom:.5rem;background-color:#fff}body.nav-fixed{padding-top:64px}body .nav-footer{border-top:1px solid #dee2e6}.nav-footer-contents{color:#6c757d;margin-top:.25rem}.nav-footer{min-height:3.5em;color:#757575}.nav-footer a{color:#757575}.nav-footer .nav-footer-left{font-size:.825em}.nav-footer .nav-footer-center{font-size:.825em}.nav-footer .nav-footer-right{font-size:.825em}.nav-footer-left .footer-items,.nav-footer-center .footer-items,.nav-footer-right .footer-items{display:inline-flex;padding-top:.3em;padding-bottom:.3em;margin-bottom:0em}.nav-footer-left .footer-items .nav-link,.nav-footer-center .footer-items .nav-link,.nav-footer-right .footer-items .nav-link{padding-left:.6em;padding-right:.6em}.nav-footer-left{flex:1 1 0px;text-align:left}.nav-footer-right{flex:1 1 0px;text-align:right}.nav-footer-center{flex:1 1 0px;min-height:3em;text-align:center}.nav-footer-center .footer-items{justify-content:center}@media(max-width: 767.98px){.nav-footer-center{margin-top:3em}}.navbar .quarto-reader-toggle.reader .quarto-reader-toggle-btn{background-color:#545555;border-radius:3px}.quarto-reader-toggle.reader.quarto-navigation-tool .quarto-reader-toggle-btn{background-color:#545555;border-radius:3px}.quarto-reader-toggle .quarto-reader-toggle-btn{display:inline-flex;padding-left:.2em;padding-right:.2em;margin-left:-0.2em;margin-right:-0.2em;text-align:center}.navbar .quarto-reader-toggle:not(.reader) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-reader-toggle.reader .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-reader-toggle:not(.reader) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-reader-toggle.reader .bi::before{background-image:url('data:image/svg+xml,')}#quarto-back-to-top{display:none;position:fixed;bottom:50px;background-color:#fff;border-radius:.25rem;box-shadow:0 .2rem .5rem #6c757d,0 0 .05rem #6c757d;color:#6c757d;text-decoration:none;font-size:.9em;text-align:center;left:50%;padding:.4rem .8rem;transform:translate(-50%, 0)}.aa-DetachedOverlay ul.aa-List,#quarto-search-results ul.aa-List{list-style:none;padding-left:0}.aa-DetachedOverlay .aa-Panel,#quarto-search-results .aa-Panel{background-color:#fff;position:absolute;z-index:2000}#quarto-search-results .aa-Panel{max-width:400px}#quarto-search input{font-size:.925rem}@media(min-width: 992px){.navbar #quarto-search{margin-left:.25rem;order:999}}@media(max-width: 991.98px){#quarto-sidebar .sidebar-search{display:none}}#quarto-sidebar .sidebar-search .aa-Autocomplete{width:100%}.navbar .aa-Autocomplete .aa-Form{width:180px}.navbar #quarto-search.type-overlay .aa-Autocomplete{width:40px}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form{background-color:inherit;border:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form:focus-within{box-shadow:none;outline:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-InputWrapper{display:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-InputWrapper:focus-within{display:inherit}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-Label svg,.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-LoadingIndicator svg{width:26px;height:26px;color:#545555;opacity:1}.navbar #quarto-search.type-overlay .aa-Autocomplete svg.aa-SubmitIcon{width:26px;height:26px;color:#545555;opacity:1}.aa-Autocomplete .aa-Form,.aa-DetachedFormContainer .aa-Form{align-items:center;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;color:#373a3c;display:flex;line-height:1em;margin:0;position:relative;width:100%}.aa-Autocomplete .aa-Form:focus-within,.aa-DetachedFormContainer .aa-Form:focus-within{box-shadow:rgba(39,128,227,.6) 0 0 0 1px;outline:currentColor none medium}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix{align-items:center;display:flex;flex-shrink:0;order:1}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-Label,.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-Label,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator{cursor:initial;flex-shrink:0;padding:0;text-align:left}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-Label svg,.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-Label svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator svg{color:#373a3c;opacity:.5}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-SubmitButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-SubmitButton{appearance:none;background:none;border:0;margin:0}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator{align-items:center;display:flex;justify-content:center}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator[hidden]{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapper,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper{order:3;position:relative;width:100%}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input{appearance:none;background:none;border:0;color:#373a3c;font:inherit;height:calc(1.5em + .1rem + 2px);padding:0;width:100%}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::placeholder,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::placeholder{color:#373a3c;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input:focus{border-color:none;box-shadow:none;outline:none}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-decoration,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-cancel-button,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-button,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-decoration,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-decoration,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-cancel-button,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-button,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-decoration{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix{align-items:center;display:flex;order:4}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton{align-items:center;background:none;border:0;color:#373a3c;opacity:.8;cursor:pointer;display:flex;margin:0;width:calc(1.5em + .1rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:hover,.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:hover,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:focus{color:#373a3c;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton[hidden]{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton svg{width:calc(1.5em + 0.75rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton{border:none;align-items:center;background:none;color:#373a3c;opacity:.4;font-size:.7rem;cursor:pointer;display:none;margin:0;width:calc(1em + .1rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:hover,.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:hover,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:focus{color:#373a3c;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton[hidden]{display:none}.aa-PanelLayout:empty{display:none}.quarto-search-no-results.no-query{display:none}.aa-Source:has(.no-query){display:none}#quarto-search-results .aa-Panel{border:solid #ced4da 1px}#quarto-search-results .aa-SourceNoResults{width:398px}.aa-DetachedOverlay .aa-Panel,#quarto-search-results .aa-Panel{max-height:65vh;overflow-y:auto;font-size:.925rem}.aa-DetachedOverlay .aa-SourceNoResults,#quarto-search-results .aa-SourceNoResults{height:60px;display:flex;justify-content:center;align-items:center}.aa-DetachedOverlay .search-error,#quarto-search-results .search-error{padding-top:10px;padding-left:20px;padding-right:20px;cursor:default}.aa-DetachedOverlay .search-error .search-error-title,#quarto-search-results .search-error .search-error-title{font-size:1.1rem;margin-bottom:.5rem}.aa-DetachedOverlay .search-error .search-error-title .search-error-icon,#quarto-search-results .search-error .search-error-title .search-error-icon{margin-right:8px}.aa-DetachedOverlay .search-error .search-error-text,#quarto-search-results .search-error .search-error-text{font-weight:300}.aa-DetachedOverlay .search-result-text,#quarto-search-results .search-result-text{font-weight:300;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.2rem;max-height:2.4rem}.aa-DetachedOverlay .aa-SourceHeader .search-result-header,#quarto-search-results .aa-SourceHeader .search-result-header{font-size:.875rem;background-color:#f2f2f2;padding-left:14px;padding-bottom:4px;padding-top:4px}.aa-DetachedOverlay .aa-SourceHeader .search-result-header-no-results,#quarto-search-results .aa-SourceHeader .search-result-header-no-results{display:none}.aa-DetachedOverlay .aa-SourceFooter .algolia-search-logo,#quarto-search-results .aa-SourceFooter .algolia-search-logo{width:110px;opacity:.85;margin:8px;float:right}.aa-DetachedOverlay .search-result-section,#quarto-search-results .search-result-section{font-size:.925em}.aa-DetachedOverlay a.search-result-link,#quarto-search-results a.search-result-link{color:inherit;text-decoration:none}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item,#quarto-search-results li.aa-Item[aria-selected=true] .search-item{background-color:#2780e3}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item.search-result-more,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-section,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-text,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-title-container,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-text-container,#quarto-search-results li.aa-Item[aria-selected=true] .search-item.search-result-more,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-section,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-text,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-title-container,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-text-container{color:#fff;background-color:#2780e3}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item mark.search-match,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-match.mark,#quarto-search-results li.aa-Item[aria-selected=true] .search-item mark.search-match,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-match.mark{color:#fff;background-color:#4b95e8}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item,#quarto-search-results li.aa-Item[aria-selected=false] .search-item{background-color:#fff}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item.search-result-more,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-section,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-text,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-title-container,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-text-container,#quarto-search-results li.aa-Item[aria-selected=false] .search-item.search-result-more,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-section,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-text,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-title-container,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-text-container{color:#373a3c}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item mark.search-match,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-match.mark,#quarto-search-results li.aa-Item[aria-selected=false] .search-item mark.search-match,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-match.mark{color:inherit;background-color:#e5effc}.aa-DetachedOverlay .aa-Item .search-result-doc:not(.document-selectable) .search-result-title-container,#quarto-search-results .aa-Item .search-result-doc:not(.document-selectable) .search-result-title-container{background-color:#fff;color:#373a3c}.aa-DetachedOverlay .aa-Item .search-result-doc:not(.document-selectable) .search-result-text-container,#quarto-search-results .aa-Item .search-result-doc:not(.document-selectable) .search-result-text-container{padding-top:0px}.aa-DetachedOverlay li.aa-Item .search-result-doc.document-selectable .search-result-text-container,#quarto-search-results li.aa-Item .search-result-doc.document-selectable .search-result-text-container{margin-top:-4px}.aa-DetachedOverlay .aa-Item,#quarto-search-results .aa-Item{cursor:pointer}.aa-DetachedOverlay .aa-Item .search-item,#quarto-search-results .aa-Item .search-item{border-left:none;border-right:none;border-top:none;background-color:#fff;border-color:#ced4da;color:#373a3c}.aa-DetachedOverlay .aa-Item .search-item p,#quarto-search-results .aa-Item .search-item p{margin-top:0;margin-bottom:0}.aa-DetachedOverlay .aa-Item .search-item i.bi,#quarto-search-results .aa-Item .search-item i.bi{padding-left:8px;padding-right:8px;font-size:1.3em}.aa-DetachedOverlay .aa-Item .search-item .search-result-title,#quarto-search-results .aa-Item .search-item .search-result-title{margin-top:.3em;margin-bottom:.1rem}.aa-DetachedOverlay .aa-Item .search-result-title-container,#quarto-search-results .aa-Item .search-result-title-container{font-size:1em;display:flex;padding:6px 4px 6px 4px}.aa-DetachedOverlay .aa-Item .search-result-text-container,#quarto-search-results .aa-Item .search-result-text-container{padding-bottom:8px;padding-right:8px;margin-left:44px}.aa-DetachedOverlay .aa-Item .search-result-doc-section,.aa-DetachedOverlay .aa-Item .search-result-more,#quarto-search-results .aa-Item .search-result-doc-section,#quarto-search-results .aa-Item .search-result-more{padding-top:8px;padding-bottom:8px;padding-left:44px}.aa-DetachedOverlay .aa-Item .search-result-more,#quarto-search-results .aa-Item .search-result-more{font-size:.8em;font-weight:400}.aa-DetachedOverlay .aa-Item .search-result-doc,#quarto-search-results .aa-Item .search-result-doc{border-top:1px solid #ced4da}.aa-DetachedSearchButton{background:none;border:none}.aa-DetachedSearchButton .aa-DetachedSearchButtonPlaceholder{display:none}.navbar .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon{color:#545555}.sidebar-tools-collapse #quarto-search,.sidebar-tools-main #quarto-search{display:inline}.sidebar-tools-collapse #quarto-search .aa-Autocomplete,.sidebar-tools-main #quarto-search .aa-Autocomplete{display:inline}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton{padding-left:4px;padding-right:4px}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon{color:#545555}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon .aa-SubmitIcon,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon .aa-SubmitIcon{margin-top:-3px}.aa-DetachedContainer{background:rgba(255,255,255,.65);width:90%;bottom:0;box-shadow:rgba(206,212,218,.6) 0 0 0 1px;outline:currentColor none medium;display:flex;flex-direction:column;left:0;margin:0;overflow:hidden;padding:0;position:fixed;right:0;top:0;z-index:1101}.aa-DetachedContainer::after{height:32px}.aa-DetachedContainer .aa-SourceHeader{margin:var(--aa-spacing-half) 0 var(--aa-spacing-half) 2px}.aa-DetachedContainer .aa-Panel{background-color:#fff;border-radius:0;box-shadow:none;flex-grow:1;margin:0;padding:0;position:relative}.aa-DetachedContainer .aa-PanelLayout{bottom:0;box-shadow:none;left:0;margin:0;max-height:none;overflow-y:auto;position:absolute;right:0;top:0;width:100%}.aa-DetachedFormContainer{background-color:#fff;border-bottom:1px solid #ced4da;display:flex;flex-direction:row;justify-content:space-between;margin:0;padding:.5em}.aa-DetachedCancelButton{background:none;font-size:.8em;border:0;border-radius:3px;color:#373a3c;cursor:pointer;margin:0 0 0 .5em;padding:0 .5em}.aa-DetachedCancelButton:hover,.aa-DetachedCancelButton:focus{box-shadow:rgba(39,128,227,.6) 0 0 0 1px;outline:currentColor none medium}.aa-DetachedContainer--modal{bottom:inherit;height:auto;margin:0 auto;position:absolute;top:100px;border-radius:6px;max-width:850px}@media(max-width: 575.98px){.aa-DetachedContainer--modal{width:100%;top:0px;border-radius:0px;border:none}}.aa-DetachedContainer--modal .aa-PanelLayout{max-height:var(--aa-detached-modal-max-height);padding-bottom:var(--aa-spacing-half);position:static}.aa-Detached{height:100vh;overflow:hidden}.aa-DetachedOverlay{background-color:rgba(55,58,60,.4);position:fixed;left:0;right:0;top:0;margin:0;padding:0;height:100vh;z-index:1100}.quarto-listing{padding-bottom:1em}.listing-pagination{padding-top:.5em}ul.pagination{float:right;padding-left:8px;padding-top:.5em}ul.pagination li{padding-right:.75em}ul.pagination li.disabled a,ul.pagination li.active a{color:#373a3c;text-decoration:none}ul.pagination li:last-of-type{padding-right:0}.listing-actions-group{display:flex}.quarto-listing-filter{margin-bottom:1em;width:200px;margin-left:auto}.quarto-listing-sort{margin-bottom:1em;margin-right:auto;width:auto}.quarto-listing-sort .input-group-text{font-size:.8em}.input-group-text{border-right:none}.quarto-listing-sort select.form-select{font-size:.8em}.listing-no-matching{text-align:center;padding-top:2em;padding-bottom:3em;font-size:1em}#quarto-margin-sidebar .quarto-listing-category{padding-top:0;font-size:1rem}#quarto-margin-sidebar .quarto-listing-category-title{cursor:pointer;font-weight:600;font-size:1rem}.quarto-listing-category .category{cursor:pointer}.quarto-listing-category .category.active{font-weight:600}.quarto-listing-category.category-cloud{display:flex;flex-wrap:wrap;align-items:baseline}.quarto-listing-category.category-cloud .category{padding-right:5px}.quarto-listing-category.category-cloud .category-cloud-1{font-size:.75em}.quarto-listing-category.category-cloud .category-cloud-2{font-size:.95em}.quarto-listing-category.category-cloud .category-cloud-3{font-size:1.15em}.quarto-listing-category.category-cloud .category-cloud-4{font-size:1.35em}.quarto-listing-category.category-cloud .category-cloud-5{font-size:1.55em}.quarto-listing-category.category-cloud .category-cloud-6{font-size:1.75em}.quarto-listing-category.category-cloud .category-cloud-7{font-size:1.95em}.quarto-listing-category.category-cloud .category-cloud-8{font-size:2.15em}.quarto-listing-category.category-cloud .category-cloud-9{font-size:2.35em}.quarto-listing-category.category-cloud .category-cloud-10{font-size:2.55em}.quarto-listing-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-1{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-2{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-3{grid-template-columns:repeat(3, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-3{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-3{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-4{grid-template-columns:repeat(4, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-4{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-4{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-5{grid-template-columns:repeat(5, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-5{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-5{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-6{grid-template-columns:repeat(6, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-6{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-6{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-7{grid-template-columns:repeat(7, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-7{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-7{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-8{grid-template-columns:repeat(8, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-8{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-8{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-9{grid-template-columns:repeat(9, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-9{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-9{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-10{grid-template-columns:repeat(10, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-10{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-10{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-11{grid-template-columns:repeat(11, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-11{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-11{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-12{grid-template-columns:repeat(12, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-12{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-12{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-grid{gap:1.5em}.quarto-grid-item.borderless{border:none}.quarto-grid-item.borderless .listing-categories .listing-category:last-of-type,.quarto-grid-item.borderless .listing-categories .listing-category:first-of-type{padding-left:0}.quarto-grid-item.borderless .listing-categories .listing-category{border:0}.quarto-grid-link{text-decoration:none;color:inherit}.quarto-grid-link:hover{text-decoration:none;color:inherit}.quarto-grid-item h5.title,.quarto-grid-item .title.h5{margin-top:0;margin-bottom:0}.quarto-grid-item .card-footer{display:flex;justify-content:space-between;font-size:.8em}.quarto-grid-item .card-footer p{margin-bottom:0}.quarto-grid-item p.card-img-top{margin-bottom:0}.quarto-grid-item p.card-img-top>img{object-fit:cover}.quarto-grid-item .card-other-values{margin-top:.5em;font-size:.8em}.quarto-grid-item .card-other-values tr{margin-bottom:.5em}.quarto-grid-item .card-other-values tr>td:first-of-type{font-weight:600;padding-right:1em;padding-left:1em;vertical-align:top}.quarto-grid-item div.post-contents{display:flex;flex-direction:column;text-decoration:none;height:100%}.quarto-grid-item .listing-item-img-placeholder{background-color:#adb5bd;flex-shrink:0}.quarto-grid-item .card-attribution{padding-top:1em;display:flex;gap:1em;text-transform:uppercase;color:#6c757d;font-weight:500;flex-grow:10;align-items:flex-end}.quarto-grid-item .description{padding-bottom:1em}.quarto-grid-item .card-attribution .date{align-self:flex-end}.quarto-grid-item .card-attribution.justify{justify-content:space-between}.quarto-grid-item .card-attribution.start{justify-content:flex-start}.quarto-grid-item .card-attribution.end{justify-content:flex-end}.quarto-grid-item .card-title{margin-bottom:.1em}.quarto-grid-item .card-subtitle{padding-top:.25em}.quarto-grid-item .card-text{font-size:.9em}.quarto-grid-item .listing-reading-time{padding-bottom:.25em}.quarto-grid-item .card-text-small{font-size:.8em}.quarto-grid-item .card-subtitle.subtitle{font-size:.9em;font-weight:600;padding-bottom:.5em}.quarto-grid-item .listing-categories{display:flex;flex-wrap:wrap;padding-bottom:5px}.quarto-grid-item .listing-categories .listing-category{color:#6c757d;border:solid 1px #dee2e6;border-radius:.25rem;text-transform:uppercase;font-size:.65em;padding-left:.5em;padding-right:.5em;padding-top:.15em;padding-bottom:.15em;cursor:pointer;margin-right:4px;margin-bottom:4px}.quarto-grid-item.card-right{text-align:right}.quarto-grid-item.card-right .listing-categories{justify-content:flex-end}.quarto-grid-item.card-left{text-align:left}.quarto-grid-item.card-center{text-align:center}.quarto-grid-item.card-center .listing-description{text-align:justify}.quarto-grid-item.card-center .listing-categories{justify-content:center}table.quarto-listing-table td.image{padding:0px}table.quarto-listing-table td.image img{width:100%;max-width:50px;object-fit:contain}table.quarto-listing-table a{text-decoration:none}table.quarto-listing-table th a{color:inherit}table.quarto-listing-table th a.asc:after{margin-bottom:-2px;margin-left:5px;display:inline-block;height:1rem;width:1rem;background-repeat:no-repeat;background-size:1rem 1rem;background-image:url('data:image/svg+xml,');content:""}table.quarto-listing-table th a.desc:after{margin-bottom:-2px;margin-left:5px;display:inline-block;height:1rem;width:1rem;background-repeat:no-repeat;background-size:1rem 1rem;background-image:url('data:image/svg+xml,');content:""}table.quarto-listing-table.table-hover td{cursor:pointer}.quarto-post.image-left{flex-direction:row}.quarto-post.image-right{flex-direction:row-reverse}@media(max-width: 767.98px){.quarto-post.image-right,.quarto-post.image-left{gap:0em;flex-direction:column}.quarto-post .metadata{padding-bottom:1em;order:2}.quarto-post .body{order:1}.quarto-post .thumbnail{order:3}}.list.quarto-listing-default div:last-of-type{border-bottom:none}@media(min-width: 992px){.quarto-listing-container-default{margin-right:2em}}div.quarto-post{display:flex;gap:2em;margin-bottom:1.5em;border-bottom:1px solid #dee2e6}@media(max-width: 767.98px){div.quarto-post{padding-bottom:1em}}div.quarto-post .metadata{flex-basis:20%;flex-grow:0;margin-top:.2em;flex-shrink:10}div.quarto-post .thumbnail{flex-basis:30%;flex-grow:0;flex-shrink:0}div.quarto-post .thumbnail img{margin-top:.4em;width:100%;object-fit:cover}div.quarto-post .body{flex-basis:45%;flex-grow:1;flex-shrink:0}div.quarto-post .body h3.listing-title,div.quarto-post .body .listing-title.h3{margin-top:0px;margin-bottom:0px;border-bottom:none}div.quarto-post .body .listing-subtitle{font-size:.875em;margin-bottom:.5em;margin-top:.2em}div.quarto-post .body .description{font-size:.9em}div.quarto-post a{color:#373a3c;display:flex;flex-direction:column;text-decoration:none}div.quarto-post a div.description{flex-shrink:0}div.quarto-post .metadata{display:flex;flex-direction:column;font-size:.8em;font-family:var(--bs-font-sans-serif);flex-basis:33%}div.quarto-post .listing-categories{display:flex;flex-wrap:wrap;padding-bottom:5px}div.quarto-post .listing-categories .listing-category{color:#6c757d;border:solid 1px #dee2e6;border-radius:.25rem;text-transform:uppercase;font-size:.65em;padding-left:.5em;padding-right:.5em;padding-top:.15em;padding-bottom:.15em;cursor:pointer;margin-right:4px;margin-bottom:4px}div.quarto-post .listing-description{margin-bottom:.5em}div.quarto-about-jolla{display:flex !important;flex-direction:column;align-items:center;margin-top:10%;padding-bottom:1em}div.quarto-about-jolla .about-image{object-fit:cover;margin-left:auto;margin-right:auto;margin-bottom:1.5em}div.quarto-about-jolla img.round{border-radius:50%}div.quarto-about-jolla img.rounded{border-radius:10px}div.quarto-about-jolla .quarto-title h1.title,div.quarto-about-jolla .quarto-title .title.h1{text-align:center}div.quarto-about-jolla .quarto-title .description{text-align:center}div.quarto-about-jolla h2,div.quarto-about-jolla .h2{border-bottom:none}div.quarto-about-jolla .about-sep{width:60%}div.quarto-about-jolla main{text-align:center}div.quarto-about-jolla .about-links{display:flex}@media(min-width: 992px){div.quarto-about-jolla .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-jolla .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-jolla .about-link{color:#686d71;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-jolla .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-jolla .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-jolla .about-link:hover{color:#2780e3}div.quarto-about-jolla .about-link i.bi{margin-right:.15em}div.quarto-about-solana{display:flex !important;flex-direction:column;padding-top:3em !important;padding-bottom:1em}div.quarto-about-solana .about-entity{display:flex !important;align-items:start;justify-content:space-between}@media(min-width: 992px){div.quarto-about-solana .about-entity{flex-direction:row}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity{flex-direction:column-reverse;align-items:center;text-align:center}}div.quarto-about-solana .about-entity .entity-contents{display:flex;flex-direction:column}@media(max-width: 767.98px){div.quarto-about-solana .about-entity .entity-contents{width:100%}}div.quarto-about-solana .about-entity .about-image{object-fit:cover}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-image{margin-bottom:1.5em}}div.quarto-about-solana .about-entity img.round{border-radius:50%}div.quarto-about-solana .about-entity img.rounded{border-radius:10px}div.quarto-about-solana .about-entity .about-links{display:flex;justify-content:left;padding-bottom:1.2em}@media(min-width: 992px){div.quarto-about-solana .about-entity .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-solana .about-entity .about-link{color:#686d71;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-solana .about-entity .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-solana .about-entity .about-link:hover{color:#2780e3}div.quarto-about-solana .about-entity .about-link i.bi{margin-right:.15em}div.quarto-about-solana .about-contents{padding-right:1.5em;flex-basis:0;flex-grow:1}div.quarto-about-solana .about-contents main.content{margin-top:0}div.quarto-about-solana .about-contents h2,div.quarto-about-solana .about-contents .h2{border-bottom:none}div.quarto-about-trestles{display:flex !important;flex-direction:row;padding-top:3em !important;padding-bottom:1em}@media(max-width: 991.98px){div.quarto-about-trestles{flex-direction:column;padding-top:0em !important}}div.quarto-about-trestles .about-entity{display:flex !important;flex-direction:column;align-items:center;text-align:center;padding-right:1em}@media(min-width: 992px){div.quarto-about-trestles .about-entity{flex:0 0 42%}}div.quarto-about-trestles .about-entity .about-image{object-fit:cover;margin-bottom:1.5em}div.quarto-about-trestles .about-entity img.round{border-radius:50%}div.quarto-about-trestles .about-entity img.rounded{border-radius:10px}div.quarto-about-trestles .about-entity .about-links{display:flex;justify-content:center}@media(min-width: 992px){div.quarto-about-trestles .about-entity .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-trestles .about-entity .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-trestles .about-entity .about-link{color:#686d71;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-trestles .about-entity .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-trestles .about-entity .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-trestles .about-entity .about-link:hover{color:#2780e3}div.quarto-about-trestles .about-entity .about-link i.bi{margin-right:.15em}div.quarto-about-trestles .about-contents{flex-basis:0;flex-grow:1}div.quarto-about-trestles .about-contents h2,div.quarto-about-trestles .about-contents .h2{border-bottom:none}@media(min-width: 992px){div.quarto-about-trestles .about-contents{border-left:solid 1px #dee2e6;padding-left:1.5em}}div.quarto-about-trestles .about-contents main.content{margin-top:0}div.quarto-about-marquee{padding-bottom:1em}div.quarto-about-marquee .about-contents{display:flex;flex-direction:column}div.quarto-about-marquee .about-image{max-height:550px;margin-bottom:1.5em;object-fit:cover}div.quarto-about-marquee img.round{border-radius:50%}div.quarto-about-marquee img.rounded{border-radius:10px}div.quarto-about-marquee h2,div.quarto-about-marquee .h2{border-bottom:none}div.quarto-about-marquee .about-links{display:flex;justify-content:center;padding-top:1.5em}@media(min-width: 992px){div.quarto-about-marquee .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-marquee .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-marquee .about-link{color:#686d71;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-marquee .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-marquee .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-marquee .about-link:hover{color:#2780e3}div.quarto-about-marquee .about-link i.bi{margin-right:.15em}@media(min-width: 992px){div.quarto-about-marquee .about-link{border:none}}div.quarto-about-broadside{display:flex;flex-direction:column;padding-bottom:1em}div.quarto-about-broadside .about-main{display:flex !important;padding-top:0 !important}@media(min-width: 992px){div.quarto-about-broadside .about-main{flex-direction:row;align-items:flex-start}}@media(max-width: 991.98px){div.quarto-about-broadside .about-main{flex-direction:column}}@media(max-width: 991.98px){div.quarto-about-broadside .about-main .about-entity{flex-shrink:0;width:100%;height:450px;margin-bottom:1.5em;background-size:cover;background-repeat:no-repeat}}@media(min-width: 992px){div.quarto-about-broadside .about-main .about-entity{flex:0 10 50%;margin-right:1.5em;width:100%;height:100%;background-size:100%;background-repeat:no-repeat}}div.quarto-about-broadside .about-main .about-contents{padding-top:14px;flex:0 0 50%}div.quarto-about-broadside h2,div.quarto-about-broadside .h2{border-bottom:none}div.quarto-about-broadside .about-sep{margin-top:1.5em;width:60%;align-self:center}div.quarto-about-broadside .about-links{display:flex;justify-content:center;column-gap:20px;padding-top:1.5em}@media(min-width: 992px){div.quarto-about-broadside .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-broadside .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-broadside .about-link{color:#686d71;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-broadside .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-broadside .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-broadside .about-link:hover{color:#2780e3}div.quarto-about-broadside .about-link i.bi{margin-right:.15em}@media(min-width: 992px){div.quarto-about-broadside .about-link{border:none}}.tippy-box[data-theme~=quarto]{background-color:#fff;border:solid 1px #dee2e6;border-radius:.25rem;color:#373a3c;font-size:.875rem}.tippy-box[data-theme~=quarto]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=quarto]>.tippy-arrow:after,.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{content:"";position:absolute;z-index:-1}.tippy-box[data-theme~=quarto]>.tippy-arrow:after{border-color:rgba(0,0,0,0);border-style:solid}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-6px}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-6px}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-6px}.tippy-box[data-placement^=left]>.tippy-arrow:before{right:-6px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:after{border-top-color:#dee2e6;border-width:7px 7px 0;top:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow>svg{top:16px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow:after{top:17px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff;bottom:16px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:after{border-bottom-color:#dee2e6;border-width:0 7px 7px;bottom:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow>svg{bottom:15px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow:after{bottom:17px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:after{border-left-color:#dee2e6;border-width:7px 0 7px 7px;left:17px;top:1px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow>svg{left:11px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow:after{left:12px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff;right:16px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:after{border-width:7px 7px 7px 0;right:17px;top:1px;border-right-color:#dee2e6}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow>svg{right:11px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow:after{right:12px}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow{fill:#373a3c}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCA2czEuNzk2LS4wMTMgNC42Ny0zLjYxNUM1Ljg1MS45IDYuOTMuMDA2IDggMGMxLjA3LS4wMDYgMi4xNDguODg3IDMuMzQzIDIuMzg1QzE0LjIzMyA2LjAwNSAxNiA2IDE2IDZIMHoiIGZpbGw9InJnYmEoMCwgOCwgMTYsIDAuMikiLz48L3N2Zz4=);background-size:16px 6px;width:16px;height:6px}.top-right{position:absolute;top:1em;right:1em}.hidden{display:none !important}.zindex-bottom{z-index:-1 !important}.quarto-layout-panel{margin-bottom:1em}.quarto-layout-panel>figure{width:100%}.quarto-layout-panel>figure>figcaption,.quarto-layout-panel>.panel-caption{margin-top:10pt}.quarto-layout-panel>.table-caption{margin-top:0px}.table-caption p{margin-bottom:.5em}.quarto-layout-row{display:flex;flex-direction:row;align-items:flex-start}.quarto-layout-valign-top{align-items:flex-start}.quarto-layout-valign-bottom{align-items:flex-end}.quarto-layout-valign-center{align-items:center}.quarto-layout-cell{position:relative;margin-right:20px}.quarto-layout-cell:last-child{margin-right:0}.quarto-layout-cell figure,.quarto-layout-cell>p{margin:.2em}.quarto-layout-cell img{max-width:100%}.quarto-layout-cell .html-widget{width:100% !important}.quarto-layout-cell div figure p{margin:0}.quarto-layout-cell figure{display:inline-block;margin-inline-start:0;margin-inline-end:0}.quarto-layout-cell table{display:inline-table}.quarto-layout-cell-subref figcaption,figure .quarto-layout-row figure figcaption{text-align:center;font-style:italic}.quarto-figure{position:relative;margin-bottom:1em}.quarto-figure>figure{width:100%;margin-bottom:0}.quarto-figure-left>figure>p,.quarto-figure-left>figure>div{text-align:left}.quarto-figure-center>figure>p,.quarto-figure-center>figure>div{text-align:center}.quarto-figure-right>figure>p,.quarto-figure-right>figure>div{text-align:right}figure>p:empty{display:none}figure>p:first-child{margin-top:0;margin-bottom:0}figure>figcaption{margin-top:.5em}div[id^=tbl-]{position:relative}.quarto-figure>.anchorjs-link{position:absolute;top:.6em;right:.5em}div[id^=tbl-]>.anchorjs-link{position:absolute;top:.7em;right:.3em}.quarto-figure:hover>.anchorjs-link,div[id^=tbl-]:hover>.anchorjs-link,h2:hover>.anchorjs-link,.h2:hover>.anchorjs-link,h3:hover>.anchorjs-link,.h3:hover>.anchorjs-link,h4:hover>.anchorjs-link,.h4:hover>.anchorjs-link,h5:hover>.anchorjs-link,.h5:hover>.anchorjs-link,h6:hover>.anchorjs-link,.h6:hover>.anchorjs-link,.reveal-anchorjs-link>.anchorjs-link{opacity:1}#title-block-header{margin-block-end:1rem;position:relative;margin-top:-1px}#title-block-header .abstract{margin-block-start:1rem}#title-block-header .abstract .abstract-title{font-weight:600}#title-block-header a{text-decoration:none}#title-block-header .author,#title-block-header .date,#title-block-header .doi{margin-block-end:.2rem}#title-block-header .quarto-title-block>div{display:flex}#title-block-header .quarto-title-block>div>h1,#title-block-header .quarto-title-block>div>.h1{flex-grow:1}#title-block-header .quarto-title-block>div>button{flex-shrink:0;height:2.25rem;margin-top:0}@media(min-width: 992px){#title-block-header .quarto-title-block>div>button{margin-top:5px}}tr.header>th>p:last-of-type{margin-bottom:0px}table,.table{caption-side:top;margin-bottom:1.5rem}caption,.table-caption{padding-top:.5rem;padding-bottom:.5rem;text-align:center}.utterances{max-width:none;margin-left:-8px}iframe{margin-bottom:1em}details{margin-bottom:1em}details[show]{margin-bottom:0}details>summary{color:#6c757d}details>summary>p:only-child{display:inline}pre.sourceCode,code.sourceCode{position:relative}p code:not(.sourceCode){white-space:pre-wrap}code{white-space:pre}@media print{code{white-space:pre-wrap}}pre>code{display:block}pre>code.sourceCode{white-space:pre-wrap}pre>code.sourceCode>span>a:first-child::before{text-decoration:none}pre.code-overflow-wrap>code.sourceCode{white-space:pre-wrap}pre.code-overflow-scroll>code.sourceCode{white-space:pre}code a:any-link{color:inherit;text-decoration:none}code a:hover{color:inherit;text-decoration:underline}ul.task-list{padding-left:1em}[data-tippy-root]{display:inline-block}.tippy-content .footnote-back{display:none}.quarto-embedded-source-code{display:none}.quarto-unresolved-ref{font-weight:600}.quarto-cover-image{max-width:35%;float:right;margin-left:30px}.cell-output-display .widget-subarea{margin-bottom:1em}.cell-output-display:not(.no-overflow-x),.knitsql-table:not(.no-overflow-x){overflow-x:auto}.panel-input{margin-bottom:1em}.panel-input>div,.panel-input>div>div{display:inline-block;vertical-align:top;padding-right:12px}.panel-input>p:last-child{margin-bottom:0}.layout-sidebar{margin-bottom:1em}.layout-sidebar .tab-content{border:none}.tab-content>.page-columns.active{display:grid}div.sourceCode>iframe{width:100%;height:300px;margin-bottom:-0.5em}div.ansi-escaped-output{font-family:monospace;display:block}/*! +* +* ansi colors from IPython notebook's +* +*/.ansi-black-fg{color:#3e424d}.ansi-black-bg{background-color:#3e424d}.ansi-black-intense-fg{color:#282c36}.ansi-black-intense-bg{background-color:#282c36}.ansi-red-fg{color:#e75c58}.ansi-red-bg{background-color:#e75c58}.ansi-red-intense-fg{color:#b22b31}.ansi-red-intense-bg{background-color:#b22b31}.ansi-green-fg{color:#00a250}.ansi-green-bg{background-color:#00a250}.ansi-green-intense-fg{color:#007427}.ansi-green-intense-bg{background-color:#007427}.ansi-yellow-fg{color:#ddb62b}.ansi-yellow-bg{background-color:#ddb62b}.ansi-yellow-intense-fg{color:#b27d12}.ansi-yellow-intense-bg{background-color:#b27d12}.ansi-blue-fg{color:#208ffb}.ansi-blue-bg{background-color:#208ffb}.ansi-blue-intense-fg{color:#0065ca}.ansi-blue-intense-bg{background-color:#0065ca}.ansi-magenta-fg{color:#d160c4}.ansi-magenta-bg{background-color:#d160c4}.ansi-magenta-intense-fg{color:#a03196}.ansi-magenta-intense-bg{background-color:#a03196}.ansi-cyan-fg{color:#60c6c8}.ansi-cyan-bg{background-color:#60c6c8}.ansi-cyan-intense-fg{color:#258f8f}.ansi-cyan-intense-bg{background-color:#258f8f}.ansi-white-fg{color:#c5c1b4}.ansi-white-bg{background-color:#c5c1b4}.ansi-white-intense-fg{color:#a1a6b2}.ansi-white-intense-bg{background-color:#a1a6b2}.ansi-default-inverse-fg{color:#fff}.ansi-default-inverse-bg{background-color:#000}.ansi-bold{font-weight:bold}.ansi-underline{text-decoration:underline}:root{--quarto-body-bg: #fff;--quarto-body-color: #373a3c;--quarto-text-muted: #6c757d;--quarto-border-color: #dee2e6;--quarto-border-width: 1px;--quarto-border-radius: 0.25rem}table.gt_table{color:var(--quarto-body-color);font-size:1em;width:100%;background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_column_spanner_outer{color:var(--quarto-body-color);background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_col_heading{color:var(--quarto-body-color);font-weight:bold;background-color:rgba(0,0,0,0)}table.gt_table thead.gt_col_headings{border-bottom:1px solid currentColor;border-top-width:inherit;border-top-color:var(--quarto-border-color)}table.gt_table thead.gt_col_headings:not(:first-child){border-top-width:1px;border-top-color:var(--quarto-border-color)}table.gt_table td.gt_row{border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-width:0px}table.gt_table tbody.gt_table_body{border-top-width:1px;border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-color:currentColor}div.columns{display:initial;gap:initial}div.column{display:inline-block;overflow-x:initial;vertical-align:top;width:50%}.code-annotation-tip-content{word-wrap:break-word}.code-annotation-container-hidden{display:none !important}dl.code-annotation-container-grid{display:grid;grid-template-columns:min-content auto}dl.code-annotation-container-grid dt{grid-column:1}dl.code-annotation-container-grid dd{grid-column:2}pre.sourceCode.code-annotation-code{padding-right:0}code.sourceCode .code-annotation-anchor{z-index:100;position:absolute;right:.5em;left:inherit;background-color:rgba(0,0,0,0)}:root{--mermaid-bg-color: #fff;--mermaid-edge-color: #373a3c;--mermaid-node-fg-color: #373a3c;--mermaid-fg-color: #373a3c;--mermaid-fg-color--lighter: #4f5457;--mermaid-fg-color--lightest: #686d71;--mermaid-font-family: Source Sans Pro, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;--mermaid-label-bg-color: #fff;--mermaid-label-fg-color: #2780e3;--mermaid-node-bg-color: rgba(39, 128, 227, 0.1);--mermaid-node-fg-color: #373a3c}@media print{:root{font-size:11pt}#quarto-sidebar,#TOC,.nav-page{display:none}.page-columns .content{grid-column-start:page-start}.fixed-top{position:relative}.panel-caption,.figure-caption,figcaption{color:#666}}.code-copy-button{position:absolute;top:0;right:0;border:0;margin-top:5px;margin-right:5px;background-color:rgba(0,0,0,0);z-index:3}.code-copy-button:focus{outline:none}.code-copy-button-tooltip{font-size:.75em}.code-copy-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}.code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}.code-copy-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}.code-copy-button-checked:hover>.bi::before{background-image:url('data:image/svg+xml,')}main ol ol,main ul ul,main ol ul,main ul ol{margin-bottom:1em}ul>li:not(:has(>p))>ul,ol>li:not(:has(>p))>ul,ul>li:not(:has(>p))>ol,ol>li:not(:has(>p))>ol{margin-bottom:0}ul>li:not(:has(>p))>ul>li:has(>p),ol>li:not(:has(>p))>ul>li:has(>p),ul>li:not(:has(>p))>ol>li:has(>p),ol>li:not(:has(>p))>ol>li:has(>p){margin-top:1rem}body{margin:0}main.page-columns>header>h1.title,main.page-columns>header>.title.h1{margin-bottom:0}@media(min-width: 992px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 56px [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(500px, calc( 850px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 56px [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(500px, calc( 850px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] 35px [page-end-inset page-end] 5fr [screen-end-inset] 1.5em}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 56px [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(500px, calc( 850px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 56px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 850px - 3em )) [body-content-end] 3em [body-end] 80px [body-end-outset] minmax(0px, 250px) [page-end-inset] minmax(80px, 160px) [page-end] 1fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 56px [page-start-inset] minmax(0px, 280px) [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(450px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 56px [page-start-inset] minmax(0px, 280px) [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(450px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(40px, 80px) [page-start-inset] minmax(80px, 240px) [body-start-outset] minmax(40px, 80px) [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 1000px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 100px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 1000px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 80px [page-start-inset] minmax(80px, 240px) [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(450px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(80px, 160px) [page-start-inset] 80px [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(500px, calc( 1000px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 80px [page-start-inset] minmax(80px, 240px) [body-start-outset] 80px [body-start] 1.5em [body-content-start] minmax(450px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 150px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(40px, 80px) [page-start-inset] minmax(80px, 240px) [body-start-outset] minmax(40px, 80px) [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 991.98px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc( 1250px - 3em )) [body-content-end body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 56px [page-start-inset] minmax(0px, 232px) [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(450px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 56px [page-start-inset] minmax(0px, 232px) [body-start-outset] 56px [body-start] 1.5em [body-content-start] minmax(450px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1.5em [body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc( 1000px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc( 800px - 3em )) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc( 750px - 3em )) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 767.98px){body .page-columns,body.fullcontent:not(.floating):not(.docked) .page-columns,body.slimcontent:not(.floating):not(.docked) .page-columns,body.docked .page-columns,body.docked.slimcontent .page-columns,body.docked.fullcontent .page-columns,body.floating .page-columns,body.floating.slimcontent .page-columns,body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}nav[role=doc-toc]{display:none}}body,.page-row-navigation{grid-template-rows:[page-top] max-content [contents-top] max-content [contents-bottom] max-content [page-bottom]}.page-rows-contents{grid-template-rows:[content-top] minmax(max-content, 1fr) [content-bottom] minmax(60px, max-content) [page-bottom]}.page-full{grid-column:screen-start/screen-end !important}.page-columns>*{grid-column:body-content-start/body-content-end}.page-columns.column-page>*{grid-column:page-start/page-end}.page-columns.column-page-left>*{grid-column:page-start/body-content-end}.page-columns.column-page-right>*{grid-column:body-content-start/page-end}.page-rows{grid-auto-rows:auto}.header{grid-column:screen-start/screen-end;grid-row:page-top/contents-top}#quarto-content{padding:0;grid-column:screen-start/screen-end;grid-row:contents-top/contents-bottom}body.floating .sidebar.sidebar-navigation{grid-column:page-start/body-start;grid-row:content-top/page-bottom}body.docked .sidebar.sidebar-navigation{grid-column:screen-start/body-start;grid-row:content-top/page-bottom}.sidebar.toc-left{grid-column:page-start/body-start;grid-row:content-top/page-bottom}.sidebar.margin-sidebar{grid-column:body-end/page-end;grid-row:content-top/page-bottom}.page-columns .content{grid-column:body-content-start/body-content-end;grid-row:content-top/content-bottom;align-content:flex-start}.page-columns .page-navigation{grid-column:body-content-start/body-content-end;grid-row:content-bottom/page-bottom}.page-columns .footer{grid-column:screen-start/screen-end;grid-row:contents-bottom/page-bottom}.page-columns .column-body{grid-column:body-content-start/body-content-end}.page-columns .column-body-fullbleed{grid-column:body-start/body-end}.page-columns .column-body-outset{grid-column:body-start-outset/body-end-outset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-body-outset table{background:#fff}.page-columns .column-body-outset-left{grid-column:body-start-outset/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-body-outset-left table{background:#fff}.page-columns .column-body-outset-right{grid-column:body-content-start/body-end-outset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-body-outset-right table{background:#fff}.page-columns .column-page{grid-column:page-start/page-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page table{background:#fff}.page-columns .column-page-inset{grid-column:page-start-inset/page-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-inset table{background:#fff}.page-columns .column-page-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-inset-left table{background:#fff}.page-columns .column-page-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-inset-right figcaption table{background:#fff}.page-columns .column-page-left{grid-column:page-start/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-left table{background:#fff}.page-columns .column-page-right{grid-column:body-content-start/page-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-page-right figcaption table{background:#fff}#quarto-content.page-columns #quarto-margin-sidebar,#quarto-content.page-columns #quarto-sidebar{z-index:1}@media(max-width: 991.98px){#quarto-content.page-columns #quarto-margin-sidebar.collapse,#quarto-content.page-columns #quarto-sidebar.collapse,#quarto-content.page-columns #quarto-margin-sidebar.collapsing,#quarto-content.page-columns #quarto-sidebar.collapsing{z-index:1055}}#quarto-content.page-columns main.column-page,#quarto-content.page-columns main.column-page-right,#quarto-content.page-columns main.column-page-left{z-index:0}.page-columns .column-screen-inset{grid-column:screen-start-inset/screen-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset table{background:#fff}.page-columns .column-screen-inset-left{grid-column:screen-start-inset/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset-left table{background:#fff}.page-columns .column-screen-inset-right{grid-column:body-content-start/screen-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset-right table{background:#fff}.page-columns .column-screen{grid-column:screen-start/screen-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen table{background:#fff}.page-columns .column-screen-left{grid-column:screen-start/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-left table{background:#fff}.page-columns .column-screen-right{grid-column:body-content-start/screen-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-right table{background:#fff}.page-columns .column-screen-inset-shaded{grid-column:screen-start/screen-end;padding:1em;background:#f8f9fa;z-index:998;transform:translate3d(0, 0, 0);margin-bottom:1em}.zindex-content{z-index:998;transform:translate3d(0, 0, 0)}.zindex-modal{z-index:1055;transform:translate3d(0, 0, 0)}.zindex-over-content{z-index:999;transform:translate3d(0, 0, 0)}img.img-fluid.column-screen,img.img-fluid.column-screen-inset-shaded,img.img-fluid.column-screen-inset,img.img-fluid.column-screen-inset-left,img.img-fluid.column-screen-inset-right,img.img-fluid.column-screen-left,img.img-fluid.column-screen-right{width:100%}@media(min-width: 992px){.margin-caption,div.aside,aside,.column-margin{grid-column:body-end/page-end !important;z-index:998}.column-sidebar{grid-column:page-start/body-start !important;z-index:998}.column-leftmargin{grid-column:screen-start-inset/body-start !important;z-index:998}.no-row-height{height:1em;overflow:visible}}@media(max-width: 991.98px){.margin-caption,div.aside,aside,.column-margin{grid-column:body-end/page-end !important;z-index:998}.no-row-height{height:1em;overflow:visible}.page-columns.page-full{overflow:visible}.page-columns.toc-left .margin-caption,.page-columns.toc-left div.aside,.page-columns.toc-left aside,.page-columns.toc-left .column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;transform:translate3d(0, 0, 0)}.page-columns.toc-left .no-row-height{height:initial;overflow:initial}}@media(max-width: 767.98px){.margin-caption,div.aside,aside,.column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;transform:translate3d(0, 0, 0)}.no-row-height{height:initial;overflow:initial}#quarto-margin-sidebar{display:none}#quarto-sidebar-toc-left{display:none}.hidden-sm{display:none}}.panel-grid{display:grid;grid-template-rows:repeat(1, 1fr);grid-template-columns:repeat(24, 1fr);gap:1em}.panel-grid .g-col-1{grid-column:auto/span 1}.panel-grid .g-col-2{grid-column:auto/span 2}.panel-grid .g-col-3{grid-column:auto/span 3}.panel-grid .g-col-4{grid-column:auto/span 4}.panel-grid .g-col-5{grid-column:auto/span 5}.panel-grid .g-col-6{grid-column:auto/span 6}.panel-grid .g-col-7{grid-column:auto/span 7}.panel-grid .g-col-8{grid-column:auto/span 8}.panel-grid .g-col-9{grid-column:auto/span 9}.panel-grid .g-col-10{grid-column:auto/span 10}.panel-grid .g-col-11{grid-column:auto/span 11}.panel-grid .g-col-12{grid-column:auto/span 12}.panel-grid .g-col-13{grid-column:auto/span 13}.panel-grid .g-col-14{grid-column:auto/span 14}.panel-grid .g-col-15{grid-column:auto/span 15}.panel-grid .g-col-16{grid-column:auto/span 16}.panel-grid .g-col-17{grid-column:auto/span 17}.panel-grid .g-col-18{grid-column:auto/span 18}.panel-grid .g-col-19{grid-column:auto/span 19}.panel-grid .g-col-20{grid-column:auto/span 20}.panel-grid .g-col-21{grid-column:auto/span 21}.panel-grid .g-col-22{grid-column:auto/span 22}.panel-grid .g-col-23{grid-column:auto/span 23}.panel-grid .g-col-24{grid-column:auto/span 24}.panel-grid .g-start-1{grid-column-start:1}.panel-grid .g-start-2{grid-column-start:2}.panel-grid .g-start-3{grid-column-start:3}.panel-grid .g-start-4{grid-column-start:4}.panel-grid .g-start-5{grid-column-start:5}.panel-grid .g-start-6{grid-column-start:6}.panel-grid .g-start-7{grid-column-start:7}.panel-grid .g-start-8{grid-column-start:8}.panel-grid .g-start-9{grid-column-start:9}.panel-grid .g-start-10{grid-column-start:10}.panel-grid .g-start-11{grid-column-start:11}.panel-grid .g-start-12{grid-column-start:12}.panel-grid .g-start-13{grid-column-start:13}.panel-grid .g-start-14{grid-column-start:14}.panel-grid .g-start-15{grid-column-start:15}.panel-grid .g-start-16{grid-column-start:16}.panel-grid .g-start-17{grid-column-start:17}.panel-grid .g-start-18{grid-column-start:18}.panel-grid .g-start-19{grid-column-start:19}.panel-grid .g-start-20{grid-column-start:20}.panel-grid .g-start-21{grid-column-start:21}.panel-grid .g-start-22{grid-column-start:22}.panel-grid .g-start-23{grid-column-start:23}@media(min-width: 576px){.panel-grid .g-col-sm-1{grid-column:auto/span 1}.panel-grid .g-col-sm-2{grid-column:auto/span 2}.panel-grid .g-col-sm-3{grid-column:auto/span 3}.panel-grid .g-col-sm-4{grid-column:auto/span 4}.panel-grid .g-col-sm-5{grid-column:auto/span 5}.panel-grid .g-col-sm-6{grid-column:auto/span 6}.panel-grid .g-col-sm-7{grid-column:auto/span 7}.panel-grid .g-col-sm-8{grid-column:auto/span 8}.panel-grid .g-col-sm-9{grid-column:auto/span 9}.panel-grid .g-col-sm-10{grid-column:auto/span 10}.panel-grid .g-col-sm-11{grid-column:auto/span 11}.panel-grid .g-col-sm-12{grid-column:auto/span 12}.panel-grid .g-col-sm-13{grid-column:auto/span 13}.panel-grid .g-col-sm-14{grid-column:auto/span 14}.panel-grid .g-col-sm-15{grid-column:auto/span 15}.panel-grid .g-col-sm-16{grid-column:auto/span 16}.panel-grid .g-col-sm-17{grid-column:auto/span 17}.panel-grid .g-col-sm-18{grid-column:auto/span 18}.panel-grid .g-col-sm-19{grid-column:auto/span 19}.panel-grid .g-col-sm-20{grid-column:auto/span 20}.panel-grid .g-col-sm-21{grid-column:auto/span 21}.panel-grid .g-col-sm-22{grid-column:auto/span 22}.panel-grid .g-col-sm-23{grid-column:auto/span 23}.panel-grid .g-col-sm-24{grid-column:auto/span 24}.panel-grid .g-start-sm-1{grid-column-start:1}.panel-grid .g-start-sm-2{grid-column-start:2}.panel-grid .g-start-sm-3{grid-column-start:3}.panel-grid .g-start-sm-4{grid-column-start:4}.panel-grid .g-start-sm-5{grid-column-start:5}.panel-grid .g-start-sm-6{grid-column-start:6}.panel-grid .g-start-sm-7{grid-column-start:7}.panel-grid .g-start-sm-8{grid-column-start:8}.panel-grid .g-start-sm-9{grid-column-start:9}.panel-grid .g-start-sm-10{grid-column-start:10}.panel-grid .g-start-sm-11{grid-column-start:11}.panel-grid .g-start-sm-12{grid-column-start:12}.panel-grid .g-start-sm-13{grid-column-start:13}.panel-grid .g-start-sm-14{grid-column-start:14}.panel-grid .g-start-sm-15{grid-column-start:15}.panel-grid .g-start-sm-16{grid-column-start:16}.panel-grid .g-start-sm-17{grid-column-start:17}.panel-grid .g-start-sm-18{grid-column-start:18}.panel-grid .g-start-sm-19{grid-column-start:19}.panel-grid .g-start-sm-20{grid-column-start:20}.panel-grid .g-start-sm-21{grid-column-start:21}.panel-grid .g-start-sm-22{grid-column-start:22}.panel-grid .g-start-sm-23{grid-column-start:23}}@media(min-width: 768px){.panel-grid .g-col-md-1{grid-column:auto/span 1}.panel-grid .g-col-md-2{grid-column:auto/span 2}.panel-grid .g-col-md-3{grid-column:auto/span 3}.panel-grid .g-col-md-4{grid-column:auto/span 4}.panel-grid .g-col-md-5{grid-column:auto/span 5}.panel-grid .g-col-md-6{grid-column:auto/span 6}.panel-grid .g-col-md-7{grid-column:auto/span 7}.panel-grid .g-col-md-8{grid-column:auto/span 8}.panel-grid .g-col-md-9{grid-column:auto/span 9}.panel-grid .g-col-md-10{grid-column:auto/span 10}.panel-grid .g-col-md-11{grid-column:auto/span 11}.panel-grid .g-col-md-12{grid-column:auto/span 12}.panel-grid .g-col-md-13{grid-column:auto/span 13}.panel-grid .g-col-md-14{grid-column:auto/span 14}.panel-grid .g-col-md-15{grid-column:auto/span 15}.panel-grid .g-col-md-16{grid-column:auto/span 16}.panel-grid .g-col-md-17{grid-column:auto/span 17}.panel-grid .g-col-md-18{grid-column:auto/span 18}.panel-grid .g-col-md-19{grid-column:auto/span 19}.panel-grid .g-col-md-20{grid-column:auto/span 20}.panel-grid .g-col-md-21{grid-column:auto/span 21}.panel-grid .g-col-md-22{grid-column:auto/span 22}.panel-grid .g-col-md-23{grid-column:auto/span 23}.panel-grid .g-col-md-24{grid-column:auto/span 24}.panel-grid .g-start-md-1{grid-column-start:1}.panel-grid .g-start-md-2{grid-column-start:2}.panel-grid .g-start-md-3{grid-column-start:3}.panel-grid .g-start-md-4{grid-column-start:4}.panel-grid .g-start-md-5{grid-column-start:5}.panel-grid .g-start-md-6{grid-column-start:6}.panel-grid .g-start-md-7{grid-column-start:7}.panel-grid .g-start-md-8{grid-column-start:8}.panel-grid .g-start-md-9{grid-column-start:9}.panel-grid .g-start-md-10{grid-column-start:10}.panel-grid .g-start-md-11{grid-column-start:11}.panel-grid .g-start-md-12{grid-column-start:12}.panel-grid .g-start-md-13{grid-column-start:13}.panel-grid .g-start-md-14{grid-column-start:14}.panel-grid .g-start-md-15{grid-column-start:15}.panel-grid .g-start-md-16{grid-column-start:16}.panel-grid .g-start-md-17{grid-column-start:17}.panel-grid .g-start-md-18{grid-column-start:18}.panel-grid .g-start-md-19{grid-column-start:19}.panel-grid .g-start-md-20{grid-column-start:20}.panel-grid .g-start-md-21{grid-column-start:21}.panel-grid .g-start-md-22{grid-column-start:22}.panel-grid .g-start-md-23{grid-column-start:23}}@media(min-width: 992px){.panel-grid .g-col-lg-1{grid-column:auto/span 1}.panel-grid .g-col-lg-2{grid-column:auto/span 2}.panel-grid .g-col-lg-3{grid-column:auto/span 3}.panel-grid .g-col-lg-4{grid-column:auto/span 4}.panel-grid .g-col-lg-5{grid-column:auto/span 5}.panel-grid .g-col-lg-6{grid-column:auto/span 6}.panel-grid .g-col-lg-7{grid-column:auto/span 7}.panel-grid .g-col-lg-8{grid-column:auto/span 8}.panel-grid .g-col-lg-9{grid-column:auto/span 9}.panel-grid .g-col-lg-10{grid-column:auto/span 10}.panel-grid .g-col-lg-11{grid-column:auto/span 11}.panel-grid .g-col-lg-12{grid-column:auto/span 12}.panel-grid .g-col-lg-13{grid-column:auto/span 13}.panel-grid .g-col-lg-14{grid-column:auto/span 14}.panel-grid .g-col-lg-15{grid-column:auto/span 15}.panel-grid .g-col-lg-16{grid-column:auto/span 16}.panel-grid .g-col-lg-17{grid-column:auto/span 17}.panel-grid .g-col-lg-18{grid-column:auto/span 18}.panel-grid .g-col-lg-19{grid-column:auto/span 19}.panel-grid .g-col-lg-20{grid-column:auto/span 20}.panel-grid .g-col-lg-21{grid-column:auto/span 21}.panel-grid .g-col-lg-22{grid-column:auto/span 22}.panel-grid .g-col-lg-23{grid-column:auto/span 23}.panel-grid .g-col-lg-24{grid-column:auto/span 24}.panel-grid .g-start-lg-1{grid-column-start:1}.panel-grid .g-start-lg-2{grid-column-start:2}.panel-grid .g-start-lg-3{grid-column-start:3}.panel-grid .g-start-lg-4{grid-column-start:4}.panel-grid .g-start-lg-5{grid-column-start:5}.panel-grid .g-start-lg-6{grid-column-start:6}.panel-grid .g-start-lg-7{grid-column-start:7}.panel-grid .g-start-lg-8{grid-column-start:8}.panel-grid .g-start-lg-9{grid-column-start:9}.panel-grid .g-start-lg-10{grid-column-start:10}.panel-grid .g-start-lg-11{grid-column-start:11}.panel-grid .g-start-lg-12{grid-column-start:12}.panel-grid .g-start-lg-13{grid-column-start:13}.panel-grid .g-start-lg-14{grid-column-start:14}.panel-grid .g-start-lg-15{grid-column-start:15}.panel-grid .g-start-lg-16{grid-column-start:16}.panel-grid .g-start-lg-17{grid-column-start:17}.panel-grid .g-start-lg-18{grid-column-start:18}.panel-grid .g-start-lg-19{grid-column-start:19}.panel-grid .g-start-lg-20{grid-column-start:20}.panel-grid .g-start-lg-21{grid-column-start:21}.panel-grid .g-start-lg-22{grid-column-start:22}.panel-grid .g-start-lg-23{grid-column-start:23}}@media(min-width: 1200px){.panel-grid .g-col-xl-1{grid-column:auto/span 1}.panel-grid .g-col-xl-2{grid-column:auto/span 2}.panel-grid .g-col-xl-3{grid-column:auto/span 3}.panel-grid .g-col-xl-4{grid-column:auto/span 4}.panel-grid .g-col-xl-5{grid-column:auto/span 5}.panel-grid .g-col-xl-6{grid-column:auto/span 6}.panel-grid .g-col-xl-7{grid-column:auto/span 7}.panel-grid .g-col-xl-8{grid-column:auto/span 8}.panel-grid .g-col-xl-9{grid-column:auto/span 9}.panel-grid .g-col-xl-10{grid-column:auto/span 10}.panel-grid .g-col-xl-11{grid-column:auto/span 11}.panel-grid .g-col-xl-12{grid-column:auto/span 12}.panel-grid .g-col-xl-13{grid-column:auto/span 13}.panel-grid .g-col-xl-14{grid-column:auto/span 14}.panel-grid .g-col-xl-15{grid-column:auto/span 15}.panel-grid .g-col-xl-16{grid-column:auto/span 16}.panel-grid .g-col-xl-17{grid-column:auto/span 17}.panel-grid .g-col-xl-18{grid-column:auto/span 18}.panel-grid .g-col-xl-19{grid-column:auto/span 19}.panel-grid .g-col-xl-20{grid-column:auto/span 20}.panel-grid .g-col-xl-21{grid-column:auto/span 21}.panel-grid .g-col-xl-22{grid-column:auto/span 22}.panel-grid .g-col-xl-23{grid-column:auto/span 23}.panel-grid .g-col-xl-24{grid-column:auto/span 24}.panel-grid .g-start-xl-1{grid-column-start:1}.panel-grid .g-start-xl-2{grid-column-start:2}.panel-grid .g-start-xl-3{grid-column-start:3}.panel-grid .g-start-xl-4{grid-column-start:4}.panel-grid .g-start-xl-5{grid-column-start:5}.panel-grid .g-start-xl-6{grid-column-start:6}.panel-grid .g-start-xl-7{grid-column-start:7}.panel-grid .g-start-xl-8{grid-column-start:8}.panel-grid .g-start-xl-9{grid-column-start:9}.panel-grid .g-start-xl-10{grid-column-start:10}.panel-grid .g-start-xl-11{grid-column-start:11}.panel-grid .g-start-xl-12{grid-column-start:12}.panel-grid .g-start-xl-13{grid-column-start:13}.panel-grid .g-start-xl-14{grid-column-start:14}.panel-grid .g-start-xl-15{grid-column-start:15}.panel-grid .g-start-xl-16{grid-column-start:16}.panel-grid .g-start-xl-17{grid-column-start:17}.panel-grid .g-start-xl-18{grid-column-start:18}.panel-grid .g-start-xl-19{grid-column-start:19}.panel-grid .g-start-xl-20{grid-column-start:20}.panel-grid .g-start-xl-21{grid-column-start:21}.panel-grid .g-start-xl-22{grid-column-start:22}.panel-grid .g-start-xl-23{grid-column-start:23}}@media(min-width: 1400px){.panel-grid .g-col-xxl-1{grid-column:auto/span 1}.panel-grid .g-col-xxl-2{grid-column:auto/span 2}.panel-grid .g-col-xxl-3{grid-column:auto/span 3}.panel-grid .g-col-xxl-4{grid-column:auto/span 4}.panel-grid .g-col-xxl-5{grid-column:auto/span 5}.panel-grid .g-col-xxl-6{grid-column:auto/span 6}.panel-grid .g-col-xxl-7{grid-column:auto/span 7}.panel-grid .g-col-xxl-8{grid-column:auto/span 8}.panel-grid .g-col-xxl-9{grid-column:auto/span 9}.panel-grid .g-col-xxl-10{grid-column:auto/span 10}.panel-grid .g-col-xxl-11{grid-column:auto/span 11}.panel-grid .g-col-xxl-12{grid-column:auto/span 12}.panel-grid .g-col-xxl-13{grid-column:auto/span 13}.panel-grid .g-col-xxl-14{grid-column:auto/span 14}.panel-grid .g-col-xxl-15{grid-column:auto/span 15}.panel-grid .g-col-xxl-16{grid-column:auto/span 16}.panel-grid .g-col-xxl-17{grid-column:auto/span 17}.panel-grid .g-col-xxl-18{grid-column:auto/span 18}.panel-grid .g-col-xxl-19{grid-column:auto/span 19}.panel-grid .g-col-xxl-20{grid-column:auto/span 20}.panel-grid .g-col-xxl-21{grid-column:auto/span 21}.panel-grid .g-col-xxl-22{grid-column:auto/span 22}.panel-grid .g-col-xxl-23{grid-column:auto/span 23}.panel-grid .g-col-xxl-24{grid-column:auto/span 24}.panel-grid .g-start-xxl-1{grid-column-start:1}.panel-grid .g-start-xxl-2{grid-column-start:2}.panel-grid .g-start-xxl-3{grid-column-start:3}.panel-grid .g-start-xxl-4{grid-column-start:4}.panel-grid .g-start-xxl-5{grid-column-start:5}.panel-grid .g-start-xxl-6{grid-column-start:6}.panel-grid .g-start-xxl-7{grid-column-start:7}.panel-grid .g-start-xxl-8{grid-column-start:8}.panel-grid .g-start-xxl-9{grid-column-start:9}.panel-grid .g-start-xxl-10{grid-column-start:10}.panel-grid .g-start-xxl-11{grid-column-start:11}.panel-grid .g-start-xxl-12{grid-column-start:12}.panel-grid .g-start-xxl-13{grid-column-start:13}.panel-grid .g-start-xxl-14{grid-column-start:14}.panel-grid .g-start-xxl-15{grid-column-start:15}.panel-grid .g-start-xxl-16{grid-column-start:16}.panel-grid .g-start-xxl-17{grid-column-start:17}.panel-grid .g-start-xxl-18{grid-column-start:18}.panel-grid .g-start-xxl-19{grid-column-start:19}.panel-grid .g-start-xxl-20{grid-column-start:20}.panel-grid .g-start-xxl-21{grid-column-start:21}.panel-grid .g-start-xxl-22{grid-column-start:22}.panel-grid .g-start-xxl-23{grid-column-start:23}}main{margin-top:1em;margin-bottom:1em}h1,.h1,h2,.h2{opacity:.9;margin-top:2rem;margin-bottom:1rem;font-weight:600}h1.title,.title.h1{margin-top:0}h2,.h2{border-bottom:1px solid #dee2e6;padding-bottom:.5rem}h3,.h3{font-weight:600}h3,.h3,h4,.h4{opacity:.9;margin-top:1.5rem}h5,.h5,h6,.h6{opacity:.9}.header-section-number{color:#747a7f}.nav-link.active .header-section-number{color:inherit}mark,.mark{padding:0em}.panel-caption,caption,.figure-caption{font-size:.9rem}.panel-caption,.figure-caption,figcaption{color:#747a7f}.table-caption,caption{color:#373a3c}.quarto-layout-cell[data-ref-parent] caption{color:#747a7f}.column-margin figcaption,.margin-caption,div.aside,aside,.column-margin{color:#747a7f;font-size:.825rem}.panel-caption.margin-caption{text-align:inherit}.column-margin.column-container p{margin-bottom:0}.column-margin.column-container>*:not(.collapse){padding-top:.5em;padding-bottom:.5em;display:block}.column-margin.column-container>*.collapse:not(.show){display:none}@media(min-width: 768px){.column-margin.column-container .callout-margin-content:first-child{margin-top:4.5em}.column-margin.column-container .callout-margin-content-simple:first-child{margin-top:3.5em}}.margin-caption>*{padding-top:.5em;padding-bottom:.5em}@media(max-width: 767.98px){.quarto-layout-row{flex-direction:column}}.nav-tabs .nav-item{margin-top:1px;cursor:pointer}.tab-content{margin-top:0px;border-left:#dee2e6 1px solid;border-right:#dee2e6 1px solid;border-bottom:#dee2e6 1px solid;margin-left:0;padding:1em;margin-bottom:1em}@media(max-width: 767.98px){.layout-sidebar{margin-left:0;margin-right:0}}.panel-sidebar,.panel-sidebar .form-control,.panel-input,.panel-input .form-control,.selectize-dropdown{font-size:.9rem}.panel-sidebar .form-control,.panel-input .form-control{padding-top:.1rem}.tab-pane div.sourceCode{margin-top:0px}.tab-pane>p{padding-top:1em}.tab-content>.tab-pane:not(.active){display:none !important}div.sourceCode{background-color:rgba(233,236,239,.65);border:1px solid rgba(233,236,239,.65);border-radius:.25rem}pre.sourceCode{background-color:rgba(0,0,0,0)}pre.sourceCode{border:none;font-size:.875em;overflow:visible !important;padding:.4em}.callout pre.sourceCode{padding-left:0}div.sourceCode{overflow-y:hidden}.callout div.sourceCode{margin-left:initial}.blockquote{font-size:inherit;padding-left:1rem;padding-right:1.5rem;color:#747a7f}.blockquote h1:first-child,.blockquote .h1:first-child,.blockquote h2:first-child,.blockquote .h2:first-child,.blockquote h3:first-child,.blockquote .h3:first-child,.blockquote h4:first-child,.blockquote .h4:first-child,.blockquote h5:first-child,.blockquote .h5:first-child{margin-top:0}pre{background-color:initial;padding:initial;border:initial}p code:not(.sourceCode),li code:not(.sourceCode),td code:not(.sourceCode){background-color:#f7f7f7;padding:.2em}nav p code:not(.sourceCode),nav li code:not(.sourceCode),nav td code:not(.sourceCode){background-color:rgba(0,0,0,0);padding:0}td code:not(.sourceCode){white-space:pre-wrap}#quarto-embedded-source-code-modal>.modal-dialog{max-width:1000px;padding-left:1.75rem;padding-right:1.75rem}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body{padding:0}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body div.sourceCode{margin:0;padding:.2rem .2rem;border-radius:0px;border:none}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-header{padding:.7rem}.code-tools-button{font-size:1rem;padding:.15rem .15rem;margin-left:5px;color:#6c757d;background-color:rgba(0,0,0,0);transition:initial;cursor:pointer}.code-tools-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}.code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}.sidebar{will-change:top;transition:top 200ms linear;position:sticky;overflow-y:auto;padding-top:1.2em;max-height:100vh}.sidebar.toc-left,.sidebar.margin-sidebar{top:0px;padding-top:1em}.sidebar.toc-left>*,.sidebar.margin-sidebar>*{padding-top:.5em}.sidebar.quarto-banner-title-block-sidebar>*{padding-top:1.65em}figure .quarto-notebook-link{margin-top:.5em}.quarto-notebook-link{font-size:.75em;color:#6c757d;margin-bottom:1em;text-decoration:none;display:block}.quarto-notebook-link:hover{text-decoration:underline;color:#2780e3}.quarto-notebook-link::before{display:inline-block;height:.75rem;width:.75rem;margin-bottom:0em;margin-right:.25em;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:.75rem .75rem}.quarto-alternate-notebooks i.bi,.quarto-alternate-formats i.bi{margin-right:.4em}.quarto-notebook .cell-container{display:flex}.quarto-notebook .cell-container .cell{flex-grow:4}.quarto-notebook .cell-container .cell-decorator{padding-top:1.5em;padding-right:1em;text-align:right}.quarto-notebook h2,.quarto-notebook .h2{border-bottom:none}.sidebar .quarto-alternate-formats a,.sidebar .quarto-alternate-notebooks a{text-decoration:none}.sidebar .quarto-alternate-formats a:hover,.sidebar .quarto-alternate-notebooks a:hover{color:#2780e3}.sidebar .quarto-alternate-notebooks h2,.sidebar .quarto-alternate-notebooks .h2,.sidebar .quarto-alternate-formats h2,.sidebar .quarto-alternate-formats .h2,.sidebar nav[role=doc-toc]>h2,.sidebar nav[role=doc-toc]>.h2{font-size:.875rem;font-weight:400;margin-bottom:.5rem;margin-top:.3rem;font-family:inherit;border-bottom:0;padding-bottom:0;padding-top:0px}.sidebar .quarto-alternate-notebooks h2,.sidebar .quarto-alternate-notebooks .h2,.sidebar .quarto-alternate-formats h2,.sidebar .quarto-alternate-formats .h2{margin-top:1rem}.sidebar nav[role=doc-toc]>ul a{border-left:1px solid #e9ecef;padding-left:.6rem}.sidebar .quarto-alternate-notebooks h2>ul a,.sidebar .quarto-alternate-notebooks .h2>ul a,.sidebar .quarto-alternate-formats h2>ul a,.sidebar .quarto-alternate-formats .h2>ul a{border-left:none;padding-left:.6rem}.sidebar .quarto-alternate-notebooks ul a:empty,.sidebar .quarto-alternate-formats ul a:empty,.sidebar nav[role=doc-toc]>ul a:empty{display:none}.sidebar .quarto-alternate-notebooks ul,.sidebar .quarto-alternate-formats ul,.sidebar nav[role=doc-toc] ul{padding-left:0;list-style:none;font-size:.875rem;font-weight:300}.sidebar .quarto-alternate-notebooks ul li a,.sidebar .quarto-alternate-formats ul li a,.sidebar nav[role=doc-toc]>ul li a{line-height:1.1rem;padding-bottom:.2rem;padding-top:.2rem;color:inherit}.sidebar nav[role=doc-toc] ul>li>ul>li>a{padding-left:1.2em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>a{padding-left:2.4em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>a{padding-left:3.6em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:4.8em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:6em}.sidebar nav[role=doc-toc] ul>li>a.active,.sidebar nav[role=doc-toc] ul>li>ul>li>a.active{border-left:1px solid #2780e3;color:#2780e3 !important}.sidebar nav[role=doc-toc] ul>li>a:hover,.sidebar nav[role=doc-toc] ul>li>ul>li>a:hover{color:#2780e3 !important}kbd,.kbd{color:#373a3c;background-color:#f8f9fa;border:1px solid;border-radius:5px;border-color:#dee2e6}div.hanging-indent{margin-left:1em;text-indent:-1em}.citation a,.footnote-ref{text-decoration:none}.footnotes ol{padding-left:1em}.tippy-content>*{margin-bottom:.7em}.tippy-content>*:last-child{margin-bottom:0}.table a{word-break:break-word}.table>thead{border-top-width:1px;border-top-color:#dee2e6;border-bottom:1px solid #b6babc}.callout{margin-top:1.25rem;margin-bottom:1.25rem;border-radius:.25rem;overflow-wrap:break-word}.callout .callout-title-container{overflow-wrap:anywhere}.callout.callout-style-simple{padding:.4em .7em;border-left:5px solid;border-right:1px solid #dee2e6;border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.callout.callout-style-default{border-left:5px solid;border-right:1px solid #dee2e6;border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.callout .callout-body-container{flex-grow:1}.callout.callout-style-simple .callout-body{font-size:.9rem;font-weight:400}.callout.callout-style-default .callout-body{font-size:.9rem;font-weight:400}.callout.callout-titled .callout-body{margin-top:.2em}.callout:not(.no-icon).callout-titled.callout-style-simple .callout-body{padding-left:1.6em}.callout.callout-titled>.callout-header{padding-top:.2em;margin-bottom:-0.2em}.callout.callout-style-simple>div.callout-header{border-bottom:none;font-size:.9rem;font-weight:600;opacity:75%}.callout.callout-style-default>div.callout-header{border-bottom:none;font-weight:600;opacity:85%;font-size:.9rem;padding-left:.5em;padding-right:.5em}.callout.callout-style-default div.callout-body{padding-left:.5em;padding-right:.5em}.callout.callout-style-default div.callout-body>:first-child{margin-top:.5em}.callout>div.callout-header[data-bs-toggle=collapse]{cursor:pointer}.callout.callout-style-default .callout-header[aria-expanded=false],.callout.callout-style-default .callout-header[aria-expanded=true]{padding-top:0px;margin-bottom:0px;align-items:center}.callout.callout-titled .callout-body>:last-child:not(.sourceCode),.callout.callout-titled .callout-body>div>:last-child:not(.sourceCode){margin-bottom:.5rem}.callout:not(.callout-titled) .callout-body>:first-child,.callout:not(.callout-titled) .callout-body>div>:first-child{margin-top:.25rem}.callout:not(.callout-titled) .callout-body>:last-child,.callout:not(.callout-titled) .callout-body>div>:last-child{margin-bottom:.2rem}.callout.callout-style-simple .callout-icon::before,.callout.callout-style-simple .callout-toggle::before{height:1rem;width:1rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.callout.callout-style-default .callout-icon::before,.callout.callout-style-default .callout-toggle::before{height:.9rem;width:.9rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:.9rem .9rem}.callout.callout-style-default .callout-toggle::before{margin-top:5px}.callout .callout-btn-toggle .callout-toggle::before{transition:transform .2s linear}.callout .callout-header[aria-expanded=false] .callout-toggle::before{transform:rotate(-90deg)}.callout .callout-header[aria-expanded=true] .callout-toggle::before{transform:none}.callout.callout-style-simple:not(.no-icon) div.callout-icon-container{padding-top:.2em;padding-right:.55em}.callout.callout-style-default:not(.no-icon) div.callout-icon-container{padding-top:.1em;padding-right:.35em}.callout.callout-style-default:not(.no-icon) div.callout-title-container{margin-top:-1px}.callout.callout-style-default.callout-caution:not(.no-icon) div.callout-icon-container{padding-top:.3em;padding-right:.35em}.callout>.callout-body>.callout-icon-container>.no-icon,.callout>.callout-header>.callout-icon-container>.no-icon{display:none}div.callout.callout{border-left-color:#6c757d}div.callout.callout-style-default>.callout-header{background-color:#6c757d}div.callout-note.callout{border-left-color:#2780e3}div.callout-note.callout-style-default>.callout-header{background-color:#e9f2fc}div.callout-note:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-tip.callout{border-left-color:#3fb618}div.callout-tip.callout-style-default>.callout-header{background-color:#ecf8e8}div.callout-tip:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-warning.callout{border-left-color:#ff7518}div.callout-warning.callout-style-default>.callout-header{background-color:#fff1e8}div.callout-warning:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-caution.callout{border-left-color:#f0ad4e}div.callout-caution.callout-style-default>.callout-header{background-color:#fef7ed}div.callout-caution:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-important.callout{border-left-color:#ff0039}div.callout-important.callout-style-default>.callout-header{background-color:#ffe6eb}div.callout-important:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important .callout-toggle::before{background-image:url('data:image/svg+xml,')}.quarto-toggle-container{display:flex;align-items:center}.quarto-reader-toggle .bi::before,.quarto-color-scheme-toggle .bi::before{display:inline-block;height:1rem;width:1rem;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.sidebar-navigation{padding-left:20px}.navbar .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.quarto-sidebar-toggle{border-color:#dee2e6;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;border-style:solid;border-width:1px;overflow:hidden;border-top-width:0px;padding-top:0px !important}.quarto-sidebar-toggle-title{cursor:pointer;padding-bottom:2px;margin-left:.25em;text-align:center;font-weight:400;font-size:.775em}#quarto-content .quarto-sidebar-toggle{background:#fafafa}#quarto-content .quarto-sidebar-toggle-title{color:#373a3c}.quarto-sidebar-toggle-icon{color:#dee2e6;margin-right:.5em;float:right;transition:transform .2s ease}.quarto-sidebar-toggle-icon::before{padding-top:5px}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-icon{transform:rotate(-180deg)}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-title{border-bottom:solid #dee2e6 1px}.quarto-sidebar-toggle-contents{background-color:#fff;padding-right:10px;padding-left:10px;margin-top:0px !important;transition:max-height .5s ease}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-contents{padding-top:1em;padding-bottom:10px}.quarto-sidebar-toggle:not(.expanded) .quarto-sidebar-toggle-contents{padding-top:0px !important;padding-bottom:0px}nav[role=doc-toc]{z-index:1020}#quarto-sidebar>*,nav[role=doc-toc]>*{transition:opacity .1s ease,border .1s ease}#quarto-sidebar.slow>*,nav[role=doc-toc].slow>*{transition:opacity .4s ease,border .4s ease}.quarto-color-scheme-toggle:not(.alternate).top-right .bi::before{background-image:url('data:image/svg+xml,')}.quarto-color-scheme-toggle.alternate.top-right .bi::before{background-image:url('data:image/svg+xml,')}#quarto-appendix.default{border-top:1px solid #dee2e6}#quarto-appendix.default{background-color:#fff;padding-top:1.5em;margin-top:2em;z-index:998}#quarto-appendix.default .quarto-appendix-heading{margin-top:0;line-height:1.4em;font-weight:600;opacity:.9;border-bottom:none;margin-bottom:0}#quarto-appendix.default .footnotes ol,#quarto-appendix.default .footnotes ol li>p:last-of-type,#quarto-appendix.default .quarto-appendix-contents>p:last-of-type{margin-bottom:0}#quarto-appendix.default .quarto-appendix-secondary-label{margin-bottom:.4em}#quarto-appendix.default .quarto-appendix-bibtex{font-size:.7em;padding:1em;border:solid 1px #dee2e6;margin-bottom:1em}#quarto-appendix.default .quarto-appendix-bibtex code.sourceCode{white-space:pre-wrap}#quarto-appendix.default .quarto-appendix-citeas{font-size:.9em;padding:1em;border:solid 1px #dee2e6;margin-bottom:1em}#quarto-appendix.default .quarto-appendix-heading{font-size:1em !important}#quarto-appendix.default *[role=doc-endnotes]>ol,#quarto-appendix.default .quarto-appendix-contents>*:not(h2):not(.h2){font-size:.9em}#quarto-appendix.default section{padding-bottom:1.5em}#quarto-appendix.default section *[role=doc-endnotes],#quarto-appendix.default section>*:not(a){opacity:.9;word-wrap:break-word}.btn.btn-quarto,div.cell-output-display .btn-quarto{color:#cbcccc;background-color:#373a3c;border-color:#373a3c}.btn.btn-quarto:hover,div.cell-output-display .btn-quarto:hover{color:#cbcccc;background-color:#555859;border-color:#4b4e50}.btn-check:focus+.btn.btn-quarto,.btn.btn-quarto:focus,.btn-check:focus+div.cell-output-display .btn-quarto,div.cell-output-display .btn-quarto:focus{color:#cbcccc;background-color:#555859;border-color:#4b4e50;box-shadow:0 0 0 .25rem rgba(77,80,82,.5)}.btn-check:checked+.btn.btn-quarto,.btn-check:active+.btn.btn-quarto,.btn.btn-quarto:active,.btn.btn-quarto.active,.show>.btn.btn-quarto.dropdown-toggle,.btn-check:checked+div.cell-output-display .btn-quarto,.btn-check:active+div.cell-output-display .btn-quarto,div.cell-output-display .btn-quarto:active,div.cell-output-display .btn-quarto.active,.show>div.cell-output-display .btn-quarto.dropdown-toggle{color:#fff;background-color:#5f6163;border-color:#4b4e50}.btn-check:checked+.btn.btn-quarto:focus,.btn-check:active+.btn.btn-quarto:focus,.btn.btn-quarto:active:focus,.btn.btn-quarto.active:focus,.show>.btn.btn-quarto.dropdown-toggle:focus,.btn-check:checked+div.cell-output-display .btn-quarto:focus,.btn-check:active+div.cell-output-display .btn-quarto:focus,div.cell-output-display .btn-quarto:active:focus,div.cell-output-display .btn-quarto.active:focus,.show>div.cell-output-display .btn-quarto.dropdown-toggle:focus{box-shadow:0 0 0 .25rem rgba(77,80,82,.5)}.btn.btn-quarto:disabled,.btn.btn-quarto.disabled,div.cell-output-display .btn-quarto:disabled,div.cell-output-display .btn-quarto.disabled{color:#fff;background-color:#373a3c;border-color:#373a3c}nav.quarto-secondary-nav.color-navbar{background-color:#f8f9fa;color:#545555}nav.quarto-secondary-nav.color-navbar h1,nav.quarto-secondary-nav.color-navbar .h1,nav.quarto-secondary-nav.color-navbar .quarto-btn-toggle{color:#545555}@media(max-width: 991.98px){body.nav-sidebar .quarto-title-banner{margin-bottom:0;padding-bottom:0}body.nav-sidebar #title-block-header{margin-block-end:0}}p.subtitle{margin-top:.25em;margin-bottom:.5em}code a:any-link{color:inherit;text-decoration-color:#6c757d}/*! light */div.observablehq table thead tr th{background-color:var(--bs-body-bg)}input,button,select,optgroup,textarea{background-color:var(--bs-body-bg)}.code-annotated .code-copy-button{margin-right:1.25em;margin-top:0;padding-bottom:0;padding-top:3px}.code-annotation-gutter-bg{background-color:#fff}.code-annotation-gutter{background-color:rgba(233,236,239,.65)}.code-annotation-gutter,.code-annotation-gutter-bg{height:100%;width:calc(20px + .5em);position:absolute;top:0;right:0}dl.code-annotation-container-grid dt{margin-right:1em;margin-top:.25rem}dl.code-annotation-container-grid dt{font-family:var(--bs-font-monospace);color:#4f5457;border:solid #4f5457 1px;border-radius:50%;height:22px;width:22px;line-height:22px;font-size:11px;text-align:center;vertical-align:middle;text-decoration:none}dl.code-annotation-container-grid dt[data-target-cell]{cursor:pointer}dl.code-annotation-container-grid dt[data-target-cell].code-annotation-active{color:#fff;border:solid #aaa 1px;background-color:#aaa}pre.code-annotation-code{padding-top:0;padding-bottom:0}pre.code-annotation-code code{z-index:3}#code-annotation-line-highlight-gutter{width:100%;border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}#code-annotation-line-highlight{margin-left:-4em;width:calc(100% + 4em);border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}code.sourceCode .code-annotation-anchor.code-annotation-active{background-color:var(--quarto-hl-normal-color, #aaaaaa);border:solid var(--quarto-hl-normal-color, #aaaaaa) 1px;color:#e9ecef;font-weight:bolder}code.sourceCode .code-annotation-anchor{font-family:var(--bs-font-monospace);color:var(--quarto-hl-co-color);border:solid var(--quarto-hl-co-color) 1px;border-radius:50%;height:18px;width:18px;font-size:9px;margin-top:2px}code.sourceCode button.code-annotation-anchor{padding:2px}code.sourceCode a.code-annotation-anchor{line-height:18px;text-align:center;vertical-align:middle;cursor:default;text-decoration:none}@media print{.page-columns .column-screen-inset{grid-column:page-start-inset/page-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset table{background:#fff}.page-columns .column-screen-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset-left table{background:#fff}.page-columns .column-screen-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-inset-right table{background:#fff}.page-columns .column-screen{grid-column:page-start/page-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen table{background:#fff}.page-columns .column-screen-left{grid-column:page-start/body-content-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-left table{background:#fff}.page-columns .column-screen-right{grid-column:body-content-start/page-end;z-index:998;transform:translate3d(0, 0, 0)}.page-columns .column-screen-right table{background:#fff}.page-columns .column-screen-inset-shaded{grid-column:page-start-inset/page-end-inset;padding:1em;background:#f8f9fa;z-index:998;transform:translate3d(0, 0, 0);margin-bottom:1em}}.quarto-video{margin-bottom:1em}.table>thead{border-top-width:0}.table>:not(caption)>*:not(:last-child)>*{border-bottom-color:#ebeced;border-bottom-style:solid;border-bottom-width:1px}.table>:not(:first-child){border-top:1px solid #b6babc;border-bottom:1px solid inherit}.table tbody{border-bottom-color:#b6babc}a.external:after{display:inline-block;height:.75rem;width:.75rem;margin-bottom:.15em;margin-left:.25em;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:.75rem .75rem}div.sourceCode code a.external:after{content:none}a.external:after:hover{cursor:pointer}.quarto-ext-icon{display:inline-block;font-size:.75em;padding-left:.3em}.code-with-filename .code-with-filename-file{margin-bottom:0;padding-bottom:2px;padding-top:2px;padding-left:.7em;border:var(--quarto-border-width) solid var(--quarto-border-color);border-radius:var(--quarto-border-radius);border-bottom:0;border-bottom-left-radius:0%;border-bottom-right-radius:0%}.code-with-filename div.sourceCode,.reveal .code-with-filename div.sourceCode{margin-top:0;border-top-left-radius:0%;border-top-right-radius:0%}.code-with-filename .code-with-filename-file pre{margin-bottom:0}.code-with-filename .code-with-filename-file,.code-with-filename .code-with-filename-file pre{background-color:rgba(219,219,219,.8)}.quarto-dark .code-with-filename .code-with-filename-file,.quarto-dark .code-with-filename .code-with-filename-file pre{background-color:#555}.code-with-filename .code-with-filename-file strong{font-weight:400}.quarto-title-banner{margin-bottom:1em;color:#545555;background:#f8f9fa}.quarto-title-banner .code-tools-button{color:#878888}.quarto-title-banner .code-tools-button:hover{color:#545555}.quarto-title-banner .code-tools-button>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .quarto-title .title{font-weight:600}.quarto-title-banner .quarto-categories{margin-top:.75em}@media(min-width: 992px){.quarto-title-banner{padding-top:2.5em;padding-bottom:2.5em}}@media(max-width: 991.98px){.quarto-title-banner{padding-top:1em;padding-bottom:1em}}main.quarto-banner-title-block>section:first-child>h2,main.quarto-banner-title-block>section:first-child>.h2,main.quarto-banner-title-block>section:first-child>h3,main.quarto-banner-title-block>section:first-child>.h3,main.quarto-banner-title-block>section:first-child>h4,main.quarto-banner-title-block>section:first-child>.h4{margin-top:0}.quarto-title .quarto-categories{display:flex;flex-wrap:wrap;row-gap:.5em;column-gap:.4em;padding-bottom:.5em;margin-top:.75em}.quarto-title .quarto-categories .quarto-category{padding:.25em .75em;font-size:.65em;text-transform:uppercase;border:solid 1px;border-radius:.25rem;opacity:.6}.quarto-title .quarto-categories .quarto-category a{color:inherit}#title-block-header.quarto-title-block.default .quarto-title-meta{display:grid;grid-template-columns:repeat(2, 1fr)}#title-block-header.quarto-title-block.default .quarto-title .title{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-author-orcid img{margin-top:-5px}#title-block-header.quarto-title-block.default .quarto-description p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p,#title-block-header.quarto-title-block.default .quarto-title-authors p,#title-block-header.quarto-title-block.default .quarto-title-affiliations p{margin-bottom:.1em}#title-block-header.quarto-title-block.default .quarto-title-meta-heading{text-transform:uppercase;margin-top:1em;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-contents{font-size:.9em}#title-block-header.quarto-title-block.default .quarto-title-meta-contents a{color:#373a3c}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p.affiliation:last-of-type{margin-bottom:.7em}#title-block-header.quarto-title-block.default p.affiliation{margin-bottom:.1em}#title-block-header.quarto-title-block.default .description,#title-block-header.quarto-title-block.default .abstract{margin-top:0}#title-block-header.quarto-title-block.default .description>p,#title-block-header.quarto-title-block.default .abstract>p{font-size:.9em}#title-block-header.quarto-title-block.default .description>p:last-of-type,#title-block-header.quarto-title-block.default .abstract>p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .description .abstract-title,#title-block-header.quarto-title-block.default .abstract .abstract-title{margin-top:1em;text-transform:uppercase;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-author{display:grid;grid-template-columns:1fr 1fr}.quarto-title-tools-only{display:flex;justify-content:right}body{-webkit-font-smoothing:antialiased}.badge.bg-light{color:#373a3c}.progress .progress-bar{font-size:8px;line-height:8px}/*# sourceMappingURL=9161419e6f82ea4435380a70856fa72b.css.map */ diff --git a/pr-preview/pr-68/site_libs/bootstrap/bootstrap.min.js b/pr-preview/pr-68/site_libs/bootstrap/bootstrap.min.js new file mode 100644 index 0000000..cc0a255 --- /dev/null +++ b/pr-preview/pr-68/site_libs/bootstrap/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.1.3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t="transitionend",e=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e},i=t=>{const i=e(t);return i&&document.querySelector(i)?i:null},n=t=>{const i=e(t);return i?document.querySelector(i):null},s=e=>{e.dispatchEvent(new Event(t))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(t):null,a=(t,e,i)=>{Object.keys(i).forEach((n=>{const s=i[n],r=e[n],a=r&&o(r)?"element":null==(l=r)?`${l}`:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();var l;if(!new RegExp(s).test(a))throw new TypeError(`${t.toUpperCase()}: Option "${n}" provided type "${a}" but expected type "${s}".`)}))},l=t=>!(!o(t)||0===t.getClientRects().length)&&"visible"===getComputedStyle(t).getPropertyValue("visibility"),c=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),h=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?h(t.parentNode):null},d=()=>{},u=t=>{t.offsetHeight},f=()=>{const{jQuery:t}=window;return t&&!document.body.hasAttribute("data-bs-no-jquery")?t:null},p=[],m=()=>"rtl"===document.documentElement.dir,g=t=>{var e;e=()=>{const e=f();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(p.length||document.addEventListener("DOMContentLoaded",(()=>{p.forEach((t=>t()))})),p.push(e)):e()},_=t=>{"function"==typeof t&&t()},b=(e,i,n=!0)=>{if(!n)return void _(e);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(i)+5;let r=!1;const a=({target:n})=>{n===i&&(r=!0,i.removeEventListener(t,a),_(e))};i.addEventListener(t,a),setTimeout((()=>{r||s(i)}),o)},v=(t,e,i,n)=>{let s=t.indexOf(e);if(-1===s)return t[!i&&n?t.length-1:0];const o=t.length;return s+=i?1:-1,n&&(s=(s+o)%o),t[Math.max(0,Math.min(s,o-1))]},y=/[^.]*(?=\..*)\.|.*/,w=/\..*/,E=/::\d+$/,A={};let T=1;const O={mouseenter:"mouseover",mouseleave:"mouseout"},C=/^(mouseenter|mouseleave)/i,k=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function L(t,e){return e&&`${e}::${T++}`||t.uidEvent||T++}function x(t){const e=L(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function D(t,e,i=null){const n=Object.keys(t);for(let s=0,o=n.length;sfunction(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};n?n=t(n):i=t(i)}const[o,r,a]=S(e,i,n),l=x(t),c=l[a]||(l[a]={}),h=D(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=L(r,e.replace(y,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(let a=o.length;a--;)if(o[a]===r)return s.delegateTarget=r,n.oneOff&&j.off(t,s.type,e,i),i.apply(r,[s]);return null}}(t,i,n):function(t,e){return function i(n){return n.delegateTarget=t,i.oneOff&&j.off(t,n.type,e),e.apply(t,[n])}}(t,i);u.delegationSelector=o?i:null,u.originalHandler=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function I(t,e,i,n,s){const o=D(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function P(t){return t=t.replace(w,""),O[t]||t}const j={on(t,e,i,n){N(t,e,i,n,!1)},one(t,e,i,n){N(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=S(e,i,n),a=r!==e,l=x(t),c=e.startsWith(".");if(void 0!==o){if(!l||!l[r])return;return void I(t,l,r,o,s?i:null)}c&&Object.keys(l).forEach((i=>{!function(t,e,i,n){const s=e[i]||{};Object.keys(s).forEach((o=>{if(o.includes(n)){const n=s[o];I(t,e,i,n.originalHandler,n.delegationSelector)}}))}(t,l,i,e.slice(1))}));const h=l[r]||{};Object.keys(h).forEach((i=>{const n=i.replace(E,"");if(!a||e.includes(n)){const e=h[i];I(t,l,r,e.originalHandler,e.delegationSelector)}}))},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=f(),s=P(e),o=e!==s,r=k.has(s);let a,l=!0,c=!0,h=!1,d=null;return o&&n&&(a=n.Event(e,i),n(t).trigger(a),l=!a.isPropagationStopped(),c=!a.isImmediatePropagationStopped(),h=a.isDefaultPrevented()),r?(d=document.createEvent("HTMLEvents"),d.initEvent(s,l,!0)):d=new CustomEvent(e,{bubbles:l,cancelable:!0}),void 0!==i&&Object.keys(i).forEach((t=>{Object.defineProperty(d,t,{get:()=>i[t]})})),h&&d.preventDefault(),c&&t.dispatchEvent(d),d.defaultPrevented&&void 0!==a&&a.preventDefault(),d}},M=new Map,H={set(t,e,i){M.has(t)||M.set(t,new Map);const n=M.get(t);n.has(e)||0===n.size?n.set(e,i):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(t,e)=>M.has(t)&&M.get(t).get(e)||null,remove(t,e){if(!M.has(t))return;const i=M.get(t);i.delete(e),0===i.size&&M.delete(t)}};class B{constructor(t){(t=r(t))&&(this._element=t,H.set(this._element,this.constructor.DATA_KEY,this))}dispose(){H.remove(this._element,this.constructor.DATA_KEY),j.off(this._element,this.constructor.EVENT_KEY),Object.getOwnPropertyNames(this).forEach((t=>{this[t]=null}))}_queueCallback(t,e,i=!0){b(t,e,i)}static getInstance(t){return H.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.1.3"}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}}const R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,s=t.NAME;j.on(document,i,`[data-bs-dismiss="${s}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),c(this))return;const o=n(this)||this.closest(`.${s}`);t.getOrCreateInstance(o)[e]()}))};class W extends B{static get NAME(){return"alert"}close(){if(j.trigger(this._element,"close.bs.alert").defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),j.trigger(this._element,"closed.bs.alert"),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=W.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(W,"close"),g(W);const $='[data-bs-toggle="button"]';class z extends B{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=z.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}function q(t){return"true"===t||"false"!==t&&(t===Number(t).toString()?Number(t):""===t||"null"===t?null:t)}function F(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}j.on(document,"click.bs.button.data-api",$,(t=>{t.preventDefault();const e=t.target.closest($);z.getOrCreateInstance(e).toggle()})),g(z);const U={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${F(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${F(e)}`)},getDataAttributes(t){if(!t)return{};const e={};return Object.keys(t.dataset).filter((t=>t.startsWith("bs"))).forEach((i=>{let n=i.replace(/^bs/,"");n=n.charAt(0).toLowerCase()+n.slice(1,n.length),e[n]=q(t.dataset[i])})),e},getDataAttribute:(t,e)=>q(t.getAttribute(`data-bs-${F(e)}`)),offset(t){const e=t.getBoundingClientRect();return{top:e.top+window.pageYOffset,left:e.left+window.pageXOffset}},position:t=>({top:t.offsetTop,left:t.offsetLeft})},V={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode;for(;n&&n.nodeType===Node.ELEMENT_NODE&&3!==n.nodeType;)n.matches(e)&&i.push(n),n=n.parentNode;return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(", ");return this.find(e,t).filter((t=>!c(t)&&l(t)))}},K="carousel",X={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},Y={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},Q="next",G="prev",Z="left",J="right",tt={ArrowLeft:J,ArrowRight:Z},et="slid.bs.carousel",it="active",nt=".active.carousel-item";class st extends B{constructor(t,e){super(t),this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._indicatorsElement=V.findOne(".carousel-indicators",this._element),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent),this._addEventListeners()}static get Default(){return X}static get NAME(){return K}next(){this._slide(Q)}nextWhenVisible(){!document.hidden&&l(this._element)&&this.next()}prev(){this._slide(G)}pause(t){t||(this._isPaused=!0),V.findOne(".carousel-item-next, .carousel-item-prev",this._element)&&(s(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null}cycle(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))}to(t){this._activeElement=V.findOne(nt,this._element);const e=this._getItemIndex(this._activeElement);if(t>this._items.length-1||t<0)return;if(this._isSliding)return void j.one(this._element,et,(()=>this.to(t)));if(e===t)return this.pause(),void this.cycle();const i=t>e?Q:G;this._slide(i,this._items[t])}_getConfig(t){return t={...X,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(K,t,Y),t}_handleSwipe(){const t=Math.abs(this.touchDeltaX);if(t<=40)return;const e=t/this.touchDeltaX;this.touchDeltaX=0,e&&this._slide(e>0?J:Z)}_addEventListeners(){this._config.keyboard&&j.on(this._element,"keydown.bs.carousel",(t=>this._keydown(t))),"hover"===this._config.pause&&(j.on(this._element,"mouseenter.bs.carousel",(t=>this.pause(t))),j.on(this._element,"mouseleave.bs.carousel",(t=>this.cycle(t)))),this._config.touch&&this._touchSupported&&this._addTouchEventListeners()}_addTouchEventListeners(){const t=t=>this._pointerEvent&&("pen"===t.pointerType||"touch"===t.pointerType),e=e=>{t(e)?this.touchStartX=e.clientX:this._pointerEvent||(this.touchStartX=e.touches[0].clientX)},i=t=>{this.touchDeltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this.touchStartX},n=e=>{t(e)&&(this.touchDeltaX=e.clientX-this.touchStartX),this._handleSwipe(),"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((t=>this.cycle(t)),500+this._config.interval))};V.find(".carousel-item img",this._element).forEach((t=>{j.on(t,"dragstart.bs.carousel",(t=>t.preventDefault()))})),this._pointerEvent?(j.on(this._element,"pointerdown.bs.carousel",(t=>e(t))),j.on(this._element,"pointerup.bs.carousel",(t=>n(t))),this._element.classList.add("pointer-event")):(j.on(this._element,"touchstart.bs.carousel",(t=>e(t))),j.on(this._element,"touchmove.bs.carousel",(t=>i(t))),j.on(this._element,"touchend.bs.carousel",(t=>n(t))))}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=tt[t.key];e&&(t.preventDefault(),this._slide(e))}_getItemIndex(t){return this._items=t&&t.parentNode?V.find(".carousel-item",t.parentNode):[],this._items.indexOf(t)}_getItemByOrder(t,e){const i=t===Q;return v(this._items,e,i,this._config.wrap)}_triggerSlideEvent(t,e){const i=this._getItemIndex(t),n=this._getItemIndex(V.findOne(nt,this._element));return j.trigger(this._element,"slide.bs.carousel",{relatedTarget:t,direction:e,from:n,to:i})}_setActiveIndicatorElement(t){if(this._indicatorsElement){const e=V.findOne(".active",this._indicatorsElement);e.classList.remove(it),e.removeAttribute("aria-current");const i=V.find("[data-bs-target]",this._indicatorsElement);for(let e=0;e{j.trigger(this._element,et,{relatedTarget:o,direction:d,from:s,to:r})};if(this._element.classList.contains("slide")){o.classList.add(h),u(o),n.classList.add(c),o.classList.add(c);const t=()=>{o.classList.remove(c,h),o.classList.add(it),n.classList.remove(it,h,c),this._isSliding=!1,setTimeout(f,0)};this._queueCallback(t,n,!0)}else n.classList.remove(it),o.classList.add(it),this._isSliding=!1,f();a&&this.cycle()}_directionToOrder(t){return[J,Z].includes(t)?m()?t===Z?G:Q:t===Z?Q:G:t}_orderToDirection(t){return[Q,G].includes(t)?m()?t===G?Z:J:t===G?J:Z:t}static carouselInterface(t,e){const i=st.getOrCreateInstance(t,e);let{_config:n}=i;"object"==typeof e&&(n={...n,...e});const s="string"==typeof e?e:n.slide;if("number"==typeof e)i.to(e);else if("string"==typeof s){if(void 0===i[s])throw new TypeError(`No method named "${s}"`);i[s]()}else n.interval&&n.ride&&(i.pause(),i.cycle())}static jQueryInterface(t){return this.each((function(){st.carouselInterface(this,t)}))}static dataApiClickHandler(t){const e=n(this);if(!e||!e.classList.contains("carousel"))return;const i={...U.getDataAttributes(e),...U.getDataAttributes(this)},s=this.getAttribute("data-bs-slide-to");s&&(i.interval=!1),st.carouselInterface(e,i),s&&st.getInstance(e).to(s),t.preventDefault()}}j.on(document,"click.bs.carousel.data-api","[data-bs-slide], [data-bs-slide-to]",st.dataApiClickHandler),j.on(window,"load.bs.carousel.data-api",(()=>{const t=V.find('[data-bs-ride="carousel"]');for(let e=0,i=t.length;et===this._element));null!==s&&o.length&&(this._selector=s,this._triggerArray.push(e))}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return rt}static get NAME(){return ot}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t,e=[];if(this._config.parent){const t=V.find(ut,this._config.parent);e=V.find(".collapse.show, .collapse.collapsing",this._config.parent).filter((e=>!t.includes(e)))}const i=V.findOne(this._selector);if(e.length){const n=e.find((t=>i!==t));if(t=n?pt.getInstance(n):null,t&&t._isTransitioning)return}if(j.trigger(this._element,"show.bs.collapse").defaultPrevented)return;e.forEach((e=>{i!==e&&pt.getOrCreateInstance(e,{toggle:!1}).hide(),t||H.set(e,"bs.collapse",null)}));const n=this._getDimension();this._element.classList.remove(ct),this._element.classList.add(ht),this._element.style[n]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const s=`scroll${n[0].toUpperCase()+n.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct,lt),this._element.style[n]="",j.trigger(this._element,"shown.bs.collapse")}),this._element,!0),this._element.style[n]=`${this._element[s]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(j.trigger(this._element,"hide.bs.collapse").defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,u(this._element),this._element.classList.add(ht),this._element.classList.remove(ct,lt);const e=this._triggerArray.length;for(let t=0;t{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct),j.trigger(this._element,"hidden.bs.collapse")}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(lt)}_getConfig(t){return(t={...rt,...U.getDataAttributes(this._element),...t}).toggle=Boolean(t.toggle),t.parent=r(t.parent),a(ot,t,at),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=V.find(ut,this._config.parent);V.find(ft,this._config.parent).filter((e=>!t.includes(e))).forEach((t=>{const e=n(t);e&&this._addAriaAndCollapsedClass([t],this._isShown(e))}))}_addAriaAndCollapsedClass(t,e){t.length&&t.forEach((t=>{e?t.classList.remove(dt):t.classList.add(dt),t.setAttribute("aria-expanded",e)}))}static jQueryInterface(t){return this.each((function(){const e={};"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1);const i=pt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}j.on(document,"click.bs.collapse.data-api",ft,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();const e=i(this);V.find(e).forEach((t=>{pt.getOrCreateInstance(t,{toggle:!1}).toggle()}))})),g(pt);var mt="top",gt="bottom",_t="right",bt="left",vt="auto",yt=[mt,gt,_t,bt],wt="start",Et="end",At="clippingParents",Tt="viewport",Ot="popper",Ct="reference",kt=yt.reduce((function(t,e){return t.concat([e+"-"+wt,e+"-"+Et])}),[]),Lt=[].concat(yt,[vt]).reduce((function(t,e){return t.concat([e,e+"-"+wt,e+"-"+Et])}),[]),xt="beforeRead",Dt="read",St="afterRead",Nt="beforeMain",It="main",Pt="afterMain",jt="beforeWrite",Mt="write",Ht="afterWrite",Bt=[xt,Dt,St,Nt,It,Pt,jt,Mt,Ht];function Rt(t){return t?(t.nodeName||"").toLowerCase():null}function Wt(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function $t(t){return t instanceof Wt(t).Element||t instanceof Element}function zt(t){return t instanceof Wt(t).HTMLElement||t instanceof HTMLElement}function qt(t){return"undefined"!=typeof ShadowRoot&&(t instanceof Wt(t).ShadowRoot||t instanceof ShadowRoot)}const Ft={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];zt(s)&&Rt(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});zt(n)&&Rt(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function Ut(t){return t.split("-")[0]}function Vt(t,e){var i=t.getBoundingClientRect();return{width:i.width/1,height:i.height/1,top:i.top/1,right:i.right/1,bottom:i.bottom/1,left:i.left/1,x:i.left/1,y:i.top/1}}function Kt(t){var e=Vt(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Xt(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&qt(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function Yt(t){return Wt(t).getComputedStyle(t)}function Qt(t){return["table","td","th"].indexOf(Rt(t))>=0}function Gt(t){return(($t(t)?t.ownerDocument:t.document)||window.document).documentElement}function Zt(t){return"html"===Rt(t)?t:t.assignedSlot||t.parentNode||(qt(t)?t.host:null)||Gt(t)}function Jt(t){return zt(t)&&"fixed"!==Yt(t).position?t.offsetParent:null}function te(t){for(var e=Wt(t),i=Jt(t);i&&Qt(i)&&"static"===Yt(i).position;)i=Jt(i);return i&&("html"===Rt(i)||"body"===Rt(i)&&"static"===Yt(i).position)?e:i||function(t){var e=-1!==navigator.userAgent.toLowerCase().indexOf("firefox");if(-1!==navigator.userAgent.indexOf("Trident")&&zt(t)&&"fixed"===Yt(t).position)return null;for(var i=Zt(t);zt(i)&&["html","body"].indexOf(Rt(i))<0;){var n=Yt(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function ee(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}var ie=Math.max,ne=Math.min,se=Math.round;function oe(t,e,i){return ie(t,ne(e,i))}function re(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function ae(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const le={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=Ut(i.placement),l=ee(a),c=[bt,_t].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return re("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:ae(t,yt))}(s.padding,i),d=Kt(o),u="y"===l?mt:bt,f="y"===l?gt:_t,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=te(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,E=oe(v,w,y),A=l;i.modifiersData[n]=((e={})[A]=E,e.centerOffset=E-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Xt(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ce(t){return t.split("-")[1]}var he={top:"auto",right:"auto",bottom:"auto",left:"auto"};function de(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=!0===h?function(t){var e=t.x,i=t.y,n=window.devicePixelRatio||1;return{x:se(se(e*n)/n)||0,y:se(se(i*n)/n)||0}}(r):"function"==typeof h?h(r):r,u=d.x,f=void 0===u?0:u,p=d.y,m=void 0===p?0:p,g=r.hasOwnProperty("x"),_=r.hasOwnProperty("y"),b=bt,v=mt,y=window;if(c){var w=te(i),E="clientHeight",A="clientWidth";w===Wt(i)&&"static"!==Yt(w=Gt(i)).position&&"absolute"===a&&(E="scrollHeight",A="scrollWidth"),w=w,s!==mt&&(s!==bt&&s!==_t||o!==Et)||(v=gt,m-=w[E]-n.height,m*=l?1:-1),s!==bt&&(s!==mt&&s!==gt||o!==Et)||(b=_t,f-=w[A]-n.width,f*=l?1:-1)}var T,O=Object.assign({position:a},c&&he);return l?Object.assign({},O,((T={})[v]=_?"0":"",T[b]=g?"0":"",T.transform=(y.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",T)):Object.assign({},O,((e={})[v]=_?m+"px":"",e[b]=g?f+"px":"",e.transform="",e))}const ue={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:Ut(e.placement),variation:ce(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,de(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,de(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var fe={passive:!0};const pe={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=Wt(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,fe)})),a&&l.addEventListener("resize",i.update,fe),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,fe)})),a&&l.removeEventListener("resize",i.update,fe)}},data:{}};var me={left:"right",right:"left",bottom:"top",top:"bottom"};function ge(t){return t.replace(/left|right|bottom|top/g,(function(t){return me[t]}))}var _e={start:"end",end:"start"};function be(t){return t.replace(/start|end/g,(function(t){return _e[t]}))}function ve(t){var e=Wt(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function ye(t){return Vt(Gt(t)).left+ve(t).scrollLeft}function we(t){var e=Yt(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ee(t){return["html","body","#document"].indexOf(Rt(t))>=0?t.ownerDocument.body:zt(t)&&we(t)?t:Ee(Zt(t))}function Ae(t,e){var i;void 0===e&&(e=[]);var n=Ee(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=Wt(n),r=s?[o].concat(o.visualViewport||[],we(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Ae(Zt(r)))}function Te(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function Oe(t,e){return e===Tt?Te(function(t){var e=Wt(t),i=Gt(t),n=e.visualViewport,s=i.clientWidth,o=i.clientHeight,r=0,a=0;return n&&(s=n.width,o=n.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(r=n.offsetLeft,a=n.offsetTop)),{width:s,height:o,x:r+ye(t),y:a}}(t)):zt(e)?function(t){var e=Vt(t);return e.top=e.top+t.clientTop,e.left=e.left+t.clientLeft,e.bottom=e.top+t.clientHeight,e.right=e.left+t.clientWidth,e.width=t.clientWidth,e.height=t.clientHeight,e.x=e.left,e.y=e.top,e}(e):Te(function(t){var e,i=Gt(t),n=ve(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=ie(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=ie(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+ye(t),l=-n.scrollTop;return"rtl"===Yt(s||i).direction&&(a+=ie(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(Gt(t)))}function Ce(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?Ut(s):null,r=s?ce(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case mt:e={x:a,y:i.y-n.height};break;case gt:e={x:a,y:i.y+i.height};break;case _t:e={x:i.x+i.width,y:l};break;case bt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?ee(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case wt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Et:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ke(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.boundary,r=void 0===o?At:o,a=i.rootBoundary,l=void 0===a?Tt:a,c=i.elementContext,h=void 0===c?Ot:c,d=i.altBoundary,u=void 0!==d&&d,f=i.padding,p=void 0===f?0:f,m=re("number"!=typeof p?p:ae(p,yt)),g=h===Ot?Ct:Ot,_=t.rects.popper,b=t.elements[u?g:h],v=function(t,e,i){var n="clippingParents"===e?function(t){var e=Ae(Zt(t)),i=["absolute","fixed"].indexOf(Yt(t).position)>=0&&zt(t)?te(t):t;return $t(i)?e.filter((function(t){return $t(t)&&Xt(t,i)&&"body"!==Rt(t)})):[]}(t):[].concat(e),s=[].concat(n,[i]),o=s[0],r=s.reduce((function(e,i){var n=Oe(t,i);return e.top=ie(n.top,e.top),e.right=ne(n.right,e.right),e.bottom=ne(n.bottom,e.bottom),e.left=ie(n.left,e.left),e}),Oe(t,o));return r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}($t(b)?b:b.contextElement||Gt(t.elements.popper),r,l),y=Vt(t.elements.reference),w=Ce({reference:y,element:_,strategy:"absolute",placement:s}),E=Te(Object.assign({},_,w)),A=h===Ot?E:y,T={top:v.top-A.top+m.top,bottom:A.bottom-v.bottom+m.bottom,left:v.left-A.left+m.left,right:A.right-v.right+m.right},O=t.modifiersData.offset;if(h===Ot&&O){var C=O[s];Object.keys(T).forEach((function(t){var e=[_t,gt].indexOf(t)>=0?1:-1,i=[mt,gt].indexOf(t)>=0?"y":"x";T[t]+=C[i]*e}))}return T}function Le(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?Lt:l,h=ce(n),d=h?a?kt:kt.filter((function(t){return ce(t)===h})):yt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ke(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[Ut(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const xe={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=Ut(g),b=l||(_!==g&&p?function(t){if(Ut(t)===vt)return[];var e=ge(t);return[be(t),e,be(e)]}(g):[ge(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(Ut(i)===vt?Le(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,E=new Map,A=!0,T=v[0],O=0;O=0,D=x?"width":"height",S=ke(e,{placement:C,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),N=x?L?_t:bt:L?gt:mt;y[D]>w[D]&&(N=ge(N));var I=ge(N),P=[];if(o&&P.push(S[k]<=0),a&&P.push(S[N]<=0,S[I]<=0),P.every((function(t){return t}))){T=C,A=!1;break}E.set(C,P)}if(A)for(var j=function(t){var e=v.find((function(e){var i=E.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==j(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function De(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function Se(t){return[mt,_t,gt,bt].some((function(e){return t[e]>=0}))}const Ne={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ke(e,{elementContext:"reference"}),a=ke(e,{altBoundary:!0}),l=De(r,n),c=De(a,s,o),h=Se(l),d=Se(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},Ie={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=Lt.reduce((function(t,i){return t[i]=function(t,e,i){var n=Ut(t),s=[bt,mt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[bt,_t].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},Pe={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=Ce({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},je={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ke(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=Ut(e.placement),b=ce(e.placement),v=!b,y=ee(_),w="x"===y?"y":"x",E=e.modifiersData.popperOffsets,A=e.rects.reference,T=e.rects.popper,O="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,C={x:0,y:0};if(E){if(o||a){var k="y"===y?mt:bt,L="y"===y?gt:_t,x="y"===y?"height":"width",D=E[y],S=E[y]+g[k],N=E[y]-g[L],I=f?-T[x]/2:0,P=b===wt?A[x]:T[x],j=b===wt?-T[x]:-A[x],M=e.elements.arrow,H=f&&M?Kt(M):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},R=B[k],W=B[L],$=oe(0,A[x],H[x]),z=v?A[x]/2-I-$-R-O:P-$-R-O,q=v?-A[x]/2+I+$+W+O:j+$+W+O,F=e.elements.arrow&&te(e.elements.arrow),U=F?"y"===y?F.clientTop||0:F.clientLeft||0:0,V=e.modifiersData.offset?e.modifiersData.offset[e.placement][y]:0,K=E[y]+z-V-U,X=E[y]+q-V;if(o){var Y=oe(f?ne(S,K):S,D,f?ie(N,X):N);E[y]=Y,C[y]=Y-D}if(a){var Q="x"===y?mt:bt,G="x"===y?gt:_t,Z=E[w],J=Z+g[Q],tt=Z-g[G],et=oe(f?ne(J,K):J,Z,f?ie(tt,X):tt);E[w]=et,C[w]=et-Z}}e.modifiersData[n]=C}},requiresIfExists:["offset"]};function Me(t,e,i){void 0===i&&(i=!1);var n=zt(e);zt(e)&&function(t){var e=t.getBoundingClientRect();e.width,t.offsetWidth,e.height,t.offsetHeight}(e);var s,o,r=Gt(e),a=Vt(t),l={scrollLeft:0,scrollTop:0},c={x:0,y:0};return(n||!n&&!i)&&(("body"!==Rt(e)||we(r))&&(l=(s=e)!==Wt(s)&&zt(s)?{scrollLeft:(o=s).scrollLeft,scrollTop:o.scrollTop}:ve(s)),zt(e)?((c=Vt(e)).x+=e.clientLeft,c.y+=e.clientTop):r&&(c.x=ye(r))),{x:a.left+l.scrollLeft-c.x,y:a.top+l.scrollTop-c.y,width:a.width,height:a.height}}function He(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var Be={placement:"bottom",modifiers:[],strategy:"absolute"};function Re(){for(var t=arguments.length,e=new Array(t),i=0;ij.on(t,"mouseover",d))),this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.add(Je),this._element.classList.add(Je),j.trigger(this._element,"shown.bs.dropdown",t)}hide(){if(c(this._element)||!this._isShown(this._menu))return;const t={relatedTarget:this._element};this._completeHide(t)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_completeHide(t){j.trigger(this._element,"hide.bs.dropdown",t).defaultPrevented||("ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>j.off(t,"mouseover",d))),this._popper&&this._popper.destroy(),this._menu.classList.remove(Je),this._element.classList.remove(Je),this._element.setAttribute("aria-expanded","false"),U.removeDataAttribute(this._menu,"popper"),j.trigger(this._element,"hidden.bs.dropdown",t))}_getConfig(t){if(t={...this.constructor.Default,...U.getDataAttributes(this._element),...t},a(Ue,t,this.constructor.DefaultType),"object"==typeof t.reference&&!o(t.reference)&&"function"!=typeof t.reference.getBoundingClientRect)throw new TypeError(`${Ue.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return t}_createPopper(t){if(void 0===Fe)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let e=this._element;"parent"===this._config.reference?e=t:o(this._config.reference)?e=r(this._config.reference):"object"==typeof this._config.reference&&(e=this._config.reference);const i=this._getPopperConfig(),n=i.modifiers.find((t=>"applyStyles"===t.name&&!1===t.enabled));this._popper=qe(e,this._menu,i),n&&U.setDataAttribute(this._menu,"popper","static")}_isShown(t=this._element){return t.classList.contains(Je)}_getMenuElement(){return V.next(this._element,ei)[0]}_getPlacement(){const t=this._element.parentNode;if(t.classList.contains("dropend"))return ri;if(t.classList.contains("dropstart"))return ai;const e="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return t.classList.contains("dropup")?e?ni:ii:e?oi:si}_detectNavbar(){return null!==this._element.closest(".navbar")}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return"static"===this._config.display&&(t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..."function"==typeof this._config.popperConfig?this._config.popperConfig(t):this._config.popperConfig}}_selectMenuItem({key:t,target:e}){const i=V.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter(l);i.length&&v(i,e,t===Ye,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=hi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(t&&(2===t.button||"keyup"===t.type&&"Tab"!==t.key))return;const e=V.find(ti);for(let i=0,n=e.length;ie+t)),this._setElementAttributes(di,"paddingRight",(e=>e+t)),this._setElementAttributes(ui,"marginRight",(e=>e-t))}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t)[e];t.style[e]=`${i(Number.parseFloat(s))}px`}))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,"paddingRight"),this._resetElementAttributes(di,"paddingRight"),this._resetElementAttributes(ui,"marginRight")}_saveInitialAttribute(t,e){const i=t.style[e];i&&U.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=U.getDataAttribute(t,e);void 0===i?t.style.removeProperty(e):(U.removeDataAttribute(t,e),t.style[e]=i)}))}_applyManipulationCallback(t,e){o(t)?e(t):V.find(t,this._element).forEach(e)}isOverflowing(){return this.getWidth()>0}}const pi={className:"modal-backdrop",isVisible:!0,isAnimated:!1,rootElement:"body",clickCallback:null},mi={className:"string",isVisible:"boolean",isAnimated:"boolean",rootElement:"(element|string)",clickCallback:"(function|null)"},gi="show",_i="mousedown.bs.backdrop";class bi{constructor(t){this._config=this._getConfig(t),this._isAppended=!1,this._element=null}show(t){this._config.isVisible?(this._append(),this._config.isAnimated&&u(this._getElement()),this._getElement().classList.add(gi),this._emulateAnimation((()=>{_(t)}))):_(t)}hide(t){this._config.isVisible?(this._getElement().classList.remove(gi),this._emulateAnimation((()=>{this.dispose(),_(t)}))):_(t)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_getConfig(t){return(t={...pi,..."object"==typeof t?t:{}}).rootElement=r(t.rootElement),a("backdrop",t,mi),t}_append(){this._isAppended||(this._config.rootElement.append(this._getElement()),j.on(this._getElement(),_i,(()=>{_(this._config.clickCallback)})),this._isAppended=!0)}dispose(){this._isAppended&&(j.off(this._element,_i),this._element.remove(),this._isAppended=!1)}_emulateAnimation(t){b(t,this._getElement(),this._config.isAnimated)}}const vi={trapElement:null,autofocus:!0},yi={trapElement:"element",autofocus:"boolean"},wi=".bs.focustrap",Ei="backward";class Ai{constructor(t){this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}activate(){const{trapElement:t,autofocus:e}=this._config;this._isActive||(e&&t.focus(),j.off(document,wi),j.on(document,"focusin.bs.focustrap",(t=>this._handleFocusin(t))),j.on(document,"keydown.tab.bs.focustrap",(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,j.off(document,wi))}_handleFocusin(t){const{target:e}=t,{trapElement:i}=this._config;if(e===document||e===i||i.contains(e))return;const n=V.focusableChildren(i);0===n.length?i.focus():this._lastTabNavDirection===Ei?n[n.length-1].focus():n[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?Ei:"forward")}_getConfig(t){return t={...vi,..."object"==typeof t?t:{}},a("focustrap",t,yi),t}}const Ti="modal",Oi="Escape",Ci={backdrop:!0,keyboard:!0,focus:!0},ki={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean"},Li="hidden.bs.modal",xi="show.bs.modal",Di="resize.bs.modal",Si="click.dismiss.bs.modal",Ni="keydown.dismiss.bs.modal",Ii="mousedown.dismiss.bs.modal",Pi="modal-open",ji="show",Mi="modal-static";class Hi extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._dialog=V.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollBar=new fi}static get Default(){return Ci}static get NAME(){return Ti}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||j.trigger(this._element,xi,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isAnimated()&&(this._isTransitioning=!0),this._scrollBar.hide(),document.body.classList.add(Pi),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),j.on(this._dialog,Ii,(()=>{j.one(this._element,"mouseup.dismiss.bs.modal",(t=>{t.target===this._element&&(this._ignoreBackdropClick=!0)}))})),this._showBackdrop((()=>this._showElement(t))))}hide(){if(!this._isShown||this._isTransitioning)return;if(j.trigger(this._element,"hide.bs.modal").defaultPrevented)return;this._isShown=!1;const t=this._isAnimated();t&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),this._focustrap.deactivate(),this._element.classList.remove(ji),j.off(this._element,Si),j.off(this._dialog,Ii),this._queueCallback((()=>this._hideModal()),this._element,t)}dispose(){[window,this._dialog].forEach((t=>j.off(t,".bs.modal"))),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new bi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new Ai({trapElement:this._element})}_getConfig(t){return t={...Ci,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(Ti,t,ki),t}_showElement(t){const e=this._isAnimated(),i=V.findOne(".modal-body",this._dialog);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0,i&&(i.scrollTop=0),e&&u(this._element),this._element.classList.add(ji),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,j.trigger(this._element,"shown.bs.modal",{relatedTarget:t})}),this._dialog,e)}_setEscapeEvent(){this._isShown?j.on(this._element,Ni,(t=>{this._config.keyboard&&t.key===Oi?(t.preventDefault(),this.hide()):this._config.keyboard||t.key!==Oi||this._triggerBackdropTransition()})):j.off(this._element,Ni)}_setResizeEvent(){this._isShown?j.on(window,Di,(()=>this._adjustDialog())):j.off(window,Di)}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(Pi),this._resetAdjustments(),this._scrollBar.reset(),j.trigger(this._element,Li)}))}_showBackdrop(t){j.on(this._element,Si,(t=>{this._ignoreBackdropClick?this._ignoreBackdropClick=!1:t.target===t.currentTarget&&(!0===this._config.backdrop?this.hide():"static"===this._config.backdrop&&this._triggerBackdropTransition())})),this._backdrop.show(t)}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(j.trigger(this._element,"hidePrevented.bs.modal").defaultPrevented)return;const{classList:t,scrollHeight:e,style:i}=this._element,n=e>document.documentElement.clientHeight;!n&&"hidden"===i.overflowY||t.contains(Mi)||(n||(i.overflowY="hidden"),t.add(Mi),this._queueCallback((()=>{t.remove(Mi),n||this._queueCallback((()=>{i.overflowY=""}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;(!i&&t&&!m()||i&&!t&&m())&&(this._element.style.paddingLeft=`${e}px`),(i&&!t&&!m()||!i&&t&&m())&&(this._element.style.paddingRight=`${e}px`)}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=Hi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}j.on(document,"click.bs.modal.data-api",'[data-bs-toggle="modal"]',(function(t){const e=n(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),j.one(e,xi,(t=>{t.defaultPrevented||j.one(e,Li,(()=>{l(this)&&this.focus()}))}));const i=V.findOne(".modal.show");i&&Hi.getInstance(i).hide(),Hi.getOrCreateInstance(e).toggle(this)})),R(Hi),g(Hi);const Bi="offcanvas",Ri={backdrop:!0,keyboard:!0,scroll:!1},Wi={backdrop:"boolean",keyboard:"boolean",scroll:"boolean"},$i="show",zi=".offcanvas.show",qi="hidden.bs.offcanvas";class Fi extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get NAME(){return Bi}static get Default(){return Ri}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||j.trigger(this._element,"show.bs.offcanvas",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._element.style.visibility="visible",this._backdrop.show(),this._config.scroll||(new fi).hide(),this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add($i),this._queueCallback((()=>{this._config.scroll||this._focustrap.activate(),j.trigger(this._element,"shown.bs.offcanvas",{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(j.trigger(this._element,"hide.bs.offcanvas").defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.remove($i),this._backdrop.hide(),this._queueCallback((()=>{this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._element.style.visibility="hidden",this._config.scroll||(new fi).reset(),j.trigger(this._element,qi)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_getConfig(t){return t={...Ri,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(Bi,t,Wi),t}_initializeBackDrop(){return new bi({className:"offcanvas-backdrop",isVisible:this._config.backdrop,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:()=>this.hide()})}_initializeFocusTrap(){return new Ai({trapElement:this._element})}_addEventListeners(){j.on(this._element,"keydown.dismiss.bs.offcanvas",(t=>{this._config.keyboard&&"Escape"===t.key&&this.hide()}))}static jQueryInterface(t){return this.each((function(){const e=Fi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}j.on(document,"click.bs.offcanvas.data-api",'[data-bs-toggle="offcanvas"]',(function(t){const e=n(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this))return;j.one(e,qi,(()=>{l(this)&&this.focus()}));const i=V.findOne(zi);i&&i!==e&&Fi.getInstance(i).hide(),Fi.getOrCreateInstance(e).toggle(this)})),j.on(window,"load.bs.offcanvas.data-api",(()=>V.find(zi).forEach((t=>Fi.getOrCreateInstance(t).show())))),R(Fi),g(Fi);const Ui=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Vi=/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i,Ki=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,Xi=(t,e)=>{const i=t.nodeName.toLowerCase();if(e.includes(i))return!Ui.has(i)||Boolean(Vi.test(t.nodeValue)||Ki.test(t.nodeValue));const n=e.filter((t=>t instanceof RegExp));for(let t=0,e=n.length;t{Xi(t,r)||i.removeAttribute(t.nodeName)}))}return n.body.innerHTML}const Qi="tooltip",Gi=new Set(["sanitize","allowList","sanitizeFn"]),Zi={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(array|string|function)",container:"(string|element|boolean)",fallbackPlacements:"array",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",allowList:"object",popperConfig:"(null|object|function)"},Ji={AUTO:"auto",TOP:"top",RIGHT:m()?"left":"right",BOTTOM:"bottom",LEFT:m()?"right":"left"},tn={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},en={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},nn="fade",sn="show",on="show",rn="out",an=".tooltip-inner",ln=".modal",cn="hide.bs.modal",hn="hover",dn="focus";class un extends B{constructor(t,e){if(void 0===Fe)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this._config=this._getConfig(e),this.tip=null,this._setListeners()}static get Default(){return tn}static get NAME(){return Qi}static get Event(){return en}static get DefaultType(){return Zi}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(t){if(this._isEnabled)if(t){const e=this._initializeOnDelegatedTarget(t);e._activeTrigger.click=!e._activeTrigger.click,e._isWithActiveTrigger()?e._enter(null,e):e._leave(null,e)}else{if(this.getTipElement().classList.contains(sn))return void this._leave(null,this);this._enter(null,this)}}dispose(){clearTimeout(this._timeout),j.off(this._element.closest(ln),cn,this._hideModalHandler),this.tip&&this.tip.remove(),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this.isWithContent()||!this._isEnabled)return;const t=j.trigger(this._element,this.constructor.Event.SHOW),e=h(this._element),i=null===e?this._element.ownerDocument.documentElement.contains(this._element):e.contains(this._element);if(t.defaultPrevented||!i)return;"tooltip"===this.constructor.NAME&&this.tip&&this.getTitle()!==this.tip.querySelector(an).innerHTML&&(this._disposePopper(),this.tip.remove(),this.tip=null);const n=this.getTipElement(),s=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME);n.setAttribute("id",s),this._element.setAttribute("aria-describedby",s),this._config.animation&&n.classList.add(nn);const o="function"==typeof this._config.placement?this._config.placement.call(this,n,this._element):this._config.placement,r=this._getAttachment(o);this._addAttachmentClass(r);const{container:a}=this._config;H.set(n,this.constructor.DATA_KEY,this),this._element.ownerDocument.documentElement.contains(this.tip)||(a.append(n),j.trigger(this._element,this.constructor.Event.INSERTED)),this._popper?this._popper.update():this._popper=qe(this._element,n,this._getPopperConfig(r)),n.classList.add(sn);const l=this._resolvePossibleFunction(this._config.customClass);l&&n.classList.add(...l.split(" ")),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>{j.on(t,"mouseover",d)}));const c=this.tip.classList.contains(nn);this._queueCallback((()=>{const t=this._hoverState;this._hoverState=null,j.trigger(this._element,this.constructor.Event.SHOWN),t===rn&&this._leave(null,this)}),this.tip,c)}hide(){if(!this._popper)return;const t=this.getTipElement();if(j.trigger(this._element,this.constructor.Event.HIDE).defaultPrevented)return;t.classList.remove(sn),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>j.off(t,"mouseover",d))),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1;const e=this.tip.classList.contains(nn);this._queueCallback((()=>{this._isWithActiveTrigger()||(this._hoverState!==on&&t.remove(),this._cleanTipClass(),this._element.removeAttribute("aria-describedby"),j.trigger(this._element,this.constructor.Event.HIDDEN),this._disposePopper())}),this.tip,e),this._hoverState=""}update(){null!==this._popper&&this._popper.update()}isWithContent(){return Boolean(this.getTitle())}getTipElement(){if(this.tip)return this.tip;const t=document.createElement("div");t.innerHTML=this._config.template;const e=t.children[0];return this.setContent(e),e.classList.remove(nn,sn),this.tip=e,this.tip}setContent(t){this._sanitizeAndSetContent(t,this.getTitle(),an)}_sanitizeAndSetContent(t,e,i){const n=V.findOne(i,t);e||!n?this.setElementContent(n,e):n.remove()}setElementContent(t,e){if(null!==t)return o(e)?(e=r(e),void(this._config.html?e.parentNode!==t&&(t.innerHTML="",t.append(e)):t.textContent=e.textContent)):void(this._config.html?(this._config.sanitize&&(e=Yi(e,this._config.allowList,this._config.sanitizeFn)),t.innerHTML=e):t.textContent=e)}getTitle(){const t=this._element.getAttribute("data-bs-original-title")||this._config.title;return this._resolvePossibleFunction(t)}updateAttachment(t){return"right"===t?"end":"left"===t?"start":t}_initializeOnDelegatedTarget(t,e){return e||this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return"function"==typeof t?t.call(this._element):t}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:t=>this._handlePopperPlacementChange(t)}],onFirstUpdate:t=>{t.options.placement!==t.placement&&this._handlePopperPlacementChange(t)}};return{...e,..."function"==typeof this._config.popperConfig?this._config.popperConfig(e):this._config.popperConfig}}_addAttachmentClass(t){this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(t)}`)}_getAttachment(t){return Ji[t.toUpperCase()]}_setListeners(){this._config.trigger.split(" ").forEach((t=>{if("click"===t)j.on(this._element,this.constructor.Event.CLICK,this._config.selector,(t=>this.toggle(t)));else if("manual"!==t){const e=t===hn?this.constructor.Event.MOUSEENTER:this.constructor.Event.FOCUSIN,i=t===hn?this.constructor.Event.MOUSELEAVE:this.constructor.Event.FOCUSOUT;j.on(this._element,e,this._config.selector,(t=>this._enter(t))),j.on(this._element,i,this._config.selector,(t=>this._leave(t)))}})),this._hideModalHandler=()=>{this._element&&this.hide()},j.on(this._element.closest(ln),cn,this._hideModalHandler),this._config.selector?this._config={...this._config,trigger:"manual",selector:""}:this._fixTitle()}_fixTitle(){const t=this._element.getAttribute("title"),e=typeof this._element.getAttribute("data-bs-original-title");(t||"string"!==e)&&(this._element.setAttribute("data-bs-original-title",t||""),!t||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",t),this._element.setAttribute("title",""))}_enter(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusin"===t.type?dn:hn]=!0),e.getTipElement().classList.contains(sn)||e._hoverState===on?e._hoverState=on:(clearTimeout(e._timeout),e._hoverState=on,e._config.delay&&e._config.delay.show?e._timeout=setTimeout((()=>{e._hoverState===on&&e.show()}),e._config.delay.show):e.show())}_leave(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusout"===t.type?dn:hn]=e._element.contains(t.relatedTarget)),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=rn,e._config.delay&&e._config.delay.hide?e._timeout=setTimeout((()=>{e._hoverState===rn&&e.hide()}),e._config.delay.hide):e.hide())}_isWithActiveTrigger(){for(const t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1}_getConfig(t){const e=U.getDataAttributes(this._element);return Object.keys(e).forEach((t=>{Gi.has(t)&&delete e[t]})),(t={...this.constructor.Default,...e,..."object"==typeof t&&t?t:{}}).container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),a(Qi,t,this.constructor.DefaultType),t.sanitize&&(t.template=Yi(t.template,t.allowList,t.sanitizeFn)),t}_getDelegateConfig(){const t={};for(const e in this._config)this.constructor.Default[e]!==this._config[e]&&(t[e]=this._config[e]);return t}_cleanTipClass(){const t=this.getTipElement(),e=new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`,"g"),i=t.getAttribute("class").match(e);null!==i&&i.length>0&&i.map((t=>t.trim())).forEach((e=>t.classList.remove(e)))}_getBasicClassPrefix(){return"bs-tooltip"}_handlePopperPlacementChange(t){const{state:e}=t;e&&(this.tip=e.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(e.placement)))}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null)}static jQueryInterface(t){return this.each((function(){const e=un.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(un);const fn={...un.Default,placement:"right",offset:[0,8],trigger:"click",content:"",template:''},pn={...un.DefaultType,content:"(string|element|function)"},mn={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"};class gn extends un{static get Default(){return fn}static get NAME(){return"popover"}static get Event(){return mn}static get DefaultType(){return pn}isWithContent(){return this.getTitle()||this._getContent()}setContent(t){this._sanitizeAndSetContent(t,this.getTitle(),".popover-header"),this._sanitizeAndSetContent(t,this._getContent(),".popover-body")}_getContent(){return this._resolvePossibleFunction(this._config.content)}_getBasicClassPrefix(){return"bs-popover"}static jQueryInterface(t){return this.each((function(){const e=gn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(gn);const _n="scrollspy",bn={offset:10,method:"auto",target:""},vn={offset:"number",method:"string",target:"(string|element)"},yn="active",wn=".nav-link, .list-group-item, .dropdown-item",En="position";class An extends B{constructor(t,e){super(t),this._scrollElement="BODY"===this._element.tagName?window:this._element,this._config=this._getConfig(e),this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,j.on(this._scrollElement,"scroll.bs.scrollspy",(()=>this._process())),this.refresh(),this._process()}static get Default(){return bn}static get NAME(){return _n}refresh(){const t=this._scrollElement===this._scrollElement.window?"offset":En,e="auto"===this._config.method?t:this._config.method,n=e===En?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),V.find(wn,this._config.target).map((t=>{const s=i(t),o=s?V.findOne(s):null;if(o){const t=o.getBoundingClientRect();if(t.width||t.height)return[U[e](o).top+n,s]}return null})).filter((t=>t)).sort(((t,e)=>t[0]-e[0])).forEach((t=>{this._offsets.push(t[0]),this._targets.push(t[1])}))}dispose(){j.off(this._scrollElement,".bs.scrollspy"),super.dispose()}_getConfig(t){return(t={...bn,...U.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}}).target=r(t.target)||document.documentElement,a(_n,t,vn),t}_getScrollTop(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop}_getScrollHeight(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)}_getOffsetHeight(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height}_process(){const t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),i=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=i){const t=this._targets[this._targets.length-1];this._activeTarget!==t&&this._activate(t)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(let e=this._offsets.length;e--;)this._activeTarget!==this._targets[e]&&t>=this._offsets[e]&&(void 0===this._offsets[e+1]||t`${e}[data-bs-target="${t}"],${e}[href="${t}"]`)),i=V.findOne(e.join(","),this._config.target);i.classList.add(yn),i.classList.contains("dropdown-item")?V.findOne(".dropdown-toggle",i.closest(".dropdown")).classList.add(yn):V.parents(i,".nav, .list-group").forEach((t=>{V.prev(t,".nav-link, .list-group-item").forEach((t=>t.classList.add(yn))),V.prev(t,".nav-item").forEach((t=>{V.children(t,".nav-link").forEach((t=>t.classList.add(yn)))}))})),j.trigger(this._scrollElement,"activate.bs.scrollspy",{relatedTarget:t})}_clear(){V.find(wn,this._config.target).filter((t=>t.classList.contains(yn))).forEach((t=>t.classList.remove(yn)))}static jQueryInterface(t){return this.each((function(){const e=An.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}j.on(window,"load.bs.scrollspy.data-api",(()=>{V.find('[data-bs-spy="scroll"]').forEach((t=>new An(t)))})),g(An);const Tn="active",On="fade",Cn="show",kn=".active",Ln=":scope > li > .active";class xn extends B{static get NAME(){return"tab"}show(){if(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&this._element.classList.contains(Tn))return;let t;const e=n(this._element),i=this._element.closest(".nav, .list-group");if(i){const e="UL"===i.nodeName||"OL"===i.nodeName?Ln:kn;t=V.find(e,i),t=t[t.length-1]}const s=t?j.trigger(t,"hide.bs.tab",{relatedTarget:this._element}):null;if(j.trigger(this._element,"show.bs.tab",{relatedTarget:t}).defaultPrevented||null!==s&&s.defaultPrevented)return;this._activate(this._element,i);const o=()=>{j.trigger(t,"hidden.bs.tab",{relatedTarget:this._element}),j.trigger(this._element,"shown.bs.tab",{relatedTarget:t})};e?this._activate(e,e.parentNode,o):o()}_activate(t,e,i){const n=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?V.children(e,kn):V.find(Ln,e))[0],s=i&&n&&n.classList.contains(On),o=()=>this._transitionComplete(t,n,i);n&&s?(n.classList.remove(Cn),this._queueCallback(o,t,!0)):o()}_transitionComplete(t,e,i){if(e){e.classList.remove(Tn);const t=V.findOne(":scope > .dropdown-menu .active",e.parentNode);t&&t.classList.remove(Tn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}t.classList.add(Tn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),u(t),t.classList.contains(On)&&t.classList.add(Cn);let n=t.parentNode;if(n&&"LI"===n.nodeName&&(n=n.parentNode),n&&n.classList.contains("dropdown-menu")){const e=t.closest(".dropdown");e&&V.find(".dropdown-toggle",e).forEach((t=>t.classList.add(Tn))),t.setAttribute("aria-expanded",!0)}i&&i()}static jQueryInterface(t){return this.each((function(){const e=xn.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}j.on(document,"click.bs.tab.data-api",'[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this)||xn.getOrCreateInstance(this).show()})),g(xn);const Dn="toast",Sn="hide",Nn="show",In="showing",Pn={animation:"boolean",autohide:"boolean",delay:"number"},jn={animation:!0,autohide:!0,delay:5e3};class Mn extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get DefaultType(){return Pn}static get Default(){return jn}static get NAME(){return Dn}show(){j.trigger(this._element,"show.bs.toast").defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(Sn),u(this._element),this._element.classList.add(Nn),this._element.classList.add(In),this._queueCallback((()=>{this._element.classList.remove(In),j.trigger(this._element,"shown.bs.toast"),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this._element.classList.contains(Nn)&&(j.trigger(this._element,"hide.bs.toast").defaultPrevented||(this._element.classList.add(In),this._queueCallback((()=>{this._element.classList.add(Sn),this._element.classList.remove(In),this._element.classList.remove(Nn),j.trigger(this._element,"hidden.bs.toast")}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this._element.classList.contains(Nn)&&this._element.classList.remove(Nn),super.dispose()}_getConfig(t){return t={...jn,...U.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}},a(Dn,t,this.constructor.DefaultType),t}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){j.on(this._element,"mouseover.bs.toast",(t=>this._onInteraction(t,!0))),j.on(this._element,"mouseout.bs.toast",(t=>this._onInteraction(t,!1))),j.on(this._element,"focusin.bs.toast",(t=>this._onInteraction(t,!0))),j.on(this._element,"focusout.bs.toast",(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=Mn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(Mn),g(Mn),{Alert:W,Button:z,Carousel:st,Collapse:pt,Dropdown:hi,Modal:Hi,Offcanvas:Fi,Popover:gn,ScrollSpy:An,Tab:xn,Toast:Mn,Tooltip:un}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/pr-preview/pr-68/site_libs/clipboard/clipboard.min.js b/pr-preview/pr-68/site_libs/clipboard/clipboard.min.js new file mode 100644 index 0000000..1103f81 --- /dev/null +++ b/pr-preview/pr-68/site_libs/clipboard/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=1.anchorjs-link,.anchorjs-link:focus{opacity:1}",u.sheet.cssRules.length),u.sheet.insertRule("[data-anchorjs-icon]::after{content:attr(data-anchorjs-icon)}",u.sheet.cssRules.length),u.sheet.insertRule('@font-face{font-family:anchorjs-icons;src:url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype")}',u.sheet.cssRules.length)),u=document.querySelectorAll("[id]"),t=[].map.call(u,function(A){return A.id}),i=0;i\]./()*\\\n\t\b\v\u00A0]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),A=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||A||!1}}}); +// @license-end \ No newline at end of file diff --git a/pr-preview/pr-68/site_libs/quarto-html/popper.min.js b/pr-preview/pr-68/site_libs/quarto-html/popper.min.js new file mode 100644 index 0000000..2269d66 --- /dev/null +++ b/pr-preview/pr-68/site_libs/quarto-html/popper.min.js @@ -0,0 +1,6 @@ +/** + * @popperjs/core v2.11.4 - MIT License + */ + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Popper={})}(this,(function(e){"use strict";function t(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function n(e){return e instanceof t(e).Element||e instanceof Element}function r(e){return e instanceof t(e).HTMLElement||e instanceof HTMLElement}function o(e){return"undefined"!=typeof ShadowRoot&&(e instanceof t(e).ShadowRoot||e instanceof ShadowRoot)}var i=Math.max,a=Math.min,s=Math.round;function f(e,t){void 0===t&&(t=!1);var n=e.getBoundingClientRect(),o=1,i=1;if(r(e)&&t){var a=e.offsetHeight,f=e.offsetWidth;f>0&&(o=s(n.width)/f||1),a>0&&(i=s(n.height)/a||1)}return{width:n.width/o,height:n.height/i,top:n.top/i,right:n.right/o,bottom:n.bottom/i,left:n.left/o,x:n.left/o,y:n.top/i}}function c(e){var n=t(e);return{scrollLeft:n.pageXOffset,scrollTop:n.pageYOffset}}function p(e){return e?(e.nodeName||"").toLowerCase():null}function u(e){return((n(e)?e.ownerDocument:e.document)||window.document).documentElement}function l(e){return f(u(e)).left+c(e).scrollLeft}function d(e){return t(e).getComputedStyle(e)}function h(e){var t=d(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function m(e,n,o){void 0===o&&(o=!1);var i,a,d=r(n),m=r(n)&&function(e){var t=e.getBoundingClientRect(),n=s(t.width)/e.offsetWidth||1,r=s(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(n),v=u(n),g=f(e,m),y={scrollLeft:0,scrollTop:0},b={x:0,y:0};return(d||!d&&!o)&&(("body"!==p(n)||h(v))&&(y=(i=n)!==t(i)&&r(i)?{scrollLeft:(a=i).scrollLeft,scrollTop:a.scrollTop}:c(i)),r(n)?((b=f(n,!0)).x+=n.clientLeft,b.y+=n.clientTop):v&&(b.x=l(v))),{x:g.left+y.scrollLeft-b.x,y:g.top+y.scrollTop-b.y,width:g.width,height:g.height}}function v(e){var t=f(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function g(e){return"html"===p(e)?e:e.assignedSlot||e.parentNode||(o(e)?e.host:null)||u(e)}function y(e){return["html","body","#document"].indexOf(p(e))>=0?e.ownerDocument.body:r(e)&&h(e)?e:y(g(e))}function b(e,n){var r;void 0===n&&(n=[]);var o=y(e),i=o===(null==(r=e.ownerDocument)?void 0:r.body),a=t(o),s=i?[a].concat(a.visualViewport||[],h(o)?o:[]):o,f=n.concat(s);return i?f:f.concat(b(g(s)))}function x(e){return["table","td","th"].indexOf(p(e))>=0}function w(e){return r(e)&&"fixed"!==d(e).position?e.offsetParent:null}function O(e){for(var n=t(e),i=w(e);i&&x(i)&&"static"===d(i).position;)i=w(i);return i&&("html"===p(i)||"body"===p(i)&&"static"===d(i).position)?n:i||function(e){var t=-1!==navigator.userAgent.toLowerCase().indexOf("firefox");if(-1!==navigator.userAgent.indexOf("Trident")&&r(e)&&"fixed"===d(e).position)return null;var n=g(e);for(o(n)&&(n=n.host);r(n)&&["html","body"].indexOf(p(n))<0;){var i=d(n);if("none"!==i.transform||"none"!==i.perspective||"paint"===i.contain||-1!==["transform","perspective"].indexOf(i.willChange)||t&&"filter"===i.willChange||t&&i.filter&&"none"!==i.filter)return n;n=n.parentNode}return null}(e)||n}var j="top",E="bottom",D="right",A="left",L="auto",P=[j,E,D,A],M="start",k="end",W="viewport",B="popper",H=P.reduce((function(e,t){return e.concat([t+"-"+M,t+"-"+k])}),[]),T=[].concat(P,[L]).reduce((function(e,t){return e.concat([t,t+"-"+M,t+"-"+k])}),[]),R=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];function S(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}function C(e){return e.split("-")[0]}function q(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&o(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function V(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function N(e,r){return r===W?V(function(e){var n=t(e),r=u(e),o=n.visualViewport,i=r.clientWidth,a=r.clientHeight,s=0,f=0;return o&&(i=o.width,a=o.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(s=o.offsetLeft,f=o.offsetTop)),{width:i,height:a,x:s+l(e),y:f}}(e)):n(r)?function(e){var t=f(e);return t.top=t.top+e.clientTop,t.left=t.left+e.clientLeft,t.bottom=t.top+e.clientHeight,t.right=t.left+e.clientWidth,t.width=e.clientWidth,t.height=e.clientHeight,t.x=t.left,t.y=t.top,t}(r):V(function(e){var t,n=u(e),r=c(e),o=null==(t=e.ownerDocument)?void 0:t.body,a=i(n.scrollWidth,n.clientWidth,o?o.scrollWidth:0,o?o.clientWidth:0),s=i(n.scrollHeight,n.clientHeight,o?o.scrollHeight:0,o?o.clientHeight:0),f=-r.scrollLeft+l(e),p=-r.scrollTop;return"rtl"===d(o||n).direction&&(f+=i(n.clientWidth,o?o.clientWidth:0)-a),{width:a,height:s,x:f,y:p}}(u(e)))}function I(e,t,o){var s="clippingParents"===t?function(e){var t=b(g(e)),o=["absolute","fixed"].indexOf(d(e).position)>=0&&r(e)?O(e):e;return n(o)?t.filter((function(e){return n(e)&&q(e,o)&&"body"!==p(e)})):[]}(e):[].concat(t),f=[].concat(s,[o]),c=f[0],u=f.reduce((function(t,n){var r=N(e,n);return t.top=i(r.top,t.top),t.right=a(r.right,t.right),t.bottom=a(r.bottom,t.bottom),t.left=i(r.left,t.left),t}),N(e,c));return u.width=u.right-u.left,u.height=u.bottom-u.top,u.x=u.left,u.y=u.top,u}function _(e){return e.split("-")[1]}function F(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function U(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?C(o):null,a=o?_(o):null,s=n.x+n.width/2-r.width/2,f=n.y+n.height/2-r.height/2;switch(i){case j:t={x:s,y:n.y-r.height};break;case E:t={x:s,y:n.y+n.height};break;case D:t={x:n.x+n.width,y:f};break;case A:t={x:n.x-r.width,y:f};break;default:t={x:n.x,y:n.y}}var c=i?F(i):null;if(null!=c){var p="y"===c?"height":"width";switch(a){case M:t[c]=t[c]-(n[p]/2-r[p]/2);break;case k:t[c]=t[c]+(n[p]/2-r[p]/2)}}return t}function z(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function X(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function Y(e,t){void 0===t&&(t={});var r=t,o=r.placement,i=void 0===o?e.placement:o,a=r.boundary,s=void 0===a?"clippingParents":a,c=r.rootBoundary,p=void 0===c?W:c,l=r.elementContext,d=void 0===l?B:l,h=r.altBoundary,m=void 0!==h&&h,v=r.padding,g=void 0===v?0:v,y=z("number"!=typeof g?g:X(g,P)),b=d===B?"reference":B,x=e.rects.popper,w=e.elements[m?b:d],O=I(n(w)?w:w.contextElement||u(e.elements.popper),s,p),A=f(e.elements.reference),L=U({reference:A,element:x,strategy:"absolute",placement:i}),M=V(Object.assign({},x,L)),k=d===B?M:A,H={top:O.top-k.top+y.top,bottom:k.bottom-O.bottom+y.bottom,left:O.left-k.left+y.left,right:k.right-O.right+y.right},T=e.modifiersData.offset;if(d===B&&T){var R=T[i];Object.keys(H).forEach((function(e){var t=[D,E].indexOf(e)>=0?1:-1,n=[j,E].indexOf(e)>=0?"y":"x";H[e]+=R[n]*t}))}return H}var G={placement:"bottom",modifiers:[],strategy:"absolute"};function J(){for(var e=arguments.length,t=new Array(e),n=0;n=0?-1:1,i="function"==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],s=i[1];return a=a||0,s=(s||0)*o,[A,D].indexOf(r)>=0?{x:s,y:a}:{x:a,y:s}}(n,t.rects,i),e}),{}),s=a[t.placement],f=s.x,c=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=f,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=a}},ie={left:"right",right:"left",bottom:"top",top:"bottom"};function ae(e){return e.replace(/left|right|bottom|top/g,(function(e){return ie[e]}))}var se={start:"end",end:"start"};function fe(e){return e.replace(/start|end/g,(function(e){return se[e]}))}function ce(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,s=n.flipVariations,f=n.allowedAutoPlacements,c=void 0===f?T:f,p=_(r),u=p?s?H:H.filter((function(e){return _(e)===p})):P,l=u.filter((function(e){return c.indexOf(e)>=0}));0===l.length&&(l=u);var d=l.reduce((function(t,n){return t[n]=Y(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[C(n)],t}),{});return Object.keys(d).sort((function(e,t){return d[e]-d[t]}))}var pe={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0===a||a,f=n.fallbackPlacements,c=n.padding,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.flipVariations,h=void 0===d||d,m=n.allowedAutoPlacements,v=t.options.placement,g=C(v),y=f||(g===v||!h?[ae(v)]:function(e){if(C(e)===L)return[];var t=ae(e);return[fe(e),t,fe(t)]}(v)),b=[v].concat(y).reduce((function(e,n){return e.concat(C(n)===L?ce(t,{placement:n,boundary:p,rootBoundary:u,padding:c,flipVariations:h,allowedAutoPlacements:m}):n)}),[]),x=t.rects.reference,w=t.rects.popper,O=new Map,P=!0,k=b[0],W=0;W=0,S=R?"width":"height",q=Y(t,{placement:B,boundary:p,rootBoundary:u,altBoundary:l,padding:c}),V=R?T?D:A:T?E:j;x[S]>w[S]&&(V=ae(V));var N=ae(V),I=[];if(i&&I.push(q[H]<=0),s&&I.push(q[V]<=0,q[N]<=0),I.every((function(e){return e}))){k=B,P=!1;break}O.set(B,I)}if(P)for(var F=function(e){var t=b.find((function(t){var n=O.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return k=t,"break"},U=h?3:1;U>0;U--){if("break"===F(U))break}t.placement!==k&&(t.modifiersData[r]._skip=!0,t.placement=k,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function ue(e,t,n){return i(e,a(t,n))}var le={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,s=void 0===o||o,f=n.altAxis,c=void 0!==f&&f,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.padding,h=n.tether,m=void 0===h||h,g=n.tetherOffset,y=void 0===g?0:g,b=Y(t,{boundary:p,rootBoundary:u,padding:d,altBoundary:l}),x=C(t.placement),w=_(t.placement),L=!w,P=F(x),k="x"===P?"y":"x",W=t.modifiersData.popperOffsets,B=t.rects.reference,H=t.rects.popper,T="function"==typeof y?y(Object.assign({},t.rects,{placement:t.placement})):y,R="number"==typeof T?{mainAxis:T,altAxis:T}:Object.assign({mainAxis:0,altAxis:0},T),S=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,q={x:0,y:0};if(W){if(s){var V,N="y"===P?j:A,I="y"===P?E:D,U="y"===P?"height":"width",z=W[P],X=z+b[N],G=z-b[I],J=m?-H[U]/2:0,K=w===M?B[U]:H[U],Q=w===M?-H[U]:-B[U],Z=t.elements.arrow,$=m&&Z?v(Z):{width:0,height:0},ee=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},te=ee[N],ne=ee[I],re=ue(0,B[U],$[U]),oe=L?B[U]/2-J-re-te-R.mainAxis:K-re-te-R.mainAxis,ie=L?-B[U]/2+J+re+ne+R.mainAxis:Q+re+ne+R.mainAxis,ae=t.elements.arrow&&O(t.elements.arrow),se=ae?"y"===P?ae.clientTop||0:ae.clientLeft||0:0,fe=null!=(V=null==S?void 0:S[P])?V:0,ce=z+ie-fe,pe=ue(m?a(X,z+oe-fe-se):X,z,m?i(G,ce):G);W[P]=pe,q[P]=pe-z}if(c){var le,de="x"===P?j:A,he="x"===P?E:D,me=W[k],ve="y"===k?"height":"width",ge=me+b[de],ye=me-b[he],be=-1!==[j,A].indexOf(x),xe=null!=(le=null==S?void 0:S[k])?le:0,we=be?ge:me-B[ve]-H[ve]-xe+R.altAxis,Oe=be?me+B[ve]+H[ve]-xe-R.altAxis:ye,je=m&&be?function(e,t,n){var r=ue(e,t,n);return r>n?n:r}(we,me,Oe):ue(m?we:ge,me,m?Oe:ye);W[k]=je,q[k]=je-me}t.modifiersData[r]=q}},requiresIfExists:["offset"]};var de={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,r=e.name,o=e.options,i=n.elements.arrow,a=n.modifiersData.popperOffsets,s=C(n.placement),f=F(s),c=[A,D].indexOf(s)>=0?"height":"width";if(i&&a){var p=function(e,t){return z("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:X(e,P))}(o.padding,n),u=v(i),l="y"===f?j:A,d="y"===f?E:D,h=n.rects.reference[c]+n.rects.reference[f]-a[f]-n.rects.popper[c],m=a[f]-n.rects.reference[f],g=O(i),y=g?"y"===f?g.clientHeight||0:g.clientWidth||0:0,b=h/2-m/2,x=p[l],w=y-u[c]-p[d],L=y/2-u[c]/2+b,M=ue(x,L,w),k=f;n.modifiersData[r]=((t={})[k]=M,t.centerOffset=M-L,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&q(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function he(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function me(e){return[j,D,E,A].some((function(t){return e[t]>=0}))}var ve={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,i=t.modifiersData.preventOverflow,a=Y(t,{elementContext:"reference"}),s=Y(t,{altBoundary:!0}),f=he(a,r),c=he(s,o,i),p=me(f),u=me(c);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:c,isReferenceHidden:p,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":p,"data-popper-escaped":u})}},ge=K({defaultModifiers:[Z,$,ne,re]}),ye=[Z,$,ne,re,oe,pe,le,de,ve],be=K({defaultModifiers:ye});e.applyStyles=re,e.arrow=de,e.computeStyles=ne,e.createPopper=be,e.createPopperLite=ge,e.defaultModifiers=ye,e.detectOverflow=Y,e.eventListeners=Z,e.flip=pe,e.hide=ve,e.offset=oe,e.popperGenerator=K,e.popperOffsets=$,e.preventOverflow=le,Object.defineProperty(e,"__esModule",{value:!0})})); + diff --git a/pr-preview/pr-68/site_libs/quarto-html/quarto-syntax-highlighting-dark.css b/pr-preview/pr-68/site_libs/quarto-html/quarto-syntax-highlighting-dark.css new file mode 100644 index 0000000..343d2f8 --- /dev/null +++ b/pr-preview/pr-68/site_libs/quarto-html/quarto-syntax-highlighting-dark.css @@ -0,0 +1,189 @@ +/* quarto syntax highlight colors */ +:root { + --quarto-hl-al-color: #f07178; + --quarto-hl-an-color: #d4d0ab; + --quarto-hl-at-color: #00e0e0; + --quarto-hl-bn-color: #d4d0ab; + --quarto-hl-bu-color: #abe338; + --quarto-hl-ch-color: #abe338; + --quarto-hl-co-color: #f8f8f2; + --quarto-hl-cv-color: #ffd700; + --quarto-hl-cn-color: #ffd700; + --quarto-hl-cf-color: #ffa07a; + --quarto-hl-dt-color: #ffa07a; + --quarto-hl-dv-color: #d4d0ab; + --quarto-hl-do-color: #f8f8f2; + --quarto-hl-er-color: #f07178; + --quarto-hl-ex-color: #00e0e0; + --quarto-hl-fl-color: #d4d0ab; + --quarto-hl-fu-color: #ffa07a; + --quarto-hl-im-color: #abe338; + --quarto-hl-in-color: #d4d0ab; + --quarto-hl-kw-color: #ffa07a; + --quarto-hl-op-color: #ffa07a; + --quarto-hl-ot-color: #00e0e0; + --quarto-hl-pp-color: #dcc6e0; + --quarto-hl-re-color: #00e0e0; + --quarto-hl-sc-color: #abe338; + --quarto-hl-ss-color: #abe338; + --quarto-hl-st-color: #abe338; + --quarto-hl-va-color: #00e0e0; + --quarto-hl-vs-color: #abe338; + --quarto-hl-wa-color: #dcc6e0; +} + +/* other quarto variables */ +:root { + --quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +code span.al { + background-color: #2a0f15; + font-weight: bold; + color: #f07178; +} + +code span.an { + color: #d4d0ab; +} + +code span.at { + color: #00e0e0; +} + +code span.bn { + color: #d4d0ab; +} + +code span.bu { + color: #abe338; +} + +code span.ch { + color: #abe338; +} + +code span.co { + font-style: italic; + color: #f8f8f2; +} + +code span.cv { + color: #ffd700; +} + +code span.cn { + color: #ffd700; +} + +code span.cf { + font-weight: bold; + color: #ffa07a; +} + +code span.dt { + color: #ffa07a; +} + +code span.dv { + color: #d4d0ab; +} + +code span.do { + color: #f8f8f2; +} + +code span.er { + color: #f07178; + text-decoration: underline; +} + +code span.ex { + font-weight: bold; + color: #00e0e0; +} + +code span.fl { + color: #d4d0ab; +} + +code span.fu { + color: #ffa07a; +} + +code span.im { + color: #abe338; +} + +code span.in { + color: #d4d0ab; +} + +code span.kw { + font-weight: bold; + color: #ffa07a; +} + +pre > code.sourceCode > span { + color: #f8f8f2; +} + +code span { + color: #f8f8f2; +} + +code.sourceCode > span { + color: #f8f8f2; +} + +div.sourceCode, +div.sourceCode pre.sourceCode { + color: #f8f8f2; +} + +code span.op { + color: #ffa07a; +} + +code span.ot { + color: #00e0e0; +} + +code span.pp { + color: #dcc6e0; +} + +code span.re { + background-color: #f8f8f2; + color: #00e0e0; +} + +code span.sc { + color: #abe338; +} + +code span.ss { + color: #abe338; +} + +code span.st { + color: #abe338; +} + +code span.va { + color: #00e0e0; +} + +code span.vs { + color: #abe338; +} + +code span.wa { + color: #dcc6e0; +} + +.prevent-inlining { + content: " code.sourceCode > span { + color: #003B4F; +} + +code span { + color: #003B4F; +} + +code.sourceCode > span { + color: #003B4F; +} + +div.sourceCode, +div.sourceCode pre.sourceCode { + color: #003B4F; +} + +code span.ot { + color: #003B4F; + font-style: inherit; +} + +code span.at { + color: #657422; + font-style: inherit; +} + +code span.ss { + color: #20794D; + font-style: inherit; +} + +code span.an { + color: #5E5E5E; + font-style: inherit; +} + +code span.fu { + color: #4758AB; + font-style: inherit; +} + +code span.st { + color: #20794D; + font-style: inherit; +} + +code span.cf { + color: #003B4F; + font-style: inherit; +} + +code span.op { + color: #5E5E5E; + font-style: inherit; +} + +code span.er { + color: #AD0000; + font-style: inherit; +} + +code span.bn { + color: #AD0000; + font-style: inherit; +} + +code span.al { + color: #AD0000; + font-style: inherit; +} + +code span.va { + color: #111111; + font-style: inherit; +} + +code span.bu { + font-style: inherit; +} + +code span.ex { + font-style: inherit; +} + +code span.pp { + color: #AD0000; + font-style: inherit; +} + +code span.in { + color: #5E5E5E; + font-style: inherit; +} + +code span.vs { + color: #20794D; + font-style: inherit; +} + +code span.wa { + color: #5E5E5E; + font-style: italic; +} + +code span.do { + color: #5E5E5E; + font-style: italic; +} + +code span.im { + color: #00769E; + font-style: inherit; +} + +code span.ch { + color: #20794D; + font-style: inherit; +} + +code span.dt { + color: #AD0000; + font-style: inherit; +} + +code span.fl { + color: #AD0000; + font-style: inherit; +} + +code span.co { + color: #5E5E5E; + font-style: inherit; +} + +code span.cv { + color: #5E5E5E; + font-style: italic; +} + +code span.cn { + color: #8f5902; + font-style: inherit; +} + +code span.sc { + color: #5E5E5E; + font-style: inherit; +} + +code span.dv { + color: #AD0000; + font-style: inherit; +} + +code span.kw { + color: #003B4F; + font-style: inherit; +} + +.prevent-inlining { + content: " { + // Find any conflicting margin elements and add margins to the + // top to prevent overlap + const marginChildren = window.document.querySelectorAll( + ".column-margin.column-container > * " + ); + + let lastBottom = 0; + for (const marginChild of marginChildren) { + if (marginChild.offsetParent !== null) { + // clear the top margin so we recompute it + marginChild.style.marginTop = null; + const top = marginChild.getBoundingClientRect().top + window.scrollY; + console.log({ + childtop: marginChild.getBoundingClientRect().top, + scroll: window.scrollY, + top, + lastBottom, + }); + if (top < lastBottom) { + const margin = lastBottom - top; + marginChild.style.marginTop = `${margin}px`; + } + const styles = window.getComputedStyle(marginChild); + const marginTop = parseFloat(styles["marginTop"]); + + console.log({ + top, + height: marginChild.getBoundingClientRect().height, + marginTop, + total: top + marginChild.getBoundingClientRect().height + marginTop, + }); + lastBottom = top + marginChild.getBoundingClientRect().height + marginTop; + } + } +}; + +window.document.addEventListener("DOMContentLoaded", function (_event) { + // Recompute the position of margin elements anytime the body size changes + if (window.ResizeObserver) { + const resizeObserver = new window.ResizeObserver( + throttle(layoutMarginEls, 50) + ); + resizeObserver.observe(window.document.body); + } + + const tocEl = window.document.querySelector('nav.toc-active[role="doc-toc"]'); + const sidebarEl = window.document.getElementById("quarto-sidebar"); + const leftTocEl = window.document.getElementById("quarto-sidebar-toc-left"); + const marginSidebarEl = window.document.getElementById( + "quarto-margin-sidebar" + ); + // function to determine whether the element has a previous sibling that is active + const prevSiblingIsActiveLink = (el) => { + const sibling = el.previousElementSibling; + if (sibling && sibling.tagName === "A") { + return sibling.classList.contains("active"); + } else { + return false; + } + }; + + // fire slideEnter for bootstrap tab activations (for htmlwidget resize behavior) + function fireSlideEnter(e) { + const event = window.document.createEvent("Event"); + event.initEvent("slideenter", true, true); + window.document.dispatchEvent(event); + } + const tabs = window.document.querySelectorAll('a[data-bs-toggle="tab"]'); + tabs.forEach((tab) => { + tab.addEventListener("shown.bs.tab", fireSlideEnter); + }); + + // fire slideEnter for tabby tab activations (for htmlwidget resize behavior) + document.addEventListener("tabby", fireSlideEnter, false); + + // Track scrolling and mark TOC links as active + // get table of contents and sidebar (bail if we don't have at least one) + const tocLinks = tocEl + ? [...tocEl.querySelectorAll("a[data-scroll-target]")] + : []; + const makeActive = (link) => tocLinks[link].classList.add("active"); + const removeActive = (link) => tocLinks[link].classList.remove("active"); + const removeAllActive = () => + [...Array(tocLinks.length).keys()].forEach((link) => removeActive(link)); + + // activate the anchor for a section associated with this TOC entry + tocLinks.forEach((link) => { + link.addEventListener("click", () => { + if (link.href.indexOf("#") !== -1) { + const anchor = link.href.split("#")[1]; + const heading = window.document.querySelector( + `[data-anchor-id=${anchor}]` + ); + if (heading) { + // Add the class + heading.classList.add("reveal-anchorjs-link"); + + // function to show the anchor + const handleMouseout = () => { + heading.classList.remove("reveal-anchorjs-link"); + heading.removeEventListener("mouseout", handleMouseout); + }; + + // add a function to clear the anchor when the user mouses out of it + heading.addEventListener("mouseout", handleMouseout); + } + } + }); + }); + + const sections = tocLinks.map((link) => { + const target = link.getAttribute("data-scroll-target"); + if (target.startsWith("#")) { + return window.document.getElementById(decodeURI(`${target.slice(1)}`)); + } else { + return window.document.querySelector(decodeURI(`${target}`)); + } + }); + + const sectionMargin = 200; + let currentActive = 0; + // track whether we've initialized state the first time + let init = false; + + const updateActiveLink = () => { + // The index from bottom to top (e.g. reversed list) + let sectionIndex = -1; + if ( + window.innerHeight + window.pageYOffset >= + window.document.body.offsetHeight + ) { + sectionIndex = 0; + } else { + sectionIndex = [...sections].reverse().findIndex((section) => { + if (section) { + return window.pageYOffset >= section.offsetTop - sectionMargin; + } else { + return false; + } + }); + } + if (sectionIndex > -1) { + const current = sections.length - sectionIndex - 1; + if (current !== currentActive) { + removeAllActive(); + currentActive = current; + makeActive(current); + if (init) { + window.dispatchEvent(sectionChanged); + } + init = true; + } + } + }; + + const inHiddenRegion = (top, bottom, hiddenRegions) => { + for (const region of hiddenRegions) { + if (top <= region.bottom && bottom >= region.top) { + return true; + } + } + return false; + }; + + const categorySelector = "header.quarto-title-block .quarto-category"; + const activateCategories = (href) => { + // Find any categories + // Surround them with a link pointing back to: + // #category=Authoring + try { + const categoryEls = window.document.querySelectorAll(categorySelector); + for (const categoryEl of categoryEls) { + const categoryText = categoryEl.textContent; + if (categoryText) { + const link = `${href}#category=${encodeURIComponent(categoryText)}`; + const linkEl = window.document.createElement("a"); + linkEl.setAttribute("href", link); + for (const child of categoryEl.childNodes) { + linkEl.append(child); + } + categoryEl.appendChild(linkEl); + } + } + } catch { + // Ignore errors + } + }; + function hasTitleCategories() { + return window.document.querySelector(categorySelector) !== null; + } + + function offsetRelativeUrl(url) { + const offset = getMeta("quarto:offset"); + return offset ? offset + url : url; + } + + function offsetAbsoluteUrl(url) { + const offset = getMeta("quarto:offset"); + const baseUrl = new URL(offset, window.location); + + const projRelativeUrl = url.replace(baseUrl, ""); + if (projRelativeUrl.startsWith("/")) { + return projRelativeUrl; + } else { + return "/" + projRelativeUrl; + } + } + + // read a meta tag value + function getMeta(metaName) { + const metas = window.document.getElementsByTagName("meta"); + for (let i = 0; i < metas.length; i++) { + if (metas[i].getAttribute("name") === metaName) { + return metas[i].getAttribute("content"); + } + } + return ""; + } + + async function findAndActivateCategories() { + const currentPagePath = offsetAbsoluteUrl(window.location.href); + const response = await fetch(offsetRelativeUrl("listings.json")); + if (response.status == 200) { + return response.json().then(function (listingPaths) { + const listingHrefs = []; + for (const listingPath of listingPaths) { + const pathWithoutLeadingSlash = listingPath.listing.substring(1); + for (const item of listingPath.items) { + if ( + item === currentPagePath || + item === currentPagePath + "index.html" + ) { + // Resolve this path against the offset to be sure + // we already are using the correct path to the listing + // (this adjusts the listing urls to be rooted against + // whatever root the page is actually running against) + const relative = offsetRelativeUrl(pathWithoutLeadingSlash); + const baseUrl = window.location; + const resolvedPath = new URL(relative, baseUrl); + listingHrefs.push(resolvedPath.pathname); + break; + } + } + } + + // Look up the tree for a nearby linting and use that if we find one + const nearestListing = findNearestParentListing( + offsetAbsoluteUrl(window.location.pathname), + listingHrefs + ); + if (nearestListing) { + activateCategories(nearestListing); + } else { + // See if the referrer is a listing page for this item + const referredRelativePath = offsetAbsoluteUrl(document.referrer); + const referrerListing = listingHrefs.find((listingHref) => { + const isListingReferrer = + listingHref === referredRelativePath || + listingHref === referredRelativePath + "index.html"; + return isListingReferrer; + }); + + if (referrerListing) { + // Try to use the referrer if possible + activateCategories(referrerListing); + } else if (listingHrefs.length > 0) { + // Otherwise, just fall back to the first listing + activateCategories(listingHrefs[0]); + } + } + }); + } + } + if (hasTitleCategories()) { + findAndActivateCategories(); + } + + const findNearestParentListing = (href, listingHrefs) => { + if (!href || !listingHrefs) { + return undefined; + } + // Look up the tree for a nearby linting and use that if we find one + const relativeParts = href.substring(1).split("/"); + while (relativeParts.length > 0) { + const path = relativeParts.join("/"); + for (const listingHref of listingHrefs) { + if (listingHref.startsWith(path)) { + return listingHref; + } + } + relativeParts.pop(); + } + + return undefined; + }; + + const manageSidebarVisiblity = (el, placeholderDescriptor) => { + let isVisible = true; + let elRect; + + return (hiddenRegions) => { + if (el === null) { + return; + } + + // Find the last element of the TOC + const lastChildEl = el.lastElementChild; + + if (lastChildEl) { + // Converts the sidebar to a menu + const convertToMenu = () => { + for (const child of el.children) { + child.style.opacity = 0; + child.style.overflow = "hidden"; + } + + nexttick(() => { + const toggleContainer = window.document.createElement("div"); + toggleContainer.style.width = "100%"; + toggleContainer.classList.add("zindex-over-content"); + toggleContainer.classList.add("quarto-sidebar-toggle"); + toggleContainer.classList.add("headroom-target"); // Marks this to be managed by headeroom + toggleContainer.id = placeholderDescriptor.id; + toggleContainer.style.position = "fixed"; + + const toggleIcon = window.document.createElement("i"); + toggleIcon.classList.add("quarto-sidebar-toggle-icon"); + toggleIcon.classList.add("bi"); + toggleIcon.classList.add("bi-caret-down-fill"); + + const toggleTitle = window.document.createElement("div"); + const titleEl = window.document.body.querySelector( + placeholderDescriptor.titleSelector + ); + if (titleEl) { + toggleTitle.append( + titleEl.textContent || titleEl.innerText, + toggleIcon + ); + } + toggleTitle.classList.add("zindex-over-content"); + toggleTitle.classList.add("quarto-sidebar-toggle-title"); + toggleContainer.append(toggleTitle); + + const toggleContents = window.document.createElement("div"); + toggleContents.classList = el.classList; + toggleContents.classList.add("zindex-over-content"); + toggleContents.classList.add("quarto-sidebar-toggle-contents"); + for (const child of el.children) { + if (child.id === "toc-title") { + continue; + } + + const clone = child.cloneNode(true); + clone.style.opacity = 1; + clone.style.display = null; + toggleContents.append(clone); + } + toggleContents.style.height = "0px"; + const positionToggle = () => { + // position the element (top left of parent, same width as parent) + if (!elRect) { + elRect = el.getBoundingClientRect(); + } + toggleContainer.style.left = `${elRect.left}px`; + toggleContainer.style.top = `${elRect.top}px`; + toggleContainer.style.width = `${elRect.width}px`; + }; + positionToggle(); + + toggleContainer.append(toggleContents); + el.parentElement.prepend(toggleContainer); + + // Process clicks + let tocShowing = false; + // Allow the caller to control whether this is dismissed + // when it is clicked (e.g. sidebar navigation supports + // opening and closing the nav tree, so don't dismiss on click) + const clickEl = placeholderDescriptor.dismissOnClick + ? toggleContainer + : toggleTitle; + + const closeToggle = () => { + if (tocShowing) { + toggleContainer.classList.remove("expanded"); + toggleContents.style.height = "0px"; + tocShowing = false; + } + }; + + // Get rid of any expanded toggle if the user scrolls + window.document.addEventListener( + "scroll", + throttle(() => { + closeToggle(); + }, 50) + ); + + // Handle positioning of the toggle + window.addEventListener( + "resize", + throttle(() => { + elRect = undefined; + positionToggle(); + }, 50) + ); + + window.addEventListener("quarto-hrChanged", () => { + elRect = undefined; + }); + + // Process the click + clickEl.onclick = () => { + if (!tocShowing) { + toggleContainer.classList.add("expanded"); + toggleContents.style.height = null; + tocShowing = true; + } else { + closeToggle(); + } + }; + }); + }; + + // Converts a sidebar from a menu back to a sidebar + const convertToSidebar = () => { + for (const child of el.children) { + child.style.opacity = 1; + child.style.overflow = null; + } + + const placeholderEl = window.document.getElementById( + placeholderDescriptor.id + ); + if (placeholderEl) { + placeholderEl.remove(); + } + + el.classList.remove("rollup"); + }; + + if (isReaderMode()) { + convertToMenu(); + isVisible = false; + } else { + // Find the top and bottom o the element that is being managed + const elTop = el.offsetTop; + const elBottom = + elTop + lastChildEl.offsetTop + lastChildEl.offsetHeight; + + if (!isVisible) { + // If the element is current not visible reveal if there are + // no conflicts with overlay regions + if (!inHiddenRegion(elTop, elBottom, hiddenRegions)) { + convertToSidebar(); + isVisible = true; + } + } else { + // If the element is visible, hide it if it conflicts with overlay regions + // and insert a placeholder toggle (or if we're in reader mode) + if (inHiddenRegion(elTop, elBottom, hiddenRegions)) { + convertToMenu(); + isVisible = false; + } + } + } + } + }; + }; + + const tabEls = document.querySelectorAll('a[data-bs-toggle="tab"]'); + for (const tabEl of tabEls) { + const id = tabEl.getAttribute("data-bs-target"); + if (id) { + const columnEl = document.querySelector( + `${id} .column-margin, .tabset-margin-content` + ); + if (columnEl) + tabEl.addEventListener("shown.bs.tab", function (event) { + const el = event.srcElement; + if (el) { + const visibleCls = `${el.id}-margin-content`; + // walk up until we find a parent tabset + let panelTabsetEl = el.parentElement; + while (panelTabsetEl) { + if (panelTabsetEl.classList.contains("panel-tabset")) { + break; + } + panelTabsetEl = panelTabsetEl.parentElement; + } + + if (panelTabsetEl) { + const prevSib = panelTabsetEl.previousElementSibling; + if ( + prevSib && + prevSib.classList.contains("tabset-margin-container") + ) { + const childNodes = prevSib.querySelectorAll( + ".tabset-margin-content" + ); + for (const childEl of childNodes) { + if (childEl.classList.contains(visibleCls)) { + childEl.classList.remove("collapse"); + } else { + childEl.classList.add("collapse"); + } + } + } + } + } + + layoutMarginEls(); + }); + } + } + + // Manage the visibility of the toc and the sidebar + const marginScrollVisibility = manageSidebarVisiblity(marginSidebarEl, { + id: "quarto-toc-toggle", + titleSelector: "#toc-title", + dismissOnClick: true, + }); + const sidebarScrollVisiblity = manageSidebarVisiblity(sidebarEl, { + id: "quarto-sidebarnav-toggle", + titleSelector: ".title", + dismissOnClick: false, + }); + let tocLeftScrollVisibility; + if (leftTocEl) { + tocLeftScrollVisibility = manageSidebarVisiblity(leftTocEl, { + id: "quarto-lefttoc-toggle", + titleSelector: "#toc-title", + dismissOnClick: true, + }); + } + + // Find the first element that uses formatting in special columns + const conflictingEls = window.document.body.querySelectorAll( + '[class^="column-"], [class*=" column-"], aside, [class*="margin-caption"], [class*=" margin-caption"], [class*="margin-ref"], [class*=" margin-ref"]' + ); + + // Filter all the possibly conflicting elements into ones + // the do conflict on the left or ride side + const arrConflictingEls = Array.from(conflictingEls); + const leftSideConflictEls = arrConflictingEls.filter((el) => { + if (el.tagName === "ASIDE") { + return false; + } + return Array.from(el.classList).find((className) => { + return ( + className !== "column-body" && + className.startsWith("column-") && + !className.endsWith("right") && + !className.endsWith("container") && + className !== "column-margin" + ); + }); + }); + const rightSideConflictEls = arrConflictingEls.filter((el) => { + if (el.tagName === "ASIDE") { + return true; + } + + const hasMarginCaption = Array.from(el.classList).find((className) => { + return className == "margin-caption"; + }); + if (hasMarginCaption) { + return true; + } + + return Array.from(el.classList).find((className) => { + return ( + className !== "column-body" && + !className.endsWith("container") && + className.startsWith("column-") && + !className.endsWith("left") + ); + }); + }); + + const kOverlapPaddingSize = 10; + function toRegions(els) { + return els.map((el) => { + const boundRect = el.getBoundingClientRect(); + const top = + boundRect.top + + document.documentElement.scrollTop - + kOverlapPaddingSize; + return { + top, + bottom: top + el.scrollHeight + 2 * kOverlapPaddingSize, + }; + }); + } + + let hasObserved = false; + const visibleItemObserver = (els) => { + let visibleElements = [...els]; + const intersectionObserver = new IntersectionObserver( + (entries, _observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + if (visibleElements.indexOf(entry.target) === -1) { + visibleElements.push(entry.target); + } + } else { + visibleElements = visibleElements.filter((visibleEntry) => { + return visibleEntry !== entry; + }); + } + }); + + if (!hasObserved) { + hideOverlappedSidebars(); + } + hasObserved = true; + }, + {} + ); + els.forEach((el) => { + intersectionObserver.observe(el); + }); + + return { + getVisibleEntries: () => { + return visibleElements; + }, + }; + }; + + const rightElementObserver = visibleItemObserver(rightSideConflictEls); + const leftElementObserver = visibleItemObserver(leftSideConflictEls); + + const hideOverlappedSidebars = () => { + marginScrollVisibility(toRegions(rightElementObserver.getVisibleEntries())); + sidebarScrollVisiblity(toRegions(leftElementObserver.getVisibleEntries())); + if (tocLeftScrollVisibility) { + tocLeftScrollVisibility( + toRegions(leftElementObserver.getVisibleEntries()) + ); + } + }; + + window.quartoToggleReader = () => { + // Applies a slow class (or removes it) + // to update the transition speed + const slowTransition = (slow) => { + const manageTransition = (id, slow) => { + const el = document.getElementById(id); + if (el) { + if (slow) { + el.classList.add("slow"); + } else { + el.classList.remove("slow"); + } + } + }; + + manageTransition("TOC", slow); + manageTransition("quarto-sidebar", slow); + }; + const readerMode = !isReaderMode(); + setReaderModeValue(readerMode); + + // If we're entering reader mode, slow the transition + if (readerMode) { + slowTransition(readerMode); + } + highlightReaderToggle(readerMode); + hideOverlappedSidebars(); + + // If we're exiting reader mode, restore the non-slow transition + if (!readerMode) { + slowTransition(!readerMode); + } + }; + + const highlightReaderToggle = (readerMode) => { + const els = document.querySelectorAll(".quarto-reader-toggle"); + if (els) { + els.forEach((el) => { + if (readerMode) { + el.classList.add("reader"); + } else { + el.classList.remove("reader"); + } + }); + } + }; + + const setReaderModeValue = (val) => { + if (window.location.protocol !== "file:") { + window.localStorage.setItem("quarto-reader-mode", val); + } else { + localReaderMode = val; + } + }; + + const isReaderMode = () => { + if (window.location.protocol !== "file:") { + return window.localStorage.getItem("quarto-reader-mode") === "true"; + } else { + return localReaderMode; + } + }; + let localReaderMode = null; + + const tocOpenDepthStr = tocEl?.getAttribute("data-toc-expanded"); + const tocOpenDepth = tocOpenDepthStr ? Number(tocOpenDepthStr) : 1; + + // Walk the TOC and collapse/expand nodes + // Nodes are expanded if: + // - they are top level + // - they have children that are 'active' links + // - they are directly below an link that is 'active' + const walk = (el, depth) => { + // Tick depth when we enter a UL + if (el.tagName === "UL") { + depth = depth + 1; + } + + // It this is active link + let isActiveNode = false; + if (el.tagName === "A" && el.classList.contains("active")) { + isActiveNode = true; + } + + // See if there is an active child to this element + let hasActiveChild = false; + for (child of el.children) { + hasActiveChild = walk(child, depth) || hasActiveChild; + } + + // Process the collapse state if this is an UL + if (el.tagName === "UL") { + if (tocOpenDepth === -1 && depth > 1) { + el.classList.add("collapse"); + } else if ( + depth <= tocOpenDepth || + hasActiveChild || + prevSiblingIsActiveLink(el) + ) { + el.classList.remove("collapse"); + } else { + el.classList.add("collapse"); + } + + // untick depth when we leave a UL + depth = depth - 1; + } + return hasActiveChild || isActiveNode; + }; + + // walk the TOC and expand / collapse any items that should be shown + + if (tocEl) { + walk(tocEl, 0); + updateActiveLink(); + } + + // Throttle the scroll event and walk peridiocally + window.document.addEventListener( + "scroll", + throttle(() => { + if (tocEl) { + updateActiveLink(); + walk(tocEl, 0); + } + if (!isReaderMode()) { + hideOverlappedSidebars(); + } + }, 5) + ); + window.addEventListener( + "resize", + throttle(() => { + if (!isReaderMode()) { + hideOverlappedSidebars(); + } + }, 10) + ); + hideOverlappedSidebars(); + highlightReaderToggle(isReaderMode()); +}); + +// grouped tabsets +window.addEventListener("pageshow", (_event) => { + function getTabSettings() { + const data = localStorage.getItem("quarto-persistent-tabsets-data"); + if (!data) { + localStorage.setItem("quarto-persistent-tabsets-data", "{}"); + return {}; + } + if (data) { + return JSON.parse(data); + } + } + + function setTabSettings(data) { + localStorage.setItem( + "quarto-persistent-tabsets-data", + JSON.stringify(data) + ); + } + + function setTabState(groupName, groupValue) { + const data = getTabSettings(); + data[groupName] = groupValue; + setTabSettings(data); + } + + function toggleTab(tab, active) { + const tabPanelId = tab.getAttribute("aria-controls"); + const tabPanel = document.getElementById(tabPanelId); + if (active) { + tab.classList.add("active"); + tabPanel.classList.add("active"); + } else { + tab.classList.remove("active"); + tabPanel.classList.remove("active"); + } + } + + function toggleAll(selectedGroup, selectorsToSync) { + for (const [thisGroup, tabs] of Object.entries(selectorsToSync)) { + const active = selectedGroup === thisGroup; + for (const tab of tabs) { + toggleTab(tab, active); + } + } + } + + function findSelectorsToSyncByLanguage() { + const result = {}; + const tabs = Array.from( + document.querySelectorAll(`div[data-group] a[id^='tabset-']`) + ); + for (const item of tabs) { + const div = item.parentElement.parentElement.parentElement; + const group = div.getAttribute("data-group"); + if (!result[group]) { + result[group] = {}; + } + const selectorsToSync = result[group]; + const value = item.innerHTML; + if (!selectorsToSync[value]) { + selectorsToSync[value] = []; + } + selectorsToSync[value].push(item); + } + return result; + } + + function setupSelectorSync() { + const selectorsToSync = findSelectorsToSyncByLanguage(); + Object.entries(selectorsToSync).forEach(([group, tabSetsByValue]) => { + Object.entries(tabSetsByValue).forEach(([value, items]) => { + items.forEach((item) => { + item.addEventListener("click", (_event) => { + setTabState(group, value); + toggleAll(value, selectorsToSync[group]); + }); + }); + }); + }); + return selectorsToSync; + } + + const selectorsToSync = setupSelectorSync(); + for (const [group, selectedName] of Object.entries(getTabSettings())) { + const selectors = selectorsToSync[group]; + // it's possible that stale state gives us empty selections, so we explicitly check here. + if (selectors) { + toggleAll(selectedName, selectors); + } + } +}); + +function throttle(func, wait) { + let waiting = false; + return function () { + if (!waiting) { + func.apply(this, arguments); + waiting = true; + setTimeout(function () { + waiting = false; + }, wait); + } + }; +} + +function nexttick(func) { + return setTimeout(func, 0); +} diff --git a/pr-preview/pr-68/site_libs/quarto-html/tippy.css b/pr-preview/pr-68/site_libs/quarto-html/tippy.css new file mode 100644 index 0000000..e6ae635 --- /dev/null +++ b/pr-preview/pr-68/site_libs/quarto-html/tippy.css @@ -0,0 +1 @@ +.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1} \ No newline at end of file diff --git a/pr-preview/pr-68/site_libs/quarto-html/tippy.umd.min.js b/pr-preview/pr-68/site_libs/quarto-html/tippy.umd.min.js new file mode 100644 index 0000000..ca292be --- /dev/null +++ b/pr-preview/pr-68/site_libs/quarto-html/tippy.umd.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@popperjs/core")):"function"==typeof define&&define.amd?define(["@popperjs/core"],t):(e=e||self).tippy=t(e.Popper)}(this,(function(e){"use strict";var t={passive:!0,capture:!0},n=function(){return document.body};function r(e,t,n){if(Array.isArray(e)){var r=e[t];return null==r?Array.isArray(n)?n[t]:n:r}return e}function o(e,t){var n={}.toString.call(e);return 0===n.indexOf("[object")&&n.indexOf(t+"]")>-1}function i(e,t){return"function"==typeof e?e.apply(void 0,t):e}function a(e,t){return 0===t?e:function(r){clearTimeout(n),n=setTimeout((function(){e(r)}),t)};var n}function s(e,t){var n=Object.assign({},e);return t.forEach((function(e){delete n[e]})),n}function u(e){return[].concat(e)}function c(e,t){-1===e.indexOf(t)&&e.push(t)}function p(e){return e.split("-")[0]}function f(e){return[].slice.call(e)}function l(e){return Object.keys(e).reduce((function(t,n){return void 0!==e[n]&&(t[n]=e[n]),t}),{})}function d(){return document.createElement("div")}function v(e){return["Element","Fragment"].some((function(t){return o(e,t)}))}function m(e){return o(e,"MouseEvent")}function g(e){return!(!e||!e._tippy||e._tippy.reference!==e)}function h(e){return v(e)?[e]:function(e){return o(e,"NodeList")}(e)?f(e):Array.isArray(e)?e:f(document.querySelectorAll(e))}function b(e,t){e.forEach((function(e){e&&(e.style.transitionDuration=t+"ms")}))}function y(e,t){e.forEach((function(e){e&&e.setAttribute("data-state",t)}))}function w(e){var t,n=u(e)[0];return null!=n&&null!=(t=n.ownerDocument)&&t.body?n.ownerDocument:document}function E(e,t,n){var r=t+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(t){e[r](t,n)}))}function O(e,t){for(var n=t;n;){var r;if(e.contains(n))return!0;n=null==n.getRootNode||null==(r=n.getRootNode())?void 0:r.host}return!1}var x={isTouch:!1},C=0;function T(){x.isTouch||(x.isTouch=!0,window.performance&&document.addEventListener("mousemove",A))}function A(){var e=performance.now();e-C<20&&(x.isTouch=!1,document.removeEventListener("mousemove",A)),C=e}function L(){var e=document.activeElement;if(g(e)){var t=e._tippy;e.blur&&!t.state.isVisible&&e.blur()}}var D=!!("undefined"!=typeof window&&"undefined"!=typeof document)&&!!window.msCrypto,R=Object.assign({appendTo:n,aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),k=Object.keys(R);function P(e){var t=(e.plugins||[]).reduce((function(t,n){var r,o=n.name,i=n.defaultValue;o&&(t[o]=void 0!==e[o]?e[o]:null!=(r=R[o])?r:i);return t}),{});return Object.assign({},e,t)}function j(e,t){var n=Object.assign({},t,{content:i(t.content,[e])},t.ignoreAttributes?{}:function(e,t){return(t?Object.keys(P(Object.assign({},R,{plugins:t}))):k).reduce((function(t,n){var r=(e.getAttribute("data-tippy-"+n)||"").trim();if(!r)return t;if("content"===n)t[n]=r;else try{t[n]=JSON.parse(r)}catch(e){t[n]=r}return t}),{})}(e,t.plugins));return n.aria=Object.assign({},R.aria,n.aria),n.aria={expanded:"auto"===n.aria.expanded?t.interactive:n.aria.expanded,content:"auto"===n.aria.content?t.interactive?null:"describedby":n.aria.content},n}function M(e,t){e.innerHTML=t}function V(e){var t=d();return!0===e?t.className="tippy-arrow":(t.className="tippy-svg-arrow",v(e)?t.appendChild(e):M(t,e)),t}function I(e,t){v(t.content)?(M(e,""),e.appendChild(t.content)):"function"!=typeof t.content&&(t.allowHTML?M(e,t.content):e.textContent=t.content)}function S(e){var t=e.firstElementChild,n=f(t.children);return{box:t,content:n.find((function(e){return e.classList.contains("tippy-content")})),arrow:n.find((function(e){return e.classList.contains("tippy-arrow")||e.classList.contains("tippy-svg-arrow")})),backdrop:n.find((function(e){return e.classList.contains("tippy-backdrop")}))}}function N(e){var t=d(),n=d();n.className="tippy-box",n.setAttribute("data-state","hidden"),n.setAttribute("tabindex","-1");var r=d();function o(n,r){var o=S(t),i=o.box,a=o.content,s=o.arrow;r.theme?i.setAttribute("data-theme",r.theme):i.removeAttribute("data-theme"),"string"==typeof r.animation?i.setAttribute("data-animation",r.animation):i.removeAttribute("data-animation"),r.inertia?i.setAttribute("data-inertia",""):i.removeAttribute("data-inertia"),i.style.maxWidth="number"==typeof r.maxWidth?r.maxWidth+"px":r.maxWidth,r.role?i.setAttribute("role",r.role):i.removeAttribute("role"),n.content===r.content&&n.allowHTML===r.allowHTML||I(a,e.props),r.arrow?s?n.arrow!==r.arrow&&(i.removeChild(s),i.appendChild(V(r.arrow))):i.appendChild(V(r.arrow)):s&&i.removeChild(s)}return r.className="tippy-content",r.setAttribute("data-state","hidden"),I(r,e.props),t.appendChild(n),n.appendChild(r),o(e.props,e.props),{popper:t,onUpdate:o}}N.$$tippy=!0;var B=1,H=[],U=[];function _(o,s){var v,g,h,C,T,A,L,k,M=j(o,Object.assign({},R,P(l(s)))),V=!1,I=!1,N=!1,_=!1,F=[],W=a(we,M.interactiveDebounce),X=B++,Y=(k=M.plugins).filter((function(e,t){return k.indexOf(e)===t})),$={id:X,reference:o,popper:d(),popperInstance:null,props:M,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:Y,clearDelayTimeouts:function(){clearTimeout(v),clearTimeout(g),cancelAnimationFrame(h)},setProps:function(e){if($.state.isDestroyed)return;ae("onBeforeUpdate",[$,e]),be();var t=$.props,n=j(o,Object.assign({},t,l(e),{ignoreAttributes:!0}));$.props=n,he(),t.interactiveDebounce!==n.interactiveDebounce&&(ce(),W=a(we,n.interactiveDebounce));t.triggerTarget&&!n.triggerTarget?u(t.triggerTarget).forEach((function(e){e.removeAttribute("aria-expanded")})):n.triggerTarget&&o.removeAttribute("aria-expanded");ue(),ie(),J&&J(t,n);$.popperInstance&&(Ce(),Ae().forEach((function(e){requestAnimationFrame(e._tippy.popperInstance.forceUpdate)})));ae("onAfterUpdate",[$,e])},setContent:function(e){$.setProps({content:e})},show:function(){var e=$.state.isVisible,t=$.state.isDestroyed,o=!$.state.isEnabled,a=x.isTouch&&!$.props.touch,s=r($.props.duration,0,R.duration);if(e||t||o||a)return;if(te().hasAttribute("disabled"))return;if(ae("onShow",[$],!1),!1===$.props.onShow($))return;$.state.isVisible=!0,ee()&&(z.style.visibility="visible");ie(),de(),$.state.isMounted||(z.style.transition="none");if(ee()){var u=re(),p=u.box,f=u.content;b([p,f],0)}A=function(){var e;if($.state.isVisible&&!_){if(_=!0,z.offsetHeight,z.style.transition=$.props.moveTransition,ee()&&$.props.animation){var t=re(),n=t.box,r=t.content;b([n,r],s),y([n,r],"visible")}se(),ue(),c(U,$),null==(e=$.popperInstance)||e.forceUpdate(),ae("onMount",[$]),$.props.animation&&ee()&&function(e,t){me(e,t)}(s,(function(){$.state.isShown=!0,ae("onShown",[$])}))}},function(){var e,t=$.props.appendTo,r=te();e=$.props.interactive&&t===n||"parent"===t?r.parentNode:i(t,[r]);e.contains(z)||e.appendChild(z);$.state.isMounted=!0,Ce()}()},hide:function(){var e=!$.state.isVisible,t=$.state.isDestroyed,n=!$.state.isEnabled,o=r($.props.duration,1,R.duration);if(e||t||n)return;if(ae("onHide",[$],!1),!1===$.props.onHide($))return;$.state.isVisible=!1,$.state.isShown=!1,_=!1,V=!1,ee()&&(z.style.visibility="hidden");if(ce(),ve(),ie(!0),ee()){var i=re(),a=i.box,s=i.content;$.props.animation&&(b([a,s],o),y([a,s],"hidden"))}se(),ue(),$.props.animation?ee()&&function(e,t){me(e,(function(){!$.state.isVisible&&z.parentNode&&z.parentNode.contains(z)&&t()}))}(o,$.unmount):$.unmount()},hideWithInteractivity:function(e){ne().addEventListener("mousemove",W),c(H,W),W(e)},enable:function(){$.state.isEnabled=!0},disable:function(){$.hide(),$.state.isEnabled=!1},unmount:function(){$.state.isVisible&&$.hide();if(!$.state.isMounted)return;Te(),Ae().forEach((function(e){e._tippy.unmount()})),z.parentNode&&z.parentNode.removeChild(z);U=U.filter((function(e){return e!==$})),$.state.isMounted=!1,ae("onHidden",[$])},destroy:function(){if($.state.isDestroyed)return;$.clearDelayTimeouts(),$.unmount(),be(),delete o._tippy,$.state.isDestroyed=!0,ae("onDestroy",[$])}};if(!M.render)return $;var q=M.render($),z=q.popper,J=q.onUpdate;z.setAttribute("data-tippy-root",""),z.id="tippy-"+$.id,$.popper=z,o._tippy=$,z._tippy=$;var G=Y.map((function(e){return e.fn($)})),K=o.hasAttribute("aria-expanded");return he(),ue(),ie(),ae("onCreate",[$]),M.showOnCreate&&Le(),z.addEventListener("mouseenter",(function(){$.props.interactive&&$.state.isVisible&&$.clearDelayTimeouts()})),z.addEventListener("mouseleave",(function(){$.props.interactive&&$.props.trigger.indexOf("mouseenter")>=0&&ne().addEventListener("mousemove",W)})),$;function Q(){var e=$.props.touch;return Array.isArray(e)?e:[e,0]}function Z(){return"hold"===Q()[0]}function ee(){var e;return!(null==(e=$.props.render)||!e.$$tippy)}function te(){return L||o}function ne(){var e=te().parentNode;return e?w(e):document}function re(){return S(z)}function oe(e){return $.state.isMounted&&!$.state.isVisible||x.isTouch||C&&"focus"===C.type?0:r($.props.delay,e?0:1,R.delay)}function ie(e){void 0===e&&(e=!1),z.style.pointerEvents=$.props.interactive&&!e?"":"none",z.style.zIndex=""+$.props.zIndex}function ae(e,t,n){var r;(void 0===n&&(n=!0),G.forEach((function(n){n[e]&&n[e].apply(n,t)})),n)&&(r=$.props)[e].apply(r,t)}function se(){var e=$.props.aria;if(e.content){var t="aria-"+e.content,n=z.id;u($.props.triggerTarget||o).forEach((function(e){var r=e.getAttribute(t);if($.state.isVisible)e.setAttribute(t,r?r+" "+n:n);else{var o=r&&r.replace(n,"").trim();o?e.setAttribute(t,o):e.removeAttribute(t)}}))}}function ue(){!K&&$.props.aria.expanded&&u($.props.triggerTarget||o).forEach((function(e){$.props.interactive?e.setAttribute("aria-expanded",$.state.isVisible&&e===te()?"true":"false"):e.removeAttribute("aria-expanded")}))}function ce(){ne().removeEventListener("mousemove",W),H=H.filter((function(e){return e!==W}))}function pe(e){if(!x.isTouch||!N&&"mousedown"!==e.type){var t=e.composedPath&&e.composedPath()[0]||e.target;if(!$.props.interactive||!O(z,t)){if(u($.props.triggerTarget||o).some((function(e){return O(e,t)}))){if(x.isTouch)return;if($.state.isVisible&&$.props.trigger.indexOf("click")>=0)return}else ae("onClickOutside",[$,e]);!0===$.props.hideOnClick&&($.clearDelayTimeouts(),$.hide(),I=!0,setTimeout((function(){I=!1})),$.state.isMounted||ve())}}}function fe(){N=!0}function le(){N=!1}function de(){var e=ne();e.addEventListener("mousedown",pe,!0),e.addEventListener("touchend",pe,t),e.addEventListener("touchstart",le,t),e.addEventListener("touchmove",fe,t)}function ve(){var e=ne();e.removeEventListener("mousedown",pe,!0),e.removeEventListener("touchend",pe,t),e.removeEventListener("touchstart",le,t),e.removeEventListener("touchmove",fe,t)}function me(e,t){var n=re().box;function r(e){e.target===n&&(E(n,"remove",r),t())}if(0===e)return t();E(n,"remove",T),E(n,"add",r),T=r}function ge(e,t,n){void 0===n&&(n=!1),u($.props.triggerTarget||o).forEach((function(r){r.addEventListener(e,t,n),F.push({node:r,eventType:e,handler:t,options:n})}))}function he(){var e;Z()&&(ge("touchstart",ye,{passive:!0}),ge("touchend",Ee,{passive:!0})),(e=$.props.trigger,e.split(/\s+/).filter(Boolean)).forEach((function(e){if("manual"!==e)switch(ge(e,ye),e){case"mouseenter":ge("mouseleave",Ee);break;case"focus":ge(D?"focusout":"blur",Oe);break;case"focusin":ge("focusout",Oe)}}))}function be(){F.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),F=[]}function ye(e){var t,n=!1;if($.state.isEnabled&&!xe(e)&&!I){var r="focus"===(null==(t=C)?void 0:t.type);C=e,L=e.currentTarget,ue(),!$.state.isVisible&&m(e)&&H.forEach((function(t){return t(e)})),"click"===e.type&&($.props.trigger.indexOf("mouseenter")<0||V)&&!1!==$.props.hideOnClick&&$.state.isVisible?n=!0:Le(e),"click"===e.type&&(V=!n),n&&!r&&De(e)}}function we(e){var t=e.target,n=te().contains(t)||z.contains(t);"mousemove"===e.type&&n||function(e,t){var n=t.clientX,r=t.clientY;return e.every((function(e){var t=e.popperRect,o=e.popperState,i=e.props.interactiveBorder,a=p(o.placement),s=o.modifiersData.offset;if(!s)return!0;var u="bottom"===a?s.top.y:0,c="top"===a?s.bottom.y:0,f="right"===a?s.left.x:0,l="left"===a?s.right.x:0,d=t.top-r+u>i,v=r-t.bottom-c>i,m=t.left-n+f>i,g=n-t.right-l>i;return d||v||m||g}))}(Ae().concat(z).map((function(e){var t,n=null==(t=e._tippy.popperInstance)?void 0:t.state;return n?{popperRect:e.getBoundingClientRect(),popperState:n,props:M}:null})).filter(Boolean),e)&&(ce(),De(e))}function Ee(e){xe(e)||$.props.trigger.indexOf("click")>=0&&V||($.props.interactive?$.hideWithInteractivity(e):De(e))}function Oe(e){$.props.trigger.indexOf("focusin")<0&&e.target!==te()||$.props.interactive&&e.relatedTarget&&z.contains(e.relatedTarget)||De(e)}function xe(e){return!!x.isTouch&&Z()!==e.type.indexOf("touch")>=0}function Ce(){Te();var t=$.props,n=t.popperOptions,r=t.placement,i=t.offset,a=t.getReferenceClientRect,s=t.moveTransition,u=ee()?S(z).arrow:null,c=a?{getBoundingClientRect:a,contextElement:a.contextElement||te()}:o,p=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!s}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(e){var t=e.state;if(ee()){var n=re().box;["placement","reference-hidden","escaped"].forEach((function(e){"placement"===e?n.setAttribute("data-placement",t.placement):t.attributes.popper["data-popper-"+e]?n.setAttribute("data-"+e,""):n.removeAttribute("data-"+e)})),t.attributes.popper={}}}}];ee()&&u&&p.push({name:"arrow",options:{element:u,padding:3}}),p.push.apply(p,(null==n?void 0:n.modifiers)||[]),$.popperInstance=e.createPopper(c,z,Object.assign({},n,{placement:r,onFirstUpdate:A,modifiers:p}))}function Te(){$.popperInstance&&($.popperInstance.destroy(),$.popperInstance=null)}function Ae(){return f(z.querySelectorAll("[data-tippy-root]"))}function Le(e){$.clearDelayTimeouts(),e&&ae("onTrigger",[$,e]),de();var t=oe(!0),n=Q(),r=n[0],o=n[1];x.isTouch&&"hold"===r&&o&&(t=o),t?v=setTimeout((function(){$.show()}),t):$.show()}function De(e){if($.clearDelayTimeouts(),ae("onUntrigger",[$,e]),$.state.isVisible){if(!($.props.trigger.indexOf("mouseenter")>=0&&$.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(e.type)>=0&&V)){var t=oe(!1);t?g=setTimeout((function(){$.state.isVisible&&$.hide()}),t):h=requestAnimationFrame((function(){$.hide()}))}}else ve()}}function F(e,n){void 0===n&&(n={});var r=R.plugins.concat(n.plugins||[]);document.addEventListener("touchstart",T,t),window.addEventListener("blur",L);var o=Object.assign({},n,{plugins:r}),i=h(e).reduce((function(e,t){var n=t&&_(t,o);return n&&e.push(n),e}),[]);return v(e)?i[0]:i}F.defaultProps=R,F.setDefaultProps=function(e){Object.keys(e).forEach((function(t){R[t]=e[t]}))},F.currentInput=x;var W=Object.assign({},e.applyStyles,{effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow)}}),X={mouseover:"mouseenter",focusin:"focus",click:"click"};var Y={name:"animateFill",defaultValue:!1,fn:function(e){var t;if(null==(t=e.props.render)||!t.$$tippy)return{};var n=S(e.popper),r=n.box,o=n.content,i=e.props.animateFill?function(){var e=d();return e.className="tippy-backdrop",y([e],"hidden"),e}():null;return{onCreate:function(){i&&(r.insertBefore(i,r.firstElementChild),r.setAttribute("data-animatefill",""),r.style.overflow="hidden",e.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(i){var e=r.style.transitionDuration,t=Number(e.replace("ms",""));o.style.transitionDelay=Math.round(t/10)+"ms",i.style.transitionDuration=e,y([i],"visible")}},onShow:function(){i&&(i.style.transitionDuration="0ms")},onHide:function(){i&&y([i],"hidden")}}}};var $={clientX:0,clientY:0},q=[];function z(e){var t=e.clientX,n=e.clientY;$={clientX:t,clientY:n}}var J={name:"followCursor",defaultValue:!1,fn:function(e){var t=e.reference,n=w(e.props.triggerTarget||t),r=!1,o=!1,i=!0,a=e.props;function s(){return"initial"===e.props.followCursor&&e.state.isVisible}function u(){n.addEventListener("mousemove",f)}function c(){n.removeEventListener("mousemove",f)}function p(){r=!0,e.setProps({getReferenceClientRect:null}),r=!1}function f(n){var r=!n.target||t.contains(n.target),o=e.props.followCursor,i=n.clientX,a=n.clientY,s=t.getBoundingClientRect(),u=i-s.left,c=a-s.top;!r&&e.props.interactive||e.setProps({getReferenceClientRect:function(){var e=t.getBoundingClientRect(),n=i,r=a;"initial"===o&&(n=e.left+u,r=e.top+c);var s="horizontal"===o?e.top:r,p="vertical"===o?e.right:n,f="horizontal"===o?e.bottom:r,l="vertical"===o?e.left:n;return{width:p-l,height:f-s,top:s,right:p,bottom:f,left:l}}})}function l(){e.props.followCursor&&(q.push({instance:e,doc:n}),function(e){e.addEventListener("mousemove",z)}(n))}function d(){0===(q=q.filter((function(t){return t.instance!==e}))).filter((function(e){return e.doc===n})).length&&function(e){e.removeEventListener("mousemove",z)}(n)}return{onCreate:l,onDestroy:d,onBeforeUpdate:function(){a=e.props},onAfterUpdate:function(t,n){var i=n.followCursor;r||void 0!==i&&a.followCursor!==i&&(d(),i?(l(),!e.state.isMounted||o||s()||u()):(c(),p()))},onMount:function(){e.props.followCursor&&!o&&(i&&(f($),i=!1),s()||u())},onTrigger:function(e,t){m(t)&&($={clientX:t.clientX,clientY:t.clientY}),o="focus"===t.type},onHidden:function(){e.props.followCursor&&(p(),c(),i=!0)}}}};var G={name:"inlinePositioning",defaultValue:!1,fn:function(e){var t,n=e.reference;var r=-1,o=!1,i=[],a={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(o){var a=o.state;e.props.inlinePositioning&&(-1!==i.indexOf(a.placement)&&(i=[]),t!==a.placement&&-1===i.indexOf(a.placement)&&(i.push(a.placement),e.setProps({getReferenceClientRect:function(){return function(e){return function(e,t,n,r){if(n.length<2||null===e)return t;if(2===n.length&&r>=0&&n[0].left>n[1].right)return n[r]||t;switch(e){case"top":case"bottom":var o=n[0],i=n[n.length-1],a="top"===e,s=o.top,u=i.bottom,c=a?o.left:i.left,p=a?o.right:i.right;return{top:s,bottom:u,left:c,right:p,width:p-c,height:u-s};case"left":case"right":var f=Math.min.apply(Math,n.map((function(e){return e.left}))),l=Math.max.apply(Math,n.map((function(e){return e.right}))),d=n.filter((function(t){return"left"===e?t.left===f:t.right===l})),v=d[0].top,m=d[d.length-1].bottom;return{top:v,bottom:m,left:f,right:l,width:l-f,height:m-v};default:return t}}(p(e),n.getBoundingClientRect(),f(n.getClientRects()),r)}(a.placement)}})),t=a.placement)}};function s(){var t;o||(t=function(e,t){var n;return{popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat(((null==(n=e.popperOptions)?void 0:n.modifiers)||[]).filter((function(e){return e.name!==t.name})),[t])})}}(e.props,a),o=!0,e.setProps(t),o=!1)}return{onCreate:s,onAfterUpdate:s,onTrigger:function(t,n){if(m(n)){var o=f(e.reference.getClientRects()),i=o.find((function(e){return e.left-2<=n.clientX&&e.right+2>=n.clientX&&e.top-2<=n.clientY&&e.bottom+2>=n.clientY})),a=o.indexOf(i);r=a>-1?a:r}},onHidden:function(){r=-1}}}};var K={name:"sticky",defaultValue:!1,fn:function(e){var t=e.reference,n=e.popper;function r(t){return!0===e.props.sticky||e.props.sticky===t}var o=null,i=null;function a(){var s=r("reference")?(e.popperInstance?e.popperInstance.state.elements.reference:t).getBoundingClientRect():null,u=r("popper")?n.getBoundingClientRect():null;(s&&Q(o,s)||u&&Q(i,u))&&e.popperInstance&&e.popperInstance.update(),o=s,i=u,e.state.isMounted&&requestAnimationFrame(a)}return{onMount:function(){e.props.sticky&&a()}}}};function Q(e,t){return!e||!t||(e.top!==t.top||e.right!==t.right||e.bottom!==t.bottom||e.left!==t.left)}return F.setDefaultProps({plugins:[Y,J,G,K],render:N}),F.createSingleton=function(e,t){var n;void 0===t&&(t={});var r,o=e,i=[],a=[],c=t.overrides,p=[],f=!1;function l(){a=o.map((function(e){return u(e.props.triggerTarget||e.reference)})).reduce((function(e,t){return e.concat(t)}),[])}function v(){i=o.map((function(e){return e.reference}))}function m(e){o.forEach((function(t){e?t.enable():t.disable()}))}function g(e){return o.map((function(t){var n=t.setProps;return t.setProps=function(o){n(o),t.reference===r&&e.setProps(o)},function(){t.setProps=n}}))}function h(e,t){var n=a.indexOf(t);if(t!==r){r=t;var s=(c||[]).concat("content").reduce((function(e,t){return e[t]=o[n].props[t],e}),{});e.setProps(Object.assign({},s,{getReferenceClientRect:"function"==typeof s.getReferenceClientRect?s.getReferenceClientRect:function(){var e;return null==(e=i[n])?void 0:e.getBoundingClientRect()}}))}}m(!1),v(),l();var b={fn:function(){return{onDestroy:function(){m(!0)},onHidden:function(){r=null},onClickOutside:function(e){e.props.showOnCreate&&!f&&(f=!0,r=null)},onShow:function(e){e.props.showOnCreate&&!f&&(f=!0,h(e,i[0]))},onTrigger:function(e,t){h(e,t.currentTarget)}}}},y=F(d(),Object.assign({},s(t,["overrides"]),{plugins:[b].concat(t.plugins||[]),triggerTarget:a,popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat((null==(n=t.popperOptions)?void 0:n.modifiers)||[],[W])})})),w=y.show;y.show=function(e){if(w(),!r&&null==e)return h(y,i[0]);if(!r||null!=e){if("number"==typeof e)return i[e]&&h(y,i[e]);if(o.indexOf(e)>=0){var t=e.reference;return h(y,t)}return i.indexOf(e)>=0?h(y,e):void 0}},y.showNext=function(){var e=i[0];if(!r)return y.show(0);var t=i.indexOf(r);y.show(i[t+1]||e)},y.showPrevious=function(){var e=i[i.length-1];if(!r)return y.show(e);var t=i.indexOf(r),n=i[t-1]||e;y.show(n)};var E=y.setProps;return y.setProps=function(e){c=e.overrides||c,E(e)},y.setInstances=function(e){m(!0),p.forEach((function(e){return e()})),o=e,m(!1),v(),l(),p=g(y),y.setProps({triggerTarget:a})},p=g(y),y},F.delegate=function(e,n){var r=[],o=[],i=!1,a=n.target,c=s(n,["target"]),p=Object.assign({},c,{trigger:"manual",touch:!1}),f=Object.assign({touch:R.touch},c,{showOnCreate:!0}),l=F(e,p);function d(e){if(e.target&&!i){var t=e.target.closest(a);if(t){var r=t.getAttribute("data-tippy-trigger")||n.trigger||R.trigger;if(!t._tippy&&!("touchstart"===e.type&&"boolean"==typeof f.touch||"touchstart"!==e.type&&r.indexOf(X[e.type])<0)){var s=F(t,f);s&&(o=o.concat(s))}}}}function v(e,t,n,o){void 0===o&&(o=!1),e.addEventListener(t,n,o),r.push({node:e,eventType:t,handler:n,options:o})}return u(l).forEach((function(e){var n=e.destroy,a=e.enable,s=e.disable;e.destroy=function(e){void 0===e&&(e=!0),e&&o.forEach((function(e){e.destroy()})),o=[],r.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),r=[],n()},e.enable=function(){a(),o.forEach((function(e){return e.enable()})),i=!1},e.disable=function(){s(),o.forEach((function(e){return e.disable()})),i=!0},function(e){var n=e.reference;v(n,"touchstart",d,t),v(n,"mouseover",d),v(n,"focusin",d),v(n,"click",d)}(e)})),l},F.hideAll=function(e){var t=void 0===e?{}:e,n=t.exclude,r=t.duration;U.forEach((function(e){var t=!1;if(n&&(t=g(n)?e.reference===n:e.popper===n.popper),!t){var o=e.props.duration;e.setProps({duration:r}),e.hide(),e.state.isDestroyed||e.setProps({duration:o})}}))},F.roundArrow='',F})); + diff --git a/pr-preview/pr-68/site_libs/quarto-nav/quarto-nav.js b/pr-preview/pr-68/site_libs/quarto-nav/quarto-nav.js new file mode 100644 index 0000000..3b21201 --- /dev/null +++ b/pr-preview/pr-68/site_libs/quarto-nav/quarto-nav.js @@ -0,0 +1,277 @@ +const headroomChanged = new CustomEvent("quarto-hrChanged", { + detail: {}, + bubbles: true, + cancelable: false, + composed: false, +}); + +window.document.addEventListener("DOMContentLoaded", function () { + let init = false; + + // Manage the back to top button, if one is present. + let lastScrollTop = window.pageYOffset || document.documentElement.scrollTop; + const scrollDownBuffer = 5; + const scrollUpBuffer = 35; + const btn = document.getElementById("quarto-back-to-top"); + const hideBackToTop = () => { + btn.style.display = "none"; + }; + const showBackToTop = () => { + btn.style.display = "inline-block"; + }; + if (btn) { + window.document.addEventListener( + "scroll", + function () { + const currentScrollTop = + window.pageYOffset || document.documentElement.scrollTop; + + // Shows and hides the button 'intelligently' as the user scrolls + if (currentScrollTop - scrollDownBuffer > lastScrollTop) { + hideBackToTop(); + lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop; + } else if (currentScrollTop < lastScrollTop - scrollUpBuffer) { + showBackToTop(); + lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop; + } + + // Show the button at the bottom, hides it at the top + if (currentScrollTop <= 0) { + hideBackToTop(); + } else if ( + window.innerHeight + currentScrollTop >= + document.body.offsetHeight + ) { + showBackToTop(); + } + }, + false + ); + } + + function throttle(func, wait) { + var timeout; + return function () { + const context = this; + const args = arguments; + const later = function () { + clearTimeout(timeout); + timeout = null; + func.apply(context, args); + }; + + if (!timeout) { + timeout = setTimeout(later, wait); + } + }; + } + + function headerOffset() { + // Set an offset if there is are fixed top navbar + const headerEl = window.document.querySelector("header.fixed-top"); + if (headerEl) { + return headerEl.clientHeight; + } else { + return 0; + } + } + + function footerOffset() { + const footerEl = window.document.querySelector("footer.footer"); + if (footerEl) { + return footerEl.clientHeight; + } else { + return 0; + } + } + + function updateDocumentOffsetWithoutAnimation() { + updateDocumentOffset(false); + } + + function updateDocumentOffset(animated) { + // set body offset + const topOffset = headerOffset(); + const bodyOffset = topOffset + footerOffset(); + const bodyEl = window.document.body; + bodyEl.setAttribute("data-bs-offset", topOffset); + bodyEl.style.paddingTop = topOffset + "px"; + + // deal with sidebar offsets + const sidebars = window.document.querySelectorAll( + ".sidebar, .headroom-target" + ); + sidebars.forEach((sidebar) => { + if (!animated) { + sidebar.classList.add("notransition"); + // Remove the no transition class after the animation has time to complete + setTimeout(function () { + sidebar.classList.remove("notransition"); + }, 201); + } + + if (window.Headroom && sidebar.classList.contains("sidebar-unpinned")) { + sidebar.style.top = "0"; + sidebar.style.maxHeight = "100vh"; + } else { + sidebar.style.top = topOffset + "px"; + sidebar.style.maxHeight = "calc(100vh - " + topOffset + "px)"; + } + }); + + // allow space for footer + const mainContainer = window.document.querySelector(".quarto-container"); + if (mainContainer) { + mainContainer.style.minHeight = "calc(100vh - " + bodyOffset + "px)"; + } + + // link offset + let linkStyle = window.document.querySelector("#quarto-target-style"); + if (!linkStyle) { + linkStyle = window.document.createElement("style"); + linkStyle.setAttribute("id", "quarto-target-style"); + window.document.head.appendChild(linkStyle); + } + while (linkStyle.firstChild) { + linkStyle.removeChild(linkStyle.firstChild); + } + if (topOffset > 0) { + linkStyle.appendChild( + window.document.createTextNode(` + section:target::before { + content: ""; + display: block; + height: ${topOffset}px; + margin: -${topOffset}px 0 0; + }`) + ); + } + if (init) { + window.dispatchEvent(headroomChanged); + } + init = true; + } + + // initialize headroom + var header = window.document.querySelector("#quarto-header"); + if (header && window.Headroom) { + const headroom = new window.Headroom(header, { + tolerance: 5, + onPin: function () { + const sidebars = window.document.querySelectorAll( + ".sidebar, .headroom-target" + ); + sidebars.forEach((sidebar) => { + sidebar.classList.remove("sidebar-unpinned"); + }); + updateDocumentOffset(); + }, + onUnpin: function () { + const sidebars = window.document.querySelectorAll( + ".sidebar, .headroom-target" + ); + sidebars.forEach((sidebar) => { + sidebar.classList.add("sidebar-unpinned"); + }); + updateDocumentOffset(); + }, + }); + headroom.init(); + + let frozen = false; + window.quartoToggleHeadroom = function () { + if (frozen) { + headroom.unfreeze(); + frozen = false; + } else { + headroom.freeze(); + frozen = true; + } + }; + } + + window.addEventListener( + "hashchange", + function (e) { + if ( + getComputedStyle(document.documentElement).scrollBehavior !== "smooth" + ) { + window.scrollTo(0, window.pageYOffset - headerOffset()); + } + }, + false + ); + + // Observe size changed for the header + const headerEl = window.document.querySelector("header.fixed-top"); + if (headerEl && window.ResizeObserver) { + const observer = new window.ResizeObserver( + updateDocumentOffsetWithoutAnimation + ); + observer.observe(headerEl, { + attributes: true, + childList: true, + characterData: true, + }); + } else { + window.addEventListener( + "resize", + throttle(updateDocumentOffsetWithoutAnimation, 50) + ); + } + setTimeout(updateDocumentOffsetWithoutAnimation, 250); + + // fixup index.html links if we aren't on the filesystem + if (window.location.protocol !== "file:") { + const links = window.document.querySelectorAll("a"); + for (let i = 0; i < links.length; i++) { + if (links[i].href) { + links[i].href = links[i].href.replace(/\/index\.html/, "/"); + } + } + + // Fixup any sharing links that require urls + // Append url to any sharing urls + const sharingLinks = window.document.querySelectorAll( + "a.sidebar-tools-main-item" + ); + for (let i = 0; i < sharingLinks.length; i++) { + const sharingLink = sharingLinks[i]; + const href = sharingLink.getAttribute("href"); + if (href) { + sharingLink.setAttribute( + "href", + href.replace("|url|", window.location.href) + ); + } + } + + // Scroll the active navigation item into view, if necessary + const navSidebar = window.document.querySelector("nav#quarto-sidebar"); + if (navSidebar) { + // Find the active item + const activeItem = navSidebar.querySelector("li.sidebar-item a.active"); + if (activeItem) { + // Wait for the scroll height and height to resolve by observing size changes on the + // nav element that is scrollable + const resizeObserver = new ResizeObserver((_entries) => { + // The bottom of the element + const elBottom = activeItem.offsetTop; + const viewBottom = navSidebar.scrollTop + navSidebar.clientHeight; + + // The element height and scroll height are the same, then we are still loading + if (viewBottom !== navSidebar.scrollHeight) { + // Determine if the item isn't visible and scroll to it + if (elBottom >= viewBottom) { + navSidebar.scrollTop = elBottom; + } + + // stop observing now since we've completed the scroll + resizeObserver.unobserve(navSidebar); + } + }); + resizeObserver.observe(navSidebar); + } + } + } +}); diff --git a/pr-preview/pr-68/site_libs/quarto-ojs/quarto-ojs-runtime.js b/pr-preview/pr-68/site_libs/quarto-ojs/quarto-ojs-runtime.js new file mode 100644 index 0000000..8e75107 --- /dev/null +++ b/pr-preview/pr-68/site_libs/quarto-ojs/quarto-ojs-runtime.js @@ -0,0 +1,20204 @@ +// quarto-ojs-runtime v0.0.15 Copyright 2023 undefined +var EOL = {}, + EOF = {}, + QUOTE = 34, + NEWLINE = 10, + RETURN = 13; + +function objectConverter(columns) { + return new Function("d", "return {" + columns.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "] || \"\""; + }).join(",") + "}"); +} + +function customConverter(columns, f) { + var object = objectConverter(columns); + return function(row, i) { + return f(object(row), i, columns); + }; +} + +// Compute unique columns in order of discovery. +function inferColumns(rows) { + var columnSet = Object.create(null), + columns = []; + + rows.forEach(function(row) { + for (var column in row) { + if (!(column in columnSet)) { + columns.push(columnSet[column] = column); + } + } + }); + + return columns; +} + +function pad$1(value, width) { + var s = value + "", length = s.length; + return length < width ? new Array(width - length + 1).join(0) + s : s; +} + +function formatYear$1(year) { + return year < 0 ? "-" + pad$1(-year, 6) + : year > 9999 ? "+" + pad$1(year, 6) + : pad$1(year, 4); +} + +function formatDate$2(date) { + var hours = date.getUTCHours(), + minutes = date.getUTCMinutes(), + seconds = date.getUTCSeconds(), + milliseconds = date.getUTCMilliseconds(); + return isNaN(date) ? "Invalid Date" + : formatYear$1(date.getUTCFullYear()) + "-" + pad$1(date.getUTCMonth() + 1, 2) + "-" + pad$1(date.getUTCDate(), 2) + + (milliseconds ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + ":" + pad$1(seconds, 2) + "." + pad$1(milliseconds, 3) + "Z" + : seconds ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + ":" + pad$1(seconds, 2) + "Z" + : minutes || hours ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + "Z" + : ""); +} + +function dsv$1(delimiter) { + var reFormat = new RegExp("[\"" + delimiter + "\n\r]"), + DELIMITER = delimiter.charCodeAt(0); + + function parse(text, f) { + var convert, columns, rows = parseRows(text, function(row, i) { + if (convert) return convert(row, i - 1); + columns = row, convert = f ? customConverter(row, f) : objectConverter(row); + }); + rows.columns = columns || []; + return rows; + } + + function parseRows(text, f) { + var rows = [], // output rows + N = text.length, + I = 0, // current character index + n = 0, // current line number + t, // current token + eof = N <= 0, // current token followed by EOF? + eol = false; // current token followed by EOL? + + // Strip the trailing newline. + if (text.charCodeAt(N - 1) === NEWLINE) --N; + if (text.charCodeAt(N - 1) === RETURN) --N; + + function token() { + if (eof) return EOF; + if (eol) return eol = false, EOL; + + // Unescape quotes. + var i, j = I, c; + if (text.charCodeAt(j) === QUOTE) { + while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE); + if ((i = I) >= N) eof = true; + else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true; + else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } + return text.slice(j + 1, i - 1).replace(/""/g, "\""); + } + + // Find next delimiter or newline. + while (I < N) { + if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true; + else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } + else if (c !== DELIMITER) continue; + return text.slice(j, i); + } + + // Return last token before EOF. + return eof = true, text.slice(j, N); + } + + while ((t = token()) !== EOF) { + var row = []; + while (t !== EOL && t !== EOF) row.push(t), t = token(); + if (f && (row = f(row, n++)) == null) continue; + rows.push(row); + } + + return rows; + } + + function preformatBody(rows, columns) { + return rows.map(function(row) { + return columns.map(function(column) { + return formatValue(row[column]); + }).join(delimiter); + }); + } + + function format(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join("\n"); + } + + function formatBody(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return preformatBody(rows, columns).join("\n"); + } + + function formatRows(rows) { + return rows.map(formatRow).join("\n"); + } + + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + + function formatValue(value) { + return value == null ? "" + : value instanceof Date ? formatDate$2(value) + : reFormat.test(value += "") ? "\"" + value.replace(/"/g, "\"\"") + "\"" + : value; + } + + return { + parse: parse, + parseRows: parseRows, + format: format, + formatBody: formatBody, + formatRows: formatRows, + formatRow: formatRow, + formatValue: formatValue + }; +} + +var csv = dsv$1(","); + +var csvParse = csv.parse; +var csvParseRows = csv.parseRows; + +var tsv = dsv$1("\t"); + +var tsvParse = tsv.parse; +var tsvParseRows = tsv.parseRows; + +function autoType(object) { + for (var key in object) { + var value = object[key].trim(), number, m; + if (!value) value = null; + else if (value === "true") value = true; + else if (value === "false") value = false; + else if (value === "NaN") value = NaN; + else if (!isNaN(number = +value)) value = number; + else if (m = value.match(/^([-+]\d{2})?\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{3})?)?(Z|[-+]\d{2}:\d{2})?)?$/)) { + if (fixtz && !!m[4] && !m[7]) value = value.replace(/-/g, "/").replace(/T/, " "); + value = new Date(value); + } + else continue; + object[key] = value; + } + return object; +} + +// https://github.com/d3/d3-dsv/issues/45 +const fixtz = new Date("2019-01-01T00:00").getHours() || new Date("2019-07-01T00:00").getHours(); + +function dependency(name, version, main) { + return { + resolve(path = main) { + return `${name}@${version}/${path}`; + } + }; +} + +const d3 = dependency("d3", "7.6.1", "dist/d3.min.js"); +const inputs = dependency("@observablehq/inputs", "0.10.4", "dist/inputs.min.js"); +const plot = dependency("@observablehq/plot", "0.6.0", "dist/plot.umd.min.js"); +const graphviz = dependency("@observablehq/graphviz", "0.2.1", "dist/graphviz.min.js"); +const highlight = dependency("@observablehq/highlight.js", "2.0.0", "highlight.min.js"); +const katex = dependency("@observablehq/katex", "0.11.1", "dist/katex.min.js"); +const lodash = dependency("lodash", "4.17.21", "lodash.min.js"); +const htl = dependency("htl", "0.3.1", "dist/htl.min.js"); +const jszip = dependency("jszip", "3.10.0", "dist/jszip.min.js"); +const marked = dependency("marked", "0.3.12", "marked.min.js"); +const sql = dependency("sql.js", "1.7.0", "dist/sql-wasm.js"); +const vega = dependency("vega", "5.22.1", "build/vega.min.js"); +const vegalite = dependency("vega-lite", "5.5.0", "build/vega-lite.min.js"); +const vegaliteApi = dependency("vega-lite-api", "5.0.0", "build/vega-lite-api.min.js"); +const arrow4 = dependency("apache-arrow", "4.0.1", "Arrow.es2015.min.js"); +const arrow9 = dependency("apache-arrow", "9.0.0", "+esm"); +const arquero = dependency("arquero", "4.8.8", "dist/arquero.min.js"); +const topojson = dependency("topojson-client", "3.1.0", "dist/topojson-client.min.js"); +const exceljs = dependency("exceljs", "4.3.0", "dist/exceljs.min.js"); +const mermaid$1 = dependency("mermaid", "9.1.6", "dist/mermaid.min.js"); +const leaflet$1 = dependency("leaflet", "1.8.0", "dist/leaflet.js"); +const duckdb = dependency("@duckdb/duckdb-wasm", "1.17.0", "+esm"); + +const metas = new Map; +const queue$1 = []; +const map$2 = queue$1.map; +const some = queue$1.some; +const hasOwnProperty$2 = queue$1.hasOwnProperty; +const identifierRe = /^((?:@[^/@]+\/)?[^/@]+)(?:@([^/]+))?(?:\/(.*))?$/; +const versionRe = /^\d+\.\d+\.\d+(-[\w-.+]+)?$/; +const extensionRe = /(?:\.[^/]*|\/)$/; + +class RequireError extends Error { + constructor(message) { + super(message); + } +} + +RequireError.prototype.name = RequireError.name; + +function parseIdentifier(identifier) { + const match = identifierRe.exec(identifier); + return match && { + name: match[1], + version: match[2], + path: match[3] + }; +} + +function resolveFrom(origin = "https://cdn.jsdelivr.net/npm/", mains = ["unpkg", "jsdelivr", "browser", "main"]) { + if (!/\/$/.test(origin)) throw new Error("origin lacks trailing slash"); + + function main(meta) { + for (const key of mains) { + let value = meta[key]; + if (typeof value === "string") { + if (value.startsWith("./")) value = value.slice(2); + return extensionRe.test(value) ? value : `${value}.js`; + } + } + } + + function resolveMeta(target) { + const url = `${origin}${target.name}${target.version ? `@${target.version}` : ""}/package.json`; + let meta = metas.get(url); + if (!meta) metas.set(url, meta = fetch(url).then(response => { + if (!response.ok) throw new RequireError("unable to load package.json"); + if (response.redirected && !metas.has(response.url)) metas.set(response.url, meta); + return response.json(); + })); + return meta; + } + + return async function resolve(name, base) { + if (name.startsWith(origin)) name = name.substring(origin.length); + if (/^(\w+:)|\/\//i.test(name)) return name; + if (/^[.]{0,2}\//i.test(name)) return new URL(name, base == null ? location : base).href; + if (!name.length || /^[\s._]/.test(name) || /\s$/.test(name)) throw new RequireError("illegal name"); + const target = parseIdentifier(name); + if (!target) return `${origin}${name}`; + if (!target.version && base != null && base.startsWith(origin)) { + const meta = await resolveMeta(parseIdentifier(base.substring(origin.length))); + target.version = meta.dependencies && meta.dependencies[target.name] || meta.peerDependencies && meta.peerDependencies[target.name]; + } + if (target.path && !extensionRe.test(target.path)) target.path += ".js"; + if (target.path && target.version && versionRe.test(target.version)) return `${origin}${target.name}@${target.version}/${target.path}`; + const meta = await resolveMeta(target); + return `${origin}${meta.name}@${meta.version}/${target.path || main(meta) || "index.js"}`; + }; +} + +var require = requireFrom(resolveFrom()); +let requestsInFlight = 0; +let prevDefine = undefined; + +function requireFrom(resolver) { + const cache = new Map; + const requireBase = requireRelative(null); + + function requireAbsolute(url) { + if (typeof url !== "string") return url; + let module = cache.get(url); + if (!module) cache.set(url, module = new Promise((resolve, reject) => { + const script = document.createElement("script"); + script.onload = () => { + try { resolve(queue$1.pop()(requireRelative(url))); } + catch (error) { reject(new RequireError("invalid module")); } + script.remove(); + requestsInFlight--; + if (requestsInFlight === 0) { + window.define = prevDefine; + } + }; + script.onerror = () => { + reject(new RequireError("unable to load module")); + script.remove(); + requestsInFlight--; + if (requestsInFlight === 0) { + window.define = prevDefine; + } + }; + script.async = true; + script.src = url; + if (requestsInFlight === 0) { + prevDefine = window.define; + window.define = define; + } + requestsInFlight++; + + document.head.appendChild(script); + })); + return module; + } + + function requireRelative(base) { + return name => Promise.resolve(resolver(name, base)).then(requireAbsolute); + } + + function requireAlias(aliases) { + return requireFrom((name, base) => { + if (name in aliases) { + name = aliases[name], base = null; + if (typeof name !== "string") return name; + } + return resolver(name, base); + }); + } + + function require(name) { + return arguments.length > 1 + ? Promise.all(map$2.call(arguments, requireBase)).then(merge) + : requireBase(name); + } + + require.alias = requireAlias; + require.resolve = resolver; + + return require; +} + +function merge(modules) { + const o = {}; + for (const m of modules) { + for (const k in m) { + if (hasOwnProperty$2.call(m, k)) { + if (m[k] == null) Object.defineProperty(o, k, {get: getter(m, k)}); + else o[k] = m[k]; + } + } + } + return o; +} + +function getter(object, name) { + return () => object[name]; +} + +function isbuiltin(name) { + name = name + ""; + return name === "exports" || name === "module"; +} + +function define(name, dependencies, factory) { + const n = arguments.length; + if (n < 2) factory = name, dependencies = []; + else if (n < 3) factory = dependencies, dependencies = typeof name === "string" ? [] : name; + queue$1.push(some.call(dependencies, isbuiltin) ? require => { + const exports = {}; + const module = {exports}; + return Promise.all(map$2.call(dependencies, name => { + name = name + ""; + return name === "exports" ? exports : name === "module" ? module : require(name); + })).then(dependencies => { + factory.apply(null, dependencies); + return module.exports; + }); + } : require => { + return Promise.all(map$2.call(dependencies, require)).then(dependencies => { + return typeof factory === "function" ? factory.apply(null, dependencies) : factory; + }); + }); +} + +define.amd = {}; + +// TODO Allow this to be overridden using the Library’s resolver. +const cdn = "https://cdn.observableusercontent.com/npm/"; + +let requireDefault = require; + +function setDefaultRequire(require) { + requireDefault = require; +} + +function requirer(resolver) { + return resolver == null ? requireDefault : requireFrom(resolver); +} + +function fromEntries(obj) { + const result = {}; + for (const [key, value] of obj) { + result[key] = value; + } + return result; +} + +async function SQLite(require) { + const [init, dist] = await Promise.all([require(sql.resolve()), require.resolve(sql.resolve("dist/"))]); + return init({locateFile: file => `${dist}${file}`}); +} + +class SQLiteDatabaseClient { + constructor(db) { + Object.defineProperties(this, { + _db: {value: db} + }); + } + static async open(source) { + const [SQL, buffer] = await Promise.all([SQLite(requireDefault), Promise.resolve(source).then(load$1)]); + return new SQLiteDatabaseClient(new SQL.Database(buffer)); + } + async query(query, params) { + return await exec(this._db, query, params); + } + async queryRow(query, params) { + return (await this.query(query, params))[0] || null; + } + async explain(query, params) { + const rows = await this.query(`EXPLAIN QUERY PLAN ${query}`, params); + return element$1("pre", {className: "observablehq--inspect"}, [ + text$2(rows.map(row => row.detail).join("\n")) + ]); + } + async describeTables({schema} = {}) { + return this.query(`SELECT NULLIF(schema, 'main') AS schema, name FROM pragma_table_list() WHERE type = 'table'${schema == null ? "" : ` AND schema = ?`} AND name NOT LIKE 'sqlite_%'`, schema == null ? [] : [schema]); + } + async describeColumns({schema, table} = {}) { + if (table == null) throw new Error(`missing table`); + const rows = await this.query(`SELECT name, type, "notnull" FROM pragma_table_info(?${schema == null ? "" : `, ?`}) ORDER BY cid`, schema == null ? [table] : [table, schema]); + if (!rows.length) throw new Error(`table not found: ${table}`); + return rows.map(({name, type, notnull}) => ({name, type: sqliteType(type), databaseType: type, nullable: !notnull})); + } + async describe(object) { + const rows = await (object === undefined + ? this.query(`SELECT name FROM sqlite_master WHERE type = 'table'`) + : this.query(`SELECT * FROM pragma_table_info(?)`, [object])); + if (!rows.length) throw new Error("Not found"); + const {columns} = rows; + return element$1("table", {value: rows}, [ + element$1("thead", [element$1("tr", columns.map(c => element$1("th", [text$2(c)])))]), + element$1("tbody", rows.map(r => element$1("tr", columns.map(c => element$1("td", [text$2(r[c])]))))) + ]); + } + async sql() { + return this.query(...this.queryTag.apply(this, arguments)); + } + queryTag(strings, ...params) { + return [strings.join("?"), params]; + } +} + +Object.defineProperty(SQLiteDatabaseClient.prototype, "dialect", { + value: "sqlite" +}); + +// https://www.sqlite.org/datatype3.html +function sqliteType(type) { + switch (type) { + case "NULL": + return "null"; + case "INT": + case "INTEGER": + case "TINYINT": + case "SMALLINT": + case "MEDIUMINT": + case "BIGINT": + case "UNSIGNED BIG INT": + case "INT2": + case "INT8": + return "integer"; + case "TEXT": + case "CLOB": + return "string"; + case "REAL": + case "DOUBLE": + case "DOUBLE PRECISION": + case "FLOAT": + case "NUMERIC": + return "number"; + case "BLOB": + return "buffer"; + case "DATE": + case "DATETIME": + return "string"; // TODO convert strings to Date instances in sql.js + default: + return /^(?:(?:(?:VARYING|NATIVE) )?CHARACTER|(?:N|VAR|NVAR)CHAR)\(/.test(type) ? "string" + : /^(?:DECIMAL|NUMERIC)\(/.test(type) ? "number" + : "other"; + } +} + +function load$1(source) { + return typeof source === "string" ? fetch(source).then(load$1) + : source instanceof Response || source instanceof Blob ? source.arrayBuffer().then(load$1) + : source instanceof ArrayBuffer ? new Uint8Array(source) + : source; +} + +async function exec(db, query, params) { + const [result] = await db.exec(query, params); + if (!result) return []; + const {columns, values} = result; + const rows = values.map(row => fromEntries(row.map((value, i) => [columns[i], value]))); + rows.columns = columns; + return rows; +} + +function element$1(name, props, children) { + if (arguments.length === 2) children = props, props = undefined; + const element = document.createElement(name); + if (props !== undefined) for (const p in props) element[p] = props[p]; + if (children !== undefined) for (const c of children) element.appendChild(c); + return element; +} + +function text$2(value) { + return document.createTextNode(value); +} + +class Workbook { + constructor(workbook) { + Object.defineProperties(this, { + _: {value: workbook}, + sheetNames: { + value: workbook.worksheets.map((s) => s.name), + enumerable: true + } + }); + } + sheet(name, options) { + const sname = + typeof name === "number" + ? this.sheetNames[name] + : this.sheetNames.includes((name += "")) + ? name + : null; + if (sname == null) throw new Error(`Sheet not found: ${name}`); + const sheet = this._.getWorksheet(sname); + return extract(sheet, options); + } +} + +function extract(sheet, {range, headers} = {}) { + let [[c0, r0], [c1, r1]] = parseRange(range, sheet); + const headerRow = headers ? sheet._rows[r0++] : null; + let names = new Set(["#"]); + for (let n = c0; n <= c1; n++) { + const value = headerRow ? valueOf(headerRow.findCell(n + 1)) : null; + let name = (value && value + "") || toColumn(n); + while (names.has(name)) name += "_"; + names.add(name); + } + names = new Array(c0).concat(Array.from(names)); + + const output = new Array(r1 - r0 + 1); + for (let r = r0; r <= r1; r++) { + const row = (output[r - r0] = Object.create(null, {"#": {value: r + 1}})); + const _row = sheet.getRow(r + 1); + if (_row.hasValues) + for (let c = c0; c <= c1; c++) { + const value = valueOf(_row.findCell(c + 1)); + if (value != null) row[names[c + 1]] = value; + } + } + + output.columns = names.filter(() => true); // Filter sparse columns + return output; +} + +function valueOf(cell) { + if (!cell) return; + const {value} = cell; + if (value && typeof value === "object" && !(value instanceof Date)) { + if (value.formula || value.sharedFormula) { + return value.result && value.result.error ? NaN : value.result; + } + if (value.richText) { + return richText(value); + } + if (value.text) { + let {text} = value; + if (text.richText) text = richText(text); + return value.hyperlink && value.hyperlink !== text + ? `${value.hyperlink} ${text}` + : text; + } + return value; + } + return value; +} + +function richText(value) { + return value.richText.map((d) => d.text).join(""); +} + +function parseRange(specifier = ":", {columnCount, rowCount}) { + specifier += ""; + if (!specifier.match(/^[A-Z]*\d*:[A-Z]*\d*$/)) + throw new Error("Malformed range specifier"); + const [[c0 = 0, r0 = 0], [c1 = columnCount - 1, r1 = rowCount - 1]] = + specifier.split(":").map(fromCellReference); + return [ + [c0, r0], + [c1, r1] + ]; +} + +// Returns the default column name for a zero-based column index. +// For example: 0 -> "A", 1 -> "B", 25 -> "Z", 26 -> "AA", 27 -> "AB". +function toColumn(c) { + let sc = ""; + c++; + do { + sc = String.fromCharCode(64 + (c % 26 || 26)) + sc; + } while ((c = Math.floor((c - 1) / 26))); + return sc; +} + +// Returns the zero-based indexes from a cell reference. +// For example: "A1" -> [0, 0], "B2" -> [1, 1], "AA10" -> [26, 9]. +function fromCellReference(s) { + const [, sc, sr] = s.match(/^([A-Z]*)(\d*)$/); + let c = 0; + if (sc) + for (let i = 0; i < sc.length; i++) + c += Math.pow(26, sc.length - i - 1) * (sc.charCodeAt(i) - 64); + return [c ? c - 1 : undefined, sr ? +sr - 1 : undefined]; +} + +async function remote_fetch(file) { + const response = await fetch(await file.url()); + if (!response.ok) throw new Error(`Unable to load file: ${file.name}`); + return response; +} + +async function dsv(file, delimiter, {array = false, typed = false} = {}) { + const text = await file.text(); + return (delimiter === "\t" + ? (array ? tsvParseRows : tsvParse) + : (array ? csvParseRows : csvParse))(text, typed && autoType); +} + +class AbstractFile { + constructor(name, mimeType) { + Object.defineProperty(this, "name", {value: name, enumerable: true}); + if (mimeType !== undefined) Object.defineProperty(this, "mimeType", {value: mimeType + "", enumerable: true}); + } + async blob() { + return (await remote_fetch(this)).blob(); + } + async arrayBuffer() { + return (await remote_fetch(this)).arrayBuffer(); + } + async text() { + return (await remote_fetch(this)).text(); + } + async json() { + return (await remote_fetch(this)).json(); + } + async stream() { + return (await remote_fetch(this)).body; + } + async csv(options) { + return dsv(this, ",", options); + } + async tsv(options) { + return dsv(this, "\t", options); + } + async image(props) { + const url = await this.url(); + return new Promise((resolve, reject) => { + const i = new Image(); + if (new URL(url, document.baseURI).origin !== new URL(location).origin) { + i.crossOrigin = "anonymous"; + } + Object.assign(i, props); + i.onload = () => resolve(i); + i.onerror = () => reject(new Error(`Unable to load file: ${this.name}`)); + i.src = url; + }); + } + async arrow({version = 4} = {}) { + switch (version) { + case 4: { + const [Arrow, response] = await Promise.all([requireDefault(arrow4.resolve()), remote_fetch(this)]); + return Arrow.Table.from(response); + } + case 9: { + const [Arrow, response] = await Promise.all([import(`${cdn}${arrow9.resolve()}`), remote_fetch(this)]); + return Arrow.tableFromIPC(response); + } + default: throw new Error(`unsupported arrow version: ${version}`); + } + } + async sqlite() { + return SQLiteDatabaseClient.open(remote_fetch(this)); + } + async zip() { + const [JSZip, buffer] = await Promise.all([requireDefault(jszip.resolve()), this.arrayBuffer()]); + return new ZipArchive(await JSZip.loadAsync(buffer)); + } + async xml(mimeType = "application/xml") { + return (new DOMParser).parseFromString(await this.text(), mimeType); + } + async html() { + return this.xml("text/html"); + } + async xlsx() { + const [ExcelJS, buffer] = await Promise.all([requireDefault(exceljs.resolve()), this.arrayBuffer()]); + return new Workbook(await new ExcelJS.Workbook().xlsx.load(buffer)); + } +} + +class FileAttachment extends AbstractFile { + constructor(url, name, mimeType) { + super(name, mimeType); + Object.defineProperty(this, "_url", {value: url}); + } + async url() { + return (await this._url) + ""; + } +} + +function NoFileAttachments(name) { + throw new Error(`File not found: ${name}`); +} + +function FileAttachments(resolve) { + return Object.assign( + name => { + const result = resolve(name += ""); + if (result == null) throw new Error(`File not found: ${name}`); + if (typeof result === "object" && "url" in result) { + const {url, mimeType} = result; + return new FileAttachment(url, name, mimeType); + } + return new FileAttachment(result, name); + }, + {prototype: FileAttachment.prototype} // instanceof + ); +} + +class ZipArchive { + constructor(archive) { + Object.defineProperty(this, "_", {value: archive}); + this.filenames = Object.keys(archive.files).filter(name => !archive.files[name].dir); + } + file(path) { + const object = this._.file(path += ""); + if (!object || object.dir) throw new Error(`file not found: ${path}`); + return new ZipArchiveEntry(object); + } +} + +class ZipArchiveEntry extends AbstractFile { + constructor(object) { + super(object.name); + Object.defineProperty(this, "_", {value: object}); + Object.defineProperty(this, "_url", {writable: true}); + } + async url() { + return this._url || (this._url = this.blob().then(URL.createObjectURL)); + } + async blob() { + return this._.async("blob"); + } + async arrayBuffer() { + return this._.async("arraybuffer"); + } + async text() { + return this._.async("text"); + } + async json() { + return JSON.parse(await this.text()); + } +} + +function canvas(width, height) { + var canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + return canvas; +} + +function context2d(width, height, dpi) { + if (dpi == null) dpi = devicePixelRatio; + var canvas = document.createElement("canvas"); + canvas.width = width * dpi; + canvas.height = height * dpi; + canvas.style.width = width + "px"; + var context = canvas.getContext("2d"); + context.scale(dpi, dpi); + return context; +} + +function download(value, name = "untitled", label = "Save") { + const a = document.createElement("a"); + const b = a.appendChild(document.createElement("button")); + b.textContent = label; + a.download = name; + + async function reset() { + await new Promise(requestAnimationFrame); + URL.revokeObjectURL(a.href); + a.removeAttribute("href"); + b.textContent = label; + b.disabled = false; + } + + a.onclick = async event => { + b.disabled = true; + if (a.href) return reset(); // Already saved. + b.textContent = "Saving…"; + try { + const object = await (typeof value === "function" ? value() : value); + b.textContent = "Download"; + a.href = URL.createObjectURL(object); // eslint-disable-line require-atomic-updates + } catch (ignore) { + b.textContent = label; + } + if (event.eventPhase) return reset(); // Already downloaded. + b.disabled = false; + }; + + return a; +} + +var namespaces = { + math: "http://www.w3.org/1998/Math/MathML", + svg: "http://www.w3.org/2000/svg", + xhtml: "http://www.w3.org/1999/xhtml", + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" +}; + +function element(name, attributes) { + var prefix = name += "", i = prefix.indexOf(":"), value; + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + var element = namespaces.hasOwnProperty(prefix) // eslint-disable-line no-prototype-builtins + ? document.createElementNS(namespaces[prefix], name) + : document.createElement(name); + if (attributes) for (var key in attributes) { + prefix = key, i = prefix.indexOf(":"), value = attributes[key]; + if (i >= 0 && (prefix = key.slice(0, i)) !== "xmlns") key = key.slice(i + 1); + if (namespaces.hasOwnProperty(prefix)) element.setAttributeNS(namespaces[prefix], key, value); // eslint-disable-line no-prototype-builtins + else element.setAttribute(key, value); + } + return element; +} + +function input$1(type) { + var input = document.createElement("input"); + if (type != null) input.type = type; + return input; +} + +function range$1(min, max, step) { + if (arguments.length === 1) max = min, min = null; + var input = document.createElement("input"); + input.min = min = min == null ? 0 : +min; + input.max = max = max == null ? 1 : +max; + input.step = step == null ? "any" : step = +step; + input.type = "range"; + return input; +} + +function select(values) { + var select = document.createElement("select"); + Array.prototype.forEach.call(values, function(value) { + var option = document.createElement("option"); + option.value = option.textContent = value; + select.appendChild(option); + }); + return select; +} + +function svg$1(width, height) { + var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.setAttribute("viewBox", [0, 0, width, height]); + svg.setAttribute("width", width); + svg.setAttribute("height", height); + return svg; +} + +function text$1(value) { + return document.createTextNode(value); +} + +var count$1 = 0; + +function uid(name) { + return new Id("O-" + (name == null ? "" : name + "-") + ++count$1); +} + +function Id(id) { + this.id = id; + this.href = new URL(`#${id}`, location) + ""; +} + +Id.prototype.toString = function() { + return "url(" + this.href + ")"; +}; + +var DOM = /*#__PURE__*/Object.freeze({ +__proto__: null, +canvas: canvas, +context2d: context2d, +download: download, +element: element, +input: input$1, +range: range$1, +select: select, +svg: svg$1, +text: text$1, +uid: uid +}); + +function buffer(file) { + return new Promise(function(resolve, reject) { + var reader = new FileReader; + reader.onload = function() { resolve(reader.result); }; + reader.onerror = reject; + reader.readAsArrayBuffer(file); + }); +} + +function text(file) { + return new Promise(function(resolve, reject) { + var reader = new FileReader; + reader.onload = function() { resolve(reader.result); }; + reader.onerror = reject; + reader.readAsText(file); + }); +} + +function url(file) { + return new Promise(function(resolve, reject) { + var reader = new FileReader; + reader.onload = function() { resolve(reader.result); }; + reader.onerror = reject; + reader.readAsDataURL(file); + }); +} + +var Files = /*#__PURE__*/Object.freeze({ +__proto__: null, +buffer: buffer, +text: text, +url: url +}); + +function that() { + return this; +} + +function disposable(value, dispose) { + let done = false; + if (typeof dispose !== "function") { + throw new Error("dispose is not a function"); + } + return { + [Symbol.iterator]: that, + next: () => done ? {done: true} : (done = true, {done: false, value}), + return: () => (done = true, dispose(value), {done: true}), + throw: () => ({done: done = true}) + }; +} + +function* filter(iterator, test) { + var result, index = -1; + while (!(result = iterator.next()).done) { + if (test(result.value, ++index)) { + yield result.value; + } + } +} + +function observe(initialize) { + let stale = false; + let value; + let resolve; + const dispose = initialize(change); + + if (dispose != null && typeof dispose !== "function") { + throw new Error(typeof dispose.then === "function" + ? "async initializers are not supported" + : "initializer returned something, but not a dispose function"); + } + + function change(x) { + if (resolve) resolve(x), resolve = null; + else stale = true; + return value = x; + } + + function next() { + return {done: false, value: stale + ? (stale = false, Promise.resolve(value)) + : new Promise(_ => (resolve = _))}; + } + + return { + [Symbol.iterator]: that, + throw: () => ({done: true}), + return: () => (dispose != null && dispose(), {done: true}), + next + }; +} + +function input(input) { + return observe(function(change) { + var event = eventof(input), value = valueof$1(input); + function inputted() { change(valueof$1(input)); } + input.addEventListener(event, inputted); + if (value !== undefined) change(value); + return function() { input.removeEventListener(event, inputted); }; + }); +} + +function valueof$1(input) { + switch (input.type) { + case "range": + case "number": return input.valueAsNumber; + case "date": return input.valueAsDate; + case "checkbox": return input.checked; + case "file": return input.multiple ? input.files : input.files[0]; + case "select-multiple": return Array.from(input.selectedOptions, o => o.value); + default: return input.value; + } +} + +function eventof(input) { + switch (input.type) { + case "button": + case "submit": + case "checkbox": return "click"; + case "file": return "change"; + default: return "input"; + } +} + +function* map$1(iterator, transform) { + var result, index = -1; + while (!(result = iterator.next()).done) { + yield transform(result.value, ++index); + } +} + +function queue(initialize) { + let resolve; + const queue = []; + const dispose = initialize(push); + + if (dispose != null && typeof dispose !== "function") { + throw new Error(typeof dispose.then === "function" + ? "async initializers are not supported" + : "initializer returned something, but not a dispose function"); + } + + function push(x) { + queue.push(x); + if (resolve) resolve(queue.shift()), resolve = null; + return x; + } + + function next() { + return {done: false, value: queue.length + ? Promise.resolve(queue.shift()) + : new Promise(_ => (resolve = _))}; + } + + return { + [Symbol.iterator]: that, + throw: () => ({done: true}), + return: () => (dispose != null && dispose(), {done: true}), + next + }; +} + +function* range(start, stop, step) { + start = +start; + stop = +stop; + step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; + var i = -1, n = Math.max(0, Math.ceil((stop - start) / step)) | 0; + while (++i < n) { + yield start + i * step; + } +} + +function valueAt(iterator, i) { + if (!isFinite(i = +i) || i < 0 || i !== i | 0) return; + var result, index = -1; + while (!(result = iterator.next()).done) { + if (++index === i) { + return result.value; + } + } +} + +function worker(source) { + const url = URL.createObjectURL(new Blob([source], {type: "text/javascript"})); + const worker = new Worker(url); + return disposable(worker, () => { + worker.terminate(); + URL.revokeObjectURL(url); + }); +} + +var Generators$1 = /*#__PURE__*/Object.freeze({ +__proto__: null, +disposable: disposable, +filter: filter, +input: input, +map: map$1, +observe: observe, +queue: queue, +range: range, +valueAt: valueAt, +worker: worker +}); + +// Returns true if the vaue is an Apache Arrow table. This uses a “duck” test +// (instead of strict instanceof) because we want it to work with a range of +// Apache Arrow versions at least 7.0.0 or above. +// https://arrow.apache.org/docs/7.0/js/classes/Arrow_dom.Table.html +function isArrowTable(value) { + return ( + value && + typeof value.getChild === "function" && + typeof value.toArray === "function" && + value.schema && + Array.isArray(value.schema.fields) + ); +} + +function getArrowTableSchema(table) { + return table.schema.fields.map(getArrowFieldSchema); +} + +function getArrowFieldSchema(field) { + return { + name: field.name, + type: getArrowType(field.type), + nullable: field.nullable, + databaseType: String(field.type) + }; +} + +// https://github.com/apache/arrow/blob/89f9a0948961f6e94f1ef5e4f310b707d22a3c11/js/src/enum.ts#L140-L141 +function getArrowType(type) { + switch (type.typeId) { + case 2: // Int + return "integer"; + case 3: // Float + case 7: // Decimal + return "number"; + case 4: // Binary + case 15: // FixedSizeBinary + return "buffer"; + case 5: // Utf8 + return "string"; + case 6: // Bool + return "boolean"; + case 8: // Date + case 9: // Time + case 10: // Timestamp + return "date"; + case 12: // List + case 16: // FixedSizeList + return "array"; + case 13: // Struct + case 14: // Union + return "object"; + case 11: // Interval + case 17: // Map + default: + return "other"; + } +} + +// Adapted from https://observablehq.com/@cmudig/duckdb-client +// Copyright 2021 CMU Data Interaction Group +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +class DuckDBClient { + constructor(db) { + Object.defineProperties(this, { + _db: {value: db} + }); + } + + async queryStream(query, params) { + const connection = await this._db.connect(); + let reader, batch; + try { + if (params?.length > 0) { + const statement = await connection.prepare(query); + reader = await statement.send(...params); + } else { + reader = await connection.send(query); + } + batch = await reader.next(); + if (batch.done) throw new Error("missing first batch"); + } catch (error) { + await connection.close(); + throw error; + } + return { + schema: getArrowTableSchema(batch.value), + async *readRows() { + try { + while (!batch.done) { + yield batch.value.toArray(); + batch = await reader.next(); + } + } finally { + await connection.close(); + } + } + }; + } + + async query(query, params) { + const result = await this.queryStream(query, params); + const results = []; + for await (const rows of result.readRows()) { + for (const row of rows) { + results.push(row); + } + } + results.schema = result.schema; + return results; + } + + async queryRow(query, params) { + const result = await this.queryStream(query, params); + const reader = result.readRows(); + try { + const {done, value} = await reader.next(); + return done || !value.length ? null : value[0]; + } finally { + await reader.return(); + } + } + + async sql(strings, ...args) { + return await this.query(strings.join("?"), args); + } + + queryTag(strings, ...params) { + return [strings.join("?"), params]; + } + + escape(name) { + return `"${name}"`; + } + + async describeTables() { + const tables = await this.query(`SHOW TABLES`); + return tables.map(({name}) => ({name})); + } + + async describeColumns({table} = {}) { + const columns = await this.query(`DESCRIBE ${table}`); + return columns.map(({column_name, column_type, null: nullable}) => ({ + name: column_name, + type: getDuckDBType(column_type), + nullable: nullable !== "NO", + databaseType: column_type + })); + } + + static async of(sources = {}, config = {}) { + const db = await createDuckDB(); + if (config.query?.castTimestampToDate === undefined) { + config = {...config, query: {...config.query, castTimestampToDate: true}}; + } + await db.open(config); + await Promise.all( + Object.entries(sources).map(async ([name, source]) => { + if (source instanceof FileAttachment) { // bare file + await insertFile(db, name, source); + } else if (isArrowTable(source)) { // bare arrow table + await insertArrowTable(db, name, source); + } else if (Array.isArray(source)) { // bare array of objects + await insertArray(db, name, source); + } else if ("data" in source) { // data + options + const {data, ...options} = source; + if (isArrowTable(data)) { + await insertArrowTable(db, name, data, options); + } else { + await insertArray(db, name, data, options); + } + } else if ("file" in source) { // file + options + const {file, ...options} = source; + await insertFile(db, name, file, options); + } else { + throw new Error(`invalid source: ${source}`); + } + }) + ); + return new DuckDBClient(db); + } +} + +Object.defineProperty(DuckDBClient.prototype, "dialect", { + value: "duckdb" +}); + +async function insertFile(database, name, file, options) { + const url = await file.url(); + if (url.startsWith("blob:")) { + const buffer = await file.arrayBuffer(); + await database.registerFileBuffer(file.name, new Uint8Array(buffer)); + } else { + await database.registerFileURL(file.name, url); + } + const connection = await database.connect(); + try { + switch (file.mimeType) { + case "text/csv": + return await connection.insertCSVFromPath(file.name, { + name, + schema: "main", + ...options + }); + case "application/json": + return await connection.insertJSONFromPath(file.name, { + name, + schema: "main", + ...options + }); + default: + if (/\.arrow$/i.test(file.name)) { + const buffer = new Uint8Array(await file.arrayBuffer()); + return await connection.insertArrowFromIPCStream(buffer, { + name, + schema: "main", + ...options + }); + } + if (/\.parquet$/i.test(file.name)) { + return await connection.query( + `CREATE VIEW '${name}' AS SELECT * FROM parquet_scan('${file.name}')` + ); + } + throw new Error(`unknown file type: ${file.mimeType}`); + } + } finally { + await connection.close(); + } +} + +async function insertArrowTable(database, name, table, options) { + const arrow = await loadArrow(); + const buffer = arrow.tableToIPC(table); + const connection = await database.connect(); + try { + await connection.insertArrowFromIPCStream(buffer, { + name, + schema: "main", + ...options + }); + } finally { + await connection.close(); + } +} + +async function insertArray(database, name, array, options) { + const arrow = await loadArrow(); + const table = arrow.tableFromJSON(array); + return await insertArrowTable(database, name, table, options); +} + +async function createDuckDB() { + const duck = await import(`${cdn}${duckdb.resolve()}`); + const bundle = await duck.selectBundle({ + mvp: { + mainModule: `${cdn}${duckdb.resolve("dist/duckdb-mvp.wasm")}`, + mainWorker: `${cdn}${duckdb.resolve("dist/duckdb-browser-mvp.worker.js")}` + }, + eh: { + mainModule: `${cdn}${duckdb.resolve("dist/duckdb-eh.wasm")}`, + mainWorker: `${cdn}${duckdb.resolve("dist/duckdb-browser-eh.worker.js")}` + } + }); + const logger = new duck.ConsoleLogger(); + const worker = await duck.createWorker(bundle.mainWorker); + const db = new duck.AsyncDuckDB(logger, worker); + await db.instantiate(bundle.mainModule); + return db; +} + +async function loadArrow() { + return await import(`${cdn}${arrow9.resolve()}`); +} + +// https://duckdb.org/docs/sql/data_types/overview +function getDuckDBType(type) { + switch (type) { + case "BIGINT": + case "HUGEINT": + case "UBIGINT": + return "bigint"; + case "DOUBLE": + case "REAL": + return "number"; + case "INTEGER": + case "SMALLINT": + case "TINYINT": + case "USMALLINT": + case "UINTEGER": + case "UTINYINT": + return "integer"; + case "BOOLEAN": + return "boolean"; + case "DATE": + case "TIMESTAMP": + case "TIMESTAMP WITH TIME ZONE": + return "date"; + case "VARCHAR": + case "UUID": + return "string"; + // case "BLOB": + // case "INTERVAL": + // case "TIME": + default: + if (/^DECIMAL\(/.test(type)) return "integer"; + return "other"; + } +} + +function template(render, wrapper) { + return function(strings) { + var string = strings[0], + parts = [], part, + root = null, + node, nodes, + walker, + i, n, j, m, k = -1; + + // Concatenate the text using comments as placeholders. + for (i = 1, n = arguments.length; i < n; ++i) { + part = arguments[i]; + if (part instanceof Node) { + parts[++k] = part; + string += ""; + } else if (Array.isArray(part)) { + for (j = 0, m = part.length; j < m; ++j) { + node = part[j]; + if (node instanceof Node) { + if (root === null) { + parts[++k] = root = document.createDocumentFragment(); + string += ""; + } + root.appendChild(node); + } else { + root = null; + string += node; + } + } + root = null; + } else { + string += part; + } + string += strings[i]; + } + + // Render the text. + root = render(string); + + // Walk the rendered content to replace comment placeholders. + if (++k > 0) { + nodes = new Array(k); + walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT, null, false); + while (walker.nextNode()) { + node = walker.currentNode; + if (/^o:/.test(node.nodeValue)) { + nodes[+node.nodeValue.slice(2)] = node; + } + } + for (i = 0; i < k; ++i) { + if (node = nodes[i]) { + node.parentNode.replaceChild(parts[i], node); + } + } + } + + // Is the rendered content + // … a parent of a single child? Detach and return the child. + // … a document fragment? Replace the fragment with an element. + // … some other node? Return it. + return root.childNodes.length === 1 ? root.removeChild(root.firstChild) + : root.nodeType === 11 ? ((node = wrapper()).appendChild(root), node) + : root; + }; +} + +const html$1 = template(function(string) { + var template = document.createElement("template"); + template.innerHTML = string.trim(); + return document.importNode(template.content, true); +}, function() { + return document.createElement("span"); +}); + +async function leaflet(require) { + const L = await require(leaflet$1.resolve()); + if (!L._style) { + const link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = await require.resolve(leaflet$1.resolve("dist/leaflet.css")); + L._style = document.head.appendChild(link); + } + return L; +} + +function md(require) { + return require(marked.resolve()).then(function(marked) { + return template( + function(string) { + var root = document.createElement("div"); + root.innerHTML = marked(string, {langPrefix: ""}).trim(); + var code = root.querySelectorAll("pre code[class]"); + if (code.length > 0) { + require(highlight.resolve()).then(function(hl) { + code.forEach(function(block) { + function done() { + hl.highlightBlock(block); + block.parentNode.classList.add("observablehq--md-pre"); + } + if (hl.getLanguage(block.className)) { + done(); + } else { + require(highlight.resolve("async-languages/index.js")) + .then(index => { + if (index.has(block.className)) { + return require(highlight.resolve("async-languages/" + index.get(block.className))).then(language => { + hl.registerLanguage(block.className, language); + }); + } + }) + .then(done, done); + } + }); + }); + } + return root; + }, + function() { + return document.createElement("div"); + } + ); + }); +} + +async function mermaid(require) { + const mer = await require(mermaid$1.resolve()); + mer.initialize({securityLevel: "loose", theme: "neutral"}); + return function mermaid() { + const root = document.createElement("div"); + root.innerHTML = mer.render(uid().id, String.raw.apply(String, arguments)); + return root.removeChild(root.firstChild); + }; +} + +function Mutable(value) { + let change; + Object.defineProperties(this, { + generator: {value: observe(_ => void (change = _))}, + value: {get: () => value, set: x => change(value = x)} // eslint-disable-line no-setter-return + }); + if (value !== undefined) change(value); +} + +function* now() { + while (true) { + yield Date.now(); + } +} + +function delay(duration, value) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(value); + }, duration); + }); +} + +var timeouts = new Map; + +function timeout(now, time) { + var t = new Promise(function(resolve) { + timeouts.delete(time); + var delay = time - now; + if (!(delay > 0)) throw new Error("invalid time"); + if (delay > 0x7fffffff) throw new Error("too long to wait"); + setTimeout(resolve, delay); + }); + timeouts.set(time, t); + return t; +} + +function when(time, value) { + var now; + return (now = timeouts.get(time = +time)) ? now.then(() => value) + : (now = Date.now()) >= time ? Promise.resolve(value) + : timeout(now, time).then(() => value); +} + +function tick(duration, value) { + return when(Math.ceil((Date.now() + 1) / duration) * duration, value); +} + +var Promises = /*#__PURE__*/Object.freeze({ +__proto__: null, +delay: delay, +tick: tick, +when: when +}); + +function resolve(name, base) { + if (/^(\w+:)|\/\//i.test(name)) return name; + if (/^[.]{0,2}\//i.test(name)) return new URL(name, base == null ? location : base).href; + if (!name.length || /^[\s._]/.test(name) || /\s$/.test(name)) throw new Error("illegal name"); + return "https://unpkg.com/" + name; +} + +const svg = template(function(string) { + var root = document.createElementNS("http://www.w3.org/2000/svg", "g"); + root.innerHTML = string.trim(); + return root; +}, function() { + return document.createElementNS("http://www.w3.org/2000/svg", "g"); +}); + +var raw = String.raw; + +function style(href) { + return new Promise(function(resolve, reject) { + var link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = href; + link.onerror = reject; + link.onload = resolve; + document.head.appendChild(link); + }); +} + +function tex(require) { + return Promise.all([ + require(katex.resolve()), + require.resolve(katex.resolve("dist/katex.min.css")).then(style) + ]).then(function(values) { + var katex = values[0], tex = renderer(); + + function renderer(options) { + return function() { + var root = document.createElement("div"); + katex.render(raw.apply(String, arguments), root, options); + return root.removeChild(root.firstChild); + }; + } + + tex.options = renderer; + tex.block = renderer({displayMode: true}); + return tex; + }); +} + +async function vl(require) { + const [v, vl, api] = await Promise.all([vega, vegalite, vegaliteApi].map(d => require(d.resolve()))); + return api.register(v, vl); +} + +function width() { + return observe(function(change) { + var width = change(document.body.clientWidth); + function resized() { + var w = document.body.clientWidth; + if (w !== width) change(width = w); + } + window.addEventListener("resize", resized); + return function() { + window.removeEventListener("resize", resized); + }; + }); +} + +function ascending(a, b) { + return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +} + +function descending(a, b) { + return a == null || b == null ? NaN + : b < a ? -1 + : b > a ? 1 + : b >= a ? 0 + : NaN; +} + +function bisector(f) { + let compare1, compare2, delta; + + // If an accessor is specified, promote it to a comparator. In this case we + // can test whether the search value is (self-) comparable. We can’t do this + // for a comparator (except for specific, known comparators) because we can’t + // tell if the comparator is symmetric, and an asymmetric comparator can’t be + // used to test whether a single value is comparable. + if (f.length !== 2) { + compare1 = ascending; + compare2 = (d, x) => ascending(f(d), x); + delta = (d, x) => f(d) - x; + } else { + compare1 = f === ascending || f === descending ? f : zero; + compare2 = f; + delta = f; + } + + function left(a, x, lo = 0, hi = a.length) { + if (lo < hi) { + if (compare1(x, x) !== 0) return hi; + do { + const mid = (lo + hi) >>> 1; + if (compare2(a[mid], x) < 0) lo = mid + 1; + else hi = mid; + } while (lo < hi); + } + return lo; + } + + function right(a, x, lo = 0, hi = a.length) { + if (lo < hi) { + if (compare1(x, x) !== 0) return hi; + do { + const mid = (lo + hi) >>> 1; + if (compare2(a[mid], x) <= 0) lo = mid + 1; + else hi = mid; + } while (lo < hi); + } + return lo; + } + + function center(a, x, lo = 0, hi = a.length) { + const i = left(a, x, lo, hi - 1); + return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i; + } + + return {left, center, right}; +} + +function zero() { + return 0; +} + +function number(x) { + return x === null ? NaN : +x; +} + +bisector(ascending); +bisector(number).center; + +function reverse(values) { + if (typeof values[Symbol.iterator] !== "function") throw new TypeError("values is not iterable"); + return Array.from(values).reverse(); +} + +const nChecks = 20; // number of values to check in each array + +// We support two levels of DatabaseClient. The simplest DatabaseClient +// implements only the client.sql tagged template literal. More advanced +// DatabaseClients implement client.query and client.queryStream, which support +// streaming and abort, and the client.queryTag tagged template literal is used +// to translate the contents of a SQL cell or Table cell into the appropriate +// arguments for calling client.query or client.queryStream. For table cells, we +// additionally require client.describeColumns. The client.describeTables method +// is optional. +function isDatabaseClient(value, mode) { + return ( + value && + (typeof value.sql === "function" || + (typeof value.queryTag === "function" && + (typeof value.query === "function" || + typeof value.queryStream === "function"))) && + (mode !== "table" || typeof value.describeColumns === "function") && + value !== __query // don’t match our internal helper + ); +} + +// Returns true if the value is a typed array (for a single-column table), or if +// it’s an array. In the latter case, the elements of the array must be +// consistently typed: either plain objects or primitives or dates. +function isDataArray(value) { + return ( + (Array.isArray(value) && + (isQueryResultSetSchema(value.schema) || + isQueryResultSetColumns(value.columns) || + arrayContainsObjects(value) || + arrayContainsPrimitives(value) || + arrayContainsDates(value))) || + isTypedArray(value) + ); +} + +// Given an array, checks that the given value is an array that does not contain +// any primitive values (at least for the first few values that we check), and +// that the first object contains enumerable keys (see computeSchema for how we +// infer the columns). We assume that the contents of the table are homogenous, +// but we don’t currently enforce this. +// https://observablehq.com/@observablehq/database-client-specification#§1 +function arrayContainsObjects(value) { + const n = Math.min(nChecks, value.length); + for (let i = 0; i < n; ++i) { + const v = value[i]; + if (v === null || typeof v !== "object") return false; + } + return n > 0 && objectHasEnumerableKeys(value[0]); +} + +// Using a for-in loop here means that we can abort after finding at least one +// enumerable key (whereas Object.keys would require materializing the array of +// all keys, which would be considerably slower if the value has many keys!). +// This function assumes that value is an object; see arrayContainsObjects. +function objectHasEnumerableKeys(value) { + for (const _ in value) return true; + return false; +} + +function isQueryResultSetSchema(schemas) { + return (Array.isArray(schemas) && schemas.every((s) => s && typeof s.name === "string")); +} + +function isQueryResultSetColumns(columns) { + return (Array.isArray(columns) && columns.every((name) => typeof name === "string")); +} + +// Returns true if the value represents an array of primitives (i.e., a +// single-column table). This should only be passed values for which +// isDataArray returns true. +function arrayIsPrimitive(value) { + return ( + isTypedArray(value) || + arrayContainsPrimitives(value) || + arrayContainsDates(value) + ); +} + +// Given an array, checks that the first n elements are primitives (number, +// string, boolean, bigint) of a consistent type. +function arrayContainsPrimitives(value) { + const n = Math.min(nChecks, value.length); + if (!(n > 0)) return false; + let type; + let hasPrimitive = false; // ensure we encounter 1+ primitives + for (let i = 0; i < n; ++i) { + const v = value[i]; + if (v == null) continue; // ignore null and undefined + const t = typeof v; + if (type === undefined) { + switch (t) { + case "number": + case "boolean": + case "string": + case "bigint": + type = t; + break; + default: + return false; + } + } else if (t !== type) { + return false; + } + hasPrimitive = true; + } + return hasPrimitive; +} + +// Given an array, checks that the first n elements are dates. +function arrayContainsDates(value) { + const n = Math.min(nChecks, value.length); + if (!(n > 0)) return false; + let hasDate = false; // ensure we encounter 1+ dates + for (let i = 0; i < n; ++i) { + const v = value[i]; + if (v == null) continue; // ignore null and undefined + if (!(v instanceof Date)) return false; + hasDate = true; + } + return hasDate; +} + +function isTypedArray(value) { + return ( + value instanceof Int8Array || + value instanceof Int16Array || + value instanceof Int32Array || + value instanceof Uint8Array || + value instanceof Uint8ClampedArray || + value instanceof Uint16Array || + value instanceof Uint32Array || + value instanceof Float32Array || + value instanceof Float64Array + ); +} + +// __query is used by table cells; __query.sql is used by SQL cells. +const __query = Object.assign( + async (source, operations, invalidation) => { + source = await loadDataSource(await source, "table"); + if (isDatabaseClient(source)) return evaluateQuery(source, makeQueryTemplate(operations, source), invalidation); + if (isDataArray(source)) return __table(source, operations); + if (!source) throw new Error("missing data source"); + throw new Error("invalid data source"); + }, + { + sql(source, invalidation) { + return async function () { + return evaluateQuery(await loadDataSource(await source, "sql"), arguments, invalidation); + }; + } + } +); + +async function loadDataSource(source, mode) { + if (source instanceof FileAttachment) { + if (mode === "table") { + switch (source.mimeType) { + case "text/csv": return source.csv({typed: true}); + case "text/tab-separated-values": return source.tsv({typed: true}); + case "application/json": return source.json(); + } + } + if (mode === "table" || mode === "sql") { + switch (source.mimeType) { + case "application/x-sqlite3": return source.sqlite(); + } + if (/\.arrow$/i.test(source.name)) return DuckDBClient.of({__table: await source.arrow({version: 9})}); + } + throw new Error(`unsupported file type: ${source.mimeType}`); + } + if ((mode === "table" || mode === "sql") && isArrowTable(source)) { + return DuckDBClient.of({__table: source}); + } + return source; +} + +async function evaluateQuery(source, args, invalidation) { + if (!source) throw new Error("missing data source"); + + // If this DatabaseClient supports abort and streaming, use that. + if (typeof source.queryTag === "function") { + const abortController = new AbortController(); + const options = {signal: abortController.signal}; + invalidation.then(() => abortController.abort("invalidated")); + if (typeof source.queryStream === "function") { + return accumulateQuery( + source.queryStream(...source.queryTag.apply(source, args), options) + ); + } + if (typeof source.query === "function") { + return source.query(...source.queryTag.apply(source, args), options); + } + } + + // Otherwise, fallback to the basic sql tagged template literal. + if (typeof source.sql === "function") { + return source.sql.apply(source, args); + } + + // TODO: test if source is a file attachment, and support CSV etc. + throw new Error("source does not implement query, queryStream, or sql"); +} + +// Generator function that yields accumulated query results client.queryStream +async function* accumulateQuery(queryRequest) { + let then = performance.now(); + const queryResponse = await queryRequest; + const values = []; + values.done = false; + values.error = null; + values.schema = queryResponse.schema; + try { + for await (const rows of queryResponse.readRows()) { + if (performance.now() - then > 10 && values.length > 0) { + yield values; + then = performance.now(); + } + for (const value of rows) { + values.push(value); + } + } + values.done = true; + yield values; + } catch (error) { + values.error = error; + yield values; + } +} + +/** + * Returns a SQL query in the form [[parts], ...params] where parts is an array + * of sub-strings and params are the parameter values to be inserted between each + * sub-string. + */ +function makeQueryTemplate(operations, source) { + const escaper = + typeof source.escape === "function" ? source.escape : (i) => i; + const {select, from, filter, sort, slice} = operations; + if (!from.table) + throw new Error("missing from table"); + if (select.columns && select.columns.length === 0) + throw new Error("at least one column must be selected"); + const columns = select.columns ? select.columns.map((c) => `t.${escaper(c)}`) : "*"; + const args = [ + [`SELECT ${columns} FROM ${formatTable(from.table, escaper)} t`] + ]; + for (let i = 0; i < filter.length; ++i) { + appendSql(i ? `\nAND ` : `\nWHERE `, args); + appendWhereEntry(filter[i], args, escaper); + } + for (let i = 0; i < sort.length; ++i) { + appendSql(i ? `, ` : `\nORDER BY `, args); + appendOrderBy(sort[i], args, escaper); + } + if (source.dialect === "mssql") { + if (slice.to !== null || slice.from !== null) { + if (!sort.length) { + if (!select.columns) + throw new Error( + "at least one column must be explicitly specified. Received '*'." + ); + appendSql(`\nORDER BY `, args); + appendOrderBy( + {column: select.columns[0], direction: "ASC"}, + args, + escaper + ); + } + appendSql(`\nOFFSET ${slice.from || 0} ROWS`, args); + appendSql( + `\nFETCH NEXT ${ + slice.to !== null ? slice.to - (slice.from || 0) : 1e9 + } ROWS ONLY`, + args + ); + } + } else { + if (slice.to !== null || slice.from !== null) { + appendSql( + `\nLIMIT ${slice.to !== null ? slice.to - (slice.from || 0) : 1e9}`, + args + ); + } + if (slice.from !== null) { + appendSql(` OFFSET ${slice.from}`, args); + } + } + return args; +} + +function formatTable(table, escaper) { + if (typeof table === "object") { // i.e., not a bare string specifier + let from = ""; + if (table.database != null) from += escaper(table.database) + "."; + if (table.schema != null) from += escaper(table.schema) + "."; + from += escaper(table.table); + return from; + } + return table; +} + +function appendSql(sql, args) { + const strings = args[0]; + strings[strings.length - 1] += sql; +} + +function appendOrderBy({column, direction}, args, escaper) { + appendSql(`t.${escaper(column)} ${direction.toUpperCase()}`, args); +} + +function appendWhereEntry({type, operands}, args, escaper) { + if (operands.length < 1) throw new Error("Invalid operand length"); + + // Unary operations + if (operands.length === 1) { + appendOperand(operands[0], args, escaper); + switch (type) { + case "n": + appendSql(` IS NULL`, args); + return; + case "nn": + appendSql(` IS NOT NULL`, args); + return; + default: + throw new Error("Invalid filter operation"); + } + } + + // Binary operations + if (operands.length === 2) { + if (["in", "nin"].includes(type)) ; else if (["c", "nc"].includes(type)) { + // TODO: Case (in)sensitive? + appendOperand(operands[0], args, escaper); + switch (type) { + case "c": + appendSql(` LIKE `, args); + break; + case "nc": + appendSql(` NOT LIKE `, args); + break; + } + appendOperand(likeOperand(operands[1]), args, escaper); + return; + } else { + appendOperand(operands[0], args, escaper); + switch (type) { + case "eq": + appendSql(` = `, args); + break; + case "ne": + appendSql(` <> `, args); + break; + case "gt": + appendSql(` > `, args); + break; + case "lt": + appendSql(` < `, args); + break; + case "gte": + appendSql(` >= `, args); + break; + case "lte": + appendSql(` <= `, args); + break; + default: + throw new Error("Invalid filter operation"); + } + appendOperand(operands[1], args, escaper); + return; + } + } + + // List operations + appendOperand(operands[0], args, escaper); + switch (type) { + case "in": + appendSql(` IN (`, args); + break; + case "nin": + appendSql(` NOT IN (`, args); + break; + default: + throw new Error("Invalid filter operation"); + } + appendListOperands(operands.slice(1), args); + appendSql(")", args); +} + +function appendOperand(o, args, escaper) { + if (o.type === "column") { + appendSql(`t.${escaper(o.value)}`, args); + } else { + args.push(o.value); + args[0].push(""); + } +} + +// TODO: Support column operands here? +function appendListOperands(ops, args) { + let first = true; + for (const op of ops) { + if (first) first = false; + else appendSql(",", args); + args.push(op.value); + args[0].push(""); + } +} + +function likeOperand(operand) { + return {...operand, value: `%${operand.value}%`}; +} + +// This function applies table cell operations to an in-memory table (array of +// objects); it should be equivalent to the corresponding SQL query. +function __table(source, operations) { + const input = source; + let {schema, columns} = source; + let primitive = arrayIsPrimitive(source); + if (primitive) source = Array.from(source, (value) => ({value})); + for (const {type, operands} of operations.filter) { + const [{value: column}] = operands; + const values = operands.slice(1).map(({value}) => value); + switch (type) { + case "eq": { + const [value] = values; + if (value instanceof Date) { + const time = +value; // compare as primitive + source = source.filter((d) => +d[column] === time); + } else { + source = source.filter((d) => d[column] === value); + } + break; + } + case "ne": { + const [value] = values; + source = source.filter((d) => d[column] !== value); + break; + } + case "c": { + const [value] = values; + source = source.filter( + (d) => typeof d[column] === "string" && d[column].includes(value) + ); + break; + } + case "nc": { + const [value] = values; + source = source.filter( + (d) => typeof d[column] === "string" && !d[column].includes(value) + ); + break; + } + case "in": { + const set = new Set(values); // TODO support dates? + source = source.filter((d) => set.has(d[column])); + break; + } + case "nin": { + const set = new Set(values); // TODO support dates? + source = source.filter((d) => !set.has(d[column])); + break; + } + case "n": { + source = source.filter((d) => d[column] == null); + break; + } + case "nn": { + source = source.filter((d) => d[column] != null); + break; + } + case "lt": { + const [value] = values; + source = source.filter((d) => d[column] < value); + break; + } + case "lte": { + const [value] = values; + source = source.filter((d) => d[column] <= value); + break; + } + case "gt": { + const [value] = values; + source = source.filter((d) => d[column] > value); + break; + } + case "gte": { + const [value] = values; + source = source.filter((d) => d[column] >= value); + break; + } + default: + throw new Error(`unknown filter type: ${type}`); + } + } + for (const {column, direction} of reverse(operations.sort)) { + const compare = direction === "desc" ? descending : ascending; + if (source === input) source = source.slice(); // defensive copy + source.sort((a, b) => compare(a[column], b[column])); + } + let {from, to} = operations.slice; + from = from == null ? 0 : Math.max(0, from); + to = to == null ? Infinity : Math.max(0, to); + if (from > 0 || to < Infinity) { + source = source.slice(Math.max(0, from), Math.max(0, to)); + } + if (operations.select.columns) { + if (schema) { + const schemaByName = new Map(schema.map((s) => [s.name, s])); + schema = operations.select.columns.map((c) => schemaByName.get(c)); + } + if (columns) { + columns = operations.select.columns; + } + source = source.map((d) => + Object.fromEntries(operations.select.columns.map((c) => [c, d[c]])) + ); + } + if (primitive) source = source.map((d) => d.value); + if (source !== input) { + if (schema) source.schema = schema; + if (columns) source.columns = columns; + } + return source; +} + +const Library = Object.assign(Object.defineProperties(function Library(resolver) { + const require = requirer(resolver); + Object.defineProperties(this, properties({ + FileAttachment: () => NoFileAttachments, + Mutable: () => Mutable, + now, + width, + + // Tagged template literals + dot: () => require(graphviz.resolve()), + htl: () => require(htl.resolve()), + html: () => html$1, + md: () => md(require), + svg: () => svg, + tex: () => tex(require), + + // Recommended libraries + // https://observablehq.com/@observablehq/recommended-libraries + _: () => require(lodash.resolve()), + aq: () => require.alias({"apache-arrow": arrow4.resolve()})(arquero.resolve()), // TODO upgrade to apache-arrow@9 + Arrow: () => require(arrow4.resolve()), // TODO upgrade to apache-arrow@9 + d3: () => require(d3.resolve()), + DuckDBClient: () => DuckDBClient, + Inputs: () => require(inputs.resolve()).then(Inputs => ({...Inputs, file: Inputs.fileOf(AbstractFile)})), + L: () => leaflet(require), + mermaid: () => mermaid(require), + Plot: () => require(plot.resolve()), + __query: () => __query, + require: () => require, + resolve: () => resolve, // deprecated; use async require.resolve instead + SQLite: () => SQLite(require), + SQLiteDatabaseClient: () => SQLiteDatabaseClient, + topojson: () => require(topojson.resolve()), + vl: () => vl(require), + + // Sample datasets + // https://observablehq.com/@observablehq/datasets + aapl: () => new FileAttachment("https://static.observableusercontent.com/files/3ccff97fd2d93da734e76829b2b066eafdaac6a1fafdec0faf6ebc443271cfc109d29e80dd217468fcb2aff1e6bffdc73f356cc48feb657f35378e6abbbb63b9").csv({typed: true}), + alphabet: () => new FileAttachment("https://static.observableusercontent.com/files/75d52e6c3130b1cae83cda89305e17b50f33e7420ef205587a135e8562bcfd22e483cf4fa2fb5df6dff66f9c5d19740be1cfaf47406286e2eb6574b49ffc685d").csv({typed: true}), + cars: () => new FileAttachment("https://static.observableusercontent.com/files/048ec3dfd528110c0665dfa363dd28bc516ffb7247231f3ab25005036717f5c4c232a5efc7bb74bc03037155cb72b1abe85a33d86eb9f1a336196030443be4f6").csv({typed: true}), + citywages: () => new FileAttachment("https://static.observableusercontent.com/files/39837ec5121fcc163131dbc2fe8c1a2e0b3423a5d1e96b5ce371e2ac2e20a290d78b71a4fb08b9fa6a0107776e17fb78af313b8ea70f4cc6648fad68ddf06f7a").csv({typed: true}), + diamonds: () => new FileAttachment("https://static.observableusercontent.com/files/87942b1f5d061a21fa4bb8f2162db44e3ef0f7391301f867ab5ba718b225a63091af20675f0bfe7f922db097b217b377135203a7eab34651e21a8d09f4e37252").csv({typed: true}), + flare: () => new FileAttachment("https://static.observableusercontent.com/files/a6b0d94a7f5828fd133765a934f4c9746d2010e2f342d335923991f31b14120de96b5cb4f160d509d8dc627f0107d7f5b5070d2516f01e4c862b5b4867533000").csv({typed: true}), + industries: () => new FileAttachment("https://static.observableusercontent.com/files/76f13741128340cc88798c0a0b7fa5a2df8370f57554000774ab8ee9ae785ffa2903010cad670d4939af3e9c17e5e18e7e05ed2b38b848ac2fc1a0066aa0005f").csv({typed: true}), + miserables: () => new FileAttachment("https://static.observableusercontent.com/files/31d904f6e21d42d4963ece9c8cc4fbd75efcbdc404bf511bc79906f0a1be68b5a01e935f65123670ed04e35ca8cae3c2b943f82bf8db49c5a67c85cbb58db052").json(), + olympians: () => new FileAttachment("https://static.observableusercontent.com/files/31ca24545a0603dce099d10ee89ee5ae72d29fa55e8fc7c9ffb5ded87ac83060d80f1d9e21f4ae8eb04c1e8940b7287d179fe8060d887fb1f055f430e210007c").csv({typed: true}), + penguins: () => new FileAttachment("https://static.observableusercontent.com/files/715db1223e067f00500780077febc6cebbdd90c151d3d78317c802732252052ab0e367039872ab9c77d6ef99e5f55a0724b35ddc898a1c99cb14c31a379af80a").csv({typed: true}), + weather: () => new FileAttachment("https://static.observableusercontent.com/files/693a46b22b33db0f042728700e0c73e836fa13d55446df89120682d55339c6db7cc9e574d3d73f24ecc9bc7eb9ac9a1e7e104a1ee52c00aab1e77eb102913c1f").csv({typed: true}), + + // Note: these are namespace objects, and thus exposed directly rather than + // being wrapped in a function. This allows library.Generators to resolve, + // rather than needing module.value. + DOM, + Files, + Generators: Generators$1, + Promises + })); +}, { + resolve: { + get: () => requireDefault.resolve, + enumerable: true, + configurable: true + }, + require: { + get: () => requireDefault, + set: setDefaultRequire, + enumerable: true, + configurable: true + } +}), { + resolveFrom, + requireFrom +}); + +function properties(values) { + return Object.fromEntries(Object.entries(values).map(property)); +} + +function property([key, value]) { + return [key, ({value, writable: true, enumerable: true})]; +} + +// src/main.js +class PandocCodeDecorator { + constructor(node) { + this._node = node; + this._spans = []; + this.normalizeCodeRange(); + this.initializeEntryPoints(); + } + normalizeCodeRange() { + const n = this._node; + const lines = n.querySelectorAll("code > span"); + for (const line of lines) { + Array.from(line.childNodes).filter((n2) => n2.nodeType === n2.TEXT_NODE).forEach((n2) => { + const newSpan = document.createElement("span"); + newSpan.textContent = n2.wholeText; + n2.replaceWith(newSpan); + }); + } + } + initializeEntryPoints() { + const lines = this._node.querySelectorAll("code > span"); + let result = []; + let offset = this._node.parentElement.dataset.sourceOffset && -Number(this._node.parentElement.dataset.sourceOffset) || 0; + for (const line of lines) { + let lineNumber = Number(line.id.split("-").pop()); + let column = 1; + Array.from(line.childNodes).filter((n) => n.nodeType === n.ELEMENT_NODE && n.nodeName === "SPAN").forEach((n) => { + result.push({ + offset, + line: lineNumber, + column, + node: n + }); + offset += n.textContent.length; + column += n.textContent.length; + }); + offset += 1; + } + this._elementEntryPoints = result; + } + locateEntry(offset) { + let candidate; + if (offset === Infinity) + return void 0; + for (let i = 0; i < this._elementEntryPoints.length; ++i) { + const entry = this._elementEntryPoints[i]; + if (entry.offset > offset) { + return { entry: candidate, index: i - 1 }; + } + candidate = entry; + } + if (offset < candidate.offset + candidate.node.textContent.length) { + return { entry: candidate, index: this._elementEntryPoints.length - 1 }; + } else { + return void 0; + } + } + offsetToLineColumn(offset) { + let entry = this.locateEntry(offset); + if (entry === void 0) { + const entries = this._elementEntryPoints; + const last = entries[entries.length - 1]; + return { + line: last.line, + column: last.column + Math.min(last.node.textContent.length, offset - last.offset) + }; + } + return { + line: entry.entry.line, + column: entry.entry.column + offset - entry.entry.offset + }; + } + *spanSelection(start, end) { + this.ensureExactSpan(start, end); + const startEntry = this.locateEntry(start); + const endEntry = this.locateEntry(end); + if (startEntry === void 0) { + return; + } + const startIndex = startEntry.index; + const endIndex = endEntry && endEntry.index || this._elementEntryPoints.length; + for (let i = startIndex; i < endIndex; ++i) { + if (this._elementEntryPoints[i] !== void 0) { + yield this._elementEntryPoints[i]; + } + } + } + decorateSpan(start, end, classes) { + for (const entryPoint of this.spanSelection(start, end)) { + for (const cssClass of classes) { + entryPoint.node.classList.add(cssClass); + } + } + } + clearSpan(start, end, classes) { + for (const entryPoint of this.spanSelection(start, end)) { + for (const cssClass of classes) { + entryPoint.node.classList.remove(cssClass); + } + } + } + ensureExactSpan(start, end) { + const splitEntry = (entry, offset) => { + const newSpan = document.createElement("span"); + for (const cssClass of entry.node.classList) { + newSpan.classList.add(cssClass); + } + const beforeText = entry.node.textContent.slice(0, offset - entry.offset); + const afterText = entry.node.textContent.slice(offset - entry.offset); + entry.node.textContent = beforeText; + newSpan.textContent = afterText; + entry.node.after(newSpan); + this._elementEntryPoints.push({ + column: entry.column + offset - entry.offset, + line: entry.line, + node: newSpan, + offset + }); + this._elementEntryPoints.sort((a, b) => a.offset - b.offset); + }; + const startEntry = this.locateEntry(start); + if (startEntry !== void 0 && startEntry.entry !== void 0 && startEntry.entry.offset != start) { + splitEntry(startEntry.entry, start); + } + const endEntry = this.locateEntry(end); + if (endEntry !== void 0 && startEntry.entry !== void 0 && endEntry.entry.offset !== end) { + splitEntry(endEntry.entry, end); + } + } + clearSpan(start, end, classes) { + this.ensureExactSpan(start, end); + const startEntry = this.locateEntry(start); + const endEntry = this.locateEntry(end); + if (startEntry === void 0) { + return; + } + const startIndex = startEntry.index; + const endIndex = endEntry && endEntry.index || this._elementEntryPoints.length; + for (let i = startIndex; i < endIndex; ++i) { + for (const cssClass of classes) { + this._elementEntryPoints[i].node.classList.remove(cssClass); + } + } + } +} + +function dispatch(node, type, detail) { + detail = detail || {}; + var document = node.ownerDocument, event = document.defaultView.CustomEvent; + if (typeof event === "function") { + event = new event(type, {detail: detail}); + } else { + event = document.createEvent("Event"); + event.initEvent(type, false, false); + event.detail = detail; + } + node.dispatchEvent(event); +} + +// TODO https://twitter.com/mbostock/status/702737065121742848 +function isarray(value) { + return Array.isArray(value) + || value instanceof Int8Array + || value instanceof Int16Array + || value instanceof Int32Array + || value instanceof Uint8Array + || value instanceof Uint8ClampedArray + || value instanceof Uint16Array + || value instanceof Uint32Array + || value instanceof Float32Array + || value instanceof Float64Array; +} + +// Non-integer keys in arrays, e.g. [1, 2, 0.5: "value"]. +function isindex(key) { + return key === (key | 0) + ""; +} + +function inspectName(name) { + const n = document.createElement("span"); + n.className = "observablehq--cellname"; + n.textContent = `${name} = `; + return n; +} + +const symbolToString = Symbol.prototype.toString; + +// Symbols do not coerce to strings; they must be explicitly converted. +function formatSymbol(symbol) { + return symbolToString.call(symbol); +} + +const {getOwnPropertySymbols, prototype: {hasOwnProperty: hasOwnProperty$1}} = Object; +const {toStringTag} = Symbol; + +const FORBIDDEN = {}; + +const symbolsof = getOwnPropertySymbols; + +function isown(object, key) { + return hasOwnProperty$1.call(object, key); +} + +function tagof(object) { + return object[toStringTag] + || (object.constructor && object.constructor.name) + || "Object"; +} + +function valueof(object, key) { + try { + const value = object[key]; + if (value) value.constructor; // Test for SecurityError. + return value; + } catch (ignore) { + return FORBIDDEN; + } +} + +const SYMBOLS = [ + { symbol: "@@__IMMUTABLE_INDEXED__@@", name: "Indexed", modifier: true }, + { symbol: "@@__IMMUTABLE_KEYED__@@", name: "Keyed", modifier: true }, + { symbol: "@@__IMMUTABLE_LIST__@@", name: "List", arrayish: true }, + { symbol: "@@__IMMUTABLE_MAP__@@", name: "Map" }, + { + symbol: "@@__IMMUTABLE_ORDERED__@@", + name: "Ordered", + modifier: true, + prefix: true + }, + { symbol: "@@__IMMUTABLE_RECORD__@@", name: "Record" }, + { + symbol: "@@__IMMUTABLE_SET__@@", + name: "Set", + arrayish: true, + setish: true + }, + { symbol: "@@__IMMUTABLE_STACK__@@", name: "Stack", arrayish: true } +]; + +function immutableName(obj) { + try { + let symbols = SYMBOLS.filter(({ symbol }) => obj[symbol] === true); + if (!symbols.length) return; + + const name = symbols.find(s => !s.modifier); + const prefix = + name.name === "Map" && symbols.find(s => s.modifier && s.prefix); + + const arrayish = symbols.some(s => s.arrayish); + const setish = symbols.some(s => s.setish); + + return { + name: `${prefix ? prefix.name : ""}${name.name}`, + symbols, + arrayish: arrayish && !setish, + setish + }; + } catch (e) { + return null; + } +} + +const {getPrototypeOf, getOwnPropertyDescriptors} = Object; +const objectPrototype = getPrototypeOf({}); + +function inspectExpanded(object, _, name, proto) { + let arrayish = isarray(object); + let tag, fields, next, n; + + if (object instanceof Map) { + if (object instanceof object.constructor) { + tag = `Map(${object.size})`; + fields = iterateMap$1; + } else { // avoid incompatible receiver error for prototype + tag = "Map()"; + fields = iterateObject$1; + } + } else if (object instanceof Set) { + if (object instanceof object.constructor) { + tag = `Set(${object.size})`; + fields = iterateSet$1; + } else { // avoid incompatible receiver error for prototype + tag = "Set()"; + fields = iterateObject$1; + } + } else if (arrayish) { + tag = `${object.constructor.name}(${object.length})`; + fields = iterateArray$1; + } else if ((n = immutableName(object))) { + tag = `Immutable.${n.name}${n.name === "Record" ? "" : `(${object.size})`}`; + arrayish = n.arrayish; + fields = n.arrayish + ? iterateImArray$1 + : n.setish + ? iterateImSet$1 + : iterateImObject$1; + } else if (proto) { + tag = tagof(object); + fields = iterateProto; + } else { + tag = tagof(object); + fields = iterateObject$1; + } + + const span = document.createElement("span"); + span.className = "observablehq--expanded"; + if (name) { + span.appendChild(inspectName(name)); + } + const a = span.appendChild(document.createElement("a")); + a.innerHTML = ` + + `; + a.appendChild(document.createTextNode(`${tag}${arrayish ? " [" : " {"}`)); + a.addEventListener("mouseup", function(event) { + event.stopPropagation(); + replace(span, inspectCollapsed(object, null, name, proto)); + }); + + fields = fields(object); + for (let i = 0; !(next = fields.next()).done && i < 20; ++i) { + span.appendChild(next.value); + } + + if (!next.done) { + const a = span.appendChild(document.createElement("a")); + a.className = "observablehq--field"; + a.style.display = "block"; + a.appendChild(document.createTextNode(` … more`)); + a.addEventListener("mouseup", function(event) { + event.stopPropagation(); + span.insertBefore(next.value, span.lastChild.previousSibling); + for (let i = 0; !(next = fields.next()).done && i < 19; ++i) { + span.insertBefore(next.value, span.lastChild.previousSibling); + } + if (next.done) span.removeChild(span.lastChild.previousSibling); + dispatch(span, "load"); + }); + } + + span.appendChild(document.createTextNode(arrayish ? "]" : "}")); + + return span; +} + +function* iterateMap$1(map) { + for (const [key, value] of map) { + yield formatMapField$1(key, value); + } + yield* iterateObject$1(map); +} + +function* iterateSet$1(set) { + for (const value of set) { + yield formatSetField(value); + } + yield* iterateObject$1(set); +} + +function* iterateImSet$1(set) { + for (const value of set) { + yield formatSetField(value); + } +} + +function* iterateArray$1(array) { + for (let i = 0, n = array.length; i < n; ++i) { + if (i in array) { + yield formatField$1(i, valueof(array, i), "observablehq--index"); + } + } + for (const key in array) { + if (!isindex(key) && isown(array, key)) { + yield formatField$1(key, valueof(array, key), "observablehq--key"); + } + } + for (const symbol of symbolsof(array)) { + yield formatField$1( + formatSymbol(symbol), + valueof(array, symbol), + "observablehq--symbol" + ); + } +} + +function* iterateImArray$1(array) { + let i1 = 0; + for (const n = array.size; i1 < n; ++i1) { + yield formatField$1(i1, array.get(i1), true); + } +} + +function* iterateProto(object) { + for (const key in getOwnPropertyDescriptors(object)) { + yield formatField$1(key, valueof(object, key), "observablehq--key"); + } + for (const symbol of symbolsof(object)) { + yield formatField$1( + formatSymbol(symbol), + valueof(object, symbol), + "observablehq--symbol" + ); + } + + const proto = getPrototypeOf(object); + if (proto && proto !== objectPrototype) { + yield formatPrototype(proto); + } +} + +function* iterateObject$1(object) { + for (const key in object) { + if (isown(object, key)) { + yield formatField$1(key, valueof(object, key), "observablehq--key"); + } + } + for (const symbol of symbolsof(object)) { + yield formatField$1( + formatSymbol(symbol), + valueof(object, symbol), + "observablehq--symbol" + ); + } + + const proto = getPrototypeOf(object); + if (proto && proto !== objectPrototype) { + yield formatPrototype(proto); + } +} + +function* iterateImObject$1(object) { + for (const [key, value] of object) { + yield formatField$1(key, value, "observablehq--key"); + } +} + +function formatPrototype(value) { + const item = document.createElement("div"); + const span = item.appendChild(document.createElement("span")); + item.className = "observablehq--field"; + span.className = "observablehq--prototype-key"; + span.textContent = ` `; + item.appendChild(document.createTextNode(": ")); + item.appendChild(inspect(value, undefined, undefined, undefined, true)); + return item; +} + +function formatField$1(key, value, className) { + const item = document.createElement("div"); + const span = item.appendChild(document.createElement("span")); + item.className = "observablehq--field"; + span.className = className; + span.textContent = ` ${key}`; + item.appendChild(document.createTextNode(": ")); + item.appendChild(inspect(value)); + return item; +} + +function formatMapField$1(key, value) { + const item = document.createElement("div"); + item.className = "observablehq--field"; + item.appendChild(document.createTextNode(" ")); + item.appendChild(inspect(key)); + item.appendChild(document.createTextNode(" => ")); + item.appendChild(inspect(value)); + return item; +} + +function formatSetField(value) { + const item = document.createElement("div"); + item.className = "observablehq--field"; + item.appendChild(document.createTextNode(" ")); + item.appendChild(inspect(value)); + return item; +} + +function hasSelection(elem) { + const sel = window.getSelection(); + return ( + sel.type === "Range" && + (sel.containsNode(elem, true) || + sel.anchorNode.isSelfOrDescendant(elem) || + sel.focusNode.isSelfOrDescendant(elem)) + ); +} + +function inspectCollapsed(object, shallow, name, proto) { + let arrayish = isarray(object); + let tag, fields, next, n; + + if (object instanceof Map) { + if (object instanceof object.constructor) { + tag = `Map(${object.size})`; + fields = iterateMap; + } else { // avoid incompatible receiver error for prototype + tag = "Map()"; + fields = iterateObject; + } + } else if (object instanceof Set) { + if (object instanceof object.constructor) { + tag = `Set(${object.size})`; + fields = iterateSet; + } else { // avoid incompatible receiver error for prototype + tag = "Set()"; + fields = iterateObject; + } + } else if (arrayish) { + tag = `${object.constructor.name}(${object.length})`; + fields = iterateArray; + } else if ((n = immutableName(object))) { + tag = `Immutable.${n.name}${n.name === 'Record' ? '' : `(${object.size})`}`; + arrayish = n.arrayish; + fields = n.arrayish ? iterateImArray : n.setish ? iterateImSet : iterateImObject; + } else { + tag = tagof(object); + fields = iterateObject; + } + + if (shallow) { + const span = document.createElement("span"); + span.className = "observablehq--shallow"; + if (name) { + span.appendChild(inspectName(name)); + } + span.appendChild(document.createTextNode(tag)); + span.addEventListener("mouseup", function(event) { + if (hasSelection(span)) return; + event.stopPropagation(); + replace(span, inspectCollapsed(object)); + }); + return span; + } + + const span = document.createElement("span"); + span.className = "observablehq--collapsed"; + if (name) { + span.appendChild(inspectName(name)); + } + const a = span.appendChild(document.createElement("a")); + a.innerHTML = ` + + `; + a.appendChild(document.createTextNode(`${tag}${arrayish ? " [" : " {"}`)); + span.addEventListener("mouseup", function(event) { + if (hasSelection(span)) return; + event.stopPropagation(); + replace(span, inspectExpanded(object, null, name, proto)); + }, true); + + fields = fields(object); + for (let i = 0; !(next = fields.next()).done && i < 20; ++i) { + if (i > 0) span.appendChild(document.createTextNode(", ")); + span.appendChild(next.value); + } + + if (!next.done) span.appendChild(document.createTextNode(", …")); + span.appendChild(document.createTextNode(arrayish ? "]" : "}")); + + return span; +} + +function* iterateMap(map) { + for (const [key, value] of map) { + yield formatMapField(key, value); + } + yield* iterateObject(map); +} + +function* iterateSet(set) { + for (const value of set) { + yield inspect(value, true); + } + yield* iterateObject(set); +} + +function* iterateImSet(set) { + for (const value of set) { + yield inspect(value, true); + } +} + +function* iterateImArray(array) { + let i0 = -1, i1 = 0; + for (const n = array.size; i1 < n; ++i1) { + if (i1 > i0 + 1) yield formatEmpty(i1 - i0 - 1); + yield inspect(array.get(i1), true); + i0 = i1; + } + if (i1 > i0 + 1) yield formatEmpty(i1 - i0 - 1); +} + +function* iterateArray(array) { + let i0 = -1, i1 = 0; + for (const n = array.length; i1 < n; ++i1) { + if (i1 in array) { + if (i1 > i0 + 1) yield formatEmpty(i1 - i0 - 1); + yield inspect(valueof(array, i1), true); + i0 = i1; + } + } + if (i1 > i0 + 1) yield formatEmpty(i1 - i0 - 1); + for (const key in array) { + if (!isindex(key) && isown(array, key)) { + yield formatField(key, valueof(array, key), "observablehq--key"); + } + } + for (const symbol of symbolsof(array)) { + yield formatField(formatSymbol(symbol), valueof(array, symbol), "observablehq--symbol"); + } +} + +function* iterateObject(object) { + for (const key in object) { + if (isown(object, key)) { + yield formatField(key, valueof(object, key), "observablehq--key"); + } + } + for (const symbol of symbolsof(object)) { + yield formatField(formatSymbol(symbol), valueof(object, symbol), "observablehq--symbol"); + } +} + +function* iterateImObject(object) { + for (const [key, value] of object) { + yield formatField(key, value, "observablehq--key"); + } +} + +function formatEmpty(e) { + const span = document.createElement("span"); + span.className = "observablehq--empty"; + span.textContent = e === 1 ? "empty" : `empty × ${e}`; + return span; +} + +function formatField(key, value, className) { + const fragment = document.createDocumentFragment(); + const span = fragment.appendChild(document.createElement("span")); + span.className = className; + span.textContent = key; + fragment.appendChild(document.createTextNode(": ")); + fragment.appendChild(inspect(value, true)); + return fragment; +} + +function formatMapField(key, value) { + const fragment = document.createDocumentFragment(); + fragment.appendChild(inspect(key, true)); + fragment.appendChild(document.createTextNode(" => ")); + fragment.appendChild(inspect(value, true)); + return fragment; +} + +function format(date, fallback) { + if (!(date instanceof Date)) date = new Date(+date); + if (isNaN(date)) return typeof fallback === "function" ? fallback(date) : fallback; + const hours = date.getUTCHours(); + const minutes = date.getUTCMinutes(); + const seconds = date.getUTCSeconds(); + const milliseconds = date.getUTCMilliseconds(); + return `${formatYear(date.getUTCFullYear())}-${pad(date.getUTCMonth() + 1, 2)}-${pad(date.getUTCDate(), 2)}${ + hours || minutes || seconds || milliseconds ? `T${pad(hours, 2)}:${pad(minutes, 2)}${ + seconds || milliseconds ? `:${pad(seconds, 2)}${ + milliseconds ? `.${pad(milliseconds, 3)}` : `` + }` : `` + }Z` : `` + }`; +} + +function formatYear(year) { + return year < 0 ? `-${pad(-year, 6)}` + : year > 9999 ? `+${pad(year, 6)}` + : pad(year, 4); +} + +function pad(value, width) { + return `${value}`.padStart(width, "0"); +} + +function formatDate$1(date) { + return format(date, "Invalid Date"); +} + +var errorToString = Error.prototype.toString; + +function formatError(value) { + return value.stack || errorToString.call(value); +} + +var regExpToString = RegExp.prototype.toString; + +function formatRegExp(value) { + return regExpToString.call(value); +} + +/* eslint-disable no-control-regex */ +const NEWLINE_LIMIT = 20; + +function formatString(string, shallow, expanded, name) { + if (shallow === false) { + // String has fewer escapes displayed with double quotes + if (count(string, /["\n]/g) <= count(string, /`|\${/g)) { + const span = document.createElement("span"); + if (name) span.appendChild(inspectName(name)); + const textValue = span.appendChild(document.createElement("span")); + textValue.className = "observablehq--string"; + textValue.textContent = JSON.stringify(string); + return span; + } + const lines = string.split("\n"); + if (lines.length > NEWLINE_LIMIT && !expanded) { + const div = document.createElement("div"); + if (name) div.appendChild(inspectName(name)); + const textValue = div.appendChild(document.createElement("span")); + textValue.className = "observablehq--string"; + textValue.textContent = "`" + templatify(lines.slice(0, NEWLINE_LIMIT).join("\n")); + const splitter = div.appendChild(document.createElement("span")); + const truncatedCount = lines.length - NEWLINE_LIMIT; + splitter.textContent = `Show ${truncatedCount} truncated line${truncatedCount > 1 ? "s": ""}`; splitter.className = "observablehq--string-expand"; + splitter.addEventListener("mouseup", function (event) { + event.stopPropagation(); + replace(div, inspect(string, shallow, true, name)); + }); + return div; + } + const span = document.createElement("span"); + if (name) span.appendChild(inspectName(name)); + const textValue = span.appendChild(document.createElement("span")); + textValue.className = `observablehq--string${expanded ? " observablehq--expanded" : ""}`; + textValue.textContent = "`" + templatify(string) + "`"; + return span; + } + + const span = document.createElement("span"); + if (name) span.appendChild(inspectName(name)); + const textValue = span.appendChild(document.createElement("span")); + textValue.className = "observablehq--string"; + textValue.textContent = JSON.stringify(string.length > 100 ? + `${string.slice(0, 50)}…${string.slice(-49)}` : string); + return span; +} + +function templatify(string) { + return string.replace(/[\\`\x00-\x09\x0b-\x19]|\${/g, templatifyChar); +} + +function templatifyChar(char) { + var code = char.charCodeAt(0); + switch (code) { + case 0x8: return "\\b"; + case 0x9: return "\\t"; + case 0xb: return "\\v"; + case 0xc: return "\\f"; + case 0xd: return "\\r"; + } + return code < 0x10 ? "\\x0" + code.toString(16) + : code < 0x20 ? "\\x" + code.toString(16) + : "\\" + char; +} + +function count(string, re) { + var n = 0; + while (re.exec(string)) ++n; + return n; +} + +var toString$2 = Function.prototype.toString, + TYPE_ASYNC = {prefix: "async ƒ"}, + TYPE_ASYNC_GENERATOR = {prefix: "async ƒ*"}, + TYPE_CLASS = {prefix: "class"}, + TYPE_FUNCTION = {prefix: "ƒ"}, + TYPE_GENERATOR = {prefix: "ƒ*"}; + +function inspectFunction(f, name) { + var type, m, t = toString$2.call(f); + + switch (f.constructor && f.constructor.name) { + case "AsyncFunction": type = TYPE_ASYNC; break; + case "AsyncGeneratorFunction": type = TYPE_ASYNC_GENERATOR; break; + case "GeneratorFunction": type = TYPE_GENERATOR; break; + default: type = /^class\b/.test(t) ? TYPE_CLASS : TYPE_FUNCTION; break; + } + + // A class, possibly named. + // class Name + if (type === TYPE_CLASS) { + return formatFunction(type, "", name); + } + + // An arrow function with a single argument. + // foo => + // async foo => + if ((m = /^(?:async\s*)?(\w+)\s*=>/.exec(t))) { + return formatFunction(type, "(" + m[1] + ")", name); + } + + // An arrow function with parenthesized arguments. + // (…) + // async (…) + if ((m = /^(?:async\s*)?\(\s*(\w+(?:\s*,\s*\w+)*)?\s*\)/.exec(t))) { + return formatFunction(type, m[1] ? "(" + m[1].replace(/\s*,\s*/g, ", ") + ")" : "()", name); + } + + // A function, possibly: async, generator, anonymous, simply arguments. + // function name(…) + // function* name(…) + // async function name(…) + // async function* name(…) + if ((m = /^(?:async\s*)?function(?:\s*\*)?(?:\s*\w+)?\s*\(\s*(\w+(?:\s*,\s*\w+)*)?\s*\)/.exec(t))) { + return formatFunction(type, m[1] ? "(" + m[1].replace(/\s*,\s*/g, ", ") + ")" : "()", name); + } + + // Something else, like destructuring, comments or default values. + return formatFunction(type, "(…)", name); +} + +function formatFunction(type, args, cellname) { + var span = document.createElement("span"); + span.className = "observablehq--function"; + if (cellname) { + span.appendChild(inspectName(cellname)); + } + var spanType = span.appendChild(document.createElement("span")); + spanType.className = "observablehq--keyword"; + spanType.textContent = type.prefix; + span.appendChild(document.createTextNode(args)); + return span; +} + +const {prototype: {toString: toString$1}} = Object; + +function inspect(value, shallow, expand, name, proto) { + let type = typeof value; + switch (type) { + case "boolean": + case "undefined": { value += ""; break; } + case "number": { value = value === 0 && 1 / value < 0 ? "-0" : value + ""; break; } + case "bigint": { value = value + "n"; break; } + case "symbol": { value = formatSymbol(value); break; } + case "function": { return inspectFunction(value, name); } + case "string": { return formatString(value, shallow, expand, name); } + default: { + if (value === null) { type = null, value = "null"; break; } + if (value instanceof Date) { type = "date", value = formatDate$1(value); break; } + if (value === FORBIDDEN) { type = "forbidden", value = "[forbidden]"; break; } + switch (toString$1.call(value)) { + case "[object RegExp]": { type = "regexp", value = formatRegExp(value); break; } + case "[object Error]": // https://github.com/lodash/lodash/blob/master/isError.js#L26 + case "[object DOMException]": { type = "error", value = formatError(value); break; } + default: return (expand ? inspectExpanded : inspectCollapsed)(value, shallow, name, proto); + } + break; + } + } + const span = document.createElement("span"); + if (name) span.appendChild(inspectName(name)); + const n = span.appendChild(document.createElement("span")); + n.className = `observablehq--${type}`; + n.textContent = value; + return span; +} + +function replace(spanOld, spanNew) { + if (spanOld.classList.contains("observablehq--inspect")) spanNew.classList.add("observablehq--inspect"); + spanOld.parentNode.replaceChild(spanNew, spanOld); + dispatch(spanNew, "load"); +} + +const LOCATION_MATCH = /\s+\(\d+:\d+\)$/m; + +class Inspector { + constructor(node) { + if (!node) throw new Error("invalid node"); + this._node = node; + node.classList.add("observablehq"); + } + pending() { + const {_node} = this; + _node.classList.remove("observablehq--error"); + _node.classList.add("observablehq--running"); + } + fulfilled(value, name) { + const {_node} = this; + if (!isnode(value) || (value.parentNode && value.parentNode !== _node)) { + value = inspect(value, false, _node.firstChild // TODO Do this better. + && _node.firstChild.classList + && _node.firstChild.classList.contains("observablehq--expanded"), name); + value.classList.add("observablehq--inspect"); + } + _node.classList.remove("observablehq--running", "observablehq--error"); + if (_node.firstChild !== value) { + if (_node.firstChild) { + while (_node.lastChild !== _node.firstChild) _node.removeChild(_node.lastChild); + _node.replaceChild(value, _node.firstChild); + } else { + _node.appendChild(value); + } + } + dispatch(_node, "update"); + } + rejected(error, name) { + const {_node} = this; + _node.classList.remove("observablehq--running"); + _node.classList.add("observablehq--error"); + while (_node.lastChild) _node.removeChild(_node.lastChild); + var div = document.createElement("div"); + div.className = "observablehq--inspect"; + if (name) div.appendChild(inspectName(name)); + div.appendChild(document.createTextNode((error + "").replace(LOCATION_MATCH, ""))); + _node.appendChild(div); + dispatch(_node, "error", {error: error}); + } +} + +Inspector.into = function(container) { + if (typeof container === "string") { + container = document.querySelector(container); + if (container == null) throw new Error("container not found"); + } + return function() { + return new Inspector(container.appendChild(document.createElement("div"))); + }; +}; + +// Returns true if the given value is something that should be added to the DOM +// by the inspector, rather than being inspected. This deliberately excludes +// DocumentFragment since appending a fragment “dissolves” (mutates) the +// fragment, and we wish for the inspector to not have side-effects. Also, +// HTMLElement.prototype is an instanceof Element, but not an element! +function isnode(value) { + return (value instanceof Element || value instanceof Text) + && (value instanceof value.constructor); +} + +class RuntimeError extends Error { + constructor(message, input) { + super(message); + this.input = input; + } +} + +RuntimeError.prototype.name = "RuntimeError"; + +function generatorish(value) { + return value + && typeof value.next === "function" + && typeof value.return === "function"; +} + +function load(notebook, library, observer) { + if (typeof library == "function") observer = library, library = null; + if (typeof observer !== "function") throw new Error("invalid observer"); + if (library == null) library = new Library(); + + const {modules, id} = notebook; + const map = new Map; + const runtime = new Runtime(library); + const main = runtime_module(id); + + function runtime_module(id) { + let module = map.get(id); + if (!module) map.set(id, module = runtime.module()); + return module; + } + + for (const m of modules) { + const module = runtime_module(m.id); + let i = 0; + for (const v of m.variables) { + if (v.from) module.import(v.remote, v.name, runtime_module(v.from)); + else if (module === main) module.variable(observer(v, i, m.variables)).define(v.name, v.inputs, v.value); + else module.define(v.name, v.inputs, v.value); + ++i; + } + } + + return runtime; +} + +function constant(x) { + return () => x; +} + +function identity$1(x) { + return x; +} + +function rethrow(error) { + return () => { + throw error; + }; +} + +const prototype = Array.prototype; +const map = prototype.map; + +function noop() {} + +const TYPE_NORMAL = 1; // a normal variable +const TYPE_IMPLICIT = 2; // created on reference +const TYPE_DUPLICATE = 3; // created on duplicate definition + +const no_observer = Symbol("no-observer"); + +function Variable(type, module, observer) { + if (!observer) observer = no_observer; + Object.defineProperties(this, { + _observer: {value: observer, writable: true}, + _definition: {value: variable_undefined, writable: true}, + _duplicate: {value: undefined, writable: true}, + _duplicates: {value: undefined, writable: true}, + _indegree: {value: NaN, writable: true}, // The number of computing inputs. + _inputs: {value: [], writable: true}, + _invalidate: {value: noop, writable: true}, + _module: {value: module}, + _name: {value: null, writable: true}, + _outputs: {value: new Set, writable: true}, + _promise: {value: Promise.resolve(undefined), writable: true}, + _reachable: {value: observer !== no_observer, writable: true}, // Is this variable transitively visible? + _rejector: {value: variable_rejector(this)}, + _type: {value: type}, + _value: {value: undefined, writable: true}, + _version: {value: 0, writable: true} + }); +} + +Object.defineProperties(Variable.prototype, { + _pending: {value: variable_pending, writable: true, configurable: true}, + _fulfilled: {value: variable_fulfilled, writable: true, configurable: true}, + _rejected: {value: variable_rejected, writable: true, configurable: true}, + define: {value: variable_define, writable: true, configurable: true}, + delete: {value: variable_delete, writable: true, configurable: true}, + import: {value: variable_import, writable: true, configurable: true} +}); + +function variable_attach(variable) { + variable._module._runtime._dirty.add(variable); + variable._outputs.add(this); +} + +function variable_detach(variable) { + variable._module._runtime._dirty.add(variable); + variable._outputs.delete(this); +} + +function variable_undefined() { + throw variable_undefined; +} + +function variable_stale() { + throw variable_stale; +} + +function variable_rejector(variable) { + return (error) => { + if (error === variable_stale) throw error; + if (error === variable_undefined) throw new RuntimeError(`${variable._name} is not defined`, variable._name); + if (error instanceof Error && error.message) throw new RuntimeError(error.message, variable._name); + throw new RuntimeError(`${variable._name} could not be resolved`, variable._name); + }; +} + +function variable_duplicate(name) { + return () => { + throw new RuntimeError(`${name} is defined more than once`); + }; +} + +function variable_define(name, inputs, definition) { + switch (arguments.length) { + case 1: { + definition = name, name = inputs = null; + break; + } + case 2: { + definition = inputs; + if (typeof name === "string") inputs = null; + else inputs = name, name = null; + break; + } + } + return variable_defineImpl.call(this, + name == null ? null : String(name), + inputs == null ? [] : map.call(inputs, this._module._resolve, this._module), + typeof definition === "function" ? definition : constant(definition) + ); +} + +function variable_defineImpl(name, inputs, definition) { + const scope = this._module._scope, runtime = this._module._runtime; + + this._inputs.forEach(variable_detach, this); + inputs.forEach(variable_attach, this); + this._inputs = inputs; + this._definition = definition; + this._value = undefined; + + // Is this an active variable (that may require disposal)? + if (definition === noop) runtime._variables.delete(this); + else runtime._variables.add(this); + + // Did the variable’s name change? Time to patch references! + if (name !== this._name || scope.get(name) !== this) { + let error, found; + + if (this._name) { // Did this variable previously have a name? + if (this._outputs.size) { // And did other variables reference this variable? + scope.delete(this._name); + found = this._module._resolve(this._name); + found._outputs = this._outputs, this._outputs = new Set; + found._outputs.forEach(function(output) { output._inputs[output._inputs.indexOf(this)] = found; }, this); + found._outputs.forEach(runtime._updates.add, runtime._updates); + runtime._dirty.add(found).add(this); + scope.set(this._name, found); + } else if ((found = scope.get(this._name)) === this) { // Do no other variables reference this variable? + scope.delete(this._name); // It’s safe to delete! + } else if (found._type === TYPE_DUPLICATE) { // Do other variables assign this name? + found._duplicates.delete(this); // This variable no longer assigns this name. + this._duplicate = undefined; + if (found._duplicates.size === 1) { // Is there now only one variable assigning this name? + found = found._duplicates.keys().next().value; // Any references are now fixed! + error = scope.get(this._name); + found._outputs = error._outputs, error._outputs = new Set; + found._outputs.forEach(function(output) { output._inputs[output._inputs.indexOf(error)] = found; }); + found._definition = found._duplicate, found._duplicate = undefined; + runtime._dirty.add(error).add(found); + runtime._updates.add(found); + scope.set(this._name, found); + } + } else { + throw new Error; + } + } + + if (this._outputs.size) throw new Error; + + if (name) { // Does this variable have a new name? + if (found = scope.get(name)) { // Do other variables reference or assign this name? + if (found._type === TYPE_DUPLICATE) { // Do multiple other variables already define this name? + this._definition = variable_duplicate(name), this._duplicate = definition; + found._duplicates.add(this); + } else if (found._type === TYPE_IMPLICIT) { // Are the variable references broken? + this._outputs = found._outputs, found._outputs = new Set; // Now they’re fixed! + this._outputs.forEach(function(output) { output._inputs[output._inputs.indexOf(found)] = this; }, this); + runtime._dirty.add(found).add(this); + scope.set(name, this); + } else { // Does another variable define this name? + found._duplicate = found._definition, this._duplicate = definition; // Now they’re duplicates. + error = new Variable(TYPE_DUPLICATE, this._module); + error._name = name; + error._definition = this._definition = found._definition = variable_duplicate(name); + error._outputs = found._outputs, found._outputs = new Set; + error._outputs.forEach(function(output) { output._inputs[output._inputs.indexOf(found)] = error; }); + error._duplicates = new Set([this, found]); + runtime._dirty.add(found).add(error); + runtime._updates.add(found).add(error); + scope.set(name, error); + } + } else { + scope.set(name, this); + } + } + + this._name = name; + } + + // If this redefined variable was previously evaluated, invalidate it. (If the + // variable was never evaluated, then the invalidated value could never have + // been exposed and we can avoid this extra work.) + if (this._version > 0) ++this._version; + + runtime._updates.add(this); + runtime._compute(); + return this; +} + +function variable_import(remote, name, module) { + if (arguments.length < 3) module = name, name = remote; + return variable_defineImpl.call(this, String(name), [module._resolve(String(remote))], identity$1); +} + +function variable_delete() { + return variable_defineImpl.call(this, null, [], noop); +} + +function variable_pending() { + if (this._observer.pending) this._observer.pending(); +} + +function variable_fulfilled(value) { + if (this._observer.fulfilled) this._observer.fulfilled(value, this._name); +} + +function variable_rejected(error) { + if (this._observer.rejected) this._observer.rejected(error, this._name); +} + +const variable_variable = Symbol("variable"); +const variable_invalidation = Symbol("invalidation"); +const variable_visibility = Symbol("visibility"); + +function Module(runtime, builtins = []) { + Object.defineProperties(this, { + _runtime: {value: runtime}, + _scope: {value: new Map}, + _builtins: {value: new Map([ + ["@variable", variable_variable], + ["invalidation", variable_invalidation], + ["visibility", variable_visibility], + ...builtins + ])}, + _source: {value: null, writable: true} + }); +} + +Object.defineProperties(Module.prototype, { + _resolve: {value: module_resolve, writable: true, configurable: true}, + redefine: {value: module_redefine, writable: true, configurable: true}, + define: {value: module_define, writable: true, configurable: true}, + derive: {value: module_derive, writable: true, configurable: true}, + import: {value: module_import, writable: true, configurable: true}, + value: {value: module_value, writable: true, configurable: true}, + variable: {value: module_variable, writable: true, configurable: true}, + builtin: {value: module_builtin, writable: true, configurable: true} +}); + +function module_redefine(name) { + const v = this._scope.get(name); + if (!v) throw new RuntimeError(`${name} is not defined`); + if (v._type === TYPE_DUPLICATE) throw new RuntimeError(`${name} is defined more than once`); + return v.define.apply(v, arguments); +} + +function module_define() { + const v = new Variable(TYPE_NORMAL, this); + return v.define.apply(v, arguments); +} + +function module_import() { + const v = new Variable(TYPE_NORMAL, this); + return v.import.apply(v, arguments); +} + +function module_variable(observer) { + return new Variable(TYPE_NORMAL, this, observer); +} + +async function module_value(name) { + let v = this._scope.get(name); + if (!v) throw new RuntimeError(`${name} is not defined`); + if (v._observer === no_observer) { + v = this.variable(true).define([name], identity$1); + try { + return await module_revalue(this._runtime, v); + } finally { + v.delete(); + } + } else { + return module_revalue(this._runtime, v); + } +} + +// If the variable is redefined before its value resolves, try again. +async function module_revalue(runtime, variable) { + await runtime._compute(); + try { + return await variable._promise; + } catch (error) { + if (error === variable_stale) return module_revalue(runtime, variable); + throw error; + } +} + +function module_derive(injects, injectModule) { + const map = new Map(); + const modules = new Set(); + const copies = []; + + // Given a module, derives an alias of that module with an initially-empty + // definition. The variables will be copied later in a second pass below. + function alias(source) { + let target = map.get(source); + if (target) return target; + target = new Module(source._runtime, source._builtins); + target._source = source; + map.set(source, target); + copies.push([target, source]); + modules.add(source); + return target; + } + + // Inject the given variables as reverse imports into the derived module. + const derive = alias(this); + for (const inject of injects) { + const {alias, name} = typeof inject === "object" ? inject : {name: inject}; + derive.import(name, alias == null ? name : alias, injectModule); + } + + // Iterate over all the variables (currently) in this module. If any + // represents an import-with (i.e., an import of a module with a _source), the + // transitive import-with must be copied, too, as direct injections may affect + // transitive injections. Note that an import-with can only be created with + // module.derive and hence it’s not possible for an import-with to be added + // later; therefore we only need to apply this check once, now. + for (const module of modules) { + for (const [name, variable] of module._scope) { + if (variable._definition === identity$1) { // import + if (module === this && derive._scope.has(name)) continue; // overridden by injection + const importedModule = variable._inputs[0]._module; + if (importedModule._source) alias(importedModule); + } + } + } + + // Finally, with the modules resolved, copy the variable definitions. + for (const [target, source] of copies) { + for (const [name, sourceVariable] of source._scope) { + const targetVariable = target._scope.get(name); + if (targetVariable && targetVariable._type !== TYPE_IMPLICIT) continue; // preserve injection + if (sourceVariable._definition === identity$1) { // import + const sourceInput = sourceVariable._inputs[0]; + const sourceModule = sourceInput._module; + target.import(sourceInput._name, name, map.get(sourceModule) || sourceModule); + } else { // non-import + target.define(name, sourceVariable._inputs.map(variable_name), sourceVariable._definition); + } + } + } + + return derive; +} + +function module_resolve(name) { + let variable = this._scope.get(name), value; + if (!variable) { + variable = new Variable(TYPE_IMPLICIT, this); + if (this._builtins.has(name)) { + variable.define(name, constant(this._builtins.get(name))); + } else if (this._runtime._builtin._scope.has(name)) { + variable.import(name, this._runtime._builtin); + } else { + try { + value = this._runtime._global(name); + } catch (error) { + return variable.define(name, rethrow(error)); + } + if (value === undefined) { + this._scope.set(variable._name = name, variable); + } else { + variable.define(name, constant(value)); + } + } + } + return variable; +} + +function module_builtin(name, value) { + this._builtins.set(name, value); +} + +function variable_name(variable) { + return variable._name; +} + +const frame = typeof requestAnimationFrame === "function" ? requestAnimationFrame + : typeof setImmediate === "function" ? setImmediate + : f => setTimeout(f, 0); + +function Runtime(builtins = new Library, global = window_global) { + const builtin = this.module(); + Object.defineProperties(this, { + _dirty: {value: new Set}, + _updates: {value: new Set}, + _precomputes: {value: [], writable: true}, + _computing: {value: null, writable: true}, + _init: {value: null, writable: true}, + _modules: {value: new Map}, + _variables: {value: new Set}, + _disposed: {value: false, writable: true}, + _builtin: {value: builtin}, + _global: {value: global} + }); + if (builtins) for (const name in builtins) { + (new Variable(TYPE_IMPLICIT, builtin)).define(name, [], builtins[name]); + } +} + +Object.defineProperties(Runtime.prototype, { + _precompute: {value: runtime_precompute, writable: true, configurable: true}, + _compute: {value: runtime_compute, writable: true, configurable: true}, + _computeSoon: {value: runtime_computeSoon, writable: true, configurable: true}, + _computeNow: {value: runtime_computeNow, writable: true, configurable: true}, + dispose: {value: runtime_dispose, writable: true, configurable: true}, + module: {value: runtime_module, writable: true, configurable: true}, + fileAttachments: {value: FileAttachments, writable: true, configurable: true}, + load: {value: load, writable: true, configurable: true} +}); + +function runtime_dispose() { + this._computing = Promise.resolve(); + this._disposed = true; + this._variables.forEach(v => { + v._invalidate(); + v._version = NaN; + }); +} + +function runtime_module(define, observer = noop) { + let module; + if (define === undefined) { + if (module = this._init) { + this._init = null; + return module; + } + return new Module(this); + } + module = this._modules.get(define); + if (module) return module; + this._init = module = new Module(this); + this._modules.set(define, module); + try { + define(this, observer); + } finally { + this._init = null; + } + return module; +} + +function runtime_precompute(callback) { + this._precomputes.push(callback); + this._compute(); +} + +function runtime_compute() { + return this._computing || (this._computing = this._computeSoon()); +} + +function runtime_computeSoon() { + return new Promise(frame).then(() => this._disposed ? undefined : this._computeNow()); +} + +async function runtime_computeNow() { + let queue = [], + variables, + variable, + precomputes = this._precomputes; + + // If there are any paused generators, resume them before computing so they + // can update (if synchronous) before computing downstream variables. + if (precomputes.length) { + this._precomputes = []; + for (const callback of precomputes) callback(); + await runtime_defer(3); + } + + // Compute the reachability of the transitive closure of dirty variables. + // Any newly-reachable variable must also be recomputed. + // Any no-longer-reachable variable must be terminated. + variables = new Set(this._dirty); + variables.forEach(function(variable) { + variable._inputs.forEach(variables.add, variables); + const reachable = variable_reachable(variable); + if (reachable > variable._reachable) { + this._updates.add(variable); + } else if (reachable < variable._reachable) { + variable._invalidate(); + } + variable._reachable = reachable; + }, this); + + // Compute the transitive closure of updating, reachable variables. + variables = new Set(this._updates); + variables.forEach(function(variable) { + if (variable._reachable) { + variable._indegree = 0; + variable._outputs.forEach(variables.add, variables); + } else { + variable._indegree = NaN; + variables.delete(variable); + } + }); + + this._computing = null; + this._updates.clear(); + this._dirty.clear(); + + // Compute the indegree of updating variables. + variables.forEach(function(variable) { + variable._outputs.forEach(variable_increment); + }); + + do { + // Identify the root variables (those with no updating inputs). + variables.forEach(function(variable) { + if (variable._indegree === 0) { + queue.push(variable); + } + }); + + // Compute the variables in topological order. + while (variable = queue.pop()) { + variable_compute(variable); + variable._outputs.forEach(postqueue); + variables.delete(variable); + } + + // Any remaining variables are circular, or depend on them. + variables.forEach(function(variable) { + if (variable_circular(variable)) { + variable_error(variable, new RuntimeError("circular definition")); + variable._outputs.forEach(variable_decrement); + variables.delete(variable); + } + }); + } while (variables.size); + + function postqueue(variable) { + if (--variable._indegree === 0) { + queue.push(variable); + } + } +} + +// We want to give generators, if they’re defined synchronously, a chance to +// update before computing downstream variables. This creates a synchronous +// promise chain of the given depth that we’ll await before recomputing +// downstream variables. +function runtime_defer(depth = 0) { + let p = Promise.resolve(); + for (let i = 0; i < depth; ++i) p = p.then(() => {}); + return p; +} + +function variable_circular(variable) { + const inputs = new Set(variable._inputs); + for (const i of inputs) { + if (i === variable) return true; + i._inputs.forEach(inputs.add, inputs); + } + return false; +} + +function variable_increment(variable) { + ++variable._indegree; +} + +function variable_decrement(variable) { + --variable._indegree; +} + +function variable_value(variable) { + return variable._promise.catch(variable._rejector); +} + +function variable_invalidator(variable) { + return new Promise(function(resolve) { + variable._invalidate = resolve; + }); +} + +function variable_intersector(invalidation, variable) { + let node = typeof IntersectionObserver === "function" && variable._observer && variable._observer._node; + let visible = !node, resolve = noop, reject = noop, promise, observer; + if (node) { + observer = new IntersectionObserver(([entry]) => (visible = entry.isIntersecting) && (promise = null, resolve())); + observer.observe(node); + invalidation.then(() => (observer.disconnect(), observer = null, reject())); + } + return function(value) { + if (visible) return Promise.resolve(value); + if (!observer) return Promise.reject(); + if (!promise) promise = new Promise((y, n) => (resolve = y, reject = n)); + return promise.then(() => value); + }; +} + +function variable_compute(variable) { + variable._invalidate(); + variable._invalidate = noop; + variable._pending(); + + const value0 = variable._value; + const version = ++variable._version; + + // Lazily-constructed invalidation variable; only constructed if referenced as an input. + let invalidation = null; + + // If the variable doesn’t have any inputs, we can optimize slightly. + const promise = variable._promise = (variable._inputs.length + ? Promise.all(variable._inputs.map(variable_value)).then(define) + : new Promise(resolve => resolve(variable._definition.call(value0)))) + .then(generate); + + // Compute the initial value of the variable. + function define(inputs) { + if (variable._version !== version) throw variable_stale; + + // Replace any reference to invalidation with the promise, lazily. + for (let i = 0, n = inputs.length; i < n; ++i) { + switch (inputs[i]) { + case variable_invalidation: { + inputs[i] = invalidation = variable_invalidator(variable); + break; + } + case variable_visibility: { + if (!invalidation) invalidation = variable_invalidator(variable); + inputs[i] = variable_intersector(invalidation, variable); + break; + } + case variable_variable: { + inputs[i] = variable; + break; + } + } + } + + return variable._definition.apply(value0, inputs); + } + + // If the value is a generator, then retrieve its first value, and dispose of + // the generator if the variable is invalidated. Note that the cell may + // already have been invalidated here, in which case we need to terminate the + // generator immediately! + function generate(value) { + if (variable._version !== version) throw variable_stale; + if (generatorish(value)) { + (invalidation || variable_invalidator(variable)).then(variable_return(value)); + return variable_generate(variable, version, value); + } + return value; + } + + promise.then((value) => { + variable._value = value; + variable._fulfilled(value); + }, (error) => { + if (error === variable_stale) return; + variable._value = undefined; + variable._rejected(error); + }); +} + +function variable_generate(variable, version, generator) { + const runtime = variable._module._runtime; + let currentValue; // so that yield resolves to the yielded value + + // Retrieve the next value from the generator; if successful, invoke the + // specified callback. The returned promise resolves to the yielded value, or + // to undefined if the generator is done. + function compute(onfulfilled) { + return new Promise(resolve => resolve(generator.next(currentValue))).then(({done, value}) => { + return done ? undefined : Promise.resolve(value).then(onfulfilled); + }); + } + + // Retrieve the next value from the generator; if successful, fulfill the + // variable, compute downstream variables, and schedule the next value to be + // pulled from the generator at the start of the next animation frame. If not + // successful, reject the variable, compute downstream variables, and return. + function recompute() { + const promise = compute((value) => { + if (variable._version !== version) throw variable_stale; + currentValue = value; + postcompute(value, promise).then(() => runtime._precompute(recompute)); + variable._fulfilled(value); + return value; + }); + promise.catch((error) => { + if (error === variable_stale || variable._version !== version) return; + postcompute(undefined, promise); + variable._rejected(error); + }); + } + + // After the generator fulfills or rejects, set its current value, promise, + // and schedule any downstream variables for update. + function postcompute(value, promise) { + variable._value = value; + variable._promise = promise; + variable._outputs.forEach(runtime._updates.add, runtime._updates); + return runtime._compute(); + } + + // When retrieving the first value from the generator, the promise graph is + // already established, so we only need to queue the next pull. + return compute((value) => { + if (variable._version !== version) throw variable_stale; + currentValue = value; + runtime._precompute(recompute); + return value; + }); +} + +function variable_error(variable, error) { + variable._invalidate(); + variable._invalidate = noop; + variable._pending(); + ++variable._version; + variable._indegree = NaN; + (variable._promise = Promise.reject(error)).catch(noop); + variable._value = undefined; + variable._rejected(error); +} + +function variable_return(generator) { + return function() { + generator.return(); + }; +} + +function variable_reachable(variable) { + if (variable._observer !== no_observer) return true; // Directly reachable. + const outputs = new Set(variable._outputs); + for (const output of outputs) { + if (output._observer !== no_observer) return true; + output._outputs.forEach(outputs.add, outputs); + } + return false; +} + +function window_global(name) { + return globalThis[name]; +} + +function renderHtml(string) { + const template = document.createElement("template"); + template.innerHTML = string; + return document.importNode(template.content, true); +} + +function renderSvg(string) { + const g = document.createElementNS("http://www.w3.org/2000/svg", "g"); + g.innerHTML = string; + return g; +} + +const html = Object.assign(hypertext(renderHtml, fragment => { + if (fragment.firstChild === null) return null; + if (fragment.firstChild === fragment.lastChild) return fragment.removeChild(fragment.firstChild); + const span = document.createElement("span"); + span.appendChild(fragment); + return span; +}), {fragment: hypertext(renderHtml, fragment => fragment)}); + +Object.assign(hypertext(renderSvg, g => { + if (g.firstChild === null) return null; + if (g.firstChild === g.lastChild) return g.removeChild(g.firstChild); + return g; +}), {fragment: hypertext(renderSvg, g => { + const fragment = document.createDocumentFragment(); + while (g.firstChild) fragment.appendChild(g.firstChild); + return fragment; +})}); + +const +CODE_TAB = 9, +CODE_LF = 10, +CODE_FF = 12, +CODE_CR = 13, +CODE_SPACE = 32, +CODE_UPPER_A = 65, +CODE_UPPER_Z = 90, +CODE_LOWER_A = 97, +CODE_LOWER_Z = 122, +CODE_LT = 60, +CODE_GT = 62, +CODE_SLASH = 47, +CODE_DASH = 45, +CODE_BANG = 33, +CODE_EQ = 61, +CODE_DQUOTE = 34, +CODE_SQUOTE = 39, +CODE_QUESTION = 63, +STATE_DATA = 1, +STATE_TAG_OPEN = 2, +STATE_END_TAG_OPEN = 3, +STATE_TAG_NAME = 4, +STATE_BOGUS_COMMENT = 5, +STATE_BEFORE_ATTRIBUTE_NAME = 6, +STATE_AFTER_ATTRIBUTE_NAME = 7, +STATE_ATTRIBUTE_NAME = 8, +STATE_BEFORE_ATTRIBUTE_VALUE = 9, +STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED = 10, +STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED = 11, +STATE_ATTRIBUTE_VALUE_UNQUOTED = 12, +STATE_AFTER_ATTRIBUTE_VALUE_QUOTED = 13, +STATE_SELF_CLOSING_START_TAG = 14, +STATE_COMMENT_START = 15, +STATE_COMMENT_START_DASH = 16, +STATE_COMMENT = 17, +STATE_COMMENT_LESS_THAN_SIGN = 18, +STATE_COMMENT_LESS_THAN_SIGN_BANG = 19, +STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH = 20, +STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH = 21, +STATE_COMMENT_END_DASH = 22, +STATE_COMMENT_END = 23, +STATE_COMMENT_END_BANG = 24, +STATE_MARKUP_DECLARATION_OPEN = 25, +STATE_RAWTEXT = 26, +STATE_RAWTEXT_LESS_THAN_SIGN = 27, +STATE_RAWTEXT_END_TAG_OPEN = 28, +STATE_RAWTEXT_END_TAG_NAME = 29, +SHOW_COMMENT = 128, +SHOW_ELEMENT = 1, +TYPE_COMMENT = 8, +TYPE_ELEMENT = 1, +NS_SVG = "http://www.w3.org/2000/svg", +NS_XLINK = "http://www.w3.org/1999/xlink", +NS_XML = "http://www.w3.org/XML/1998/namespace", +NS_XMLNS = "http://www.w3.org/2000/xmlns/"; + +const svgAdjustAttributes = new Map([ + "attributeName", + "attributeType", + "baseFrequency", + "baseProfile", + "calcMode", + "clipPathUnits", + "diffuseConstant", + "edgeMode", + "filterUnits", + "glyphRef", + "gradientTransform", + "gradientUnits", + "kernelMatrix", + "kernelUnitLength", + "keyPoints", + "keySplines", + "keyTimes", + "lengthAdjust", + "limitingConeAngle", + "markerHeight", + "markerUnits", + "markerWidth", + "maskContentUnits", + "maskUnits", + "numOctaves", + "pathLength", + "patternContentUnits", + "patternTransform", + "patternUnits", + "pointsAtX", + "pointsAtY", + "pointsAtZ", + "preserveAlpha", + "preserveAspectRatio", + "primitiveUnits", + "refX", + "refY", + "repeatCount", + "repeatDur", + "requiredExtensions", + "requiredFeatures", + "specularConstant", + "specularExponent", + "spreadMethod", + "startOffset", + "stdDeviation", + "stitchTiles", + "surfaceScale", + "systemLanguage", + "tableValues", + "targetX", + "targetY", + "textLength", + "viewBox", + "viewTarget", + "xChannelSelector", + "yChannelSelector", + "zoomAndPan" +].map(name => [name.toLowerCase(), name])); + +const svgForeignAttributes = new Map([ + ["xlink:actuate", NS_XLINK], + ["xlink:arcrole", NS_XLINK], + ["xlink:href", NS_XLINK], + ["xlink:role", NS_XLINK], + ["xlink:show", NS_XLINK], + ["xlink:title", NS_XLINK], + ["xlink:type", NS_XLINK], + ["xml:lang", NS_XML], + ["xml:space", NS_XML], + ["xmlns", NS_XMLNS], + ["xmlns:xlink", NS_XMLNS] +]); + +function hypertext(render, postprocess) { + return function({raw: strings}) { + let state = STATE_DATA; + let string = ""; + let tagNameStart; // either an open tag or an end tag + let tagName; // only open; beware nesting! used only for rawtext + let attributeNameStart; + let attributeNameEnd; + let nodeFilter = 0; + + for (let j = 0, m = arguments.length; j < m; ++j) { + const input = strings[j]; + + if (j > 0) { + const value = arguments[j]; + switch (state) { + case STATE_RAWTEXT: { + if (value != null) { + const text = `${value}`; + if (isEscapableRawText(tagName)) { + string += text.replace(/[<]/g, entity); + } else if (new RegExp(`/]`, "i").test(string.slice(-tagName.length - 2) + text)) { + throw new Error("unsafe raw text"); // appropriate end tag + } else { + string += text; + } + } + break; + } + case STATE_DATA: { + if (value == null) ; else if (value instanceof Node + || (typeof value !== "string" && value[Symbol.iterator]) + || (/(?:^|>)$/.test(strings[j - 1]) && /^(?:<|$)/.test(input))) { + string += ""; + nodeFilter |= SHOW_COMMENT; + } else { + string += `${value}`.replace(/[<&]/g, entity); + } + break; + } + case STATE_BEFORE_ATTRIBUTE_VALUE: { + state = STATE_ATTRIBUTE_VALUE_UNQUOTED; + let text; + if (/^[\s>]/.test(input)) { + if (value == null || value === false) { + string = string.slice(0, attributeNameStart - strings[j - 1].length); + break; + } + if (value === true || (text = `${value}`) === "") { + string += "''"; + break; + } + const name = strings[j - 1].slice(attributeNameStart, attributeNameEnd); + if ((name === "style" && isObjectLiteral(value)) || typeof value === "function") { + string += "::" + j; + nodeFilter |= SHOW_ELEMENT; + break; + } + } + if (text === undefined) text = `${value}`; + if (text === "") throw new Error("unsafe unquoted empty string"); + string += text.replace(/^['"]|[\s>&]/g, entity); + break; + } + case STATE_ATTRIBUTE_VALUE_UNQUOTED: { + string += `${value}`.replace(/[\s>&]/g, entity); + break; + } + case STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: { + string += `${value}`.replace(/['&]/g, entity); + break; + } + case STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: { + string += `${value}`.replace(/["&]/g, entity); + break; + } + case STATE_BEFORE_ATTRIBUTE_NAME: { + if (isObjectLiteral(value)) { + string += "::" + j + "=''"; + nodeFilter |= SHOW_ELEMENT; + break; + } + throw new Error("invalid binding"); + } + case STATE_COMMENT: break; + default: throw new Error("invalid binding"); + } + } + + for (let i = 0, n = input.length; i < n; ++i) { + const code = input.charCodeAt(i); + + switch (state) { + case STATE_DATA: { + if (code === CODE_LT) { + state = STATE_TAG_OPEN; + } + break; + } + case STATE_TAG_OPEN: { + if (code === CODE_BANG) { + state = STATE_MARKUP_DECLARATION_OPEN; + } else if (code === CODE_SLASH) { + state = STATE_END_TAG_OPEN; + } else if (isAsciiAlphaCode(code)) { + tagNameStart = i, tagName = undefined; + state = STATE_TAG_NAME, --i; + } else if (code === CODE_QUESTION) { + state = STATE_BOGUS_COMMENT, --i; + } else { + state = STATE_DATA, --i; + } + break; + } + case STATE_END_TAG_OPEN: { + if (isAsciiAlphaCode(code)) { + state = STATE_TAG_NAME, --i; + } else if (code === CODE_GT) { + state = STATE_DATA; + } else { + state = STATE_BOGUS_COMMENT, --i; + } + break; + } + case STATE_TAG_NAME: { + if (isSpaceCode(code)) { + state = STATE_BEFORE_ATTRIBUTE_NAME; + tagName = lower(input, tagNameStart, i); + } else if (code === CODE_SLASH) { + state = STATE_SELF_CLOSING_START_TAG; + } else if (code === CODE_GT) { + tagName = lower(input, tagNameStart, i); + state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; + } + break; + } + case STATE_BEFORE_ATTRIBUTE_NAME: { + if (isSpaceCode(code)) ; else if (code === CODE_SLASH || code === CODE_GT) { + state = STATE_AFTER_ATTRIBUTE_NAME, --i; + } else if (code === CODE_EQ) { + state = STATE_ATTRIBUTE_NAME; + attributeNameStart = i + 1, attributeNameEnd = undefined; + } else { + state = STATE_ATTRIBUTE_NAME, --i; + attributeNameStart = i + 1, attributeNameEnd = undefined; + } + break; + } + case STATE_ATTRIBUTE_NAME: { + if (isSpaceCode(code) || code === CODE_SLASH || code === CODE_GT) { + state = STATE_AFTER_ATTRIBUTE_NAME, --i; + attributeNameEnd = i; + } else if (code === CODE_EQ) { + state = STATE_BEFORE_ATTRIBUTE_VALUE; + attributeNameEnd = i; + } + break; + } + case STATE_AFTER_ATTRIBUTE_NAME: { + if (isSpaceCode(code)) ; else if (code === CODE_SLASH) { + state = STATE_SELF_CLOSING_START_TAG; + } else if (code === CODE_EQ) { + state = STATE_BEFORE_ATTRIBUTE_VALUE; + } else if (code === CODE_GT) { + state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; + } else { + state = STATE_ATTRIBUTE_NAME, --i; + attributeNameStart = i + 1, attributeNameEnd = undefined; + } + break; + } + case STATE_BEFORE_ATTRIBUTE_VALUE: { + if (isSpaceCode(code)) ; else if (code === CODE_DQUOTE) { + state = STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED; + } else if (code === CODE_SQUOTE) { + state = STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED; + } else if (code === CODE_GT) { + state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; + } else { + state = STATE_ATTRIBUTE_VALUE_UNQUOTED, --i; + } + break; + } + case STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: { + if (code === CODE_DQUOTE) { + state = STATE_AFTER_ATTRIBUTE_VALUE_QUOTED; + } + break; + } + case STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: { + if (code === CODE_SQUOTE) { + state = STATE_AFTER_ATTRIBUTE_VALUE_QUOTED; + } + break; + } + case STATE_ATTRIBUTE_VALUE_UNQUOTED: { + if (isSpaceCode(code)) { + state = STATE_BEFORE_ATTRIBUTE_NAME; + } else if (code === CODE_GT) { + state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; + } + break; + } + case STATE_AFTER_ATTRIBUTE_VALUE_QUOTED: { + if (isSpaceCode(code)) { + state = STATE_BEFORE_ATTRIBUTE_NAME; + } else if (code === CODE_SLASH) { + state = STATE_SELF_CLOSING_START_TAG; + } else if (code === CODE_GT) { + state = isRawText(tagName) ? STATE_RAWTEXT : STATE_DATA; + } else { + state = STATE_BEFORE_ATTRIBUTE_NAME, --i; + } + break; + } + case STATE_SELF_CLOSING_START_TAG: { + if (code === CODE_GT) { + state = STATE_DATA; + } else { + state = STATE_BEFORE_ATTRIBUTE_NAME, --i; + } + break; + } + case STATE_BOGUS_COMMENT: { + if (code === CODE_GT) { + state = STATE_DATA; + } + break; + } + case STATE_COMMENT_START: { + if (code === CODE_DASH) { + state = STATE_COMMENT_START_DASH; + } else if (code === CODE_GT) { + state = STATE_DATA; + } else { + state = STATE_COMMENT, --i; + } + break; + } + case STATE_COMMENT_START_DASH: { + if (code === CODE_DASH) { + state = STATE_COMMENT_END; + } else if (code === CODE_GT) { + state = STATE_DATA; + } else { + state = STATE_COMMENT, --i; + } + break; + } + case STATE_COMMENT: { + if (code === CODE_LT) { + state = STATE_COMMENT_LESS_THAN_SIGN; + } else if (code === CODE_DASH) { + state = STATE_COMMENT_END_DASH; + } + break; + } + case STATE_COMMENT_LESS_THAN_SIGN: { + if (code === CODE_BANG) { + state = STATE_COMMENT_LESS_THAN_SIGN_BANG; + } else if (code !== CODE_LT) { + state = STATE_COMMENT, --i; + } + break; + } + case STATE_COMMENT_LESS_THAN_SIGN_BANG: { + if (code === CODE_DASH) { + state = STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH; + } else { + state = STATE_COMMENT, --i; + } + break; + } + case STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH: { + if (code === CODE_DASH) { + state = STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH; + } else { + state = STATE_COMMENT_END, --i; + } + break; + } + case STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH: { + state = STATE_COMMENT_END, --i; + break; + } + case STATE_COMMENT_END_DASH: { + if (code === CODE_DASH) { + state = STATE_COMMENT_END; + } else { + state = STATE_COMMENT, --i; + } + break; + } + case STATE_COMMENT_END: { + if (code === CODE_GT) { + state = STATE_DATA; + } else if (code === CODE_BANG) { + state = STATE_COMMENT_END_BANG; + } else if (code !== CODE_DASH) { + state = STATE_COMMENT, --i; + } + break; + } + case STATE_COMMENT_END_BANG: { + if (code === CODE_DASH) { + state = STATE_COMMENT_END_DASH; + } else if (code === CODE_GT) { + state = STATE_DATA; + } else { + state = STATE_COMMENT, --i; + } + break; + } + case STATE_MARKUP_DECLARATION_OPEN: { + if (code === CODE_DASH && input.charCodeAt(i + 1) === CODE_DASH) { + state = STATE_COMMENT_START, ++i; + } else { // Note: CDATA and DOCTYPE unsupported! + state = STATE_BOGUS_COMMENT, --i; + } + break; + } + case STATE_RAWTEXT: { + if (code === CODE_LT) { + state = STATE_RAWTEXT_LESS_THAN_SIGN; + } + break; + } + case STATE_RAWTEXT_LESS_THAN_SIGN: { + if (code === CODE_SLASH) { + state = STATE_RAWTEXT_END_TAG_OPEN; + } else { + state = STATE_RAWTEXT, --i; + } + break; + } + case STATE_RAWTEXT_END_TAG_OPEN: { + if (isAsciiAlphaCode(code)) { + tagNameStart = i; + state = STATE_RAWTEXT_END_TAG_NAME, --i; + } else { + state = STATE_RAWTEXT, --i; + } + break; + } + case STATE_RAWTEXT_END_TAG_NAME: { + if (isSpaceCode(code) && tagName === lower(input, tagNameStart, i)) { + state = STATE_BEFORE_ATTRIBUTE_NAME; + } else if (code === CODE_SLASH && tagName === lower(input, tagNameStart, i)) { + state = STATE_SELF_CLOSING_START_TAG; + } else if (code === CODE_GT && tagName === lower(input, tagNameStart, i)) { + state = STATE_DATA; + } else if (!isAsciiAlphaCode(code)) { + state = STATE_RAWTEXT, --i; + } + break; + } + default: { + state = undefined; + break; + } + } + } + + string += input; + } + + const root = render(string); + + const walker = document.createTreeWalker(root, nodeFilter, null, false); + const removeNodes = []; + while (walker.nextNode()) { + const node = walker.currentNode; + switch (node.nodeType) { + case TYPE_ELEMENT: { + const attributes = node.attributes; + for (let i = 0, n = attributes.length; i < n; ++i) { + const {name, value: currentValue} = attributes[i]; + if (/^::/.test(name)) { + const value = arguments[+name.slice(2)]; + removeAttribute(node, name), --i, --n; + for (const key in value) { + const subvalue = value[key]; + if (subvalue == null || subvalue === false) ; else if (typeof subvalue === "function") { + node[key] = subvalue; + } else if (key === "style" && isObjectLiteral(subvalue)) { + setStyles(node[key], subvalue); + } else { + setAttribute(node, key, subvalue === true ? "" : subvalue); + } + } + } else if (/^::/.test(currentValue)) { + const value = arguments[+currentValue.slice(2)]; + removeAttribute(node, name), --i, --n; + if (typeof value === "function") { + node[name] = value; + } else { // style + setStyles(node[name], value); + } + } + } + break; + } + case TYPE_COMMENT: { + if (/^::/.test(node.data)) { + const parent = node.parentNode; + const value = arguments[+node.data.slice(2)]; + if (value instanceof Node) { + parent.insertBefore(value, node); + } else if (typeof value !== "string" && value[Symbol.iterator]) { + if (value instanceof NodeList || value instanceof HTMLCollection) { + for (let i = value.length - 1, r = node; i >= 0; --i) { + r = parent.insertBefore(value[i], r); + } + } else { + for (const subvalue of value) { + if (subvalue == null) continue; + parent.insertBefore(subvalue instanceof Node ? subvalue : document.createTextNode(subvalue), node); + } + } + } else { + parent.insertBefore(document.createTextNode(value), node); + } + removeNodes.push(node); + } + break; + } + } + } + + for (const node of removeNodes) { + node.parentNode.removeChild(node); + } + + return postprocess(root); + }; +} + +function entity(character) { + return `&#${character.charCodeAt(0).toString()};`; +} + +function isAsciiAlphaCode(code) { + return (CODE_UPPER_A <= code && code <= CODE_UPPER_Z) + || (CODE_LOWER_A <= code && code <= CODE_LOWER_Z); +} + +function isSpaceCode(code) { + return code === CODE_TAB + || code === CODE_LF + || code === CODE_FF + || code === CODE_SPACE + || code === CODE_CR; // normalize newlines +} + +function isObjectLiteral(value) { + return value && value.toString === Object.prototype.toString; +} + +function isRawText(tagName) { + return tagName === "script" || tagName === "style" || isEscapableRawText(tagName); +} + +function isEscapableRawText(tagName) { + return tagName === "textarea" || tagName === "title"; +} + +function lower(input, start, end) { + return input.slice(start, end).toLowerCase(); +} + +function setAttribute(node, name, value) { + if (node.namespaceURI === NS_SVG) { + name = name.toLowerCase(); + name = svgAdjustAttributes.get(name) || name; + if (svgForeignAttributes.has(name)) { + node.setAttributeNS(svgForeignAttributes.get(name), name, value); + return; + } + } + node.setAttribute(name, value); +} + +function removeAttribute(node, name) { + if (node.namespaceURI === NS_SVG) { + name = name.toLowerCase(); + name = svgAdjustAttributes.get(name) || name; + if (svgForeignAttributes.has(name)) { + node.removeAttributeNS(svgForeignAttributes.get(name), name); + return; + } + } + node.removeAttribute(name); +} + +// We can’t use Object.assign because custom properties… +function setStyles(style, values) { + for (const name in values) { + const value = values[name]; + if (name.startsWith("--")) style.setProperty(name, value); + else style[name] = value; + } +} + +function length(x) { + return x == null ? null : typeof x === "number" ? `${x}px` : `${x}`; +} + +const bubbles = {bubbles: true}; + +function preventDefault(event) { + event.preventDefault(); +} + +function dispatchInput({currentTarget}) { + (currentTarget.form || currentTarget).dispatchEvent(new Event("input", bubbles)); +} + +function identity(x) { + return x; +} + +let nextId = 0; + +function newId() { + return `__ns__-${++nextId}`; +} + +function maybeLabel(label, input) { + if (!label) return; + label = html`