Lawliet18 commited on
Commit
6342ac4
·
1 Parent(s): db6cefc

Add application file

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
README.md CHANGED
@@ -1,12 +1,196 @@
1
- ---
2
- title: Swiftlenss
3
- emoji: 📉
4
- colorFrom: red
5
- colorTo: red
6
- sdk: gradio
7
- sdk_version: 5.29.0
8
- app_file: app.py
9
- pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # InstructIR: High-Quality Image Restoration Following Human Instructions (ECCV 2024)
2
+
3
+ [![arXiv](https://img.shields.io/badge/arXiv-Paper-<COLOR>.svg)](https://arxiv.org/abs/2401.16468)
4
+ <a href="https://colab.research.google.com/drive/1OrTvS-i6uLM2Y8kIkq8ZZRwEQxQFchfq?usp=sharing"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="google colab logo"></a>
5
+ [![Hugging Face](https://img.shields.io/badge/Demo-%F0%9F%A4%97%20Hugging%20Face-blue)](https://huggingface.co/spaces/marcosv/InstructIR)
6
+ [![Replicate](https://img.shields.io/badge/Demo-%F0%9F%9A%80%20Replicate-blue)](https://replicate.com/mv-lab/instructir)
7
+ [![Paper page](https://huggingface.co/datasets/huggingface/badges/resolve/main/paper-page-sm.svg)](https://huggingface.co/papers/2401.16468)
8
+
9
+
10
+ [Marcos V. Conde](https://mv-lab.github.io/), [Gregor Geigle](https://scholar.google.com/citations?user=uIlyqRwAAAAJ&hl=en), [Radu Timofte](https://scholar.google.com/citations?user=u3MwH5kAAAAJ&hl=en)
11
+
12
+ Computer Vision Lab, University of Wuerzburg | Sony PlayStation, FTG
13
+
14
+
15
+ <a href="https://mv-lab.github.io/InstructIR/"><img src="images/instructir.gif" alt="InstructIR" width=100%></a>
16
+
17
+ Video courtesy of Gradio ([see their post about InstructIR](https://twitter.com/Gradio/status/1752776176811041049)). Also shoutout to AK -- [see his tweet](https://twitter.com/_akhaliq/status/1752551364566126798).
18
+
19
+
20
+ ### TL;DR: quickstart
21
+ InstructIR takes as input an image and a human-written instruction for how to improve that image. The neural model performs all-in-one image restoration. InstructIR achieves state-of-the-art results on several restoration tasks including image denoising, deraining, deblurring, dehazing, and (low-light) image enhancement.
22
+
23
+ **🚀 You can start with the [demo tutorial](demo.ipynb)**
24
+
25
+ <details>
26
+ <summary> <b> Abstract</b> (click me to read)</summary>
27
+ <p>
28
+ Image restoration is a fundamental problem that involves recovering a high-quality clean image from its degraded observation. All-In-One image restoration models can effectively restore images from various types and levels of degradation using degradation-specific information as prompts to guide the restoration model. In this work, we present the first approach that uses human-written instructions to guide the image restoration model. Given natural language prompts, our model can recover high-quality images from their degraded counterparts, considering multiple degradation types. Our method, InstructIR, achieves state-of-the-art results on several restoration tasks including image denoising, deraining, deblurring, dehazing, and (low-light) image enhancement. InstructIR improves +1dB over previous all-in-one restoration methods. Moreover, our dataset and results represent a novel benchmark for new research on text-guided image restoration and enhancement.
29
+ </p>
30
+ </details>
31
+
32
+
33
+ ### TODO / News 🔥
34
+
35
+ - [ ] Upload Model weights and results for other InstructIR variants (3D, 5D).
36
+
37
+ - [x] [download all the test datasets](https://drive.google.com/file/d/11wGsKOMDVrBlsle4xtzORPLZAsGhel8c/view?usp=sharing) for all-in-one restoration.
38
+
39
+ - [x] check the instructions below to run `eval_instructir.py` and get all the metrics and results for all-in-one restoration.
40
+
41
+ - [x] You can download all the qualitative results here [instructir_results.zip](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip)
42
+
43
+ - [x] Upload models to HF 🤗 [(download the models here)](https://huggingface.co/marcosv/InstructIR)
44
+
45
+ - [x] 🤗 [Hugging Face Demo](https://huggingface.co/spaces/marcosv/InstructIR) try it now
46
+
47
+ - [x] [Google Colab Tutorial](https://colab.research.google.com/drive/1OrTvS-i6uLM2Y8kIkq8ZZRwEQxQFchfq?usp=sharing) (check [demo.ipynb](demo.ipynb))
48
+
49
+ ### Try it / Tutorial
50
+
51
+ [Try it]((https://huggingface.co/spaces/marcosv/InstructIR)) directly on 🤗 Hugging Face at no cost, no code.
52
+
53
+
54
+ 🚀 You can start with the [demo tutorial](demo.ipynb). We also host the same tutorial on [google colab](https://colab.research.google.com/drive/1OrTvS-i6uLM2Y8kIkq8ZZRwEQxQFchfq?usp=sharing) so you can run it using free GPUs!.
55
+
56
+
57
+ <a href="https://mv-lab.github.io/InstructIR/"><img src="images/instructir_teaser.png" alt="InstructIR" width=100%></a>
58
+
59
+ ## Results
60
+
61
+ Check `test.py` and `eval_instructir.py`. The following command provides all the metric for all the benchmarks using the pre-trained models in `models/`. The results from InstructIR are saved in the indicated folder `results/`
62
+
63
+ ```
64
+ python eval_instructir.py --model models/im_instructir-7d.pt --lm models/lm_instructir-7d.pt --device 0 --config configs/eval5d.yml --save results/
65
+ ```
66
+
67
+ An example of the output log is:
68
+
69
+ ```
70
+ >>> Eval on CBSD68_15 noise 0
71
+ CBSD68_15_base 24.84328738380881
72
+ CBSD68_15_psnr 33.98722295200123 68
73
+ CBSD68_15_ssim 0.9315137801801457
74
+
75
+ ....
76
+ ```
77
+
78
+ You can **[download all the test datasets](https://drive.google.com/file/d/11wGsKOMDVrBlsle4xtzORPLZAsGhel8c/view?usp=sharing)**, and locate them in `test-data/`. Make sure the paths are updated in the config file `configs/eval5d.yml`.
79
+
80
+ -------
81
+
82
+ You can **[download all the paper results](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip)** -check releases-. We test InstructIR in the following benchmarks:
83
+
84
+ | Dataset | Task | Test Results |
85
+ | :---------------- | :------ | ----: |
86
+ | BSD68 | Denoising | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
87
+ | Urban100 | Denoising | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
88
+ | Rain100 | Deraining | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
89
+ | [GoPro](https://seungjunnah.github.io/Datasets/gopro) | Deblurring | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
90
+ | [LOL](https://daooshee.github.io/BMVC2018website/) | Lol Image Enhancement | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
91
+ | [MIT5K](https://data.csail.mit.edu/graphics/fivek/) | Image Enhancement | [Download](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) |
92
+
93
+ In releases or clicking the link above you can download [instructir_results.zip](https://github.com/mv-lab/InstructIR/releases/download/instructir-results/instructir_results.zip) which includes all the qualitative results for those datasets [1.9 Gbs].
94
+
95
+
96
+ <img src="static/tables/table1.png" width=100%>
97
+
98
+ <br>
99
+
100
+ <details>
101
+ <summary> <b> Multi-task Results on Dehazing, Deraining, Denoising </b> </summary>
102
+ <img src="static/tables/table-3d.png" width=100%>
103
+ </details>
104
+
105
+ <details>
106
+ <summary> <b> Denoising Results (click to read) </b> </summary>
107
+ <img src="static/tables/table-dn.png" width=100%>
108
+ </details>
109
+
110
+ <details>
111
+ <summary> <b> Low-light Image Enhancement (LOL) Results (click to read) </b> </summary>
112
+ <img src="static/tables/table-lol.png" width=100%>
113
+ </details>
114
+
115
+ <details>
116
+ <summary> <b> Color Image Enhancement (MIT5K) Results (click to read) </b> </summary>
117
+ <img src="static/tables/table-mit5k.png" width=100%>
118
+ </details>
119
+
120
+ <br>
121
+
122
+ --------
123
+
124
+ ### Control and Interact
125
+
126
+ Sometimes the blur, rain, or film grain noise are pleasant effects and part of the **"aesthetics"**. Here we show a simple example on how to interact with InstructIR.
127
+
128
+ | Input |(1) I love this photo, could you remove the raindrops? please keep the content intact | (2) Can you make it look stunning? like a professional photo |
129
+ | --- | :---- | :--- |
130
+ | <img src="images/rain-020.png" width=100%> | <img src="images/results/result1.png" width=95%> | <img src="images/results/result2.png" width=100%> |
131
+ | Input |(1) my image is too dark, I cannot see anything, can you fix it? | (2) Great it looks nice! can you apply tone mapping? |
132
+ | <img src="images/lol_748.png" width=100%> | <img src="images/results/resultlol1.png" width=95%> | <img src="images/results/resultlol2.png" width=100%> |
133
+ | Input |(1) can you remove the tiny dots in the image? it is very unpleasant | (2) now please inprove the quality and resolution of the picture |
134
+ | <img src="images/frog.png" width=100%> | <img src="images/results/resultns1.png" width=95%> | <img src="images/results/resultns2.png" width=100%> |
135
+
136
+
137
+ As you can see our model accepts diverse humman-written prompts, from ambiguous to precise instructions. *How does it work?* Imagine we have the following image as input:
138
+
139
+ <img src="images/rain-020.png" width=50%>
140
+
141
+ Now we can use InstructIR. with the following prompt (1):
142
+ > I love this photo, could you remove the raindrops? please keep the content intact
143
+
144
+ <img src="images/results/result1.png" width=50%>
145
+
146
+ Now, let's enhance the image a bit further (2).
147
+ > Can you make it look stunning? like a professional photo
148
+
149
+ <img src="images/results/result2.png" width=50%>
150
+
151
+ The final result looks indeed stunning 🤗 You can do it yourself in the [demo tutorial]().
152
+
153
+ ### FAQS
154
+
155
+ > Disclaimer: please remember this is not a product, thus, you will notice some limitations. As most all-in-one restoration methods, it struggles to generalize on real-world images -- we are working on improving it.
156
+
157
+ - ***How should I start?*** Check our [demo Tutorial](demo.ipynb) and also our [google collab](https://colab.research.google.com/drive/1OrTvS-i6uLM2Y8kIkq8ZZRwEQxQFchfq?usp=sharing) notebook.
158
+
159
+ - ***How can I compare with your method?*** You can download the results for several benchmarks above on [Results](###Results).
160
+
161
+ - ***How can I test the model? I just want to play with it***: Visit our 🤗 [Hugging Face demo](https://huggingface.co/spaces/marcosv/InstructIR) and test ir for free,
162
+
163
+ - ***Why aren't you using diffusion-based models?*** (1) We want to keep the solution simple and efficient. (2) Our priority is high-fidelity --as in many industry scenarios realted to computational photography--.
164
+
165
+ ### Gradio Demo <a href='https://github.com/gradio-app/gradio'><img src='https://img.shields.io/github/stars/gradio-app/gradio'></a>
166
+ We made a simple [Gradio demo](app.py) you can run (locally) on your machine [here](app.py). You need Python>=3.9 and [these requirements](requirements_gradio.txt) for it: `pip install -r requirements_gradio.txt`
167
+
168
+ ```
169
+ python app.py
170
+ ```
171
+
172
+ <br>
173
+ <a href="https://huggingface.co/spaces/marcosv/InstructIR">
174
+ <img src="images/gradio.png" alt="InstructIR Gradio">
175
+ </a>
176
+
177
+
178
+ ### Acknowledgments
179
+ This work was partly supported by the The Humboldt Foundation (AvH). Marcos Conde is also supported by Sony Interactive Entertainment, FTG.
180
+
181
+ This work is inspired in [InstructPix2Pix](https://arxiv.org/abs/2211.09800).
182
+
183
+ ### Contacts
184
+ For any inquiries contact Marcos V. Conde: <a href="mailto:[email protected]">marcos.conde [at] uni-wuerzburg.de</a>
185
+
186
+
187
+ ### Citation BibTeX
188
+
189
+ ```
190
+ @inproceedings{conde2024high,
191
+ title={InstructIR: High-Quality Image Restoration Following Human Instructions},
192
+ author={Conde, Marcos V and Geigle, Gregor and Timofte, Radu},
193
+ booktitle = {Proceedings of the European Conference on Computer Vision (ECCV)},
194
+ year={2024}
195
+ }
196
+ ```
__pycache__/utils.cpython-310.pyc ADDED
Binary file (2.8 kB). View file
 
app.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import numpy as np
4
+ from PIL import Image
5
+ import yaml
6
+ import os
7
+ from utils import load_img, plot_all, dict2namespace, seed_everything
8
+ from models import instructir
9
+ from text.models import LanguageModel, LMHead
10
+
11
+ # Setup
12
+ SEED = 42
13
+ seed_everything(SEED=SEED)
14
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
15
+
16
+ CONFIG = "configs/eval5d.yml"
17
+ LM_MODEL = "models/lm_instructir-7d.pt"
18
+ MODEL_NAME = "models/im_instructir-7d.pt"
19
+
20
+ # Load config
21
+ with open(CONFIG, "r") as f:
22
+ config = yaml.safe_load(f)
23
+ cfg = dict2namespace(config)
24
+
25
+ # Load image model
26
+ model = instructir.create_model(
27
+ input_channels=cfg.model.in_ch,
28
+ width=cfg.model.width,
29
+ enc_blks=cfg.model.enc_blks,
30
+ middle_blk_num=cfg.model.middle_blk_num,
31
+ dec_blks=cfg.model.dec_blks,
32
+ txtdim=cfg.model.textdim
33
+ ).to(device)
34
+ model.load_state_dict(torch.load(MODEL_NAME, map_location=device), strict=True)
35
+ model.eval()
36
+
37
+ # Load language model
38
+ language_model = LanguageModel(model=cfg.llm.model)
39
+ lm_head = LMHead(embedding_dim=cfg.llm.model_dim, hidden_dim=cfg.llm.embd_dim, num_classes=cfg.llm.nclasses)
40
+ lm_head.load_state_dict(torch.load(LM_MODEL, map_location=device), strict=True)
41
+ lm_head.eval()
42
+
43
+ def process(image, prompt):
44
+ image = image.convert("RGB")
45
+ image = np.array(image).astype(np.float32) / 255.0
46
+ y = torch.tensor(image).permute(2, 0, 1).unsqueeze(0).to(device)
47
+
48
+ lm_embd = language_model(prompt)
49
+ text_embd, _ = lm_head(lm_embd)
50
+ x_hat = model(y, text_embd)
51
+
52
+ restored = x_hat[0].permute(1, 2, 0).cpu().detach().numpy()
53
+ restored = np.clip(restored, 0., 1.)
54
+ restored = (restored * 255).astype(np.uint8)
55
+ return Image.fromarray(restored)
56
+
57
+ interface = gr.Interface(
58
+ fn=process,
59
+ inputs=[
60
+ gr.Image(type="pil"),
61
+ gr.Textbox(label="Prompt", placeholder="Describe the restoration..."),
62
+ ],
63
+ outputs=gr.Image(type="pil"),
64
+ title="swiftlens: Prompt-Guided Image Restoration"
65
+ )
66
+
67
+ if __name__ == "__main__":
68
+ interface.launch()
cog.yaml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configuration for Cog ⚙️
2
+ # Reference: https://github.com/replicate/cog/blob/main/docs/yaml.md
3
+
4
+ build:
5
+ gpu: true
6
+ system_packages:
7
+ - "libgl1-mesa-glx"
8
+ - "libglib2.0-0"
9
+ python_version: "3.11"
10
+ python_packages:
11
+ - torch==2.0.1
12
+ - transformers==4.37.2
13
+ - PyYAML==6.0.1
14
+ - Pillow==10.2.0
15
+ - sentence-transformers==2.3.0
16
+ - opencv-python==4.9.0.80
17
+ - matplotlib==3.8.2
18
+ - imageio==2.33.1
19
+ predict: "predict.py:Predictor"
configs/eval5d.yml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ llm:
2
+ model: 'TaylorAI/bge-micro-v2' # See Paper Sec. 3.2 and Appendix
3
+ model_dim: 384
4
+ embd_dim: 256
5
+ nclasses: 7 # noise, blur, rain, haze, lol, enhancement, upsampling (Paper Sec. 4.3)
6
+ weights: False
7
+
8
+ model:
9
+ arch: "instructir"
10
+ use_text: True
11
+ in_ch: 3
12
+ out_ch: 3
13
+ width : 32
14
+ enc_blks: [2, 2, 4, 8]
15
+ middle_blk_num: 4
16
+ dec_blks: [2, 2, 2, 2]
17
+ textdim: 256
18
+ weights: False
19
+
20
+ test:
21
+ batch_size: 1
22
+ num_workers: 3
23
+
24
+ dn_datapath: "test-data/denoising_testsets/"
25
+ dn_datasets: ["CBSD68", "urban100", "Kodak24"]
26
+ dn_sigmas: [15, 25, 50]
27
+
28
+ rain_targets: ["test-data/Rain100L/target/"]
29
+ rain_inputs: ["test-data/Rain100L/input/"]
30
+
31
+ haze_targets: "test-data/SOTS/GT/"
32
+ haze_inputs : "test-data/SOTS/IN/"
33
+
34
+ lol_targets: "test-data/LOL/high/"
35
+ lol_inputs : "test-data/LOL/low/"
36
+
37
+ gopro_targets: "test-data/GoPro/target/"
38
+ gopro_inputs: "test-data/GoPro/input/"
data/.gitkeep ADDED
File without changes
datasets.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch.nn.functional as F
2
+ from torch.utils.data import DataLoader, Dataset
3
+ import torchvision
4
+ import torchvision.transforms.functional as TF
5
+ import numpy as np
6
+ import json
7
+ import os
8
+ from glob import glob
9
+
10
+ from utils import load_img, modcrop
11
+
12
+
13
+ DEG_MAP = {
14
+ "noise": 0,
15
+ "blur" : 1,
16
+ "rain" : 2,
17
+ "haze" : 3,
18
+ "lol" : 4,
19
+ "sr" : 5,
20
+ "en" : 6,
21
+ }
22
+
23
+ DEG2TASK = {
24
+ "noise": "denoising",
25
+ "blur" : "deblurring",
26
+ "rain" : "deraining",
27
+ "haze" : "dehazing",
28
+ "lol" : "lol",
29
+ "sr" : "sr",
30
+ "en" : "enhancement"
31
+ }
32
+
33
+ def augment_prompt (prompt):
34
+ ### special prompts
35
+ lol_prompts = ["fix the illumination", "increase the exposure of the photo", "the image is too dark to see anything, correct the photo", "poor illumination, improve the shot", "brighten dark regions", "make it HDR", "improve the light of the image", "Can you make the image brighter?"]
36
+ sr_prompts = ["I need to enhance the size and quality of this image.", "My photo is lacking size and clarity; can you improve it?", "I'd appreciate it if you could upscale this photo.", "My picture is too little, enlarge it.", "upsample this image", "increase the resolution of this photo", "increase the number of pixels", "upsample this photo", "Add details to this image", "improve the quality of this photo"]
37
+ en_prompts = ["make my image look like DSLR", "improve the colors of my image", "improve the contrast of this photo", "apply tonemapping", "enhance the colors of the image", "retouch the photo like a photograper"]
38
+
39
+ init = np.random.choice(["Remove the", "Reduce the", "Clean the", "Fix the", "Remove", "Improve the", "Correct the",])
40
+ end = np.random.choice(["please", "fast", "now", "in the photo", "in the picture", "in the image", ""])
41
+ newp = f"{init} {prompt} {end}"
42
+
43
+ if "lol" in prompt:
44
+ newp = np.random.choice(lol_prompts)
45
+ elif "sr" in prompt:
46
+ newp = np.random.choice(sr_prompts)
47
+ elif "en" in prompt:
48
+ newp = np.random.choice(en_prompts)
49
+
50
+ newp = newp.strip().replace(" ", " ").replace("\n", "")
51
+ return newp
52
+
53
+ def get_deg_name(path):
54
+ """
55
+ Get the degradation name from the path
56
+ """
57
+
58
+ if ("gopro" in path) or ("GoPro" in path) or ("blur" in path) or ("Blur" in path) or ("RealBlur" in path):
59
+ return "blur"
60
+ elif ("SOTS" in path) or ("haze" in path) or ("sots" in path) or ("RESIDE" in path):
61
+ return "haze"
62
+ elif ("LOL" in path):
63
+ return "lol"
64
+ elif ("fiveK" in path):
65
+ return "en"
66
+ elif ("super" in path) or ("classicalSR" in path):
67
+ return "sr"
68
+ elif ("Rain100" in path) or ("rain13k" in path) or ("Rain13k" in path):
69
+ return "rain"
70
+ else:
71
+ return "noise"
72
+
73
+ def crop_img(image, base=16):
74
+ """
75
+ Mod crop the image to ensure the dimension is divisible by base. Also done by SwinIR, Restormer and others.
76
+ """
77
+ h = image.shape[0]
78
+ w = image.shape[1]
79
+ crop_h = h % base
80
+ crop_w = w % base
81
+ return image[crop_h // 2:h - crop_h + crop_h // 2, crop_w // 2:w - crop_w + crop_w // 2, :]
82
+
83
+
84
+ ################# DATASETS
85
+
86
+
87
+ class RefDegImage(Dataset):
88
+ """
89
+ Dataset for Image Restoration having low-quality image and the reference image.
90
+ Tasks: synthetic denoising, deblurring, super-res, etc.
91
+ """
92
+
93
+ def __init__(self, hq_img_paths, lq_img_paths, augmentations=None, val=False, name="test", deg_name="noise", deg_class=0):
94
+
95
+ assert len(hq_img_paths) == len(lq_img_paths)
96
+
97
+ self.hq_paths = hq_img_paths
98
+ self.lq_paths = lq_img_paths
99
+ self.totensor = torchvision.transforms.ToTensor()
100
+ self.val = val
101
+ self.augs = augmentations
102
+ self.name = name
103
+ self.degradation = deg_name
104
+ self.deg_class = deg_class
105
+
106
+ if self.val:
107
+ self.augs = None # No augmentations during validation/test
108
+
109
+ def __len__(self):
110
+ return len(self.hq_paths)
111
+
112
+ def __getitem__(self, idx):
113
+ hq_path = self.hq_paths[idx]
114
+ lq_path = self.lq_paths[idx]
115
+
116
+ hq_image = load_img(hq_path)
117
+ lq_image = load_img(lq_path)
118
+
119
+ if self.val:
120
+ # if an image has an odd number dimension we trim for example from [321, 189] to [320, 188].
121
+ hq_image = crop_img(hq_image)
122
+ lq_image = crop_img(lq_image)
123
+
124
+ hq_image = self.totensor(hq_image.astype(np.float32))
125
+ lq_image = self.totensor(lq_image.astype(np.float32))
126
+
127
+ return hq_image, lq_image, hq_path
128
+
129
+
130
+
131
+ def create_testsets (testsets, debug=False):
132
+ """
133
+ Given a list of testsets create pytorch datasets for each.
134
+ The method requires the paths to references and noisy images.
135
+ """
136
+ assert len(testsets) > 0
137
+
138
+ if debug:
139
+ print (20*'****')
140
+ print ("Creating Testsets", len(testsets))
141
+
142
+ datasets = []
143
+ for testdt in testsets:
144
+
145
+ path_hq , path_lq = testdt[0], testdt[1]
146
+ if debug: print (path_hq , path_lq)
147
+
148
+ if ("denoising" in path_hq) or ("jpeg" in path_hq):
149
+ dataset_name = path_hq.split("/")[-1]
150
+ dataset_sigma = path_lq.split("/")[-1].split("_")[-1].split(".")[0]
151
+ dataset_name = dataset_name+ f"_{dataset_sigma}"
152
+ elif "Rain" in path_hq:
153
+ if "Rain100L" in path_hq:
154
+ dataset_name = "Rain100L"
155
+ else:
156
+ dataset_name = path_hq.split("/")[3]
157
+
158
+ elif ("gopro" in path_hq) or ("GoPro" in path_hq):
159
+ dataset_name = "GoPro"
160
+ elif "LOL" in path_hq:
161
+ dataset_name = "LOL"
162
+ elif "SOTS" in path_hq:
163
+ dataset_name = "SOTS"
164
+ elif "fiveK" in path_hq:
165
+ dataset_name = "MIT5K"
166
+ else:
167
+ assert False, f"{path_hq} - unknown dataset"
168
+
169
+ hq_img_paths = sorted(glob(os.path.join(path_hq, "*")))
170
+ lq_img_paths = sorted(glob(os.path.join(path_lq, "*")))
171
+
172
+ if "SOTS" in path_hq:
173
+ # Haze removal SOTS test dataset
174
+ dataset_name = "SOTS"
175
+ hq_img_paths = sorted(glob(os.path.join(path_hq, "*.jpg")))
176
+ assert len(hq_img_paths) == 500
177
+
178
+ lq_img_paths = [file.replace("GT", "IN") for file in hq_img_paths]
179
+
180
+ if "fiveK" in path_hq:
181
+ dataset_name = "MIT5K"
182
+ testf = "test-data/mit5k/test.txt"
183
+ f = open(testf, "r")
184
+ test_ids = f.readlines()
185
+ test_ids = [x.strip() for x in test_ids]
186
+ f.close()
187
+ hq_img_paths = [os.path.join(path_hq, f"{x}.jpg") for x in test_ids]
188
+ lq_img_paths = [x.replace("expertC", "input") for x in hq_img_paths]
189
+ assert len(hq_img_paths) == 498
190
+
191
+ if "gopro" in path_hq:
192
+ assert len(hq_img_paths) == 1111
193
+
194
+ if "LOL" in path_hq:
195
+ assert len(hq_img_paths) == 15
196
+
197
+ assert len(hq_img_paths) == len(lq_img_paths)
198
+
199
+ deg_name = get_deg_name(path_hq)
200
+ deg_class = DEG_MAP[deg_name]
201
+
202
+ valdts = RefDegImage(hq_img_paths = hq_img_paths,
203
+ lq_img_paths = lq_img_paths,
204
+ val = True, name= dataset_name, deg_name=deg_name, deg_class=deg_class)
205
+
206
+ datasets.append(valdts)
207
+
208
+ assert len(datasets) == len(testsets)
209
+ print (20*'****')
210
+
211
+ return datasets
demo.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
eval_instructir.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+ import torch.nn.functional as F
4
+ from torch.utils.data import DataLoader, Dataset
5
+ import torchvision
6
+ import torchvision.transforms.functional as TF
7
+
8
+ import json
9
+ import os
10
+ from PIL import Image
11
+ import numpy as np
12
+ import matplotlib.pyplot as plt
13
+ import yaml
14
+ import random
15
+ import gc
16
+
17
+ from utils import *
18
+ from models import instructir
19
+
20
+ from text.models import LanguageModel, LMHead
21
+
22
+ from test import test_model
23
+
24
+
25
+ def seed_everything(SEED=42):
26
+ random.seed(SEED)
27
+ np.random.seed(SEED)
28
+ torch.manual_seed(SEED)
29
+ torch.cuda.manual_seed(SEED)
30
+ torch.cuda.manual_seed_all(SEED)
31
+ torch.backends.cudnn.benchmark = True
32
+
33
+
34
+ if __name__=="__main__":
35
+
36
+ parser = argparse.ArgumentParser()
37
+ parser.add_argument('--config', type=str, default='configs/eval5d.yml', help='Path to config file')
38
+ parser.add_argument('--model', type=str, default="models/im_instructir-7d.pt", help='Path to the image model weights')
39
+ parser.add_argument('--lm', type=str, default="models/lm_instructir-7d.pt", help='Path to the language model weights')
40
+ parser.add_argument('--promptify', type=str, default="simple_augment")
41
+ parser.add_argument('--device', type=int, default=0, help="GPU device")
42
+ parser.add_argument('--debug', action='store_true', help="Debug mode")
43
+ parser.add_argument('--save', type=str, default='results/', help="Path to save the resultant images")
44
+ args = parser.parse_args()
45
+
46
+ SEED=42
47
+ seed_everything(SEED=SEED)
48
+ torch.backends.cudnn.deterministic = True
49
+
50
+ GPU = args.device
51
+ DEBUG = args.debug
52
+ MODEL_NAME = args.model
53
+ CONFIG = args.config
54
+ LM_MODEL = args.lm
55
+ SAVE_PATH = args.save
56
+
57
+ print ('CUDA GPU available: ', torch.cuda.is_available())
58
+
59
+ torch.cuda.set_device(f'cuda:{GPU}')
60
+ device = torch.device(f'cuda:{GPU}' if torch.cuda.is_available() else "cpu")
61
+ print ('CUDA visible devices: ' + str(torch.cuda.device_count()))
62
+ print ('CUDA current device: ', torch.cuda.current_device(), torch.cuda.get_device_name(torch.cuda.current_device()))
63
+
64
+ # parse config file
65
+ with open(os.path.join(CONFIG), "r") as f:
66
+ config = yaml.safe_load(f)
67
+
68
+ cfg = dict2namespace(config)
69
+
70
+
71
+ print (20*"****")
72
+ print ("EVALUATION")
73
+ print (MODEL_NAME, LM_MODEL, device, DEBUG, CONFIG, args.promptify)
74
+ print (20*"****")
75
+
76
+ ################### TESTING DATASET
77
+
78
+ TESTSETS = []
79
+ dn_testsets = []
80
+ rain_testsets = []
81
+
82
+ # Denoising
83
+ try:
84
+ for testset in cfg.test.dn_datasets:
85
+ for sigma in cfg.test.dn_sigmas:
86
+ noisy_testpath = os.path.join(cfg.test.dn_datapath, testset+ f"_{sigma}")
87
+ clean_testpath = os.path.join(cfg.test.dn_datapath, testset)
88
+ #print (clean_testpath, noisy_testpath)
89
+ dn_testsets.append([clean_testpath, noisy_testpath])
90
+ except:
91
+ dn_testsets = []
92
+
93
+ # RAIN
94
+ try:
95
+ for noisy_testpath, clean_testpath in zip(cfg.test.rain_inputs, cfg.test.rain_targets):
96
+ rain_testsets.append([clean_testpath, noisy_testpath])
97
+ except:
98
+ rain_testsets = []
99
+
100
+ # HAZE
101
+ try:
102
+ haze_testsets = [[cfg.test.haze_targets, cfg.test.haze_inputs]]
103
+ except:
104
+ haze_testsets = []
105
+
106
+ # BLUR
107
+ try:
108
+ blur_testsets = [[cfg.test.gopro_targets, cfg.test.gopro_inputs]]
109
+ except:
110
+ blur_testsets = []
111
+
112
+ # LOL
113
+ try:
114
+ lol_testsets = [[cfg.test.lol_targets, cfg.test.lol_inputs]]
115
+ except:
116
+ lol_testsets = []
117
+
118
+ # MIT5K
119
+ try:
120
+ mit_testsets = [[cfg.test.mit_targets, cfg.test.mit_inputs]]
121
+ except:
122
+ mit_testsets = []
123
+
124
+ TESTSETS += dn_testsets
125
+ TESTSETS += rain_testsets
126
+ TESTSETS += haze_testsets
127
+ TESTSETS += blur_testsets
128
+ TESTSETS += lol_testsets
129
+ TESTSETS += mit_testsets
130
+
131
+ # print ("Tests:", TESTSETS)
132
+ print ("TOTAL TESTSET:", len(TESTSETS))
133
+ print (20 * "----")
134
+
135
+
136
+ ################### RESTORATION MODEL
137
+
138
+ print ("Creating InstructIR")
139
+ model = instructir.create_model(input_channels =cfg.model.in_ch, width=cfg.model.width, enc_blks = cfg.model.enc_blks,
140
+ middle_blk_num = cfg.model.middle_blk_num, dec_blks = cfg.model.dec_blks, txtdim=cfg.model.textdim)
141
+
142
+ ################### LOAD IMAGE MODEL
143
+
144
+ assert MODEL_NAME, "Model weights required for evaluation"
145
+
146
+ print ("IMAGE MODEL CKPT:", MODEL_NAME)
147
+ model.load_state_dict(torch.load(MODEL_NAME), strict=True)
148
+
149
+ model = model.to(device)
150
+
151
+ nparams = count_params (model)
152
+ print ("Loaded weights!", nparams / 1e6)
153
+
154
+ ################### LANGUAGE MODEL
155
+
156
+ try:
157
+ PROMPT_DB = cfg.llm.text_db
158
+ except:
159
+ PROMPT_DB = None
160
+
161
+ if cfg.model.use_text:
162
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
163
+
164
+ # Initialize the LanguageModel class
165
+ LMODEL = cfg.llm.model
166
+ language_model = LanguageModel(model=LMODEL)
167
+ lm_head = LMHead(embedding_dim=cfg.llm.model_dim, hidden_dim=cfg.llm.embd_dim, num_classes=cfg.llm.nclasses)
168
+ lm_head = lm_head.to(device)
169
+ lm_nparams = count_params (lm_head)
170
+
171
+ print ("LMHEAD MODEL CKPT:", LM_MODEL)
172
+ lm_head.load_state_dict(torch.load(LM_MODEL), strict=True)
173
+ print ("Loaded weights!")
174
+
175
+ else:
176
+ LMODEL = None
177
+ language_model = None
178
+ lm_head = None
179
+ lm_nparams = 0
180
+
181
+ print (20 * "----")
182
+
183
+ ################### TESTING !!
184
+
185
+ from datasets import RefDegImage, augment_prompt, create_testsets
186
+
187
+ if args.promptify == "simple_augment":
188
+ promptify = augment_prompt
189
+ elif args.promptify == "chatgpt":
190
+ prompts = json.load(open(cfg.llm.text_db))
191
+ def promptify(deg):
192
+
193
+ return np.random.choice(prompts[deg])
194
+ else:
195
+ def promptify(deg):
196
+ return args.promptify
197
+
198
+ torch.cuda.empty_cache()
199
+ torch.cuda.reset_peak_memory_stats()
200
+
201
+ test_datasets = create_testsets(TESTSETS, debug=True)
202
+
203
+ test_model (model, language_model, lm_head, test_datasets, device, promptify, savepath=SAVE_PATH)
204
+
im_instructir-7d.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f28d8f0f66ff57449ebe2be52241dfdd53a3dfab1003d63e65493f96ea152fd0
3
+ size 63627895
index.html ADDED
@@ -0,0 +1,440 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html class="fontawesome-i2svg-active fontawesome-i2svg-complete" lang="en-US"><head>
3
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
4
+ <meta charset="utf-8">
5
+ <meta name="description" content="InstructIR: High-Quality Image Restoration Following Human Instructions ">
6
+ <meta name="keywords" content="Computer Vision, Image Restoration, Multimodal, Prompt">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>InstructIR</title>
9
+
10
+ <style type="text/css">svg:not(:root).svg-inline--fa{overflow:visible}.svg-inline--fa{display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em}.svg-inline--fa.fa-lg{vertical-align:-.225em}.svg-inline--fa.fa-w-1{width:.0625em}.svg-inline--fa.fa-w-2{width:.125em}.svg-inline--fa.fa-w-3{width:.1875em}.svg-inline--fa.fa-w-4{width:.25em}.svg-inline--fa.fa-w-5{width:.3125em}.svg-inline--fa.fa-w-6{width:.375em}.svg-inline--fa.fa-w-7{width:.4375em}.svg-inline--fa.fa-w-8{width:.5em}.svg-inline--fa.fa-w-9{width:.5625em}.svg-inline--fa.fa-w-10{width:.625em}.svg-inline--fa.fa-w-11{width:.6875em}.svg-inline--fa.fa-w-12{width:.75em}.svg-inline--fa.fa-w-13{width:.8125em}.svg-inline--fa.fa-w-14{width:.875em}.svg-inline--fa.fa-w-15{width:.9375em}.svg-inline--fa.fa-w-16{width:1em}.svg-inline--fa.fa-w-17{width:1.0625em}.svg-inline--fa.fa-w-18{width:1.125em}.svg-inline--fa.fa-w-19{width:1.1875em}.svg-inline--fa.fa-w-20{width:1.25em}.svg-inline--fa.fa-pull-left{margin-right:.3em;width:auto}.svg-inline--fa.fa-pull-right{margin-left:.3em;width:auto}.svg-inline--fa.fa-border{height:1.5em}.svg-inline--fa.fa-li{width:2em}.svg-inline--fa.fa-fw{width:1.25em}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-.125em;width:1em}.fa-layers svg.svg-inline--fa{-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers-text{left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter{background-color:#ff253a;border-radius:1em;-webkit-box-sizing:border-box;box-sizing:border-box;color:#fff;height:1.5em;line-height:1;max-width:5em;min-width:1.5em;overflow:hidden;padding:.25em;right:0;text-overflow:ellipsis;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-bottom-right{bottom:0;right:0;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom right;transform-origin:bottom right}.fa-layers-bottom-left{bottom:0;left:0;right:auto;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom left;transform-origin:bottom left}.fa-layers-top-right{right:0;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-top-left{left:0;right:auto;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top left;transform-origin:top left}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-webkit-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1,-1);transform:scale(-1,-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;position:relative;width:2.5em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.svg-inline--fa.fa-stack-1x{height:1em;width:1.25em}.svg-inline--fa.fa-stack-2x{height:2em;width:2.5em}.fa-inverse{color:#fff}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.svg-inline--fa .fa-primary{fill:var(--fa-primary-color,currentColor);opacity:1;opacity:var(--fa-primary-opacity,1)}.svg-inline--fa .fa-secondary{fill:var(--fa-secondary-color,currentColor);opacity:.4;opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-primary{opacity:.4;opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-secondary{opacity:1;opacity:var(--fa-primary-opacity,1)}.svg-inline--fa mask .fa-primary,.svg-inline--fa mask .fa-secondary{fill:#000}.fad.fa-inverse{color:#fff}</style><link rel="stylesheet" href="static/css.css">
11
+ <link rel="stylesheet" href="static/bulma.min.css">
12
+ <link rel="stylesheet" href="static/bootstrap.min.css">
13
+ <link rel="stylesheet" href="static/academicons.min.css">
14
+ <link rel="stylesheet" href="static/all.min.css">
15
+ <link rel="stylesheet" href="static/index.css">
16
+ <link rel="icon" href="https://emojiisland.com/cdn/shop/products/Robot_Emoji_Icon_abe1111a-1293-4668-bdf9-9ceb05cff58e_large.png?v=1571606090">
17
+ <link href="static/icon.css" rel="stylesheet">
18
+
19
+
20
+ <script src="static/jquery.min.js"></script>
21
+ <script defer="defer" src="static/all.min.js"></script>
22
+ <script type="module" src="static/gradio.js"></script>
23
+ <style>
24
+ .expandable-card .card-text-container {
25
+ max-height: 200px;
26
+ overflow-y: hidden;
27
+ position: relative;
28
+ }
29
+
30
+ .expandable-card.expanded .card-text-container {
31
+ max-height: none;
32
+ }
33
+
34
+ .expand-btn {
35
+ position: relative;
36
+ display: none;
37
+ background-color: rgba(255, 255, 255, 0.8);
38
+ /* margin-top: -20px; */
39
+ /* justify-content: center; */
40
+ color: #510c75;
41
+ border-color: transparent;
42
+ }
43
+
44
+ .expand-btn:hover {
45
+ background-color: rgba(200, 200, 200, 0.8);
46
+ text-decoration: none;
47
+ border-color: transparent;
48
+ color: #510c75;
49
+ }
50
+
51
+ .expand-btn:focus {
52
+ outline: none;
53
+ text-decoration: none;
54
+ }
55
+
56
+ .expandable-card:not(.expanded) .card-text-container:after {
57
+ content: "";
58
+ position: absolute;
59
+ bottom: 0;
60
+ left: 0;
61
+ width: 100%;
62
+ height: 90px;
63
+ background: linear-gradient(rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 1));
64
+ }
65
+
66
+ .expandable-card:not(.expanded) .expand-btn {
67
+ margin-top: -40px;
68
+ }
69
+
70
+ .card-body {
71
+ padding-bottom: 5px;
72
+ }
73
+
74
+ .vertical-flex-layout {
75
+ justify-content: center;
76
+ align-items: center;
77
+ height: 100%;
78
+ display: flex;
79
+ flex-direction: column;
80
+ gap: 5px;
81
+ }
82
+
83
+ .figure-img {
84
+ max-width: 100%;
85
+ height: auto;
86
+ }
87
+
88
+ .adjustable-font-size {
89
+ font-size: calc(0.5rem + 2vw);
90
+ }
91
+
92
+ .chat-history {
93
+ flex-grow: 1;
94
+ overflow-y: auto;
95
+ /* overflow-x: hidden; */
96
+ padding: 5px;
97
+ border-bottom: 1px solid #ccc;
98
+ margin-bottom: 10px;
99
+ }
100
+
101
+ #gradio pre {
102
+ background-color: transparent;
103
+ }
104
+ </style><script type="module" crossorigin="" src="static/index-9405f928.js"></script><link rel="stylesheet" href="static/index-8f5e8d2d.css"><link rel="stylesheet" href="static/theme.css"><link rel="stylesheet" href="static/css2.css"><link rel="stylesheet" href="static/css2_002.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Blocks-b7e1d3bc.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Button-496612d6.js"><link rel="stylesheet" href="static/Button-3657eefc.css"><link rel="stylesheet" href="static/Blocks-005a10ea.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-7da00dd0.js"><link rel="modulepreload" as="script" crossorigin="" href="static/index-9405f928.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-e350ed90.js"><link rel="stylesheet" href="static/index-edf307d2.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-9454ebde.js"><link rel="stylesheet" href="static/index-93c91554.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-29aa4c6e.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Column-56337312.js"><link rel="stylesheet" href="static/Column-2853eb31.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-6c061571.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/BlockTitle-3b63dcc6.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Info-88fa40fc.js"><link rel="stylesheet" href="static/ColorPicker-41813019.css"><link rel="stylesheet" href="static/DropdownArrow-5fa4dd09.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-dc4f9a55.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/BlockLabel-eae79103.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Image-0296a7e2.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/StaticImage.svelte_svelte_type_style_lang-943673fc.js"><link rel="stylesheet" href="static/StaticImage-ede66243.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/ModifyUpload-3ceaec64.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/ModifyUpload.svelte_svelte_type_style_lang-ba6baa96.js"><link rel="stylesheet" href="static/ModifyUpload-77b0d4b2.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Upload-0b7d7edd.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Empty-0bf01d93.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Download-836e8a5d.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/UploadText-67055cc3.js"><link rel="stylesheet" href="static/UploadText-33d53a1c.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Image-4f594cb8.js"><link rel="stylesheet" href="static/Image-003ee87c.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-fb7b6d6a.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-4360065a.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/_commonjsHelpers-042e6b4d.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/csv-b0b7514a.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/dsv-576afacd.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Model3D-49e4759c.js"><link rel="stylesheet" href="static/Model3D-98fc2b2c.css"><link rel="stylesheet" href="static/index-4a8edf2e.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-544cdc5f.js"><link rel="stylesheet" href="static/index-8f1feca1.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-efacc33c.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-5ff6e9da.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Form-e2ba6e12.js"><link rel="stylesheet" href="static/Form-a4a7741e.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-74280621.js"><link rel="stylesheet" href="static/index-d9aad8e1.css"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-f67a924c.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Textbox-91bfa043.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/Copy-4761247d.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-00a3ebda.js"><link rel="modulepreload" as="script" crossorigin="" href="https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-1c9d35e7.js"><link rel="stylesheet" href="static/index-3ca142e0.css"><script async="" defer="defer" src="static/js.js"></script></head>
105
+
106
+
107
+
108
+ <body>
109
+
110
+
111
+ <section class="hero">
112
+ <div class="hero-body">
113
+ <div class="container is-max-desktop">
114
+ <div class="columns is-centered">
115
+ <div class="column has-text-centered">
116
+ <h1 class="title is-1 publication-title">InstructIR: High-Quality Image Restoration Following Human Instructions</h1>
117
+ <br>
118
+ <div class="is-size-4 publication-authors">
119
+ <span class="author-block">
120
+ <a href="https://mv-lab.github.io/" style="color:#f68946;font-weight:normal;">Marcos V. Conde<sup>1,2</sup></a>,
121
+ </span>
122
+ <span class="author-block">
123
+ <a href="https://scholar.google.com/citations?user=uIlyqRwAAAAJ&hl=en" style="color:#008AD7;font-weight:normal;">Gregor Geigle<sup>1</sup></a>,
124
+ </span>
125
+ <span class="author-block">
126
+ <a href="https://scholar.google.com/citations?hl=en&user=u3MwH5kAAAAJ" style="color:#F2A900;font-weight:normal;">Radu Timofte<sup>1</sup></a>,
127
+ </span>
128
+
129
+ </div>
130
+
131
+ <div class="is-size-5 publication-authors">
132
+ <span class="author-block"><b style="color:#f68946; font-weight:normal">▶ </b> <sup>1</sup>Computer Vision Lab, University of Wuerzburg</span>
133
+ &nbsp&nbsp <span class="author-block"><b style="color:#008AD7; font-weight:normal">▶ </b> <sup>2</sup>Sony PlayStation, FTG</span>
134
+ </div>
135
+
136
+ <br>
137
+
138
+ <div class="column has-text-centered">
139
+ <div class="publication-links">
140
+
141
+
142
+ <span class="link-block">
143
+ <a href="https://arxiv.org/pdf/2401.16468.pdf" target="_blank" class="external-link button is-normal is-rounded is-dark">
144
+ <span class="icon">
145
+ <svg class="svg-inline--fa fa-file-pdf fa-w-12" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-pdf" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" data-fa-i2svg=""><path fill="currentColor" d="M181.9 256.1c-5-16-4.9-46.9-2-46.9 8.4 0 7.6 36.9 2 46.9zm-1.7 47.2c-7.7 20.2-17.3 43.3-28.4 62.7 18.3-7 39-17.2 62.9-21.9-12.7-9.6-24.9-23.4-34.5-40.8zM86.1 428.1c0 .8 13.2-5.4 34.9-40.2-6.7 6.3-29.1 24.5-34.9 40.2zM248 160h136v328c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V24C0 10.7 10.7 0 24 0h200v136c0 13.2 10.8 24 24 24zm-8 171.8c-20-12.2-33.3-29-42.7-53.8 4.5-18.5 11.6-46.6 6.2-64.2-4.7-29.4-42.4-26.5-47.8-6.8-5 18.3-.4 44.1 8.1 77-11.6 27.6-28.7 64.6-40.8 85.8-.1 0-.1.1-.2.1-27.1 13.9-73.6 44.5-54.5 68 5.6 6.9 16 10 21.5 10 17.9 0 35.7-18 61.1-61.8 25.8-8.5 54.1-19.1 79-23.2 21.7 11.8 47.1 19.5 64 19.5 29.2 0 31.2-32 19.7-43.4-13.9-13.6-54.3-9.7-73.6-7.2zM377 105L279 7c-4.5-4.5-10.6-7-17-7h-6v128h128v-6.1c0-6.3-2.5-12.4-7-16.9zm-74.1 255.3c4.1-2.7-2.5-11.9-42.8-9 37.1 15.8 42.8 9 42.8 9z"></path></svg><!-- <i class="fas fa-file-pdf"></i> Font Awesome fontawesome.com -->
146
+ </span>
147
+ <span>Paper</span>
148
+ </a>
149
+ </span>
150
+
151
+ <span class="link-block">
152
+ <a href="https://arxiv.org/abs/2401.16468" target="_blank" class="external-link button is-normal is-rounded is-dark">
153
+ <span class="icon">
154
+ <i class="ai ai-arxiv"></i>
155
+ </span>
156
+ <span>arXiv</span>
157
+ </a>
158
+ </span>
159
+ <span class="link-block">
160
+ <a href="https://github.com/mv-lab/InstructIR/" target="_blank" class="external-link button is-normal is-rounded is-dark">
161
+ <span class="icon">
162
+ <svg class="svg-inline--fa fa-github fa-w-16" aria-hidden="true" focusable="false" data-prefix="fab" data-icon="github" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512" data-fa-i2svg=""><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg><!-- <i class="fab fa-github"></i> Font Awesome fontawesome.com -->
163
+ </span>
164
+ <span>Code</span>
165
+ </a>
166
+ </span>
167
+ <span class="link-block">
168
+ <a href="https://huggingface.co/spaces/marcosv/InstructIR" target="_blank" class="external-link button is-normal is-rounded is-dark">
169
+ <span class="icon">
170
+ <svg class="svg-inline--fa fa-images fa-w-18" aria-hidden="true" focusable="false" data-prefix="far" data-icon="images" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-fa-i2svg=""><path fill="currentColor" d="M480 416v16c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V176c0-26.51 21.49-48 48-48h16v48H54a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6v-10h48zm42-336H150a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6V86a6 6 0 0 0-6-6zm6-48c26.51 0 48 21.49 48 48v256c0 26.51-21.49 48-48 48H144c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h384zM264 144c0 22.091-17.909 40-40 40s-40-17.909-40-40 17.909-40 40-40 40 17.909 40 40zm-72 96l39.515-39.515c4.686-4.686 12.284-4.686 16.971 0L288 240l103.515-103.515c4.686-4.686 12.284-4.686 16.971 0L480 208v80H192v-48z"></path></svg><!-- <i class="far fa-images"></i> Font Awesome fontawesome.com -->
171
+ </span>
172
+ <span>Demo 🤗</span>
173
+ </a>
174
+ </span>
175
+
176
+ <span class="link-block">
177
+ <a href="https://huggingface.co/marcosv/InstructIR" target="_blank" class="external-link button is-normal is-rounded is-dark">
178
+ <span class="icon">
179
+ <svg class="svg-inline--fa fa-images fa-w-18" aria-hidden="true" focusable="false" data-prefix="far" data-icon="images" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-fa-i2svg=""><path fill="currentColor" d="M480 416v16c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V176c0-26.51 21.49-48 48-48h16v48H54a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6v-10h48zm42-336H150a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6V86a6 6 0 0 0-6-6zm6-48c26.51 0 48 21.49 48 48v256c0 26.51-21.49 48-48 48H144c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h384zM264 144c0 22.091-17.909 40-40 40s-40-17.909-40-40 17.909-40 40-40 40 17.909 40 40zm-72 96l39.515-39.515c4.686-4.686 12.284-4.686 16.971 0L288 240l103.515-103.515c4.686-4.686 12.284-4.686 16.971 0L480 208v80H192v-48z"></path></svg><!-- <i class="far fa-images"></i> Font Awesome fontawesome.com -->
180
+ </span>
181
+ <span>Models 🤗</span>
182
+ </a>
183
+ </span>
184
+
185
+ </div>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ </div>
191
+ </section>
192
+
193
+ <section class="section" style="background-color:#efeff081">
194
+ <div class="container is-max-desktop">
195
+ <!-- Abstract. -->
196
+ <div class="columns is-centered has-text-centered">
197
+ <div class="column is-six-fifths">
198
+ <h2 class="title is-3">TL;DR</h2>
199
+
200
+ <div class="content has-text-justified">
201
+
202
+ <b>InstructIR takes as input an image and a human-written instruction for how to improve that image.</b>
203
+ The (single) neural model performs all-in-one image restoration.
204
+ InstructIR achieves state-of-the-art results on several restoration tasks including image denoising, deraining, deblurring, dehazing, and (low-light) image enhancement.
205
+ Test the model now on <a href="https://huggingface.co/spaces/marcosv/InstructIR"> HF 🤗 InstructIR space </a>
206
+ <br>
207
+ 🚀 You can start with the <a href="https://github.com/mv-lab/InstructIR/blob/main/demo.ipynb">demo tutorial</a> from our github.
208
+ <br>
209
+ <br>
210
+ <b>🔥🔥 More content comming soon: all test results, more model versions, tables, etc.</b>
211
+ <br>
212
+ <br>
213
+
214
+ </div>
215
+
216
+ </div>
217
+ </div>
218
+
219
+ </div>
220
+ </section>
221
+
222
+
223
+
224
+ <section class="section">
225
+
226
+ <div class="columns is-centered has-text-centered">
227
+ <div class="column is-six-fifths">
228
+ <h2 class="title is-3"> Examples of InstructIR</h2>
229
+
230
+ <video width="860" height="640" autoplay loop controls>
231
+ <source src="images/instructir.mp4" type="video/mp4">
232
+ Your browser does not support the video tag.
233
+ </video>
234
+
235
+ <!--
236
+ <img src="images/instructir_teaser.png" width="50%">
237
+ -->
238
+
239
+
240
+ </div>
241
+ </div>
242
+
243
+
244
+ <center>
245
+ <br>
246
+ <br>
247
+ <h2 class="title">Demo App 🤗</h2>
248
+
249
+ <iframe
250
+ src="https://marcosv-instructir.hf.space"
251
+ frameborder="0"
252
+ width="850"
253
+ height="450"
254
+ ></iframe>
255
+
256
+ </center>
257
+
258
+
259
+ <div class="container mt-5">
260
+ <!-- <h2 class="text-center mb-5">Who's GPT-4's favorite? Battles between State-of-the-Art Chatbots</h2> -->
261
+ <!-- Selection -->
262
+ <div class="form-row" style="justify-content: flex-end;">
263
+ <div class="form-group col-md-1">
264
+ <div class="col-md-2" style="width: 100%"><label>&nbsp;</label></div>
265
+ <div class="btn-group" role="group" aria-label="Left and Right Controller" style="width: 100%;align-items: flex-end;justify-content: center;flex-direction: row;display: flex;">
266
+ <button type="button" class="form-control btn btn-primary" id="prev-question"><i class="material-icons">keyboard_arrow_left</i></button>
267
+ <button type="button" class="form-control btn btn-primary" id="next-question"><i class="material-icons">keyboard_arrow_right</i></button>
268
+
269
+ </div>
270
+ </div>
271
+ </div>
272
+
273
+ <!-- Question Card -->
274
+ <div style="display: flex; justify-content: center; align-items: center;">
275
+ <div class="card mb-4" style="width: 100%; display: flex; align-items: center;">
276
+ <!-- <p><b>Description:</b> Monalisa is a famous painting by Leonardo da Vinci. </p> -->
277
+
278
+ <div class="card-body" id="selected-question" style="display: flex; height: 80vh;">
279
+ <div class="chat-history"><article class="media"><figure class="media-left"><span class="icon is-large"><svg class="svg-inline--fa fa-user fa-w-14 fa-2x" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="user" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" data-fa-i2svg=""><path fill="currentColor" d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"></path></svg><!-- <i class="fas fas fa-2x fa-user "></i> Font Awesome fontawesome.com --></span></figure><div class="media-content"><div class="content"><p><strong>User</strong><br><pre style="background-color: white; font-size: 18px; font-family: Arial; padding: 0px; margin: 0px; white-space: pre-wrap; overflow-wrap: break-word;"></pre><img src="static/monalisa.jpg" style="max-width: 100%; max-height: 300px;"></p></div></div></article><article class="media"><figure class="media-left"><span class="icon is-large"><svg class="svg-inline--fa fa-user fa-w-14 fa-2x" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="user" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" data-fa-i2svg=""><path fill="currentColor" d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"></path></svg><!-- <i class="fas fas fa-2x fa-user "></i> Font Awesome fontawesome.com --></span></figure><div class="media-content"><div class="content"><p><strong>User</strong><br><pre style="background-color: white; font-size: 18px; font-family: Arial; padding: 0px; margin: 0px; white-space: pre-wrap; overflow-wrap: break-word;">Do you know who drew this painting?​</pre></p></div></div></article><article class="media"><figure class="media-left"><span class="icon is-large"><svg class="svg-inline--fa fa-robot fa-w-20 fa-2x" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="robot" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" data-fa-i2svg=""><path fill="currentColor" d="M32,224H64V416H32A31.96166,31.96166,0,0,1,0,384V256A31.96166,31.96166,0,0,1,32,224Zm512-48V448a64.06328,64.06328,0,0,1-64,64H160a64.06328,64.06328,0,0,1-64-64V176a79.974,79.974,0,0,1,80-80H288V32a32,32,0,0,1,64,0V96H464A79.974,79.974,0,0,1,544,176ZM264,256a40,40,0,1,0-40,40A39.997,39.997,0,0,0,264,256Zm-8,128H192v32h64Zm96,0H288v32h64ZM456,256a40,40,0,1,0-40,40A39.997,39.997,0,0,0,456,256Zm-8,128H384v32h64ZM640,256V384a31.96166,31.96166,0,0,1-32,32H576V224h32A31.96166,31.96166,0,0,1,640,256Z"></path></svg><!-- <i class="fas fas fa-2x fa-robot"></i> Font Awesome fontawesome.com --></span></figure><div class="media-content"><div class="content"><p><strong>LLaVA</strong><br><pre style="background-color: white; font-size: 18px; font-family: Arial; padding: 0px; margin: 0px; white-space: pre-wrap; overflow-wrap: break-word;">The painting depicts a woman, commonly believed to be Mona Lisa, the famous artwork by Leonardo da Vinci. It is a portrait painting that showcases the woman's enigmatic smile and has become one of the most famous and iconic art pieces in the world. The original work is displayed in the Louvre Museum in Paris, and it is known for its intricate details, use of oil paint, and the artist's innovative techniques that contributed to its enduring appeal and mystery.​​</pre></p></div></div></article></div>
280
+
281
+ </div>
282
+ </div>
283
+ </div>
284
+
285
+ </div>
286
+ </section>
287
+
288
+
289
+ <section class="section" id="BibTeX">
290
+ <div class="container is-max-desktop content">
291
+ <h2 class="title">Citation BibTeX</h2>
292
+ <pre><code>
293
+ @misc{conde2024instructir,
294
+ title={High-Quality Image Restoration Following Human Instructions},
295
+ author={Marcos V. Conde, Gregor Geigle, Radu Timofte},
296
+ year={2024},
297
+ journal={arXiv preprint}
298
+ }
299
+ </code></pre>
300
+ </div>
301
+ </section>
302
+
303
+ <section class="section" id="Acknowledgement">
304
+ <div class="container is-max-desktop content">
305
+ <h2 class="title">Acknowledgement</h2>
306
+ <p>
307
+ This work was partly supported by the The Humboldt Foundation (AvH). Marcos Conde is also supported by Sony Interactive Entertainment, FTG.
308
+ This work is inspired in <a href="https://www.timothybrooks.com/instruct-pix2pix/">InstructPix2Pix</a>.
309
+ <br>
310
+ For any inquiries contact Marcos V. Conde: marcos.conde [at] uni-wuerzburg.de
311
+ </p>
312
+ <p>
313
+ This website is adapted from <a href="https://github.com/nerfies/nerfies.github.io">Nerfies</a> and <a href="https://github.com/nerfies/nerfies.github.io">LLaVA</a>, licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative
314
+ Commons Attribution-ShareAlike 4.0 International License</a>. We thank the original authors of this website template.
315
+ </p>
316
+
317
+ <script>
318
+ // Handle message showing
319
+ function createChatRow(sender, text, imageSrc) {
320
+ var article = document.createElement("article");
321
+ article.className = "media"
322
+
323
+ var figure = document.createElement("figure");
324
+ figure.className = "media-left";
325
+
326
+ var span = document.createElement("span");
327
+ span.className = "icon is-large";
328
+
329
+ var icon = document.createElement("i");
330
+ icon.className = "fas fas fa-2x" + (sender === "User" ? " fa-user " : sender === "InstructIR" ? " fa-robot" : "");
331
+
332
+ var media = document.createElement("div");
333
+ media.className = "media-content";
334
+
335
+ var content = document.createElement("div");
336
+ content.className = "content";
337
+
338
+ var para = document.createElement("p");
339
+
340
+ // wrap text in pre tag to preserve whitespace and line breaks
341
+ var pre_text = document.createElement("pre");
342
+ pre_text.style = "background-color: white; font-size: 18px; font-family: Arial; padding: 0; margin: 0; white-space: pre-wrap; word-wrap: break-word;";
343
+ var paraText = document.createTextNode(text);
344
+ pre_text.appendChild(paraText);
345
+
346
+ var strong = document.createElement("strong");
347
+ strong.innerHTML = sender;
348
+ var br = document.createElement("br");
349
+
350
+ para.appendChild(strong);
351
+ para.appendChild(br);
352
+ para.appendChild(pre_text);
353
+
354
+ // Add image if imageSrc is provided
355
+ if (imageSrc) {
356
+ var img = document.createElement("img");
357
+ img.src = imageSrc;
358
+ img.style = "max-width: 100%; max-height: 300px;"; // Adjust the style as needed
359
+ para.appendChild(img);
360
+ }
361
+
362
+ content.appendChild(para);
363
+ media.appendChild(content);
364
+ span.appendChild(icon);
365
+ figure.appendChild(span);
366
+ if (sender !== "Description") {
367
+ article.appendChild(figure);
368
+ };
369
+ article.appendChild(media);
370
+ return article;
371
+ }
372
+
373
+ function addMessageToChatHistory(sender, message, imageSrc) {
374
+ const chatHistory = document.querySelector('.chat-history');
375
+ const chatRow = createChatRow(sender, message, imageSrc);
376
+ chatHistory.appendChild(chatRow);
377
+ chatHistory.scrollTop = chatHistory.scrollHeight;
378
+ }
379
+
380
+ function clearChatHistory() {
381
+ const chatHistory = document.querySelector('.chat-history');
382
+ chatHistory.innerHTML = "";
383
+ }
384
+
385
+ //
386
+ const conversations = [
387
+ {
388
+ "description": "Restore an image using natural language",
389
+ "turns": [
390
+ ["User", "I love this photo, could you remove the raindrops? please keep the content intact", "images/rain-020.png"],
391
+ ["InstructIR", "Sure! let me remove the rain", "images/results/result1.png"],
392
+ ["User", "Great! can you make it look stunning? like a professional photo"],
393
+ ["InstructIR", "I will enhance it", "images/results/result2.png"],
394
+ ["User", "amazing, thank you InstructIR"],
395
+ ]
396
+ },
397
+ ];
398
+
399
+ // The current image index
400
+ let currentIndex = 0;
401
+
402
+ // The function to update the displayed chat history
403
+ function update_dialog_demo() {
404
+ // Clear the chat history
405
+ clearChatHistory();
406
+
407
+ for (let i = 0; i < conversations[currentIndex].turns.length; i++) {
408
+ if (conversations[currentIndex].turns[i].length == 2) {
409
+ addMessageToChatHistory(conversations[currentIndex].turns[i][0], conversations[currentIndex].turns[i][1]);
410
+ }
411
+ else {
412
+ addMessageToChatHistory(conversations[currentIndex].turns[i][0], conversations[currentIndex].turns[i][1], conversations[currentIndex].turns[i][2]);
413
+ }
414
+ }
415
+
416
+ // scroll to the top of the chat history
417
+ document.querySelector('.chat-history').scrollTop = 0;
418
+ }
419
+
420
+ // Initialize the displayed image
421
+ update_dialog_demo();
422
+
423
+ // Event listeners for the buttons
424
+ document.getElementById('prev-question').addEventListener('click', () => {
425
+ currentIndex = (currentIndex - 1 + conversations.length) % conversations.length;
426
+ update_dialog_demo();
427
+ });
428
+
429
+ document.getElementById('next-question').addEventListener('click', () => {
430
+ currentIndex = (currentIndex + 1) % conversations.length;
431
+ update_dialog_demo();
432
+ });
433
+
434
+
435
+ </script>
436
+
437
+
438
+
439
+
440
+ </body></html>
lm_instructir-7d.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b239e5d5dbc811813a90e709f9647dead0e35a96a294a7d6c5263da549016fe6
3
+ size 403275
metrics.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import math
3
+ import cv2
4
+ import torch
5
+
6
+
7
+ def np_psnr(y_true, y_pred, maxval=1.):
8
+ mse = np.mean((y_true - y_pred) ** 2)
9
+ if(mse == 0):
10
+ return np.inf
11
+
12
+ psnr = 20 * np.log10(maxval / np.sqrt(mse))
13
+ return psnr
14
+
15
+ def pt_psnr(y_true, y_pred, maxval=1.):
16
+ mse = torch.mean((y_true - y_pred) ** 2, dim=(1, 2, 3))
17
+ psnr = 20 * torch.log10(maxval / torch.sqrt(mse))
18
+ return psnr.unsqueeze(1)
19
+
20
+
21
+ ############# SWINIR METRICS
22
+ # https://github.com/JingyunLiang/SwinIR/blob/6545850fbf8df298df73d81f3e8cba638787c8bd/utils/util_calculate_psnr_ssim.py#L243
23
+
24
+
25
+ def calculate_psnr(img1, img2, crop_border, input_order='HWC', test_y_channel=False):
26
+ """Calculate PSNR (Peak Signal-to-Noise Ratio).
27
+
28
+ Ref: https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
29
+
30
+ Args:
31
+ img1 (ndarray): Images with range [0, 255].
32
+ img2 (ndarray): Images with range [0, 255].
33
+ crop_border (int): Cropped pixels in each edge of an image. These
34
+ pixels are not involved in the PSNR calculation.
35
+ input_order (str): Whether the input order is 'HWC' or 'CHW'.
36
+ Default: 'HWC'.
37
+ test_y_channel (bool): Test on Y channel of YCbCr. Default: False.
38
+
39
+ Returns:
40
+ float: psnr result.
41
+ """
42
+
43
+ assert img1.shape == img2.shape, (f'Image shapes are differnet: {img1.shape}, {img2.shape}.')
44
+ if input_order not in ['HWC', 'CHW']:
45
+ raise ValueError(f'Wrong input_order {input_order}. Supported input_orders are ' '"HWC" and "CHW"')
46
+ img1 = reorder_image(img1, input_order=input_order)
47
+ img2 = reorder_image(img2, input_order=input_order)
48
+ img1 = img1.astype(np.float64)
49
+ img2 = img2.astype(np.float64)
50
+
51
+ if crop_border != 0:
52
+ img1 = img1[crop_border:-crop_border, crop_border:-crop_border, ...]
53
+ img2 = img2[crop_border:-crop_border, crop_border:-crop_border, ...]
54
+
55
+ if test_y_channel:
56
+ img1 = to_y_channel(img1)
57
+ img2 = to_y_channel(img2)
58
+
59
+ mse = np.mean((img1 - img2) ** 2)
60
+ if mse == 0:
61
+ return float('inf')
62
+ return 20. * np.log10(255. / np.sqrt(mse))
63
+
64
+
65
+ def _ssim(img1, img2):
66
+ """Calculate SSIM (structural similarity) for one channel images.
67
+
68
+ It is called by func:`calculate_ssim`.
69
+
70
+ Args:
71
+ img1 (ndarray): Images with range [0, 255] with order 'HWC'.
72
+ img2 (ndarray): Images with range [0, 255] with order 'HWC'.
73
+
74
+ Returns:
75
+ float: ssim result.
76
+ """
77
+
78
+ C1 = (0.01 * 255) ** 2
79
+ C2 = (0.03 * 255) ** 2
80
+
81
+ img1 = img1.astype(np.float64)
82
+ img2 = img2.astype(np.float64)
83
+ kernel = cv2.getGaussianKernel(11, 1.5)
84
+ window = np.outer(kernel, kernel.transpose())
85
+
86
+ mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5]
87
+ mu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]
88
+ mu1_sq = mu1 ** 2
89
+ mu2_sq = mu2 ** 2
90
+ mu1_mu2 = mu1 * mu2
91
+ sigma1_sq = cv2.filter2D(img1 ** 2, -1, window)[5:-5, 5:-5] - mu1_sq
92
+ sigma2_sq = cv2.filter2D(img2 ** 2, -1, window)[5:-5, 5:-5] - mu2_sq
93
+ sigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2
94
+
95
+ ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) * (sigma1_sq + sigma2_sq + C2))
96
+ return ssim_map.mean()
97
+
98
+
99
+ def calculate_ssim(img1, img2, crop_border, input_order='HWC', test_y_channel=False):
100
+ """Calculate SSIM (structural similarity).
101
+
102
+ Ref:
103
+ Image quality assessment: From error visibility to structural similarity
104
+
105
+ The results are the same as that of the official released MATLAB code in
106
+ https://ece.uwaterloo.ca/~z70wang/research/ssim/.
107
+
108
+ For three-channel images, SSIM is calculated for each channel and then
109
+ averaged.
110
+
111
+ Args:
112
+ img1 (ndarray): Images with range [0, 255].
113
+ img2 (ndarray): Images with range [0, 255].
114
+ crop_border (int): Cropped pixels in each edge of an image. These
115
+ pixels are not involved in the SSIM calculation.
116
+ input_order (str): Whether the input order is 'HWC' or 'CHW'.
117
+ Default: 'HWC'.
118
+ test_y_channel (bool): Test on Y channel of YCbCr. Default: False.
119
+
120
+ Returns:
121
+ float: ssim result.
122
+ """
123
+
124
+ assert img1.shape == img2.shape, (f'Image shapes are differnet: {img1.shape}, {img2.shape}.')
125
+ if input_order not in ['HWC', 'CHW']:
126
+ raise ValueError(f'Wrong input_order {input_order}. Supported input_orders are ' '"HWC" and "CHW"')
127
+ img1 = reorder_image(img1, input_order=input_order)
128
+ img2 = reorder_image(img2, input_order=input_order)
129
+ img1 = img1.astype(np.float64)
130
+ img2 = img2.astype(np.float64)
131
+
132
+ if crop_border != 0:
133
+ img1 = img1[crop_border:-crop_border, crop_border:-crop_border, ...]
134
+ img2 = img2[crop_border:-crop_border, crop_border:-crop_border, ...]
135
+
136
+ if test_y_channel:
137
+ img1 = to_y_channel(img1)
138
+ img2 = to_y_channel(img2)
139
+
140
+ ssims = []
141
+ for i in range(img1.shape[2]):
142
+ ssims.append(_ssim(img1[..., i], img2[..., i]))
143
+ return np.array(ssims).mean()
144
+
145
+
146
+ def reorder_image(img, input_order='HWC'):
147
+ """Reorder images to 'HWC' order.
148
+
149
+ If the input_order is (h, w), return (h, w, 1);
150
+ If the input_order is (c, h, w), return (h, w, c);
151
+ If the input_order is (h, w, c), return as it is.
152
+
153
+ Args:
154
+ img (ndarray): Input image.
155
+ input_order (str): Whether the input order is 'HWC' or 'CHW'.
156
+ If the input image shape is (h, w), input_order will not have
157
+ effects. Default: 'HWC'.
158
+
159
+ Returns:
160
+ ndarray: reordered image.
161
+ """
162
+
163
+ if input_order not in ['HWC', 'CHW']:
164
+ raise ValueError(f'Wrong input_order {input_order}. Supported input_orders are ' "'HWC' and 'CHW'")
165
+ if len(img.shape) == 2:
166
+ img = img[..., None]
167
+ if input_order == 'CHW':
168
+ img = img.transpose(1, 2, 0)
169
+ return img
170
+
171
+
172
+ def to_y_channel(img):
173
+ """Change to Y channel of YCbCr.
174
+
175
+ Args:
176
+ img (ndarray): Images with range [0, 255].
177
+
178
+ Returns:
179
+ (ndarray): Images with range [0, 255] (float type) without round.
180
+ """
181
+ if np.max(img) > 1.:
182
+ img = img.astype(np.float32) / 255.
183
+
184
+ if img.ndim == 3 and img.shape[2] == 3:
185
+ img = bgr2ycbcr(img, y_only=True)
186
+ img = img[..., None]
187
+ return img * 255.
188
+
189
+
190
+ def _convert_input_type_range(img):
191
+ """Convert the type and range of the input image.
192
+
193
+ It converts the input image to np.float32 type and range of [0, 1].
194
+ It is mainly used for pre-processing the input image in colorspace
195
+ convertion functions such as rgb2ycbcr and ycbcr2rgb.
196
+
197
+ Args:
198
+ img (ndarray): The input image. It accepts:
199
+ 1. np.uint8 type with range [0, 255];
200
+ 2. np.float32 type with range [0, 1].
201
+
202
+ Returns:
203
+ (ndarray): The converted image with type of np.float32 and range of
204
+ [0, 1].
205
+ """
206
+ img_type = img.dtype
207
+ img = img.astype(np.float32)
208
+ if img_type == np.float32:
209
+ pass
210
+ elif img_type == np.uint8:
211
+ img /= 255.
212
+ else:
213
+ raise TypeError('The img type should be np.float32 or np.uint8, ' f'but got {img_type}')
214
+ return img
215
+
216
+
217
+ def _convert_output_type_range(img, dst_type):
218
+ """Convert the type and range of the image according to dst_type.
219
+
220
+ It converts the image to desired type and range. If `dst_type` is np.uint8,
221
+ images will be converted to np.uint8 type with range [0, 255]. If
222
+ `dst_type` is np.float32, it converts the image to np.float32 type with
223
+ range [0, 1].
224
+ It is mainly used for post-processing images in colorspace convertion
225
+ functions such as rgb2ycbcr and ycbcr2rgb.
226
+
227
+ Args:
228
+ img (ndarray): The image to be converted with np.float32 type and
229
+ range [0, 255].
230
+ dst_type (np.uint8 | np.float32): If dst_type is np.uint8, it
231
+ converts the image to np.uint8 type with range [0, 255]. If
232
+ dst_type is np.float32, it converts the image to np.float32 type
233
+ with range [0, 1].
234
+
235
+ Returns:
236
+ (ndarray): The converted image with desired type and range.
237
+ """
238
+ if dst_type not in (np.uint8, np.float32):
239
+ raise TypeError('The dst_type should be np.float32 or np.uint8, ' f'but got {dst_type}')
240
+ if dst_type == np.uint8:
241
+ img = img.round()
242
+ else:
243
+ img /= 255.
244
+ return img.astype(dst_type)
245
+
246
+
247
+ def bgr2ycbcr(img, y_only=False):
248
+ """Convert a BGR image to YCbCr image.
249
+
250
+ The bgr version of rgb2ycbcr.
251
+ It implements the ITU-R BT.601 conversion for standard-definition
252
+ television. See more details in
253
+ https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion.
254
+
255
+ It differs from a similar function in cv2.cvtColor: `BGR <-> YCrCb`.
256
+ In OpenCV, it implements a JPEG conversion. See more details in
257
+ https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion.
258
+
259
+ Args:
260
+ img (ndarray): The input image. It accepts:
261
+ 1. np.uint8 type with range [0, 255];
262
+ 2. np.float32 type with range [0, 1].
263
+ y_only (bool): Whether to only return Y channel. Default: False.
264
+
265
+ Returns:
266
+ ndarray: The converted YCbCr image. The output image has the same type
267
+ and range as input image.
268
+ """
269
+ img_type = img.dtype
270
+ img = _convert_input_type_range(img)
271
+ if y_only:
272
+ out_img = np.dot(img, [24.966, 128.553, 65.481]) + 16.0
273
+ else:
274
+ out_img = np.matmul(
275
+ img, [[24.966, 112.0, -18.214], [128.553, -74.203, -93.786], [65.481, -37.797, 112.0]]) + [16, 128, 128]
276
+ out_img = _convert_output_type_range(out_img, img_type)
277
+ return out_img
278
+
models/__pycache__/instructir.cpython-310.pyc ADDED
Binary file (4.19 kB). View file
 
models/__pycache__/nafnet.cpython-310.pyc ADDED
Binary file (5.51 kB). View file
 
models/__pycache__/nafnet_utils.cpython-310.pyc ADDED
Binary file (5.41 kB). View file
 
models/im_instructir-7d.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f28d8f0f66ff57449ebe2be52241dfdd53a3dfab1003d63e65493f96ea152fd0
3
+ size 63627895
models/instructir.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import torch
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+ from torch.nn import init as init
6
+ from torch.nn.modules.batchnorm import _BatchNorm
7
+
8
+ from models.nafnet_utils import Local_Base, LayerNorm2d
9
+ from models.nafnet import SimpleGate, NAFBlock
10
+
11
+
12
+ class ICB(nn.Module):
13
+ """
14
+ Instruction Condition Block (ICB)
15
+ Paper Section 3.3
16
+ """
17
+
18
+ def __init__(self, feature_dim, text_dim=768):
19
+ super(ICB, self).__init__()
20
+ self.fc = nn.Linear(text_dim, feature_dim)
21
+ self.block = NAFBlock(feature_dim)
22
+ self.beta = nn.Parameter(torch.zeros((1, feature_dim, 1, 1)), requires_grad=True)
23
+ self.gamma = nn.Parameter(torch.zeros((1, feature_dim, 1, 1)), requires_grad=True)
24
+
25
+ def forward(self, x, text_embedding):
26
+ gating_factors = torch.sigmoid(self.fc(text_embedding))
27
+ gating_factors = gating_factors.unsqueeze(-1).unsqueeze(-1)
28
+
29
+ f = x * self.gamma + self.beta # 1) learned feature scaling/modulation
30
+ f = f * gating_factors # 2) (soft) feature routing based on text
31
+ f = self.block(f) # 3) block feature enhancement
32
+ return f + x
33
+
34
+
35
+ class InstructIR(nn.Module):
36
+ """
37
+ InstructIR model using NAFNet (ECCV 2022) as backbone.
38
+ The model takes as input an RGB image and a text embedding (encoded instruction).
39
+ Described in Paper Section 3.3
40
+ """
41
+
42
+ def __init__(self, img_channel=3, width=16, middle_blk_num=1, enc_blk_nums=[], dec_blk_nums=[], txtdim=768):
43
+ super().__init__()
44
+
45
+ self.intro = nn.Conv2d(in_channels=img_channel, out_channels=width, kernel_size=3, padding=1, stride=1, groups=1,
46
+ bias=True)
47
+ self.ending = nn.Conv2d(in_channels=width, out_channels=img_channel, kernel_size=3, padding=1, stride=1, groups=1,
48
+ bias=True)
49
+
50
+ self.encoders = nn.ModuleList()
51
+ self.decoders = nn.ModuleList()
52
+ self.middle_blks = nn.ModuleList()
53
+ self.ups = nn.ModuleList()
54
+ self.downs = nn.ModuleList()
55
+ self.enc_cond = nn.ModuleList()
56
+ self.dec_cond = nn.ModuleList()
57
+
58
+ chan = width
59
+ for num in enc_blk_nums:
60
+ self.encoders.append(
61
+ nn.Sequential(
62
+ *[NAFBlock(chan) for _ in range(num)]
63
+ )
64
+ )
65
+
66
+ self.enc_cond.append(ICB(chan, txtdim))
67
+
68
+ self.downs.append(
69
+ nn.Conv2d(chan, 2*chan, 2, 2)
70
+ )
71
+ chan = chan * 2
72
+
73
+ self.middle_blks = nn.Sequential(
74
+ *[NAFBlock(chan) for _ in range(middle_blk_num)]
75
+ )
76
+
77
+ for num in dec_blk_nums:
78
+ self.ups.append(
79
+ nn.Sequential(
80
+ nn.Conv2d(chan, chan * 2, 1, bias=False),
81
+ nn.PixelShuffle(2)
82
+ )
83
+ )
84
+ chan = chan // 2
85
+ self.decoders.append(
86
+ nn.Sequential(
87
+ *[NAFBlock(chan) for _ in range(num)]
88
+ )
89
+ )
90
+ # Add text embedding as modulation
91
+ self.dec_cond.append(ICB(chan, txtdim))
92
+
93
+ self.padder_size = 2 ** len(self.encoders)
94
+
95
+ def forward(self, inp, txtembd):
96
+ B, C, H, W = inp.shape
97
+ inp = self.check_image_size(inp)
98
+
99
+ x = self.intro(inp)
100
+ encs = []
101
+
102
+ for encoder, enc_mod, down in zip(self.encoders, self.enc_cond, self.downs):
103
+ x = encoder(x)
104
+ x = enc_mod(x, txtembd)
105
+ encs.append(x)
106
+ x = down(x)
107
+
108
+ x = self.middle_blks(x)
109
+
110
+ for decoder, up, enc_skip, dec_mod in zip(self.decoders, self.ups, encs[::-1], self.dec_cond):
111
+ x = up(x)
112
+ x = x + enc_skip
113
+ x = decoder(x)
114
+ x = dec_mod(x, txtembd)
115
+
116
+ x = self.ending(x)
117
+ x = x + inp
118
+
119
+ return x[:, :, :H, :W]
120
+
121
+ def check_image_size(self, x):
122
+ _, _, h, w = x.size()
123
+ mod_pad_h = (self.padder_size - h % self.padder_size) % self.padder_size
124
+ mod_pad_w = (self.padder_size - w % self.padder_size) % self.padder_size
125
+ x = F.pad(x, (0, mod_pad_w, 0, mod_pad_h))
126
+ return x
127
+
128
+
129
+ def create_model(input_channels = 3, width = 32, enc_blks = [2, 2, 4, 8], middle_blk_num = 12, dec_blks = [2, 2, 2, 2], txtdim=768):
130
+
131
+ net = InstructIR(img_channel=input_channels, width=width, middle_blk_num=middle_blk_num,
132
+ enc_blk_nums=enc_blks, dec_blk_nums=dec_blks, txtdim=txtdim)
133
+
134
+ return net
models/lm_instructir-7d.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b239e5d5dbc811813a90e709f9647dead0e35a96a294a7d6c5263da549016fe6
3
+ size 403275
models/nafnet.py ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ------------------------------------------------------------------------
2
+ # Copyright (c) 2022 megvii-model. All Rights Reserved.
3
+ # ------------------------------------------------------------------------
4
+ # Source: https://github.com/megvii-research/NAFNet
5
+
6
+ '''
7
+ Simple Baselines for Image Restoration
8
+
9
+ @article{chen2022simple,
10
+ title={Simple Baselines for Image Restoration},
11
+ author={Chen, Liangyu and Chu, Xiaojie and Zhang, Xiangyu and Sun, Jian},
12
+ journal={arXiv preprint arXiv:2204.04676},
13
+ year={2022}
14
+ }
15
+ '''
16
+
17
+ import math
18
+ import torch
19
+ import torch.nn as nn
20
+ import torch.nn.functional as F
21
+ from torch.nn import init as init
22
+ from torch.nn.modules.batchnorm import _BatchNorm
23
+ from models.nafnet_utils import Local_Base, LayerNorm2d
24
+
25
+
26
+ class SimpleGate(nn.Module):
27
+ def forward(self, x):
28
+ x1, x2 = x.chunk(2, dim=1)
29
+ return x1 * x2
30
+
31
+ class NAFBlock(nn.Module):
32
+ def __init__(self, c, DW_Expand=2, FFN_Expand=2, drop_out_rate=0.):
33
+ super().__init__()
34
+ dw_channel = c * DW_Expand
35
+ self.conv1 = nn.Conv2d(in_channels=c, out_channels=dw_channel, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
36
+ self.conv2 = nn.Conv2d(in_channels=dw_channel, out_channels=dw_channel, kernel_size=3, padding=1, stride=1, groups=dw_channel,
37
+ bias=True)
38
+ self.conv3 = nn.Conv2d(in_channels=dw_channel // 2, out_channels=c, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
39
+
40
+ # Simplified Channel Attention
41
+ self.sca = nn.Sequential(
42
+ nn.AdaptiveAvgPool2d(1),
43
+ nn.Conv2d(in_channels=dw_channel // 2, out_channels=dw_channel // 2, kernel_size=1, padding=0, stride=1,
44
+ groups=1, bias=True),
45
+ )
46
+
47
+ # SimpleGate
48
+ self.sg = SimpleGate()
49
+
50
+ ffn_channel = FFN_Expand * c
51
+ self.conv4 = nn.Conv2d(in_channels=c, out_channels=ffn_channel, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
52
+ self.conv5 = nn.Conv2d(in_channels=ffn_channel // 2, out_channels=c, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
53
+
54
+ self.norm1 = LayerNorm2d(c)
55
+ self.norm2 = LayerNorm2d(c)
56
+
57
+ self.dropout1 = nn.Dropout(drop_out_rate) if drop_out_rate > 0. else nn.Identity()
58
+ self.dropout2 = nn.Dropout(drop_out_rate) if drop_out_rate > 0. else nn.Identity()
59
+
60
+ self.beta = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
61
+ self.gamma = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
62
+
63
+ def forward(self, inp):
64
+ x = inp
65
+
66
+ x = self.norm1(x)
67
+
68
+ x = self.conv1(x)
69
+ x = self.conv2(x)
70
+ x = self.sg(x)
71
+ x = x * self.sca(x)
72
+ x = self.conv3(x)
73
+
74
+ x = self.dropout1(x)
75
+
76
+ y = inp + x * self.beta
77
+
78
+ x = self.conv4(self.norm2(y))
79
+ x = self.sg(x)
80
+ x = self.conv5(x)
81
+
82
+ x = self.dropout2(x)
83
+
84
+ return y + x * self.gamma
85
+
86
+
87
+ class NAFNet(nn.Module):
88
+
89
+ def __init__(self, img_channel=3, width=16, middle_blk_num=1, enc_blk_nums=[], dec_blk_nums=[]):
90
+ super().__init__()
91
+
92
+ self.intro = nn.Conv2d(in_channels=img_channel, out_channels=width, kernel_size=3, padding=1, stride=1, groups=1,
93
+ bias=True)
94
+ self.ending = nn.Conv2d(in_channels=width, out_channels=img_channel, kernel_size=3, padding=1, stride=1, groups=1,
95
+ bias=True)
96
+
97
+ self.encoders = nn.ModuleList()
98
+ self.decoders = nn.ModuleList()
99
+ self.middle_blks = nn.ModuleList()
100
+ self.ups = nn.ModuleList()
101
+ self.downs = nn.ModuleList()
102
+
103
+ chan = width
104
+ for num in enc_blk_nums:
105
+ self.encoders.append(
106
+ nn.Sequential(
107
+ *[NAFBlock(chan) for _ in range(num)]
108
+ )
109
+ )
110
+ self.downs.append(
111
+ nn.Conv2d(chan, 2*chan, 2, 2)
112
+ )
113
+ chan = chan * 2
114
+
115
+ self.middle_blks = \
116
+ nn.Sequential(
117
+ *[NAFBlock(chan) for _ in range(middle_blk_num)]
118
+ )
119
+
120
+ for num in dec_blk_nums:
121
+ self.ups.append(
122
+ nn.Sequential(
123
+ nn.Conv2d(chan, chan * 2, 1, bias=False),
124
+ nn.PixelShuffle(2)
125
+ )
126
+ )
127
+ chan = chan // 2
128
+ self.decoders.append(
129
+ nn.Sequential(
130
+ *[NAFBlock(chan) for _ in range(num)]
131
+ )
132
+ )
133
+
134
+ self.padder_size = 2 ** len(self.encoders)
135
+
136
+ def forward(self, inp):
137
+ B, C, H, W = inp.shape
138
+ inp = self.check_image_size(inp)
139
+
140
+ x = self.intro(inp)
141
+
142
+ encs = []
143
+
144
+ for encoder, down in zip(self.encoders, self.downs):
145
+ x = encoder(x)
146
+ encs.append(x)
147
+ x = down(x)
148
+
149
+ x = self.middle_blks(x)
150
+
151
+ for decoder, up, enc_skip in zip(self.decoders, self.ups, encs[::-1]):
152
+ x = up(x)
153
+ x = x + enc_skip
154
+ x = decoder(x)
155
+
156
+ x = self.ending(x)
157
+ x = x + inp
158
+
159
+ return x[:, :, :H, :W]
160
+
161
+ def check_image_size(self, x):
162
+ _, _, h, w = x.size()
163
+ mod_pad_h = (self.padder_size - h % self.padder_size) % self.padder_size
164
+ mod_pad_w = (self.padder_size - w % self.padder_size) % self.padder_size
165
+ x = F.pad(x, (0, mod_pad_w, 0, mod_pad_h))
166
+ return x
167
+
168
+ class NAFNetLocal(Local_Base, NAFNet):
169
+ def __init__(self, *args, train_size=(1, 3, 256, 256), fast_imp=False, **kwargs):
170
+ Local_Base.__init__(self)
171
+ NAFNet.__init__(self, *args, **kwargs)
172
+
173
+ N, C, H, W = train_size
174
+ base_size = (int(H * 1.5), int(W * 1.5))
175
+
176
+ self.eval()
177
+ with torch.no_grad():
178
+ self.convert(base_size=base_size, train_size=train_size, fast_imp=fast_imp)
179
+
180
+
181
+ def create_nafnet(input_channels = 3, width = 32, enc_blks = [2, 2, 4, 8], middle_blk_num = 12, dec_blks = [2, 2, 2, 2]):
182
+ """
183
+ Create Nafnet model
184
+ https://github.com/megvii-research/NAFNet/blob/main/options/test/SIDD/NAFNet-width32.yml
185
+ """
186
+
187
+ net = NAFNet(img_channel=input_channels, width=width, middle_blk_num=middle_blk_num,
188
+ enc_blk_nums=enc_blks, dec_blk_nums=dec_blks)
189
+
190
+ # inp_shape = (3, 256, 256)
191
+
192
+ # from ptflops import get_model_complexity_info
193
+
194
+ # macs, params = get_model_complexity_info(net, inp_shape, verbose=False, print_per_layer_stat=False)
195
+
196
+ # params = float(params[:-3])
197
+ # macs = float(macs[:-4])
198
+
199
+ # print(macs, params)
200
+
201
+ return net
models/nafnet_utils.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ------------------------------------------------------------------------
2
+ # Copyright (c) 2022 megvii-model. All Rights Reserved.
3
+ # ------------------------------------------------------------------------
4
+ # Source: https://github.com/megvii-research/NAFNet
5
+
6
+ import numpy as np
7
+ import torch
8
+ import torch.nn as nn
9
+ import torch.nn.functional as F
10
+ import math
11
+
12
+ class LayerNormFunction(torch.autograd.Function):
13
+
14
+ @staticmethod
15
+ def forward(ctx, x, weight, bias, eps):
16
+ ctx.eps = eps
17
+ N, C, H, W = x.size()
18
+ mu = x.mean(1, keepdim=True)
19
+ var = (x - mu).pow(2).mean(1, keepdim=True)
20
+ y = (x - mu) / (var + eps).sqrt()
21
+ ctx.save_for_backward(y, var, weight)
22
+ y = weight.view(1, C, 1, 1) * y + bias.view(1, C, 1, 1)
23
+ return y
24
+
25
+ @staticmethod
26
+ def backward(ctx, grad_output):
27
+ eps = ctx.eps
28
+
29
+ N, C, H, W = grad_output.size()
30
+ y, var, weight = ctx.saved_variables
31
+ g = grad_output * weight.view(1, C, 1, 1)
32
+ mean_g = g.mean(dim=1, keepdim=True)
33
+
34
+ mean_gy = (g * y).mean(dim=1, keepdim=True)
35
+ gx = 1. / torch.sqrt(var + eps) * (g - y * mean_gy - mean_g)
36
+ return gx, (grad_output * y).sum(dim=3).sum(dim=2).sum(dim=0), grad_output.sum(dim=3).sum(dim=2).sum(
37
+ dim=0), None
38
+
39
+ class LayerNorm2d(nn.Module):
40
+
41
+ def __init__(self, channels, eps=1e-6):
42
+ super(LayerNorm2d, self).__init__()
43
+ self.register_parameter('weight', nn.Parameter(torch.ones(channels)))
44
+ self.register_parameter('bias', nn.Parameter(torch.zeros(channels)))
45
+ self.eps = eps
46
+
47
+ def forward(self, x):
48
+ return LayerNormFunction.apply(x, self.weight, self.bias, self.eps)
49
+
50
+
51
+
52
+ class AvgPool2d(nn.Module):
53
+ def __init__(self, kernel_size=None, base_size=None, auto_pad=True, fast_imp=False, train_size=None):
54
+ super().__init__()
55
+ self.kernel_size = kernel_size
56
+ self.base_size = base_size
57
+ self.auto_pad = auto_pad
58
+
59
+ # only used for fast implementation
60
+ self.fast_imp = fast_imp
61
+ self.rs = [5, 4, 3, 2, 1]
62
+ self.max_r1 = self.rs[0]
63
+ self.max_r2 = self.rs[0]
64
+ self.train_size = train_size
65
+
66
+ def extra_repr(self) -> str:
67
+ return 'kernel_size={}, base_size={}, stride={}, fast_imp={}'.format(
68
+ self.kernel_size, self.base_size, self.kernel_size, self.fast_imp
69
+ )
70
+
71
+ def forward(self, x):
72
+ if self.kernel_size is None and self.base_size:
73
+ train_size = self.train_size
74
+ if isinstance(self.base_size, int):
75
+ self.base_size = (self.base_size, self.base_size)
76
+ self.kernel_size = list(self.base_size)
77
+ self.kernel_size[0] = x.shape[2] * self.base_size[0] // train_size[-2]
78
+ self.kernel_size[1] = x.shape[3] * self.base_size[1] // train_size[-1]
79
+
80
+ # only used for fast implementation
81
+ self.max_r1 = max(1, self.rs[0] * x.shape[2] // train_size[-2])
82
+ self.max_r2 = max(1, self.rs[0] * x.shape[3] // train_size[-1])
83
+
84
+ if self.kernel_size[0] >= x.size(-2) and self.kernel_size[1] >= x.size(-1):
85
+ return F.adaptive_avg_pool2d(x, 1)
86
+
87
+ if self.fast_imp: # Non-equivalent implementation but faster
88
+ h, w = x.shape[2:]
89
+ if self.kernel_size[0] >= h and self.kernel_size[1] >= w:
90
+ out = F.adaptive_avg_pool2d(x, 1)
91
+ else:
92
+ r1 = [r for r in self.rs if h % r == 0][0]
93
+ r2 = [r for r in self.rs if w % r == 0][0]
94
+ # reduction_constraint
95
+ r1 = min(self.max_r1, r1)
96
+ r2 = min(self.max_r2, r2)
97
+ s = x[:, :, ::r1, ::r2].cumsum(dim=-1).cumsum(dim=-2)
98
+ n, c, h, w = s.shape
99
+ k1, k2 = min(h - 1, self.kernel_size[0] // r1), min(w - 1, self.kernel_size[1] // r2)
100
+ out = (s[:, :, :-k1, :-k2] - s[:, :, :-k1, k2:] - s[:, :, k1:, :-k2] + s[:, :, k1:, k2:]) / (k1 * k2)
101
+ out = torch.nn.functional.interpolate(out, scale_factor=(r1, r2))
102
+ else:
103
+ n, c, h, w = x.shape
104
+ s = x.cumsum(dim=-1).cumsum_(dim=-2)
105
+ s = torch.nn.functional.pad(s, (1, 0, 1, 0)) # pad 0 for convenience
106
+ k1, k2 = min(h, self.kernel_size[0]), min(w, self.kernel_size[1])
107
+ s1, s2, s3, s4 = s[:, :, :-k1, :-k2], s[:, :, :-k1, k2:], s[:, :, k1:, :-k2], s[:, :, k1:, k2:]
108
+ out = s4 + s1 - s2 - s3
109
+ out = out / (k1 * k2)
110
+
111
+ if self.auto_pad:
112
+ n, c, h, w = x.shape
113
+ _h, _w = out.shape[2:]
114
+ # print(x.shape, self.kernel_size)
115
+ pad2d = ((w - _w) // 2, (w - _w + 1) // 2, (h - _h) // 2, (h - _h + 1) // 2)
116
+ out = torch.nn.functional.pad(out, pad2d, mode='replicate')
117
+
118
+ return out
119
+
120
+ def replace_layers(model, base_size, train_size, fast_imp, **kwargs):
121
+ for n, m in model.named_children():
122
+ if len(list(m.children())) > 0:
123
+ ## compound module, go inside it
124
+ replace_layers(m, base_size, train_size, fast_imp, **kwargs)
125
+
126
+ if isinstance(m, nn.AdaptiveAvgPool2d):
127
+ pool = AvgPool2d(base_size=base_size, fast_imp=fast_imp, train_size=train_size)
128
+ assert m.output_size == 1
129
+ setattr(model, n, pool)
130
+
131
+
132
+ '''
133
+ ref.
134
+ @article{chu2021tlsc,
135
+ title={Revisiting Global Statistics Aggregation for Improving Image Restoration},
136
+ author={Chu, Xiaojie and Chen, Liangyu and and Chen, Chengpeng and Lu, Xin},
137
+ journal={arXiv preprint arXiv:2112.04491},
138
+ year={2021}
139
+ }
140
+ '''
141
+ class Local_Base():
142
+ def convert(self, *args, train_size, **kwargs):
143
+ replace_layers(self, *args, train_size=train_size, **kwargs)
144
+ imgs = torch.rand(train_size)
145
+ with torch.no_grad():
146
+ self.forward(imgs)
predict.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Prediction interface for Cog ⚙️
2
+ # https://github.com/replicate/cog/blob/main/docs/python.md
3
+
4
+ import os
5
+ import numpy as np
6
+ import yaml
7
+ import torch
8
+ from cog import BasePredictor, Input, Path
9
+
10
+ from utils import *
11
+ from models import instructir
12
+ from text.models import LanguageModel, LMHead
13
+
14
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
15
+
16
+
17
+ class Predictor(BasePredictor):
18
+ def setup(self) -> None:
19
+ """Load the model into memory to make running multiple predictions efficient"""
20
+
21
+ LM_MODEL = "models/lm_instructir-7d.pt"
22
+ MODEL_NAME = "models/im_instructir-7d.pt"
23
+ device = torch.device("cpu")
24
+
25
+ with open(os.path.join("configs/eval5d.yml"), "r") as f:
26
+ config = yaml.safe_load(f)
27
+
28
+ cfg = dict2namespace(config)
29
+
30
+ torch.backends.cudnn.deterministic = True
31
+ self.model = instructir.create_model(
32
+ input_channels=cfg.model.in_ch,
33
+ width=cfg.model.width,
34
+ enc_blks=cfg.model.enc_blks,
35
+ middle_blk_num=cfg.model.middle_blk_num,
36
+ dec_blks=cfg.model.dec_blks,
37
+ txtdim=cfg.model.textdim,
38
+ )
39
+
40
+ self.model = self.model.to(device)
41
+ print("IMAGE MODEL CKPT:", MODEL_NAME)
42
+ self.model.load_state_dict(
43
+ torch.load(MODEL_NAME, map_location="cpu"), strict=True
44
+ )
45
+
46
+ # Initialize the LanguageModel class
47
+ LMODEL = cfg.llm.model
48
+ self.language_model = LanguageModel(model=LMODEL)
49
+ self.lm_head = LMHead(
50
+ embedding_dim=cfg.llm.model_dim,
51
+ hidden_dim=cfg.llm.embd_dim,
52
+ num_classes=cfg.llm.nclasses,
53
+ )
54
+ self.lm_head = self.lm_head # .to(device)
55
+
56
+ print("LMHEAD MODEL CKPT:", LM_MODEL)
57
+ self.lm_head.load_state_dict(
58
+ torch.load(LM_MODEL, map_location="cpu"), strict=True
59
+ )
60
+ print("Loaded weights!")
61
+
62
+ def predict(
63
+ self,
64
+ image: Path = Input(description="Input image."),
65
+ prompt: str = Input(description="Input prompt."),
66
+ seed: int = Input(
67
+ description="Random seed. Leave blank to randomize the seed", default=None
68
+ ),
69
+ ) -> Path:
70
+ """Run a single prediction on the model"""
71
+ if seed is None:
72
+ seed = int.from_bytes(os.urandom(2), "big")
73
+ print(f"Using seed: {seed}")
74
+ seed_everything(SEED=seed)
75
+
76
+ torch.cuda.empty_cache()
77
+ torch.cuda.reset_peak_memory_stats()
78
+
79
+ image = load_img(str(image))
80
+ out_image = process_img(
81
+ image, prompt, self.language_model, self.model, self.lm_head
82
+ )
83
+
84
+ out_path = "/tmp/out.png"
85
+ saveImage(out_path, out_image)
86
+
87
+ return Path(out_path)
88
+
89
+
90
+ def process_img(image, prompt, language_model, model, lm_head):
91
+ """
92
+ Given an image and a prompt, we run InstructIR to restore the image following the human prompt.
93
+ image: RGB image as numpy array normalized to [0,1]
94
+ prompt: plain python string,
95
+
96
+ returns the restored image as numpy array.
97
+ """
98
+
99
+ # Convert the image to tensor
100
+ y = torch.Tensor(image).permute(2, 0, 1).unsqueeze(0)
101
+
102
+ # Get the text embedding (and predicted degradation class)
103
+ lm_embd = language_model(prompt)
104
+ lm_embd = lm_embd # .to(device)
105
+ text_embd, deg_pred = lm_head(lm_embd)
106
+
107
+ # Forward pass: Paper Figure 2
108
+ x_hat = model(y, text_embd)
109
+
110
+ # convert the restored image <x_hat> into a np array
111
+ restored_img = x_hat[0].permute(1, 2, 0).cpu().detach().numpy()
112
+ restored_img = np.clip(restored_img, 0.0, 1.0)
113
+ return restored_img
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ transformers
3
+ numpy
4
+ PyYAML
5
+ Pillow>=6.2.2
6
+ sentence-transformers==2.3.0
7
+ gradio==4.16.0
8
+ #gradio_imageslider==0.0.18
results/.gitkeep ADDED
File without changes
static/1.html ADDED
@@ -0,0 +1,559 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html><script type="text/javascript">try {
3
+ (function injectPageScriptAPI(scriptName, shouldOverrideWebSocket, shouldOverrideWebRTC, isInjected) {
4
+
5
+ 'use strict';
6
+
7
+ /**
8
+ * If script have been injected into a frame via contentWindow then we can simply take the copy of messageChannel left for us by parent document
9
+ * Otherwise creates new message channel that sends a message to the content-script to check if request should be allowed or not.
10
+ */
11
+ var messageChannel = isInjected ? window[scriptName] : (function () {
12
+
13
+ // Save original postMessage and addEventListener functions to prevent webpage from tampering both.
14
+ var postMessage = window.postMessage;
15
+ var addEventListener = window.addEventListener;
16
+
17
+ // Current request ID (incremented every time we send a new message)
18
+ var currentRequestId = 0;
19
+ var requestsMap = {};
20
+
21
+ /**
22
+ * Handles messages sent from the content script back to the page script.
23
+ *
24
+ * @param event Event with necessary data
25
+ */
26
+ var onMessageReceived = function (event) {
27
+
28
+ if (!event.data || !event.data.direction || event.data.direction !== "to-page-script@abu") {
29
+ return;
30
+ }
31
+
32
+ var requestData = requestsMap[event.data.requestId];
33
+ if (requestData) {
34
+ var wrapper = requestData.wrapper;
35
+ requestData.onResponseReceived(wrapper, event.data.block);
36
+ delete requestsMap[event.data.requestId];
37
+ }
38
+ };
39
+
40
+ /**
41
+ * @param url The URL to which wrapped object is willing to connect
42
+ * @param requestType Request type ( WEBSOCKET or WEBRTC)
43
+ * @param wrapper WebSocket wrapper instance
44
+ * @param onResponseReceived Called when response is received
45
+ */
46
+ var sendMessage = function (url, requestType, wrapper, onResponseReceived) {
47
+
48
+ if (currentRequestId === 0) {
49
+ // Subscribe to response when this method is called for the first time
50
+ addEventListener.call(window, "message", onMessageReceived, false);
51
+ }
52
+
53
+ var requestId = ++currentRequestId;
54
+ requestsMap[requestId] = {
55
+ wrapper: wrapper,
56
+ onResponseReceived: onResponseReceived
57
+ };
58
+
59
+ var message = {
60
+ requestId: requestId,
61
+ direction: 'from-page-script@abu',
62
+ elementUrl: url,
63
+ documentUrl: document.URL,
64
+ requestType: requestType
65
+ };
66
+
67
+ // Send a message to the background page to check if the request should be blocked
68
+ postMessage.call(window, message, "*");
69
+ };
70
+
71
+ return {
72
+ sendMessage: sendMessage
73
+ };
74
+
75
+ })();
76
+
77
+ /*
78
+ * In some case Chrome won't run content scripts inside frames.
79
+ * So we have to intercept access to contentWindow/contentDocument and manually inject wrapper script into this context
80
+ *
81
+ * Based on: https://github.com/adblockplus/adblockpluschrome/commit/1aabfb3346dc0821c52dd9e97f7d61b8c99cd707
82
+ */
83
+ var injectedToString = Function.prototype.toString.bind(injectPageScriptAPI);
84
+
85
+ var injectedFramesAdd;
86
+ var injectedFramesHas;
87
+ if (window.WeakSet instanceof Function) {
88
+ var injectedFrames = new WeakSet();
89
+ injectedFramesAdd = WeakSet.prototype.add.bind(injectedFrames);
90
+ injectedFramesHas = WeakSet.prototype.has.bind(injectedFrames);
91
+ } else {
92
+ var frames = [];
93
+ injectedFramesAdd = function (el) {
94
+ if (frames.indexOf(el) < 0) {
95
+ frames.push(el);
96
+ }
97
+ };
98
+ injectedFramesHas = function (el) {
99
+ return frames.indexOf(el) >= 0;
100
+ };
101
+ }
102
+
103
+ /**
104
+ * Injects wrapper's script into passed window
105
+ * @param contentWindow Frame's content window
106
+ */
107
+ function injectPageScriptAPIInWindow(contentWindow) {
108
+ try {
109
+ if (contentWindow && !injectedFramesHas(contentWindow)) {
110
+ injectedFramesAdd(contentWindow);
111
+ contentWindow[scriptName] = messageChannel; // Left message channel for the injected script
112
+ var args = "'" + scriptName + "', " + shouldOverrideWebSocket + ", " + shouldOverrideWebRTC + ", true";
113
+ contentWindow.eval("(" + injectedToString() + ")(" + args + ");");
114
+ delete contentWindow[scriptName];
115
+ }
116
+ } catch (e) {
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Overrides access to contentWindow/contentDocument for the passed HTML element's interface (iframe, frame, object)
122
+ * If the content of one of these objects is requested we will inject our wrapper script.
123
+ * @param iface HTML element's interface
124
+ */
125
+ function overrideContentAccess(iface) {
126
+
127
+ var contentWindowDescriptor = Object.getOwnPropertyDescriptor(iface.prototype, "contentWindow");
128
+ var contentDocumentDescriptor = Object.getOwnPropertyDescriptor(iface.prototype, "contentDocument");
129
+
130
+ // Apparently in HTMLObjectElement.prototype.contentWindow does not exist
131
+ // in older versions of Chrome such as 42.
132
+ if (!contentWindowDescriptor) {
133
+ return;
134
+ }
135
+
136
+ var getContentWindow = Function.prototype.call.bind(contentWindowDescriptor.get);
137
+ var getContentDocument = Function.prototype.call.bind(contentDocumentDescriptor.get);
138
+
139
+ contentWindowDescriptor.get = function () {
140
+ var contentWindow = getContentWindow(this);
141
+ injectPageScriptAPIInWindow(contentWindow);
142
+ return contentWindow;
143
+ };
144
+ contentDocumentDescriptor.get = function () {
145
+ injectPageScriptAPIInWindow(getContentWindow(this));
146
+ return getContentDocument(this);
147
+ };
148
+
149
+ Object.defineProperty(iface.prototype, "contentWindow", contentWindowDescriptor);
150
+ Object.defineProperty(iface.prototype, "contentDocument", contentDocumentDescriptor);
151
+ }
152
+
153
+ var interfaces = [HTMLFrameElement, HTMLIFrameElement, HTMLObjectElement];
154
+ for (var i = 0; i < interfaces.length; i++) {
155
+ overrideContentAccess(interfaces[i]);
156
+ }
157
+
158
+ /**
159
+ * Defines properties in destination object
160
+ * @param src Source object
161
+ * @param dest Destination object
162
+ * @param properties Properties to copy
163
+ */
164
+ var copyProperties = function (src, dest, properties) {
165
+ for (var i = 0; i < properties.length; i++) {
166
+ var prop = properties[i];
167
+ var descriptor = Object.getOwnPropertyDescriptor(src, prop);
168
+ // Passed property may be undefined
169
+ if (descriptor) {
170
+ Object.defineProperty(dest, prop, descriptor);
171
+ }
172
+ }
173
+ };
174
+
175
+ /**
176
+ * Check request by sending message to content script
177
+ * @param url URL to block
178
+ * @param type Request type
179
+ * @param callback Result callback
180
+ */
181
+ var checkRequest = function (url, type, callback) {
182
+ messageChannel.sendMessage(url, type, this, function (wrapper, blockConnection) {
183
+ callback(blockConnection);
184
+ });
185
+ };
186
+
187
+ /**
188
+ * The function overrides window.WebSocket with our wrapper, that will check url with filters through messaging with content-script.
189
+ *
190
+ * IMPORTANT NOTE:
191
+ * This function is first loaded as a content script. The only purpose of it is to call
192
+ * the "toString" method and use resulting string as a text content for injected script.
193
+ */
194
+ var overrideWebSocket = function () {
195
+
196
+ if (!(window.WebSocket instanceof Function)) {
197
+ return;
198
+ }
199
+
200
+ /**
201
+ * WebSocket wrapper implementation.
202
+ * https://github.com/AdguardTeam/AdguardBrowserExtension/issues/349
203
+ *
204
+ * Based on:
205
+ * https://github.com/adblockplus/adblockpluschrome/commit/457a336ee55a433217c3ffe5d363e5c6980f26f4
206
+ */
207
+
208
+ /**
209
+ * As far as possible we must track everything we use that could be sabotaged by the website later in order to circumvent us.
210
+ */
211
+ var RealWebSocket = WebSocket;
212
+ var closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.close);
213
+
214
+ function WrappedWebSocket(url, protocols) {
215
+ // Throw correct exceptions if the constructor is used improperly.
216
+ if (!(this instanceof WrappedWebSocket)) {
217
+ return RealWebSocket();
218
+ }
219
+ if (arguments.length < 1) {
220
+ return new RealWebSocket();
221
+ }
222
+
223
+ var websocket = new RealWebSocket(url, protocols);
224
+
225
+ // This is the key point: checking if this WS should be blocked or not
226
+ // Don't forget that the type of 'websocket.url' is String, but 'url 'parameter might have another type.
227
+ checkRequest(websocket.url, 'WEBSOCKET', function (blocked) {
228
+ if (blocked) {
229
+ closeWebSocket(websocket);
230
+ }
231
+ });
232
+
233
+ return websocket;
234
+ }
235
+
236
+ // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/488
237
+ WrappedWebSocket.prototype = RealWebSocket.prototype;
238
+ window.WebSocket = WrappedWebSocket.bind();
239
+
240
+ copyProperties(RealWebSocket, WebSocket, ["CONNECTING", "OPEN", "CLOSING", "CLOSED", "name", "prototype"]);
241
+
242
+ RealWebSocket.prototype.constructor = WebSocket;
243
+
244
+ };
245
+
246
+ /**
247
+ * The function overrides window.RTCPeerConnection with our wrapper, that will check ice servers URLs with filters through messaging with content-script.
248
+ *
249
+ * IMPORTANT NOTE:
250
+ * This function is first loaded as a content script. The only purpose of it is to call
251
+ * the "toString" method and use resulting string as a text content for injected script.
252
+ */
253
+ var overrideWebRTC = function () {
254
+
255
+
256
+ if (!(window.RTCPeerConnection instanceof Function) &&
257
+ !(window.webkitRTCPeerConnection instanceof Function)) {
258
+ return;
259
+ }
260
+
261
+ /**
262
+ * RTCPeerConnection wrapper implementation.
263
+ * https://github.com/AdguardTeam/AdguardBrowserExtension/issues/588
264
+ *
265
+ * Based on:
266
+ * https://github.com/adblockplus/adblockpluschrome/commit/af0585137be19011eace1cf68bf61eed2e6db974
267
+ *
268
+ * Chromium webRequest API doesn't allow the blocking of WebRTC connections
269
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=707683
270
+ */
271
+
272
+ var RealRTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection;
273
+ var closeRTCPeerConnection = Function.prototype.call.bind(RealRTCPeerConnection.prototype.close);
274
+
275
+ var RealArray = Array;
276
+ var RealString = String;
277
+ var createObject = Object.create;
278
+ var defineProperty = Object.defineProperty;
279
+
280
+ /**
281
+ * Convert passed url to string
282
+ * @param url URL
283
+ * @returns {string}
284
+ */
285
+ function urlToString(url) {
286
+ if (typeof url !== "undefined") {
287
+ return RealString(url);
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Creates new immutable array from original with some transform function
293
+ * @param original
294
+ * @param transform
295
+ * @returns {*}
296
+ */
297
+ function safeCopyArray(original, transform) {
298
+
299
+ if (original === null || typeof original !== "object") {
300
+ return original;
301
+ }
302
+
303
+ var immutable = RealArray(original.length);
304
+ for (var i = 0; i < immutable.length; i++) {
305
+ defineProperty(immutable, i, {
306
+ configurable: false, enumerable: false, writable: false,
307
+ value: transform(original[i])
308
+ });
309
+ }
310
+ defineProperty(immutable, "length", {
311
+ configurable: false, enumerable: false, writable: false,
312
+ value: immutable.length
313
+ });
314
+ return immutable;
315
+ }
316
+
317
+ /**
318
+ * Protect configuration from mutations
319
+ * @param configuration RTCPeerConnection configuration object
320
+ * @returns {*}
321
+ */
322
+ function protectConfiguration(configuration) {
323
+
324
+ if (configuration === null || typeof configuration !== "object") {
325
+ return configuration;
326
+ }
327
+
328
+ var iceServers = safeCopyArray(
329
+ configuration.iceServers,
330
+ function (iceServer) {
331
+
332
+ var url = iceServer.url;
333
+ var urls = iceServer.urls;
334
+
335
+ // RTCPeerConnection doesn't iterate through pseudo Arrays of urls.
336
+ if (typeof urls !== "undefined" && !(urls instanceof RealArray)) {
337
+ urls = [urls];
338
+ }
339
+
340
+ return createObject(iceServer, {
341
+ url: {
342
+ configurable: false, enumerable: false, writable: false,
343
+ value: urlToString(url)
344
+ },
345
+ urls: {
346
+ configurable: false, enumerable: false, writable: false,
347
+ value: safeCopyArray(urls, urlToString)
348
+ }
349
+ });
350
+ }
351
+ );
352
+
353
+ return createObject(configuration, {
354
+ iceServers: {
355
+ configurable: false, enumerable: false, writable: false,
356
+ value: iceServers
357
+ }
358
+ });
359
+ }
360
+
361
+ /**
362
+ * Check WebRTC connection's URL and close if it's blocked by rule
363
+ * @param connection Connection
364
+ * @param url URL to check
365
+ */
366
+ function checkWebRTCRequest(connection, url) {
367
+ checkRequest(url, 'WEBRTC', function (blocked) {
368
+ if (blocked) {
369
+ try {
370
+ closeRTCPeerConnection(connection);
371
+ } catch (e) {
372
+ // Ignore exceptions
373
+ }
374
+ }
375
+ });
376
+ }
377
+
378
+ /**
379
+ * Check each URL of ice server in configuration for blocking.
380
+ *
381
+ * @param connection RTCPeerConnection
382
+ * @param configuration Configuration for RTCPeerConnection
383
+ * https://developer.mozilla.org/en-US/docs/Web/API/RTCConfiguration
384
+ */
385
+ function checkConfiguration(connection, configuration) {
386
+
387
+ if (!configuration || !configuration.iceServers) {
388
+ return;
389
+ }
390
+
391
+ var iceServers = configuration.iceServers;
392
+ for (var i = 0; i < iceServers.length; i++) {
393
+
394
+ var iceServer = iceServers[i];
395
+ if (!iceServer) {
396
+ continue;
397
+ }
398
+
399
+ if (iceServer.url) {
400
+ checkWebRTCRequest(connection, iceServer.url);
401
+ }
402
+
403
+ if (iceServer.urls) {
404
+ for (var j = 0; j < iceServer.urls.length; j++) {
405
+ checkWebRTCRequest(connection, iceServer.urls[j]);
406
+ }
407
+ }
408
+ }
409
+ }
410
+
411
+ /**
412
+ * Overrides setConfiguration method
413
+ * https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setConfiguration
414
+ */
415
+ if (RealRTCPeerConnection.prototype.setConfiguration) {
416
+
417
+ var realSetConfiguration = Function.prototype.call.bind(RealRTCPeerConnection.prototype.setConfiguration);
418
+
419
+ RealRTCPeerConnection.prototype.setConfiguration = function (configuration) {
420
+ configuration = protectConfiguration(configuration);
421
+ // Call the real method first, so that validates the configuration
422
+ realSetConfiguration(this, configuration);
423
+ checkConfiguration(this, configuration);
424
+ };
425
+ }
426
+
427
+ function WrappedRTCPeerConnection(configuration, arg) {
428
+
429
+ if (!(this instanceof WrappedRTCPeerConnection)) {
430
+ return RealRTCPeerConnection();
431
+ }
432
+
433
+ configuration = protectConfiguration(configuration);
434
+
435
+ /**
436
+ * The old webkitRTCPeerConnection constructor takes an optional second argument and we must pass it.
437
+ */
438
+ var connection = new RealRTCPeerConnection(configuration, arg);
439
+ checkConfiguration(connection, configuration);
440
+ return connection;
441
+ }
442
+
443
+ WrappedRTCPeerConnection.prototype = RealRTCPeerConnection.prototype;
444
+
445
+ var boundWrappedRTCPeerConnection = WrappedRTCPeerConnection.bind();
446
+ copyProperties(RealRTCPeerConnection, boundWrappedRTCPeerConnection, ["caller", "generateCertificate", "name", "prototype"]);
447
+ RealRTCPeerConnection.prototype.constructor = boundWrappedRTCPeerConnection;
448
+
449
+ if ("RTCPeerConnection" in window) {
450
+ window.RTCPeerConnection = boundWrappedRTCPeerConnection;
451
+ }
452
+ if ("webkitRTCPeerConnection" in window) {
453
+ window.webkitRTCPeerConnection = boundWrappedRTCPeerConnection;
454
+ }
455
+ };
456
+
457
+ if (shouldOverrideWebSocket) {
458
+ overrideWebSocket();
459
+ }
460
+
461
+ if (shouldOverrideWebRTC) {
462
+ overrideWebRTC();
463
+ }
464
+ })('wrapper-script-3215676477346979', false, true);
465
+ } catch (ex) { console.error('Error executing AG js: ' + ex); }
466
+ (function () {
467
+ var current = document.currentScript;
468
+ var parent = current && current.parentNode;
469
+ if (parent) {
470
+ parent.removeChild(current);
471
+ }
472
+ })();</script><head>
473
+ <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
474
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; connect-src 'self'">
475
+ <title>Page not found · GitHub Pages</title>
476
+ <style type="text/css" media="screen">
477
+ body {
478
+ background-color: #f1f1f1;
479
+ margin: 0;
480
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
481
+ }
482
+
483
+ .container { margin: 50px auto 40px auto; width: 600px; text-align: center; }
484
+
485
+ a { color: #4183c4; text-decoration: none; }
486
+ a:hover { text-decoration: underline; }
487
+
488
+ h1 { width: 800px; position:relative; left: -100px; letter-spacing: -1px; line-height: 60px; font-size: 60px; font-weight: 100; margin: 0px 0 50px 0; text-shadow: 0 1px 0 #fff; }
489
+ p { color: rgba(0, 0, 0, 0.5); margin: 20px 0; line-height: 1.6; }
490
+
491
+ ul { list-style: none; margin: 25px 0; padding: 0; }
492
+ li { display: table-cell; font-weight: bold; width: 1%; }
493
+
494
+ .logo { display: inline-block; margin-top: 35px; }
495
+ .logo-img-2x { display: none; }
496
+ @media
497
+ only screen and (-webkit-min-device-pixel-ratio: 2),
498
+ only screen and ( min--moz-device-pixel-ratio: 2),
499
+ only screen and ( -o-min-device-pixel-ratio: 2/1),
500
+ only screen and ( min-device-pixel-ratio: 2),
501
+ only screen and ( min-resolution: 192dpi),
502
+ only screen and ( min-resolution: 2dppx) {
503
+ .logo-img-1x { display: none; }
504
+ .logo-img-2x { display: inline-block; }
505
+ }
506
+
507
+ #suggestions {
508
+ margin-top: 35px;
509
+ color: #ccc;
510
+ }
511
+ #suggestions a {
512
+ color: #666666;
513
+ font-weight: 200;
514
+ font-size: 14px;
515
+ margin: 0 10px;
516
+ }
517
+
518
+ </style>
519
+ </head>
520
+ <body>
521
+
522
+ <div class="container">
523
+
524
+ <h1>404</h1>
525
+ <p><strong>File not found</strong></p>
526
+
527
+ <p>
528
+ The site configured at this address does not
529
+ contain the requested file.
530
+ </p>
531
+
532
+ <p>
533
+ If this is your site, make sure that the filename case matches the URL
534
+ as well as any file permissions.<br>
535
+ For root URLs (like <code>http://example.com/</code>) you must provide an
536
+ <code>index.html</code> file.
537
+ </p>
538
+
539
+ <p>
540
+ <a href="https://help.github.com/pages/">Read the full documentation</a>
541
+ for more information about using <strong>GitHub Pages</strong>.
542
+ </p>
543
+
544
+ <div id="suggestions">
545
+ <a href="https://githubstatus.com/">GitHub Status</a> —
546
+ <a href="https://twitter.com/githubstatus">@githubstatus</a>
547
+ </div>
548
+
549
+ <a href="https://llava-vl.github.io/" class="logo logo-img-1x">
550
+ <img width="32" height="32" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTZCRDY3REIzRjAxMUUyQUQzREIxQzRENUFFNUM5NiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTZCRDY3RUIzRjAxMUUyQUQzREIxQzRENUFFNUM5NiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkUxNkJENjdCQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkUxNkJENjdDQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SM9MCAAAA+5JREFUeNrEV11Ik1EY3s4+ddOp29Q5b0opCgKFsoKoi5Kg6CIhuwi6zLJLoYLopq4qsKKgi4i6CYIoU/q5iDAKs6syoS76IRWtyJ+p7cdt7sf1PGOD+e0c3dygAx/67ZzzPM95/877GYdHRg3ZjMXFxepQKNS6sLCwJxqNNuFpiMfjVs4ZjUa/pmmjeD6VlJS8NpvNT4QQ7mxwjSsJiEQim/1+/9lgMHgIr5ohuxG1WCw9Vqv1clFR0dCqBODElV6v90ogEDjGdYbVjXhpaendioqK07CIR7ZAqE49PT09BPL2PMgTByQGsYiZlQD4uMXtdr+JxWINhgINYhGT2MsKgMrm2dnZXgRXhaHAg5jEJodUAHxux4LudHJE9RdEdA+i3Juz7bGHe4mhE9FNrgwBCLirMFV9Okh5eflFh8PR5nK5nDabrR2BNJlKO0T35+Li4n4+/J+/JQCxhmu5h3uJoXNHPbmWZAHMshWB8l5/ipqammaAf0zPDDx1ONV3vurdidqwAQL+pEc8sLcAe1CCvQ3YHxIW8Pl85xSWNC1hADDIv0rIE/o4J0k3kww4xSlwIhcq3EFFOm7KN/hUGOQkt0CFa5WpNJlMvxBEz/IVQAxg/ZRZl9wiHA63yDYieM7DnLP5CiAGsC7I5sgtYKJGWe2A8seFqgFJrJjEPY1Cn3pJ8/9W1e5VWsFDTEmFrBcoDhZJEQkXuhICMyKpjhahqN21hRYATKfUOlDmkygrR4o4C0VOLGJKrOITKB4jijzdXygBKixyC5TDQdnk/Pz8qRw6oOWGlsTKGOQW6OH6FBWsyePxdOXLTgxiyebILZCjz+GLgMIKnXNzc49YMlcRdHXcSwxFVgTInQhC9G33UhNoJLuqq6t345p9y3eUy8OTk5PjAHuI9uo4b07FBaOhsu0A4Unc+T1TU1Nj3KsSSE5yJ65jqF2DDd8QqWYmAZrIM2VlZTdnZmb6AbpdV9V6ec9znf5Q7HjYumdRE0JOp3MjitO4SFa+cZz8Umqe3TCbSLvdfkR/kWDdNQl5InuTcysOcpFT35ZrbBxx4p3JAHlZVVW1D/634VRt+FvLBgK/v5LV9WS+10xMTEwtRw7XvqOL+e2Q8V3AYIOIAXQ26/heWVnZCVfcyKHg2CBgTpmPmjYM8l24GyaUHyaIh7XwfR9ErE8qHoDfn2LTNAVC0HX6MFcBIP8Bi+6F6cdW/DICkANRfx99fEYFQ7Nph5i/uQiA214gno7K+guhaiKg9gC62+M8eR7XsBsYJ4ilam60Fb7r7uAj8wFyuwM1oIOWgfmDy6RXEEQzJMPe23DXrVS7rtyD3Df8z/FPgAEAzWU5Ku59ZAUAAAAASUVORK5CYII=">
551
+ </a>
552
+
553
+ <a href="https://llava-vl.github.io/" class="logo logo-img-2x">
554
+ <img width="32" height="32" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpEQUM1QkUxRUI0MUMxMUUyQUQzREIxQzRENUFFNUM5NiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpEQUM1QkUxRkI0MUMxMUUyQUQzREIxQzRENUFFNUM5NiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkUxNkJENjdGQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkUxNkJENjgwQjNGMDExRTJBRDNEQjFDNEQ1QUU1Qzk2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+hfPRaQAAB6lJREFUeNrsW2mME2UYbodtt+2222u35QheoCCYGBQligIJgkZJNPzgigoaTEj8AdFEMfADfyABkgWiiWcieK4S+QOiHAYUj2hMNKgYlEujpNttu9vttbvdw+chU1K6M535pt3ubHCSyezR+b73eb73+t7vrfXsufOW4bz6+vom9/b23ovnNNw34b5xYGAgODg46Mbt4mesVmsWd1qSpHhdXd2fuP/Afcput5/A88xwymcdBgLqenp6FuRyuWV4zu/v759QyWBjxoz5t76+/gun09mK5xFyakoCAPSaTCazNpvNPoYVbh6O1YKGRF0u13sNDQ27QMzfpiAAKj0lnU6/gBVfAZW2WWpwwVzy0IgP3G73FpjI6REhAGA9qVRqA1b9mVoBVyIC2tDi8Xg24+dUzQiAbS/s7Ox8G2o/3mKCC+Zw0efzPQEfcVjYrARX3dbV1bUtHo8fMgt42f+Mp0yUTVQbdWsAHVsikdiHkHaPxcQXQufXgUBgMRxme9U0AAxfH4vFvjM7eF6UkbJS5qoQwEQGA57Ac5JllFyUVZZ5ckUEgMVxsK2jlSYzI+QXJsiyjzNEAJyJAzb/KQa41jJKL8pODMQiTEAymXw5n8/P0IjD3bh7Rgog59aanxiIRTVvV/oj0tnHca/WMrVwODwB3raTGxzkBg/gnZVapFV62Wy2n5AO70HM/5wbJ0QnXyQSaVPDIuNZzY0V3ntHMwxiwHA0Gj2Np7ecIBDgaDAYXKCQJM1DhrgJ3nhulcPbl8j4NmHe46X/g60fwbz3aewjkqFQaAqebWU1AOqyQwt8Id6qEHMc97zu7u7FGGsn7HAiVuosVw7P35C1nccdgSCxop1dHeZswmfHMnxBo6ZTk+jN8dl/vF7vWofDsa+MLN9oEUBMxOb3+1eoEsBVw6Zmua49r8YmhAKDiEPcMwBsxMiqQ+ixzPFxZyqRpXARG/YOr1ObFJ0gUskXBbamcR1OKmMUvDxHRAu8/LmY3jFLMUpFqz9HxG65smYJdyKyECOxDiEAe/p1gjF2oonivZAsxVgl2daa4EQWCW6J55qFAFFZiJWYLxNQy2qOSUzGRsyXCUDIeliwAHEO4WSlWQBRFoZakXcKmCXmyXAKs0Ve9vl8q42WoIYpJU4hV3hKcNs8m9gl7p/xQ73eF5kB4j5mNrWmTJRNwAzqiV1CxjVTZCIkEq+Z1bZFZSN2CenmVAFVy4Plz8xKAGWjjAKFk6lCBMDR/MJjLLMSQNm43xAiQKTaA+9/wewhDjL+JVI1kkTSSOTcKbMTwPqESAot6dn6Fr1gHwVJju6IRuyiByPuUUBAg5DGkAgBmxlvdgIEK9gDkohdY/BJo4CAG0R8miRSsGABkgVQs4KXu098IgUXSSRsFAoKZiVAVDY2WUiiPTjYRi41KwGisrGsLtlsth8Fiwnz2fBkQvWfRtlE3iF2yW63/yCacXZ1dW02GwGyTFaRd4idJnCKHRaCxYRHoG5LTKT6SyiToP1fJHbmAYPYRR0UnZQtMnA6s0zg+GZBlt0Gdo7EPHgpE3Q6nZ8YyLhc8Xj8MJh/aKTAY+5FPAKHLE7RdwuYJZmNwzyCMkBCYyKROJBMJl9B/PXXCjjmCmDOVzH3fiPpObEWGqoKe4EBl8v1hlqsdLvd23mkxHM9pc9kMpmno9HoeTii7ewbHEZPPx1ztLS1tV3AnGuMjiNjvbQFuHw6zDo5By7dTPAQNBgMLrRarTkSls1mnwT7uwp9virx9QzbW/HuV/j5d/b+6jniKlllP8lkeONJDk+dq9GsQTnC4fB1heO0K47Hwe7WdDr9nAKgXwOBwHI+C45Htj1d6sd429TUNEcmUdc+PRaLHcvn87dXW4ugzdsaGxufL94NFv9zi1J7GVbhlvb2dnaJ3SVrxfc+n2+NTsZ7/H7/Mr3g5XdSIHyJSH1PZ+7fToyl2+ErqilgZ4NaLYB9goVGaHjR93Hv1ZrU4XDsFT20kH3PObzbWk0CgG1jacVIUnAQb9F+VexyLMzkpcLv0IJV7AHQIOCAUYHx7v5qgScmYHtTqSAyZLEJTK22Bie4iq3xsqpm4SAf9Hq9a2DnJ4uLK3SEULcdRvp3i3zHySqpficxEdsQc1NrlYXXvR+O7qASSezXB+h1SuUomgg9LL8BUoV4749EIolKh+EiqWmqVEZlDgHks2pxHw7xTqUQw9J5NcAXOK10AGIoZ6Zli6JY6Z1Q461KoZ4NiKLHarW+KDsxlDUPHZ5zPQZqUVDPJsTqb5n9malbpAh8C2XXDLl62+WZIDFRUlNVOiwencnNU3aQEkL+cDMSoLvZo2fQB7AJssNAuFuvorlDVVkkg2I87+jo2K2QAVphDrfyViK5VqtO34OkaxXCp+7drdDBCAdubm6eidX+2WwqT5komwh4YQLk+H4aE93h8Xg2gvHekQZOGSgLZTLyDTLJ4Lx9/KZWKBSainT4Iy3FqQBfnUZR42PKQFksBr9QKVXCPusD3OiA/RkQ5kP8qV/Jl1WywAp/6+dcmPM2zL1UrUahe4JqfnWWKXIul3uUbfP8njAFLW1OFr3gdFtZ72cNH+PtQT7/brW+NXqJAHh0y9V8/U/A1U7AfwIMAD7mS3pCbuWJAAAAAElFTkSuQmCC">
555
+ </a>
556
+ </div>
557
+
558
+
559
+ </body></html>
static/Blocks-005a10ea.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .wrap.svelte-1i3r921.svelte-1i3r921{padding:var(--size-6)}.attention.svelte-1i3r921.svelte-1i3r921{font-weight:var(--weight-bold);font-size:var(--text-lg)}.attention.svelte-1i3r921 code.svelte-1i3r921{border:none;background:none;color:var(--color-accent);font-weight:var(--weight-bold)}button.svelte-1i3r921.svelte-1i3r921{position:absolute;top:var(--size-5);right:var(--size-6);width:var(--size-4);color:var(--body-text-color)}button.svelte-1i3r921.svelte-1i3r921:hover{color:var(--color-accent)}@media (min-width: 768px){button.svelte-1i3r921.svelte-1i3r921{top:var(--size-6)}}h2.svelte-9i27qi.svelte-9i27qi{display:flex;color:var(--body-text-color);font-weight:var(--weight-semibold)}h2.svelte-9i27qi img.svelte-9i27qi{margin-right:var(--size-2);width:var(--size-4)}span.svelte-9i27qi.svelte-9i27qi{color:var(--color-accent)}button.svelte-9i27qi.svelte-9i27qi{position:absolute;top:var(--size-5);right:var(--size-6);width:var(--size-4);color:var(--body-text-color)}button.svelte-9i27qi.svelte-9i27qi:hover{color:var(--color-accent)}@media (min-width: 768px){button.svelte-9i27qi.svelte-9i27qi{top:var(--size-6)}h2.svelte-9i27qi img.svelte-9i27qi{width:var(--size-5)}}.counts.svelte-9i27qi.svelte-9i27qi{margin-top:auto;margin-right:var(--size-8);margin-bottom:auto;margin-left:auto;color:var(--body-text-color);font-weight:var(--weight-light)}.load-wrap.svelte-1c7hj3i{display:flex;justify-content:center;align-items:center}h4.svelte-1c7hj3i{display:flex;align-items:center;margin-top:var(--size-6);margin-bottom:var(--size-3);color:var(--body-text-color);font-weight:var(--weight-bold)}.toggle-icon.svelte-1c7hj3i{display:flex;align-items:center;margin-right:var(--size-2);border-radius:var(--radius-full);background:var(--color-grey-300);width:12px;height:4px}.toggle-dot.svelte-1c7hj3i{margin-left:auto;border-radius:var(--radius-full);background:var(--color-grey-700);width:6px;height:6px}.response-wrap.svelte-1c7hj3i{font-family:var(--font-mono)}.desc.svelte-1c7hj3i{color:var(--body-text-color-subdued)}.hide.svelte-1c7hj3i{display:none}.second-level.svelte-1c7hj3i{margin-left:var(--size-4)}code.svelte-1pu3gsl pre.svelte-1pu3gsl{overflow-x:auto;color:var(--body-text-color);font-family:var(--font-mono);tab-size:2}code.svelte-1pu3gsl.svelte-1pu3gsl{position:relative}.copy.svelte-1pu3gsl.svelte-1pu3gsl{position:absolute;top:0;right:0;margin-top:-5px;margin-right:-5px}h3.svelte-41kcm6{color:var(--body-text-color);font-weight:var(--section-header-text-weight);font-size:var(--text-lg)}.post.svelte-41kcm6{margin-right:var(--size-2);border:1px solid var(--border-color-accent);border-radius:var(--radius-sm);background:var(--color-accent-soft);padding-right:var(--size-1);padding-bottom:var(--size-1);padding-left:var(--size-1);color:var(--color-accent);font-weight:var(--weight-semibold)}code.svelte-1bqxtsy pre.svelte-1bqxtsy{overflow-x:auto;color:var(--body-text-color);font-family:var(--font-mono);tab-size:2}.token.string.svelte-1bqxtsy.svelte-1bqxtsy{display:contents;color:var(--color-accent-base)}code.svelte-1bqxtsy.svelte-1bqxtsy{position:relative}.copy.svelte-1bqxtsy.svelte-1bqxtsy{position:absolute;top:0;right:0;margin-top:-5px;margin-right:-5px}.container.svelte-1bqxtsy.svelte-1bqxtsy{display:flex;flex-direction:column;gap:var(--spacing-xxl);margin-top:var(--size-3);margin-bottom:var(--size-3)}.error.svelte-1bqxtsy.svelte-1bqxtsy{color:var(--error-text-color)}.desc.svelte-1bqxtsy.svelte-1bqxtsy{color:var(--body-text-color-subdued)}.example-inputs.svelte-1bqxtsy.svelte-1bqxtsy{border:1px solid var(--border-color-accent);border-radius:var(--radius-sm);background:var(--color-accent-soft);padding-right:var(--size-1);padding-left:var(--size-1);color:var(--color-accent)}.space.svelte-1j8n062{display:flex;flex-basis:1;margin-top:var(--size-4)}.banner-wrap.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{position:relative;border-bottom:1px solid var(--border-color-primary);padding:var(--size-4) var(--size-6);font-size:var(--text-md)}@media (min-width: 768px){.banner-wrap.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{font-size:var(--text-xl)}}.docs-wrap.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{display:flex;flex-direction:column;gap:var(--spacing-xxl)}.endpoint.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{border-radius:var(--radius-md);background:var(--background-fill-primary);padding:var(--size-6);padding-top:var(--size-1);font-size:var(--text-md)}.client-doc.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{padding-top:var(--size-6);padding-right:var(--size-6);padding-left:var(--size-6);font-size:var(--text-xl)}.library.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{border:1px solid var(--border-color-accent);border-radius:var(--radius-sm);background:var(--color-accent-soft);padding-right:var(--size-1);padding-bottom:var(--size-1);padding-left:var(--size-1);color:var(--color-accent)}.snippets.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{display:flex;align-items:center;margin-bottom:var(--size-4)}.snippets.svelte-rzp0ym>.svelte-rzp0ym+.svelte-rzp0ym{margin-left:var(--size-2)}.snippet.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{display:flex;align-items:center;border:1px solid var(--border-color-primary);border-radius:var(--radius-md);padding:var(--size-1) var(--size-1-5);color:var(--body-text-color-subdued);color:var(--body-text-color);line-height:1;user-select:none;text-transform:capitalize}.current-lang.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{border:1px solid var(--body-text-color-subdued);color:var(--body-text-color)}.inactive-lang.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{cursor:pointer;color:var(--body-text-color-subdued)}.inactive-lang.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym:hover,.inactive-lang.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym:focus{box-shadow:var(--shadow-drop);color:var(--body-text-color)}.snippet.svelte-rzp0ym img.svelte-rzp0ym.svelte-rzp0ym{margin-right:var(--size-1-5);width:var(--size-3)}.header.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{margin-top:var(--size-3);margin-bottom:var(--size-3);font-size:var(--text-xl)}.endpoint-container.svelte-rzp0ym.svelte-rzp0ym.svelte-rzp0ym{margin-top:var(--size-3);margin-bottom:var(--size-3);border:1px solid var(--border-color-primary);border-radius:var(--radius-xl);padding:var(--size-3);padding-top:0}.wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;flex-grow:1;flex-direction:column;width:var(--size-full);font-weight:var(--body-text-weight);font-size:var(--body-text-size)}footer.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;justify-content:center;margin-top:var(--size-4);color:var(--body-text-color-subdued)}footer.svelte-1lyswbr>.svelte-1lyswbr+.svelte-1lyswbr{margin-left:var(--size-2)}.show-api.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;align-items:center}.show-api.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr:hover{color:var(--body-text-color)}.show-api.svelte-1lyswbr img.svelte-1lyswbr.svelte-1lyswbr{margin-right:var(--size-1);margin-left:var(--size-2);width:var(--size-3)}.built-with.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;align-items:center}.built-with.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr:hover{color:var(--body-text-color)}.built-with.svelte-1lyswbr img.svelte-1lyswbr.svelte-1lyswbr{margin-right:var(--size-1);margin-left:var(--size-2);width:var(--size-3)}.api-docs.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{display:flex;position:fixed;top:0;right:0;z-index:var(--layer-5);background:rgba(0,0,0,.5);width:var(--size-screen);height:var(--size-screen-h)}.backdrop.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{flex:1 1 0%;backdrop-filter:blur(4px)}.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{box-shadow:var(--shadow-drop-lg);background:var(--background-fill-primary);overflow-x:hidden;overflow-y:auto}@media (min-width: 768px){.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{border-top-left-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg);width:950px}}@media (min-width: 1536px){.api-docs-wrap.svelte-1lyswbr.svelte-1lyswbr.svelte-1lyswbr{width:1150px}}
static/Button-3657eefc.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .block.svelte-mppz8v{position:relative;margin:0;box-shadow:var(--block-shadow);border-width:var(--block-border-width);border-color:var(--block-border-color);border-radius:var(--block-radius);background:var(--block-background-fill);width:100%;line-height:var(--line-sm)}.block.border_focus.svelte-mppz8v{border-color:var(--color-accent)}.padded.svelte-mppz8v{padding:var(--block-padding)}.hidden.svelte-mppz8v{display:none}div.svelte-e8n7p6{margin-bottom:var(--spacing-lg);color:var(--block-info-text-color);font-weight:var(--block-info-text-weight);font-size:var(--block-info-text-size);line-height:var(--line-sm)}span.has-info.svelte-1gfkn6j{margin-bottom:var(--spacing-xs)}span.svelte-1gfkn6j:not(.has-info){margin-bottom:var(--spacing-lg)}span.svelte-1gfkn6j{display:inline-block;position:relative;z-index:var(--layer-4);border:solid var(--block-title-border-width) var(--block-title-border-color);border-radius:var(--block-title-radius);background:var(--block-title-background-fill);padding:var(--block-title-padding);color:var(--block-title-text-color);font-weight:var(--block-title-text-weight);font-size:var(--block-title-text-size);line-height:var(--line-sm)}.hide.svelte-1gfkn6j{margin:0;height:0}div.svelte-1frtwj3{display:inline-flex;align-items:center;z-index:var(--layer-2);box-shadow:var(--block-shadow);border:var(--block-label-border-width) solid var(--border-color-primary);border-top:none;border-left:none;border-radius:var(--block-label-radius);background:var(--block-label-background-fill);padding:var(--block-label-padding);pointer-events:none;color:var(--block-label-text-color);font-weight:var(--block-label-text-weight);font-size:var(--block-label-text-size);line-height:var(--line-sm)}div.float.svelte-1frtwj3{position:absolute;top:var(--block-label-margin);left:var(--block-label-margin)}div.svelte-1frtwj3:not(.float){position:static;margin-top:var(--block-label-margin);margin-left:var(--block-label-margin)}.hide.svelte-1frtwj3{height:0}span.svelte-1frtwj3{opacity:.8;margin-right:var(--size-2);width:calc(var(--block-label-text-size) - 1px);height:calc(var(--block-label-text-size) - 1px)}button.svelte-1p4r00v{display:flex;justify-content:center;align-items:center;z-index:var(--layer-1);box-shadow:var(--shadow-drop);border:1px solid var(--button-secondary-border-color);border-radius:var(--radius-sm);background:var(--background-fill-primary);width:var(--size-5);height:var(--size-5);color:var(--block-label-text-color)}button.svelte-1p4r00v:hover{cursor:pointer;border:2px solid var(--button-secondary-border-color-hover);color:var(--block-label-text-color)}div.svelte-1p4r00v{width:60%;height:60%}.empty.svelte-1u5vjgs{display:flex;justify-content:center;align-items:center;height:var(--size-full)}.icon.svelte-1u5vjgs{opacity:.5;height:var(--size-5);color:var(--body-text-color)}.small.svelte-1u5vjgs{height:calc(var(--size-32) - 20px)}.large.svelte-1u5vjgs{height:calc(var(--size-64) - 20px)}.unpadded_box.small.svelte-1u5vjgs{min-height:var(--size-32)}.unpadded_box.large.svelte-1u5vjgs{min-height:var(--size-64)}button.svelte-1ipelgc{display:inline-flex;justify-content:center;align-items:center;transition:var(--button-transition);box-shadow:var(--button-shadow);padding:var(--size-0-5) var(--size-2);text-align:center}button.svelte-1ipelgc:hover,button[disabled].svelte-1ipelgc{box-shadow:var(--button-shadow-hover)}button.svelte-1ipelgc:active{box-shadow:var(--button-shadow-active)}button[disabled].svelte-1ipelgc{opacity:.5;filter:grayscale(30%);cursor:not-allowed}.hide.svelte-1ipelgc{display:none}.primary.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-primary-border-color);background:var(--button-primary-background-fill);color:var(--button-primary-text-color)}.primary.svelte-1ipelgc:hover,.primary[disabled].svelte-1ipelgc{border-color:var(--button-primary-border-color-hover);background:var(--button-primary-background-fill-hover);color:var(--button-primary-text-color-hover)}.secondary.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-secondary-border-color);background:var(--button-secondary-background-fill);color:var(--button-secondary-text-color)}.secondary.svelte-1ipelgc:hover,.secondary[disabled].svelte-1ipelgc{border-color:var(--button-secondary-border-color-hover);background:var(--button-secondary-background-fill-hover);color:var(--button-secondary-text-color-hover)}.stop.svelte-1ipelgc{border:var(--button-border-width) solid var(--button-cancel-border-color);background:var(--button-cancel-background-fill);color:var(--button-cancel-text-color)}.stop.svelte-1ipelgc:hover,.stop[disabled].svelte-1ipelgc{border-color:var(--button-cancel-border-color-hover);background:var(--button-cancel-background-fill-hover);color:var(--button-cancel-text-color-hover)}.sm.svelte-1ipelgc{border-radius:var(--button-small-radius);padding:var(--button-small-padding);font-weight:var(--button-small-text-weight);font-size:var(--button-small-text-size)}.lg.svelte-1ipelgc{border-radius:var(--button-large-radius);padding:var(--button-large-padding);font-weight:var(--button-large-text-weight);font-size:var(--button-large-text-size)}
static/ColorPicker-41813019.css ADDED
@@ -0,0 +1 @@
 
 
1
+ label.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{display:flex;align-items:center;cursor:pointer;color:var(--body-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1ojmf70>.svelte-1ojmf70+.svelte-1ojmf70{margin-left:var(--size-2)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{--ring-color:transparent;position:relative;box-shadow:var(--input-shadow);border:1px solid var(--checkbox-border-color);border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked,input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked:hover,input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70,.disabled.svelte-1ojmf70.svelte-1ojmf70.svelte-1ojmf70{cursor:not-allowed}.wrap.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{display:flex;flex-wrap:wrap;gap:var(--checkbox-label-gap)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:hover{background:var(--checkbox-label-background-fill-hover)}label.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:focus{background:var(--checkbox-label-background-fill-focus)}label.selected.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{background:var(--checkbox-label-background-fill-selected);color:var(--checkbox-label-text-color-selected)}label.svelte-1qxcj04>.svelte-1qxcj04+.svelte-1qxcj04{margin-left:var(--size-2)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{--ring-color:transparent;position:relative;box-shadow:var(--checkbox-shadow);border:var(--checkbox-border-width) solid var(--checkbox-border-color);border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked,input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked:hover,input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04,.disabled.svelte-1qxcj04.svelte-1qxcj04.svelte-1qxcj04{cursor:not-allowed}.options.svelte-1oas11n{--window-padding:var(--size-8);position:absolute;z-index:var(--layer-5);margin-left:0;box-shadow:var(--shadow-drop-lg);border-radius:var(--container-radius);background:var(--background-fill-primary);width:var(--size-full);overflow:auto;color:var(--body-text-color);list-style:none}.item.svelte-1oas11n{display:flex;cursor:pointer;padding:var(--size-2)}.item.svelte-1oas11n:hover,.active.svelte-1oas11n{background:var(--background-fill-secondary)}.inner-item.svelte-1oas11n{padding-right:var(--size-1)}.hide.svelte-1oas11n{visibility:hidden}.wrap.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{position:relative;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--border-color-primary);border-radius:var(--input-radius);background:var(--input-background-fill)}.wrap.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu:focus-within{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}.wrap-inner.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{display:flex;position:relative;flex-wrap:wrap;align-items:center;gap:var(--checkbox-label-gap);padding:var(--checkbox-label-gap)}.token.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}.token.svelte-1ythexu>.svelte-1ythexu+.svelte-1ythexu{margin-left:var(--size-2)}.token-remove.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{fill:var(--body-text-color);display:flex;justify-content:center;align-items:center;cursor:pointer;border:var(--checkbox-border-width) solid var(--border-color-primary);border-radius:var(--radius-full);background:var(--background-fill-primary);padding:var(--size-0-5);width:18px;height:18px}.single-select.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{margin:var(--spacing-sm);color:var(--body-text-color)}.secondary-wrap.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{display:flex;flex:1 1 0%;align-items:center;border:none;min-width:min-content}input.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{margin:var(--spacing-sm);outline:none;border:none;background:inherit;width:var(--size-full);color:var(--body-text-color);font-size:var(--input-text-size)}input.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu:disabled{cursor:not-allowed}.remove-all.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{margin-left:var(--size-1);width:20px;height:20px}.hide.svelte-1ythexu.svelte-1ythexu.svelte-1ythexu{display:none}input[type=number].svelte-1nnxs9b{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--input-padding);width:100%;color:var(--body-text-color);font-size:var(--input-text-size);line-height:var(--line-sm)}input.svelte-1nnxs9b:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-1nnxs9b::placeholder{color:var(--input-placeholder-color)}.wrap.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{display:flex;flex-wrap:wrap;gap:var(--checkbox-label-gap)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{display:flex;align-items:center;transition:var(--button-transition);cursor:pointer;box-shadow:var(--checkbox-label-shadow);border:var(--checkbox-label-border-width) solid var(--checkbox-label-border-color);border-radius:var(--button-small-radius);background:var(--checkbox-label-background-fill);padding:var(--checkbox-label-padding);color:var(--checkbox-label-text-color);font-weight:var(--checkbox-label-text-weight);font-size:var(--checkbox-label-text-size);line-height:var(--line-md)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:hover{background:var(--checkbox-label-background-fill-hover)}label.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:focus{background:var(--checkbox-label-background-fill-focus)}label.selected.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{background:var(--checkbox-label-background-fill-selected);color:var(--checkbox-label-text-color-selected)}label.svelte-1p9xokt>.svelte-1p9xokt+.svelte-1p9xokt{margin-left:var(--size-2)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{--ring-color:transparent;position:relative;box-shadow:var(--checkbox-shadow);border:var(--checkbox-border-width) solid var(--checkbox-border-color);border-radius:var(--radius-full);background-color:var(--checkbox-background-color);line-height:var(--line-sm)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked,input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked:hover,input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:checked:focus{border-color:var(--checkbox-border-color-selected);background-image:var(--radio-circle);background-color:var(--checkbox-background-color-selected)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:hover{border-color:var(--checkbox-border-color-hover);background-color:var(--checkbox-background-color-hover)}input.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt:focus{border-color:var(--checkbox-border-color-focus);background-color:var(--checkbox-background-color-focus)}input[disabled].svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt,.disabled.svelte-1p9xokt.svelte-1p9xokt.svelte-1p9xokt{cursor:not-allowed}label.svelte-4xt1ch{display:block;width:100%}input[type=text].svelte-4xt1ch,input[type=password].svelte-4xt1ch,input[type=email].svelte-4xt1ch,textarea.svelte-4xt1ch{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--input-padding);width:100%;color:var(--body-text-color);font-weight:var(--input-text-weight);font-size:var(--input-text-size);line-height:var(--line-sm)}input.svelte-4xt1ch:focus,textarea.svelte-4xt1ch:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-4xt1ch::placeholder,textarea.svelte-4xt1ch::placeholder{color:var(--input-placeholder-color)}button.svelte-4xt1ch{display:flex;position:absolute;top:var(--block-label-margin);right:var(--block-label-margin);align-items:center;box-shadow:var(--shadow-drop);border:1px solid var(--color-border-primary);border-top:none;border-right:none;border-radius:var(--block-label-right-radius);background:var(--block-label-background-fill);padding:5px;width:22px;height:22px;overflow:hidden;color:var(--block-label-color);font:var(--font-sans);font-size:var(--button-small-text-size)}.wrap.svelte-jigama{display:flex;flex-direction:column;width:100%}.head.svelte-jigama{display:flex;justify-content:space-between}input[type=number].svelte-jigama{display:block;position:relative;outline:none!important;box-shadow:var(--input-shadow);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-radius);background:var(--input-background-fill);padding:var(--size-2) var(--size-2);height:var(--size-6);color:var(--body-text-color);font-size:var(--input-text-size);line-height:var(--line-sm);text-align:center}input[type=number].svelte-jigama:focus{box-shadow:var(--input-shadow-focus);border-color:var(--input-border-color-focus)}input.svelte-jigama::placeholder{color:var(--input-placeholder-color)}input[type=range].svelte-jigama{width:100%;accent-color:var(--slider-color)}input[disabled].svelte-jigama{cursor:not-allowed}input.svelte-56zyyb{display:block;position:relative;background:var(--background-fill-primary);line-height:var(--line-sm)}
static/Column-2853eb31.css ADDED
@@ -0,0 +1 @@
 
 
1
+ div.svelte-vt1mxs{display:flex;position:relative;flex-direction:column}div.svelte-vt1mxs>*,div.svelte-vt1mxs>.form>*{width:var(--size-full)}.gap.svelte-vt1mxs{gap:var(--layout-gap)}.hide.svelte-vt1mxs{display:none}.compact.svelte-vt1mxs>*,.compact.svelte-vt1mxs .box{border-radius:0}.compact.svelte-vt1mxs,.panel.svelte-vt1mxs{border:solid var(--panel-border-width) var(--panel-border-color);border-radius:var(--container-radius);background:var(--panel-background-fill);padding:var(--spacing-lg)}
static/DropdownArrow-5fa4dd09.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .dropdown-arrow.svelte-p5edak{fill:var(--body-text-color);margin-right:var(--size-2);width:var(--size-5)}
static/Form-a4a7741e.css ADDED
@@ -0,0 +1 @@
 
 
1
+ div.svelte-awbtu4{display:flex;flex-direction:inherit;flex-wrap:wrap;gap:var(--form-gap-width);box-shadow:var(--block-shadow);border:var(--block-border-width) solid var(--border-color-primary);border-radius:var(--radius-lg);background:var(--border-color-primary);overflow:hidden}div.svelte-awbtu4 .block{box-shadow:none!important;border-width:0px!important;border-radius:0!important}.hidden.svelte-awbtu4{display:none}
static/Image-003ee87c.css ADDED
@@ -0,0 +1 @@
 
 
1
+ img.svelte-gqt00k{border-radius:var(--radius-lg);max-width:none}img.selected.svelte-gqt00k{border-color:var(--border-color-accent)}.table.svelte-gqt00k{margin:0 auto;border:2px solid var(--border-color-primary);border-radius:var(--radius-lg);width:var(--size-20);height:var(--size-20);object-fit:cover}.gallery.svelte-gqt00k{border:2px solid var(--border-color-primary);max-height:var(--size-20);object-fit:cover}
static/Model3D-98fc2b2c.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .gallery.svelte-1ayixqk{padding:var(--size-1) var(--size-2)}
static/ModifyUpload-77b0d4b2.css ADDED
@@ -0,0 +1 @@
 
 
1
+ div.svelte-116rqfv{cursor:pointer;width:var(--size-full);height:var(--size-full)}.center.svelte-116rqfv{text-align:center}.flex.svelte-116rqfv{display:flex;justify-content:center;align-items:center}input.svelte-116rqfv{display:none}div.svelte-19sk1im{display:flex;top:var(--size-2);right:var(--size-2);justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-1)}.not-absolute.svelte-19sk1im{margin:var(--size-1)}
static/StaticImage-ede66243.css ADDED
@@ -0,0 +1 @@
 
 
1
+ canvas.svelte-yigbas{display:block;position:absolute;inset:0;margin:auto}.lr.svelte-yigbas{border-right:1px solid var(--border-color-primary);border-left:1px solid var(--border-color-primary)}.tb.svelte-yigbas{border-top:1px solid var(--border-color-primary);border-bottom:1px solid var(--border-color-primary)}canvas.svelte-yigbas:hover{cursor:none}.wrap.svelte-yigbas{position:relative;width:var(--size-full);height:var(--size-full);touch-action:none}.start-prompt.svelte-yigbas{display:flex;position:absolute;inset:0;justify-content:center;align-items:center;z-index:var(--layer-4);touch-action:none;pointer-events:none;color:var(--body-text-color-subdued)}.wrap.svelte-xbxfke{position:relative;width:var(--size-full);height:var(--size-full);min-height:var(--size-60)}video.svelte-xbxfke{width:var(--size-full);height:var(--size-full)}button.svelte-xbxfke{display:flex;position:absolute;right:0;bottom:var(--size-2);left:0;justify-content:center;align-items:center;margin:auto;box-shadow:var(--shadow-drop-lg);border-radius:var(--radius-xl);background-color:#000000e6;width:var(--size-10);height:var(--size-10)}@media (min-width: 768px){button.svelte-xbxfke{bottom:var(--size-4)}}@media (min-width: 1280px){button.svelte-xbxfke{bottom:var(--size-8)}}.icon.svelte-xbxfke{opacity:.8;width:50%;height:50%;color:#fff}.flip.svelte-xbxfke{transform:scaleX(-1)}div.svelte-s6ybro{display:flex;position:absolute;top:var(--size-2);right:var(--size-2);justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-5)}.wrap.svelte-p4aq0j.svelte-p4aq0j{display:flex;position:absolute;top:var(--size-10);right:var(--size-2);flex-direction:column;justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-5)}.brush.svelte-p4aq0j.svelte-p4aq0j{top:0;right:0}.brush.svelte-p4aq0j input.svelte-p4aq0j{position:absolute;top:3px;right:calc(100% + 5px)}.col.svelte-p4aq0j input.svelte-p4aq0j{position:absolute;right:calc(100% + 5px);bottom:-4px}.image-container.svelte-p3y7hu,img.svelte-p3y7hu{width:var(--size-full);height:var(--size-full)}img.svelte-p3y7hu{object-fit:contain}.selectable.svelte-p3y7hu{cursor:crosshair}.absolute-img.svelte-p3y7hu{position:absolute;opacity:0}.webcam.svelte-p3y7hu{transform:scaleX(-1)}img.svelte-ms5bsk{width:var(--size-full);height:var(--size-full);object-fit:contain}.selectable.svelte-ms5bsk{cursor:crosshair}.download.svelte-ms5bsk{position:absolute;top:6px;right:6px}
static/UploadText-33d53a1c.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .wrap.svelte-xwlu1w{display:flex;flex-direction:column;justify-content:center;min-height:var(--size-60);color:var(--block-label-text-color);line-height:var(--line-md)}.or.svelte-xwlu1w{color:var(--body-text-color-subdued)}@media (min-width: 768px){.wrap.svelte-xwlu1w{font-size:var(--text-lg)}}
static/a.html ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ <html><head>
2
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8"></head><body></body></html>
static/academicons.min.css ADDED
@@ -0,0 +1 @@
 
 
1
+ @font-face {font-family: 'Academicons';font-style: normal;font-weight: 400;font-display: block;src:url('../fonts/academicons.eot');src:url('../fonts/academicons.eot') format('embedded-opentype'), url('../fonts/academicons.ttf') format('truetype'), url('../fonts/academicons.woff') format('woff'), url('../fonts/academicons.svg') format('svg');}.ai {font-family: 'Academicons';font-weight: 400;-moz-osx-font-smoothing: grayscale;-webkit-font-smoothing: antialiased;display: inline-block;font-style: normal;font-variant: normal;text-rendering: auto;line-height: 1;}.ai-academia:before {content: "\e9af";}.ai-academia-square:before {content: "\e93d";}.ai-acclaim:before {content: "\e92e";}.ai-acclaim-square:before {content: "\e93a";}.ai-acm:before {content: "\e93c";}.ai-acm-square:before {content: "\e95d";}.ai-acmdl:before {content: "\e96a";}.ai-acmdl-square:before {content: "\e9d3";}.ai-ads:before {content: "\e9cb";}.ai-ads-square:before {content: "\e94a";}.ai-africarxiv:before {content: "\e91b";}.ai-africarxiv-square:before {content: "\e90b";}.ai-archive:before {content: "\e955";}.ai-archive-square:before {content: "\e956";}.ai-arxiv:before {content: "\e974";}.ai-arxiv-square:before {content: "\e9a6";}.ai-biorxiv:before {content: "\e9a2";}.ai-biorxiv-square:before {content: "\e98b";}.ai-ceur:before {content: "\e96d";}.ai-ceur-square:before {content: "\e92f";}.ai-ciencia-vitae:before {content: "\e912";}.ai-ciencia-vitae-square:before {content: "\e913";}.ai-clarivate:before {content: "\e924";}.ai-clarivate-square:before {content: "\e925";}.ai-closed-access:before {content: "\e942";}.ai-closed-access-square:before {content: "\e943";}.ai-conversation:before {content: "\e94c";}.ai-conversation-square:before {content: "\e915";}.ai-coursera:before {content: "\e95f";}.ai-coursera-square:before {content: "\e97f";}.ai-crossref:before {content: "\e918";}.ai-crossref-square:before {content: "\e919";}.ai-cv:before {content: "\e9a5";}.ai-cv-square:before {content: "\e90a";}.ai-datacite:before {content: "\e91c";}.ai-datacite-square:before {content: "\e91d";}.ai-dataverse:before {content: "\e9f7";}.ai-dataverse-square:before {content: "\e9e4";}.ai-dblp:before {content: "\e94f";}.ai-dblp-square:before {content: "\e93f";}.ai-depsy:before {content: "\e97a";}.ai-depsy-square:before {content: "\e94b";}.ai-doi:before {content: "\e97e";}.ai-doi-square:before {content: "\e98f";}.ai-dryad:before {content: "\e97c";}.ai-dryad-square:before {content: "\e98c";}.ai-elsevier:before {content: "\e961";}.ai-elsevier-square:before {content: "\e910";}.ai-figshare:before {content: "\e981";}.ai-figshare-square:before {content: "\e9e7";}.ai-google-scholar:before {content: "\e9d4";}.ai-google-scholar-square:before {content: "\e9f9";}.ai-hal:before {content: "\e92c";}.ai-hal-square:before {content: "\e92d";}.ai-hypothesis:before {content: "\e95a";}.ai-hypothesis-square:before {content: "\e95b";}.ai-ideas-repec:before {content: "\e9ed";}.ai-ideas-repec-square:before {content: "\e9f8";}.ai-ieee:before {content: "\e929";}.ai-ieee-square:before {content: "\e9b9";}.ai-impactstory:before {content: "\e9cf";}.ai-impactstory-square:before {content: "\e9aa";}.ai-inaturalist:before {content: "\e900";}.ai-inaturalist-square:before {content: "\e901";}.ai-inpn:before {content: "\e902";}.ai-inpn-square:before {content: "\e903";}.ai-inspire:before {content: "\e9e9";}.ai-inspire-square:before {content: "\e9fe";}.ai-isidore:before {content: "\e936";}.ai-isidore-square:before {content: "\e954";}.ai-isni:before {content: "\e957";}.ai-isni-square:before {content: "\e958";}.ai-jstor:before {content: "\e938";}.ai-jstor-square:before {content: "\e944";}.ai-lattes:before {content: "\e9b3";}.ai-lattes-square:before {content: "\e99c";}.ai-mathoverflow:before {content: "\e9f6";}.ai-mathoverflow-square:before {content: "\e97b";}.ai-mendeley:before {content: "\e9f0";}.ai-mendeley-square:before {content: "\e9f3";}.ai-moodle:before {content: "\e907";}.ai-moodle-square:before {content: "\e908";}.ai-mtmt:before {content: "\e950";}.ai-mtmt-square:before {content: "\e951";}.ai-nakala:before {content: "\e940";}.ai-nakala-square:before {content: "\e941";}.ai-obp:before {content: "\e92a";}.ai-obp-square:before {content: "\e92b";}.ai-open-access:before {content: "\e939";}.ai-open-access-square:before {content: "\e9f4";}.ai-open-data:before {content: "\e966";}.ai-open-data-square:before {content: "\e967";}.ai-open-materials:before {content: "\e968";}.ai-open-materials-square:before {content: "\e969";}.ai-openedition:before {content: "\e946";}.ai-openedition-square:before {content: "\e947";}.ai-orcid:before {content: "\e9d9";}.ai-orcid-square:before {content: "\e9c3";}.ai-osf:before {content: "\e9ef";}.ai-osf-square:before {content: "\e931";}.ai-overleaf:before {content: "\e914";}.ai-overleaf-square:before {content: "\e98d";}.ai-philpapers:before {content: "\e98a";}.ai-philpapers-square:before {content: "\e96f";}.ai-piazza:before {content: "\e99a";}.ai-piazza-square:before {content: "\e90c";}.ai-preregistered:before {content: "\e906";}.ai-preregistered-square:before {content: "\e96b";}.ai-protocols:before {content: "\e952";}.ai-protocols-square:before {content: "\e953";}.ai-psyarxiv:before {content: "\e90e";}.ai-psyarxiv-square:before {content: "\e90f";}.ai-publons:before {content: "\e937";}.ai-publons-square:before {content: "\e94e";}.ai-pubmed:before {content: "\e99f";}.ai-pubmed-square:before {content: "\e97d";}.ai-pubpeer:before {content: "\e922";}.ai-pubpeer-square:before {content: "\e923";}.ai-researcherid:before {content: "\e91a";}.ai-researcherid-square:before {content: "\e95c";}.ai-researchgate:before {content: "\e95e";}.ai-researchgate-square:before {content: "\e99e";}.ai-ror:before {content: "\e948";}.ai-ror-square:before {content: "\e949";}.ai-sci-hub:before {content: "\e959";}.ai-sci-hub-square:before {content: "\e905";}.ai-scirate:before {content: "\e98e";}.ai-scirate-square:before {content: "\e99d";}.ai-scopus:before {content: "\e91e";}.ai-scopus-square:before {content: "\e91f";}.ai-semantic-scholar:before {content: "\e96e";}.ai-semantic-scholar-square:before {content: "\e96c";}.ai-springer:before {content: "\e928";}.ai-springer-square:before {content: "\e99b";}.ai-ssrn:before {content: "\e916";}.ai-ssrn-square:before {content: "\e917";}.ai-stackoverflow:before {content: "\e920";}.ai-stackoverflow-square:before {content: "\e921";}.ai-viaf:before {content: "\e933";}.ai-viaf-square:before {content: "\e934";}.ai-wiley:before {content: "\e926";}.ai-wiley-square:before {content: "\e927";}.ai-zenodo:before {content: "\e911";}.ai-zotero:before {content: "\e962";}.ai-zotero-square:before {content: "\e932";}.ai-lg {font-size: 1.33333em;line-height: 0.75em;vertical-align: -.0667em;}.ai-xs {font-size: .75em;}.ai-sm {font-size: .875em;}.ai-1x {font-size: 1em;}.ai-2x {font-size: 2em;}.ai-3x {font-size: 3em;}.ai-4x {font-size: 4em;}.ai-5x {font-size: 5em;}.ai-6x {font-size: 6em;}.ai-7x {font-size: 7em;}.ai-8x {font-size: 8em;}.ai-9x {font-size: 9em;}.ai-10x {font-size: 10em;}.ai-fw {text-align: center;width: 1.25em;}.ai-ul {list-style-type: none;margin-left: 2.5em;padding-left: 0;}.ai-ul > li {position: relative;}.ai-li {left: -2em;position: absolute;text-align: center;width: 2em;line-height: inherit;}.ai-border {border: solid 0.08em #eee;border-radius: .1em;padding: .2em .25em .15em;}.ai-pull-left {float: left;}.ai-pull-right {float: right;}.ai.ai-pull-left {margin-right: .3em;}.ai.ai-pull-right {margin-right: .3em;}.ai-stack {display: inline-block;height: 2em;line-height: 2em;position: relative;vertical-align: middle;width: 2.5em;}.ai-stack-1x, .ai-stack-2x {left: 0;position: absolute;text-align: center;width: 100%;}.ai-stack-1x {line-height: inherit;}.ai-stack-2x {font-size: 2em;}.ai-inverse {color: #fff;}
static/all.min.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ /*!
2
+ * Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com
3
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4
+ */
5
+ .fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudflare:before{content:"\e07d"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guilded:before{content:"\e07e"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\e05e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hive:before{content:"\e07f"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\e065"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\e013"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-innosoft:before{content:"\e080"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-instalod:before{content:"\e081"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\e066"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\e01a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-octopus-deploy:before{content:"\e082"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\e068"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-perbyte:before{content:"\e083"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-rust:before{content:"\e07a"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\e057"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sink:before{content:"\e06d"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\e070"}.fa-store-slash:before{content:"\e071"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-tiktok:before{content:"\e07b"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-uncharted:before{content:"\e084"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-vest:before{content:"\e085"}.fa-vest-patches:before{content:"\e086"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\e074"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-watchman-monitoring:before{content:"\e087"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wodu:before{content:"\e088"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900}
static/all.min.js ADDED
The diff for this file is too large to render. See raw diff
 
static/bootstrap.min.css ADDED
The diff for this file is too large to render. See raw diff
 
static/bulma.min.css ADDED
The diff for this file is too large to render. See raw diff
 
static/css.css ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * See: https://fonts.google.com/license/googlerestricted
3
+ */
4
+ /* latin-ext */
5
+ @font-face {
6
+ font-family: 'Castoro';
7
+ font-style: normal;
8
+ font-weight: 400;
9
+ src: url(https://fonts.gstatic.com/s/castoro/v19/1q2GY5yMCld3-O4cLYFOzdYe.woff2) format('woff2');
10
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
11
+ }
12
+ /* latin */
13
+ @font-face {
14
+ font-family: 'Castoro';
15
+ font-style: normal;
16
+ font-weight: 400;
17
+ src: url(https://fonts.gstatic.com/s/castoro/v19/1q2GY5yMCld3-O4cLY9OzQ.woff2) format('woff2');
18
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
19
+ }
20
+ /* armenian */
21
+ @font-face {
22
+ font-family: 'Google Sans';
23
+ font-style: normal;
24
+ font-weight: 400;
25
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl1pynSEg.woff2) format('woff2');
26
+ unicode-range: U+0308, U+0530-058F, U+2010, U+2024, U+25CC, U+FB13-FB17;
27
+ }
28
+ /* bengali */
29
+ @font-face {
30
+ font-family: 'Google Sans';
31
+ font-style: normal;
32
+ font-weight: 400;
33
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl3pynSEg.woff2) format('woff2');
34
+ unicode-range: U+0964-0965, U+0980-09FE, U+1CF7, U+1CFA, U+200C-200D, U+20B9, U+25CC;
35
+ }
36
+ /* cyrillic-ext */
37
+ @font-face {
38
+ font-family: 'Google Sans';
39
+ font-style: normal;
40
+ font-weight: 400;
41
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlopynSEg.woff2) format('woff2');
42
+ unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
43
+ }
44
+ /* cyrillic */
45
+ @font-face {
46
+ font-family: 'Google Sans';
47
+ font-style: normal;
48
+ font-weight: 400;
49
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlhpynSEg.woff2) format('woff2');
50
+ unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
51
+ }
52
+ /* devanagari */
53
+ @font-face {
54
+ font-family: 'Google Sans';
55
+ font-style: normal;
56
+ font-weight: 400;
57
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlkpynSEg.woff2) format('woff2');
58
+ unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FF;
59
+ }
60
+ /* ethiopic */
61
+ @font-face {
62
+ font-family: 'Google Sans';
63
+ font-style: normal;
64
+ font-weight: 400;
65
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl0pynSEg.woff2) format('woff2');
66
+ unicode-range: U+1200-1399, U+2D80-2DDE, U+AB01-AB2E, U+1E7E0-1E7E6, U+1E7E8-1E7EB, U+1E7ED-1E7EE, U+1E7F0-1E7FE;
67
+ }
68
+ /* georgian */
69
+ @font-face {
70
+ font-family: 'Google Sans';
71
+ font-style: normal;
72
+ font-weight: 400;
73
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl6pynSEg.woff2) format('woff2');
74
+ unicode-range: U+0589, U+10A0-10FF, U+1C90-1CBA, U+1CBD-1CBF, U+2D00-2D2F;
75
+ }
76
+ /* greek */
77
+ @font-face {
78
+ font-family: 'Google Sans';
79
+ font-style: normal;
80
+ font-weight: 400;
81
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlmpynSEg.woff2) format('woff2');
82
+ unicode-range: U+0370-03FF;
83
+ }
84
+ /* gujarati */
85
+ @font-face {
86
+ font-family: 'Google Sans';
87
+ font-style: normal;
88
+ font-weight: 400;
89
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl-pynSEg.woff2) format('woff2');
90
+ unicode-range: U+0964-0965, U+0A80-0AFF, U+200C-200D, U+20B9, U+25CC, U+A830-A839;
91
+ }
92
+ /* gurmukhi */
93
+ @font-face {
94
+ font-family: 'Google Sans';
95
+ font-style: normal;
96
+ font-weight: 400;
97
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlGpynSEg.woff2) format('woff2');
98
+ unicode-range: U+0964-0965, U+0A01-0A76, U+200C-200D, U+20B9, U+25CC, U+262C, U+A830-A839;
99
+ }
100
+ /* hebrew */
101
+ @font-face {
102
+ font-family: 'Google Sans';
103
+ font-style: normal;
104
+ font-weight: 400;
105
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlnpynSEg.woff2) format('woff2');
106
+ unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
107
+ }
108
+ /* khmer */
109
+ @font-face {
110
+ font-family: 'Google Sans';
111
+ font-style: normal;
112
+ font-weight: 400;
113
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlupynSEg.woff2) format('woff2');
114
+ unicode-range: U+1780-17FF, U+19E0-19FF, U+200C, U+25CC;
115
+ }
116
+ /* lao */
117
+ @font-face {
118
+ font-family: 'Google Sans';
119
+ font-style: normal;
120
+ font-weight: 400;
121
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlspynSEg.woff2) format('woff2');
122
+ unicode-range: U+0E81-0EDF, U+25CC;
123
+ }
124
+ /* oriya */
125
+ @font-face {
126
+ font-family: 'Google Sans';
127
+ font-style: normal;
128
+ font-weight: 400;
129
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl8pynSEg.woff2) format('woff2');
130
+ unicode-range: U+0964-0965, U+0B01-0B77, U+200C-200D, U+20B9, U+25CC;
131
+ }
132
+ /* sinhala */
133
+ @font-face {
134
+ font-family: 'Google Sans';
135
+ font-style: normal;
136
+ font-weight: 400;
137
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl4pynSEg.woff2) format('woff2');
138
+ unicode-range: U+0964-0965, U+0D81-0DF4, U+200C-200D, U+25CC, U+111E1-111F4;
139
+ }
140
+ /* tamil */
141
+ @font-face {
142
+ font-family: 'Google Sans';
143
+ font-style: normal;
144
+ font-weight: 400;
145
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlzpynSEg.woff2) format('woff2');
146
+ unicode-range: U+0964-0965, U+0B82-0BFA, U+200C-200D, U+20B9, U+25CC;
147
+ }
148
+ /* telugu */
149
+ @font-face {
150
+ font-family: 'Google Sans';
151
+ font-style: normal;
152
+ font-weight: 400;
153
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJl5pynSEg.woff2) format('woff2');
154
+ unicode-range: U+0951-0952, U+0964-0965, U+0C00-0C7F, U+1CDA, U+200C-200D, U+25CC;
155
+ }
156
+ /* thai */
157
+ @font-face {
158
+ font-family: 'Google Sans';
159
+ font-style: normal;
160
+ font-weight: 400;
161
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlxpynSEg.woff2) format('woff2');
162
+ unicode-range: U+0E01-0E5B, U+200C-200D, U+25CC;
163
+ }
164
+ /* vietnamese */
165
+ @font-face {
166
+ font-family: 'Google Sans';
167
+ font-style: normal;
168
+ font-weight: 400;
169
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlqpynSEg.woff2) format('woff2');
170
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
171
+ }
172
+ /* latin-ext */
173
+ @font-face {
174
+ font-family: 'Google Sans';
175
+ font-style: normal;
176
+ font-weight: 400;
177
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJlrpynSEg.woff2) format('woff2');
178
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
179
+ }
180
+ /* latin */
181
+ @font-face {
182
+ font-family: 'Google Sans';
183
+ font-style: normal;
184
+ font-weight: 400;
185
+ src: url(https://fonts.gstatic.com/s/googlesans/v58/4Ua_rENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RFD48TE63OOYKtrwEIJllpyk.woff2) format('woff2');
186
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
187
+ }
188
+ /* cyrillic-ext */
189
+ @font-face {
190
+ font-family: 'Noto Sans';
191
+ font-style: normal;
192
+ font-weight: 400;
193
+ font-stretch: 100%;
194
+ src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9X6VLKzA.woff2) format('woff2');
195
+ unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
196
+ }
197
+ /* cyrillic */
198
+ @font-face {
199
+ font-family: 'Noto Sans';
200
+ font-style: normal;
201
+ font-weight: 400;
202
+ font-stretch: 100%;
203
+ src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9e6VLKzA.woff2) format('woff2');
204
+ unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
205
+ }
206
+ /* devanagari */
207
+ @font-face {
208
+ font-family: 'Noto Sans';
209
+ font-style: normal;
210
+ font-weight: 400;
211
+ font-stretch: 100%;
212
+ src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9b6VLKzA.woff2) format('woff2');
213
+ unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FF;
214
+ }
215
+ /* greek-ext */
216
+ @font-face {
217
+ font-family: 'Noto Sans';
218
+ font-style: normal;
219
+ font-weight: 400;
220
+ font-stretch: 100%;
221
+ src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9W6VLKzA.woff2) format('woff2');
222
+ unicode-range: U+1F00-1FFF;
223
+ }
224
+ /* greek */
225
+ @font-face {
226
+ font-family: 'Noto Sans';
227
+ font-style: normal;
228
+ font-weight: 400;
229
+ font-stretch: 100%;
230
+ src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9Z6VLKzA.woff2) format('woff2');
231
+ unicode-range: U+0370-03FF;
232
+ }
233
+ /* vietnamese */
234
+ @font-face {
235
+ font-family: 'Noto Sans';
236
+ font-style: normal;
237
+ font-weight: 400;
238
+ font-stretch: 100%;
239
+ src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9V6VLKzA.woff2) format('woff2');
240
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
241
+ }
242
+ /* latin-ext */
243
+ @font-face {
244
+ font-family: 'Noto Sans';
245
+ font-style: normal;
246
+ font-weight: 400;
247
+ font-stretch: 100%;
248
+ src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9U6VLKzA.woff2) format('woff2');
249
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
250
+ }
251
+ /* latin */
252
+ @font-face {
253
+ font-family: 'Noto Sans';
254
+ font-style: normal;
255
+ font-weight: 400;
256
+ font-stretch: 100%;
257
+ src: url(https://fonts.gstatic.com/s/notosans/v35/o-0mIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjcz6L1SoM-jCpoiyD9A-9a6VI.woff2) format('woff2');
258
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
259
+ }
static/css2.css ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* cyrillic-ext */
2
+ @font-face {
3
+ font-family: 'Source Sans Pro';
4
+ font-style: normal;
5
+ font-weight: 400;
6
+ font-display: swap;
7
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNa7lqDY.woff2) format('woff2');
8
+ unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
9
+ }
10
+ /* cyrillic */
11
+ @font-face {
12
+ font-family: 'Source Sans Pro';
13
+ font-style: normal;
14
+ font-weight: 400;
15
+ font-display: swap;
16
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qPK7lqDY.woff2) format('woff2');
17
+ unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
18
+ }
19
+ /* greek-ext */
20
+ @font-face {
21
+ font-family: 'Source Sans Pro';
22
+ font-style: normal;
23
+ font-weight: 400;
24
+ font-display: swap;
25
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNK7lqDY.woff2) format('woff2');
26
+ unicode-range: U+1F00-1FFF;
27
+ }
28
+ /* greek */
29
+ @font-face {
30
+ font-family: 'Source Sans Pro';
31
+ font-style: normal;
32
+ font-weight: 400;
33
+ font-display: swap;
34
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qO67lqDY.woff2) format('woff2');
35
+ unicode-range: U+0370-03FF;
36
+ }
37
+ /* vietnamese */
38
+ @font-face {
39
+ font-family: 'Source Sans Pro';
40
+ font-style: normal;
41
+ font-weight: 400;
42
+ font-display: swap;
43
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qN67lqDY.woff2) format('woff2');
44
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
45
+ }
46
+ /* latin-ext */
47
+ @font-face {
48
+ font-family: 'Source Sans Pro';
49
+ font-style: normal;
50
+ font-weight: 400;
51
+ font-display: swap;
52
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNq7lqDY.woff2) format('woff2');
53
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
54
+ }
55
+ /* latin */
56
+ @font-face {
57
+ font-family: 'Source Sans Pro';
58
+ font-style: normal;
59
+ font-weight: 400;
60
+ font-display: swap;
61
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format('woff2');
62
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
63
+ }
64
+ /* cyrillic-ext */
65
+ @font-face {
66
+ font-family: 'Source Sans Pro';
67
+ font-style: normal;
68
+ font-weight: 600;
69
+ font-display: swap;
70
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmhduz8A.woff2) format('woff2');
71
+ unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
72
+ }
73
+ /* cyrillic */
74
+ @font-face {
75
+ font-family: 'Source Sans Pro';
76
+ font-style: normal;
77
+ font-weight: 600;
78
+ font-display: swap;
79
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwkxduz8A.woff2) format('woff2');
80
+ unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
81
+ }
82
+ /* greek-ext */
83
+ @font-face {
84
+ font-family: 'Source Sans Pro';
85
+ font-style: normal;
86
+ font-weight: 600;
87
+ font-display: swap;
88
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmxduz8A.woff2) format('woff2');
89
+ unicode-range: U+1F00-1FFF;
90
+ }
91
+ /* greek */
92
+ @font-face {
93
+ font-family: 'Source Sans Pro';
94
+ font-style: normal;
95
+ font-weight: 600;
96
+ font-display: swap;
97
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwlBduz8A.woff2) format('woff2');
98
+ unicode-range: U+0370-03FF;
99
+ }
100
+ /* vietnamese */
101
+ @font-face {
102
+ font-family: 'Source Sans Pro';
103
+ font-style: normal;
104
+ font-weight: 600;
105
+ font-display: swap;
106
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmBduz8A.woff2) format('woff2');
107
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
108
+ }
109
+ /* latin-ext */
110
+ @font-face {
111
+ font-family: 'Source Sans Pro';
112
+ font-style: normal;
113
+ font-weight: 600;
114
+ font-display: swap;
115
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmRduz8A.woff2) format('woff2');
116
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
117
+ }
118
+ /* latin */
119
+ @font-face {
120
+ font-family: 'Source Sans Pro';
121
+ font-style: normal;
122
+ font-weight: 600;
123
+ font-display: swap;
124
+ src: url(https://fonts.gstatic.com/s/sourcesanspro/v22/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwlxdu.woff2) format('woff2');
125
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
126
+ }
static/css2_002.css ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* cyrillic-ext */
2
+ @font-face {
3
+ font-family: 'IBM Plex Mono';
4
+ font-style: normal;
5
+ font-weight: 400;
6
+ font-display: swap;
7
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1iIq129k.woff2) format('woff2');
8
+ unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
9
+ }
10
+ /* cyrillic */
11
+ @font-face {
12
+ font-family: 'IBM Plex Mono';
13
+ font-style: normal;
14
+ font-weight: 400;
15
+ font-display: swap;
16
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1isq129k.woff2) format('woff2');
17
+ unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
18
+ }
19
+ /* vietnamese */
20
+ @font-face {
21
+ font-family: 'IBM Plex Mono';
22
+ font-style: normal;
23
+ font-weight: 400;
24
+ font-display: swap;
25
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1iAq129k.woff2) format('woff2');
26
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
27
+ }
28
+ /* latin-ext */
29
+ @font-face {
30
+ font-family: 'IBM Plex Mono';
31
+ font-style: normal;
32
+ font-weight: 400;
33
+ font-display: swap;
34
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1iEq129k.woff2) format('woff2');
35
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
36
+ }
37
+ /* latin */
38
+ @font-face {
39
+ font-family: 'IBM Plex Mono';
40
+ font-style: normal;
41
+ font-weight: 400;
42
+ font-display: swap;
43
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F63fjptAgt5VM-kVkqdyU8n1i8q1w.woff2) format('woff2');
44
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
45
+ }
46
+ /* cyrillic-ext */
47
+ @font-face {
48
+ font-family: 'IBM Plex Mono';
49
+ font-style: normal;
50
+ font-weight: 600;
51
+ font-display: swap;
52
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwl1FgtIU.woff2) format('woff2');
53
+ unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
54
+ }
55
+ /* cyrillic */
56
+ @font-face {
57
+ font-family: 'IBM Plex Mono';
58
+ font-style: normal;
59
+ font-weight: 600;
60
+ font-display: swap;
61
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwlRFgtIU.woff2) format('woff2');
62
+ unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
63
+ }
64
+ /* vietnamese */
65
+ @font-face {
66
+ font-family: 'IBM Plex Mono';
67
+ font-style: normal;
68
+ font-weight: 600;
69
+ font-display: swap;
70
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwl9FgtIU.woff2) format('woff2');
71
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
72
+ }
73
+ /* latin-ext */
74
+ @font-face {
75
+ font-family: 'IBM Plex Mono';
76
+ font-style: normal;
77
+ font-weight: 600;
78
+ font-display: swap;
79
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwl5FgtIU.woff2) format('woff2');
80
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
81
+ }
82
+ /* latin */
83
+ @font-face {
84
+ font-family: 'IBM Plex Mono';
85
+ font-style: normal;
86
+ font-weight: 600;
87
+ font-display: swap;
88
+ src: url(https://fonts.gstatic.com/s/ibmplexmono/v19/-F6qfjptAgt5VM-kVkqdyU8n3vAOwlBFgg.woff2) format('woff2');
89
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
90
+ }
static/gradio.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ function make_script(src) {
4
+ const script = document.createElement('script');
5
+ script.type = 'module';
6
+ script.setAttribute("crossorigin", "");
7
+ script.src = src;
8
+ document.head.appendChild(script);
9
+ }
10
+ make_script("https://gradio.s3-us-west-2.amazonaws.com/3.27.0/assets/index-9405f928.js");
static/icon.css ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* fallback */
2
+ @font-face {
3
+ font-family: 'Material Icons';
4
+ font-style: normal;
5
+ font-weight: 400;
6
+ src: url(https://fonts.gstatic.com/s/materialicons/v140/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2');
7
+ }
8
+
9
+ .material-icons {
10
+ font-family: 'Material Icons';
11
+ font-weight: normal;
12
+ font-style: normal;
13
+ font-size: 24px;
14
+ line-height: 1;
15
+ letter-spacing: normal;
16
+ text-transform: none;
17
+ display: inline-block;
18
+ white-space: nowrap;
19
+ word-wrap: normal;
20
+ direction: ltr;
21
+ -moz-font-feature-settings: 'liga';
22
+ -moz-osx-font-smoothing: grayscale;
23
+ }
static/index-3ca142e0.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .spacer.svelte-1kspdo{display:inline-block;width:0;height:0}.json-node.svelte-1kspdo{display:inline;color:var(--body-text-color);line-height:var(--line-sm);font-family:var(--font-mono)}.expand-array.svelte-1kspdo{border:1px solid var(--border-color-primary);border-radius:var(--radius-sm);background:var(--background-fill-secondary);padding:0 var(--size-1);color:var(--body-text-color)}.expand-array.svelte-1kspdo:hover{background:var(--background-fill-primary)}.children.svelte-1kspdo{padding-left:var(--size-4)}.json-item.svelte-1kspdo{display:inline}.null.svelte-1kspdo{color:var(--body-text-color-subdued)}.string.svelte-1kspdo{color:var(--color-green-500)}.number.svelte-1kspdo{color:var(--color-blue-500)}.bool.svelte-1kspdo{color:var(--color-red-500)}.json-holder.svelte-1trjy9a{padding:var(--size-2)}button.svelte-1trjy9a{display:flex;position:absolute;top:var(--block-label-margin);right:var(--block-label-margin);align-items:center;box-shadow:var(--shadow-drop);border:1px solid var(--border-color-primary);border-top:none;border-right:none;border-radius:var(--block-label-right-radius);background:var(--block-label-background-fill);padding:5px;width:22px;height:22px;overflow:hidden;color:var(--block-label-text-color);font:var(--font);font-size:var(--button-small-text-size)}
static/index-4a8edf2e.css ADDED
@@ -0,0 +1 @@
 
 
1
+ video.svelte-1tntsc1{flex:none;border:2px solid var(--border-color-primary);border-radius:var(--radius-lg);max-width:none}video.svelte-1tntsc1:hover,video.selected.svelte-1tntsc1{border-color:var(--border-color-accent)}.table.svelte-1tntsc1{margin:0 auto;width:var(--size-20);height:var(--size-20);object-fit:cover}.gallery.svelte-1tntsc1{max-height:var(--size-20);object-fit:cover}div.svelte-rgtszb{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gallery.svelte-rgtszb{display:flex;align-items:center;cursor:pointer;padding:var(--size-1) var(--size-2);text-align:left}table.svelte-1cib1xd.svelte-1cib1xd{position:relative}td.svelte-1cib1xd.svelte-1cib1xd{border:1px solid var(--table-border-color);padding:var(--size-2);font-size:var(--text-sm);font-family:var(--font-mono)}.selected.svelte-1cib1xd td.svelte-1cib1xd{border-color:var(--border-color-accent)}.table.svelte-1cib1xd.svelte-1cib1xd{display:inline-block;margin:0 auto}.gallery.svelte-1cib1xd td.svelte-1cib1xd:first-child{border-left:none}.gallery.svelte-1cib1xd tr:first-child td.svelte-1cib1xd{border-top:none}.gallery.svelte-1cib1xd td.svelte-1cib1xd:last-child{border-right:none}.gallery.svelte-1cib1xd tr:last-child td.svelte-1cib1xd{border-bottom:none}.overlay.svelte-1cib1xd.svelte-1cib1xd{--gradient-to:transparent;position:absolute;bottom:0;background:linear-gradient(to bottom,transparent,var(--gradient-to));width:var(--size-full);height:50%}.odd.svelte-1cib1xd.svelte-1cib1xd{--gradient-to:var(--table-even-background-fill)}.even.svelte-1cib1xd.svelte-1cib1xd{--gradient-to:var(--table-odd-background-fill)}.button.svelte-1cib1xd.svelte-1cib1xd{--gradient-to:var(--background-fill-primary)}div.svelte-h6ogpl{width:var(--size-10);height:var(--size-10)}.table.svelte-h6ogpl{margin:0 auto}.gallery.svelte-1ayixqk{padding:var(--size-1) var(--size-2)}.gallery.svelte-zvfedn{padding:var(--size-2)}pre.svelte-agpzo2{text-align:left}.gallery.svelte-agpzo2{padding:var(--size-1) var(--size-2)}.wrap.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:inline-block;width:var(--size-full);max-width:var(--size-full);color:var(--body-text-color)}.hide.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:none}.label.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:flex;align-items:center;margin-bottom:var(--size-2);color:var(--block-label-text-color);font-weight:var(--block-label-text-weight);font-size:var(--block-label-text-size);line-height:var(--line-sm)}svg.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{margin-right:var(--size-1)}.gallery.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:flex;flex-wrap:wrap;gap:var(--spacing-lg)}.gallery-item.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{border:1px solid var(--border-color-primary);border-radius:var(--button-large-radius);overflow:hidden}.gallery-item.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno:hover{border-color:var(--border-color-accent);background:var(--table-row-focus)}.table-wrap.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{border:1px solid var(--border-color-primary);border-radius:var(--table-radius);width:var(--size-full);table-layout:auto;overflow-x:auto;line-height:var(--line-sm)}table.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{width:var(--size-full)}.tr-head.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{box-shadow:var(--shadow-drop-lg);border-bottom:1px solid var(--border-color-primary)}.tr-head.svelte-13hsdno>.svelte-13hsdno+.svelte-13hsdno{border-right-width:0px;border-left-width:1px;border-color:var(--border-color-primary)}th.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{padding:var(--size-2);white-space:nowrap}.tr-body.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{cursor:pointer;border-bottom:1px solid var(--border-color-primary);background:var(--table-even-background-fill)}.tr-body.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno:last-child{border:none}.tr-body.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno:nth-child(odd){background:var(--table-odd-background-fill)}.tr-body.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno:hover{background:var(--table-row-focus)}.tr-body.svelte-13hsdno>.svelte-13hsdno+.svelte-13hsdno{border-right-width:0px;border-left-width:1px;border-color:var(--border-color-primary)}.tr-body.svelte-13hsdno:hover>.svelte-13hsdno+.svelte-13hsdno{border-color:var(--border-color-accent)}td.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{padding:var(--size-2);text-align:center}.paginate.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{display:flex;justify-content:center;align-items:center;gap:var(--spacing-sm);margin-top:var(--size-2);color:var(--block-label-text-color);font-size:var(--text-sm)}button.current-page.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno{font-weight:var(--weight-bold)}
static/index-8f1feca1.css ADDED
@@ -0,0 +1 @@
 
 
1
+ span.svelte-s1r2yt{font-weight:var(--section-header-text-weight);font-size:var(--section-header-text-size)}.label-wrap.svelte-s1r2yt{display:flex;justify-content:space-between;cursor:pointer;width:var(--size-full)}.label-wrap.open.svelte-s1r2yt{margin-bottom:var(--size-2)}.icon.svelte-s1r2yt{transition:.15s}