├── CNAME ├── LICENSE ├── README.md ├── images ├── bridge.png ├── mpds.png ├── multiscale.png ├── optimade-text-right-transparent-bg.png └── optimade_dbs.png ├── index.html ├── notebooks ├── 1_plot_pn_vs_eneg.ipynb ├── 2_atomic_simulation_environment.ipynb └── 3_online_databases.ipynb └── webassets └── reveal ├── plugin └── highlight │ ├── highlight.esm.js │ ├── highlight.js │ ├── monokai.css │ ├── plugin.js │ └── zenburn.css ├── reset.css ├── reveal.css ├── reveal.js └── theme ├── fonts └── source-sans-pro │ ├── LICENSE │ ├── source-sans-pro-italic.eot │ ├── source-sans-pro-italic.ttf │ ├── source-sans-pro-italic.woff │ ├── source-sans-pro-regular.eot │ ├── source-sans-pro-regular.ttf │ ├── source-sans-pro-regular.woff │ ├── source-sans-pro-semibold.eot │ ├── source-sans-pro-semibold.ttf │ ├── source-sans-pro-semibold.woff │ ├── source-sans-pro-semibolditalic.eot │ ├── source-sans-pro-semibolditalic.ttf │ ├── source-sans-pro-semibolditalic.woff │ └── source-sans-pro.css ├── reveal.css └── white.css /CNAME: -------------------------------------------------------------------------------- 1 | tutorial.tilde.pro -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | Copyright (c) 2022, Evgeny Blokhin, Tilde Materials Informatics, Germany 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Materials Informatics Introductory Tutorial 2 | 3 | This lecture is a part of the winter semester course "Introduction to Computational Materials Design" at the Chair of Materials Engineering of Additive Manufacturing, Technical University of Munich (Germany). 4 | 5 | An interactive set of slides is available at the [tutorial.tilde.pro](https://tutorial.tilde.pro) website. 6 | 7 | The accompanying Python notebooks are available in the `notebooks` folder and live in the [Binder online executable environment](https://mybinder.org/v2/gh/blokhin/materials-informatics-tutorial/master?filepath=notebooks). 8 | 9 | ### The topics covered are: 10 | 11 | - length scales (nanometers meters) 12 | - known initiatives and research groups to follow 13 | - crystalline formats 14 | - [Atomic Simulation Environment (ASE)](https://wiki.fysik.dtu.dk/ase/) 15 | - online visualization of crystals with the [cifplayer](https://tilde-lab.github.io/cifplayer) 16 | - phase diagrams and physical properties related to crystal structure 17 | - [Materials Platform for Data Science](https://mpds.io) 18 | - [Optimade](https://optimade.org) API standard 19 | - Optimade [online aggregator](https://optimade.science) 20 | - materials informatics community forums 21 | - online researcher profile catalogues 22 | -------------------------------------------------------------------------------- /images/bridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/images/bridge.png -------------------------------------------------------------------------------- /images/mpds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/images/mpds.png -------------------------------------------------------------------------------- /images/multiscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/images/multiscale.png -------------------------------------------------------------------------------- /images/optimade-text-right-transparent-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/images/optimade-text-right-transparent-bg.png -------------------------------------------------------------------------------- /images/optimade_dbs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/images/optimade_dbs.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Introduction to materials informatics 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | 23 |
24 |
25 | 26 |
27 | Introduction to materials informatics 28 |
29 | 30 |
31 |
Hi, that's me 🤓
32 |
33 | 34 |
35 |

Outline

36 |
37 |
    38 |
  • data & formats
  • 39 |
  • software & simulations
  • 40 |
  • collaboration & sharing
  • 41 |
42 |

43 | Open the Python notebooks meanwhile. 44 |
45 | 46 |
47 |

From nanometers to meters

48 |
49 | multiscale modeling bridge 50 | multiscale modeling lengths 51 |
52 | 53 |
54 | 55 |
56 | 57 |
58 |

Data formats for nanometers 🔬

59 |
60 | 65 |
66 | 67 |
68 | POSCAR 69 |
70 |

 71 | https://mpds.io/entry/S251615
 72 | 1.0000000000000000
 73 |     0.0000   2.0245   2.0245
 74 |     2.0245   0.0000   2.0245
 75 |     2.0245   2.0245   0.0000
 76 |   Al
 77 |    1
 78 | Direct
 79 |   0.000000  0.000000  0.000000
 80 |         
81 |
82 | 83 |
84 | CIF 85 |
86 |

 87 | data_mpds_labs
 88 | _cell_length_a    15.017668
 89 | _cell_length_b    30.035337
 90 | _cell_length_c    30.035337
 91 | _cell_angle_alpha 118.543768
 92 | _cell_angle_beta  118.543768
 93 | _cell_angle_gamma 92.541335
 94 | _symmetry_space_group_name_H-M 'P1'
 95 | _symmetry_Int_Tables_number 1
 96 | loop_
 97 |  _symmetry_equiv_pos_as_xyz
 98 |  +x,+y,+z
 99 | loop_
100 |  _atom_site_type_symbol
101 |  _atom_site_fract_x
102 |  _atom_site_fract_y
103 |  _atom_site_fract_z
104 |  Ca   0.462 -0.342 -0.179
105 |  Be   0.362 -0.274 -0.420
106 | ...
107 |         
108 |
109 | 110 |
111 | Optimade 112 |
113 |

114 | {
115 |    "attributes":{
116 |       "immutable_id":42,
117 |       "species":[
118 |          {
119 |             "chemical_symbols":[
120 |                "Au"
121 |             ]
122 |          }
123 |       ],
124 |       "cartesian_site_positions":[
125 |          [0,0,0]
126 |       ],
127 |       "lattice_vectors":[
128 |          [0,2,2],
129 |          [2,0,2],
130 |          [2,2,0]
131 |       ]
132 |    }
133 | }
134 |         
135 |
136 | 137 |
138 | 139 |
140 |

Python 🐍 & ASE 💎

141 |
142 |

143 | from ase.spacegroup import crystal
144 | 
145 | crystal_obj = crystal(
146 |     ('Al', 'Y', 'Cu', 'Cu'),
147 |     basis=[
148 |         ( 0.235, 0.0, 0.5 ),
149 |         ( 0.5861, 0.0, 0.0 ),
150 |         ( 0.333, 0.666, 0.5 ),
151 |         ( 0.0, 0.0, 0.0 )
152 |     ],
153 |     spacegroup=189,
154 |     cellpar=[7.033, 7.033, 4.023, 90, 90, 120],
155 |     primitive_cell=True
156 | )
157 |         
158 | Have a look at the ASE website. Then head over to the Python notebooks you have opened earlier. 159 |
160 | 161 |
162 |

MPDS

163 |
164 | MPDS: Materials Platform for Data Science 165 | 166 | phase diagrams 167 | crystal structures 168 | physical properties 169 | published literature 170 | MPDS platform 171 | 172 |

173 | Phase diagrams, physical properties, and crystal structures are interlinked from the published literature. Just hover and click the colored circles at the logo. 174 |
175 | 176 |
177 |

Wow, many online databases?

178 | MPDS, Materials Project, Aflowlib, OQMD, COD, Nomad 179 |
180 | 181 |
182 |

Let's link them all together 🤝

183 | Optimade logo 184 |
185 | 186 |
187 |

Optimade queries

188 |
189 |

190 | filter=elements HAS ALL "Al","Mg","Sc","Mn","O"
191 | filter=chemical_formula_reduced="NaCl"
192 | filter=elements HAS ANY "Np","Cf"
193 |     AND elements HAS "O"
194 |     AND nelements=2
195 | filter=chemical_formula_anonymous="A2B"
196 |     AND chemical_formula_anonymous="AB2"
197 | filter=_mp_bandgap > 5.0
198 | filter=chemical_formula_descriptive IS KNOWN
199 |         
200 | Let's play with them at the Optimade.Science aggregator. Then head over to the Python notebooks you have opened earlier. 201 |
202 | 203 |
204 |

Our community 👫

205 |
206 | 210 |
211 | 212 |
213 |

Have your online profiles ready 🎓

214 |
215 | 219 |
220 | 221 |
222 |

Conclusions 👌

223 |
224 |
    225 |
  • materials informatics is just about how to handle materials data efficiently
  • 226 |
  • Python + ASE can do anything about the nanometers for you
  • 227 |
  • POSCAR & CIF are the most common formats for crystal structures, but the Optimade is coming
  • 228 |
  • the modern materials simulations can be prepared and even conducted fully online.
  • 229 |
230 |
231 | 232 |
233 |

PS

234 |
235 |
    236 |
  • contact me in case of any questions
  • 237 |
  • these slides are the code on GitHub 🤓
  • 238 |
239 |
240 | 241 |
242 |
243 | 244 | 245 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /notebooks/1_plot_pn_vs_eneg.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "Short intro: basic plotting using the periodic table\n", 9 | "==========\n", 10 | "\n", 11 | "- **Complexity level**: novice\n", 12 | "- **Requirements**: basic knowledge of chemistry and Python\n", 13 | "\n", 14 | "The reader would probably agree, that the periodic table is crucially important. The **chemical elements**, as well as the **chemical formulae** are introduced here. Let's explore this a bit.\n", 15 | "\n", 16 | "We know the inorganic chemical formulae are constructed according to the electronegativities of the chemical elements. Generally, **the more** the electronegativity value, **the more** to the right the chemical element in the formula. Although there are some details, concerned with the exact definition of the electronegativity.\n", 17 | "\n", 18 | "Let's plot the Pauling electronegativities _vs._ periodic numbers of the chemical elements using the popular `matplotlib` Python library.\n" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "!pip install numpy\n", 28 | "!pip install matplotlib\n", 29 | "import numpy as np\n", 30 | "import matplotlib.pyplot as plt\n", 31 | "plt.switch_backend('agg')\n" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "\n", 39 | "Now we define the periodic table and electronegativities.\n", 40 | "\n", 41 | "Note that there are several electronegativity scales (see _e.g._ those given in the [mendeleev database](http://mendeleev.readthedocs.io/en/stable/data.html#electronegativities)). And here we use the Pauling's scale.\n", 42 | "\n", 43 | "The **periodic numbers** reflect the periodic table proposed by Julius-Lothar Meyer in 1870. How is that different from the well-known one by Dmitry Mendeleev? The rows and columns are exchanged!\n" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "chemical_elements = [\n", 53 | "'H', 'He',\n", 54 | "'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne',\n", 55 | "'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar',\n", 56 | "'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr',\n", 57 | "'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe',\n", 58 | "'Cs', 'Ba', 'La', 'Ce', 'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn',\n", 59 | "'Fr', 'Ra', 'Ac', 'Th', 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm', 'Bk', 'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr', 'Rf', 'Db', 'Sg', 'Bh', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'Nh', 'Fl', 'Mc', 'Lv', 'Ts', 'Og']\n", 60 | "\n", 61 | "periodic_numbers = [\n", 62 | "1, 112,\n", 63 | "2, 8, 82, 88, 94, 100, 106, 113,\n", 64 | "3, 9, 83, 89, 95, 101, 107, 114,\n", 65 | "4, 10, 14, 46, 50, 54, 58, 62, 66, 70, 74, 78, 84, 90, 96, 102, 108, 115,\n", 66 | "5, 11, 15, 47, 51, 55, 59, 63, 67, 71, 75, 79, 85, 91, 97, 103, 109, 116,\n", 67 | "6, 12, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 86, 92, 98, 104, 110, 117,\n", 68 | "7, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 87, 93, 99, 105, 111, 118]\n", 69 | "\n", 70 | "electronegativities = [\n", 71 | "2.2, 0,\n", 72 | "0.98, 1.57, 2.04, 2.55, 3.04, 3.44, 3.98, 0,\n", 73 | "0.93, 1.31, 1.61, 1.90, 2.19, 2.58, 3.16, 0,\n", 74 | "0.82, 1.00, 1.36, 1.54, 1.63, 1.66, 1.55, 1.83, 1.88, 1.91, 1.9, 1.65, 1.81, 2.01, 2.18, 2.55, 2.96, 3,\n", 75 | "0.82, 0.95, 1.22, 1.33, 1.60, 2.16, 1.90, 2.20, 2.28, 2.20, 1.93, 1.69, 1.78, 1.96, 2.05, 2.10, 2.66, 2.6,\n", 76 | "0.79, 0.89, 1.1, 1.12, 1.13, 1.14, 1.13, 1.17, 1.2, 1.2, 1.1, 1.22, 1.23, 1.24, 1.25, 1.1, 1.27, 1.30, 1.50, 2.36, 1.90, 2.20, 2.20, 2.28, 2.54, 2.00, 1.62, 2.33, 2.02, 2.00, 2.20, 2.20,\n", 77 | "0.70, 0.90, 1.1, 1.30, 1.50, 1.38, 1.36, 1.28, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "\n", 85 | "Then we _massage_ our data a little bit adding a summary trend line.\n", 86 | "\n", 87 | "We're good to go:\n" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "%matplotlib inline\n", 97 | "\n", 98 | "points = [pair for pair in zip(electronegativities, periodic_numbers) if pair[0] > 0]\n", 99 | "x, y = zip(*points)\n", 100 | "\n", 101 | "fitted_coeffs = np.polyfit(x, y, 1)\n", 102 | "fitted_fn = np.poly1d(fitted_coeffs)\n", 103 | "\n", 104 | "fig, ax = plt.subplots(figsize=(15, 10))\n", 105 | "\n", 106 | "ax.set_xlabel('Electronegativity')\n", 107 | "ax.set_ylabel('Periodic Number')\n", 108 | "\n", 109 | "ax.scatter(x, y, c='b', s=2, label='Chem. elements')\n", 110 | "plt.plot(x, fitted_fn(x), c='g', linewidth=0.5, label='Linear fit')\n", 111 | "plt.legend()\n", 112 | "\n", 113 | "for i, label in enumerate(chemical_elements):\n", 114 | " ax.annotate(\n", 115 | " label,\n", 116 | " (electronegativities[i], periodic_numbers[i]),\n", 117 | " size=10\n", 118 | " )" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "\n", 126 | "Look, the whole chemistry is encoded in the resulted figure :)\n", 127 | "\n", 128 | "Were you able to follow everything? Please, try to explain the plot: why it looks specifically like this?\n" 129 | ] 130 | } 131 | ], 132 | "metadata": {}, 133 | "nbformat": 4, 134 | "nbformat_minor": 2 135 | } 136 | -------------------------------------------------------------------------------- /notebooks/2_atomic_simulation_environment.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "Orchestrating molecules and crystals using ASE\n", 9 | "==========\n", 10 | "\n", 11 | "- **Complexity level**: intermediate\n", 12 | "- **Requirements**: basic knowledge of crystallography and Python\n", 13 | "\n" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": null, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "!pip install ase\n", 23 | "import ase\n", 24 | "ase.__version__" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "\n", 32 | "Which ASE version was installed? Note, you can also install specific version of a package with: `!pip install some_nice_package==0.42.0`\n", 33 | "\n", 34 | "Let's continue.\n" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "from io import StringIO\n", 44 | "from ase import Atom, Atoms\n", 45 | "from ase.spacegroup import crystal\n", 46 | "from ase.calculators.emt import EMT\n", 47 | "from ase.optimize import BFGS\n", 48 | "from ase.io.vasp import read_vasp\n", 49 | "from ase.io import write\n", 50 | "from ase.build import surface\n", 51 | "from ase.geometry import cell_to_cellpar\n", 52 | "import spglib # Gotcha here :-) a reader is expected to fix an error" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "\n", 60 | "These are all the imports we need today.\n", 61 | "\n", 62 | "Let's build a non-periodic molecule and then create a periodic structure from it.\n" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "molecule = Atoms('OCCHHHHHH', positions=[\n", 72 | " [-1.1712, 0.2997, 0 ], \n", 73 | " [-0.0463, -0.5665, 0 ], \n", 74 | " [ 1.2175, 0.2668, 0 ], \n", 75 | " [-0.0958, -1.212, 0.8819], \n", 76 | " [-0.0952, -1.1938, -0.8946], \n", 77 | " [ 2.105, -0.372, -0.0177], \n", 78 | " [ 1.2426, 0.9307, -0.8704], \n", 79 | " [ 1.2616, 0.9052, 0.8886], \n", 80 | " [-1.1291, 0.8364, 0.8099], \n", 81 | "]) \n", 82 | "periodic_molecule = Atoms([atom for atom in molecule], cell=(12, 12, 12), pbc=True)" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "\n", 90 | "We have now `molecule` and `periodic_molecule`. What is the difference?\n", 91 | "\n", 92 | "Let's visualize what we have built.\n" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "write('-', molecule, format='vasp') # Gotcha here :-) a reader is expected to fix an error" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "\n", 109 | "Here are some more functions we might use.\n", 110 | "\n", 111 | "This is `refine`:\n" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "def refine(ase_obj, accuracy=1E-03, conventional_cell=False): \n", 121 | " try: \n", 122 | " symmetry = spglib.get_spacegroup(ase_obj, symprec=accuracy) \n", 123 | " lattice, positions, numbers = spglib.standardize_cell(ase_obj, \n", 124 | " symprec=accuracy, to_primitive=not conventional_cell) \n", 125 | " except: \n", 126 | " return None, 'Error while structure refinement' \n", 127 | " try: \n", 128 | " spacegroup = int( symmetry.split()[1].replace('(', '').replace(')', '') )\n", 129 | " except (ValueError, IndexError, AttributeError): \n", 130 | " return None, 'Symmetry error (coinciding atoms?) in structure' \n", 131 | " try: \n", 132 | " return crystal( \n", 133 | " Atoms( \n", 134 | " numbers=numbers, \n", 135 | " cell=lattice, \n", 136 | " scaled_positions=positions, \n", 137 | " pbc=True \n", 138 | " ), \n", 139 | " spacegroup=spacegroup, \n", 140 | " primitive_cell=not conventional_cell, \n", 141 | " onduplicates='replace' \n", 142 | " ), None \n", 143 | " except: \n", 144 | " return None, 'Unrecognized sites or invalid site symmetry in structure' " 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "\n", 152 | "This is `poscar_to_ase`:\n" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": null, 158 | "metadata": {}, 159 | "outputs": [], 160 | "source": [ 161 | "def poscar_to_ase(poscar_string): \n", 162 | " ase_obj, error = None, None \n", 163 | " buff = StringIO(poscar_string) \n", 164 | " try: \n", 165 | " ase_obj = read_vasp(buff) \n", 166 | " except AttributeError: \n", 167 | " error = 'Types of atoms can be neither found nor inferred'\n", 168 | " except Exception: \n", 169 | " error = 'Cannot process POSCAR: invalid or missing data' \n", 170 | " buff.close() \n", 171 | " return ase_obj, error " 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "\n", 179 | "Let's have a look what we can do more:\n" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "crystal_obj.get_chemical_formula()\n", 189 | "crystal_obj *= (2, 2, 2)\n", 190 | "obj2d = surface(crystal_obj, (0, 0, 1), 5, periodic=True)" 191 | ] 192 | }, 193 | { 194 | "cell_type": "markdown", 195 | "metadata": {}, 196 | "source": [ 197 | "\n", 198 | "Try to write a function calculating a volume of the primitive cell for any ASE crystalline structure. It is given by the determinant of the cell parameters 3x3 matrix. In ASE it's a `.cell` attribute of your crystal structure object.\n", 199 | "\n", 200 | "Hint: you'll need a `det` function from the `numpy.linalg` Python package.\n" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": null, 206 | "metadata": {}, 207 | "outputs": [], 208 | "source": [ 209 | "# use this cell for your custom Python code\n", 210 | "# copy and paste your code here from the slides and the other cells" 211 | ] 212 | } 213 | ], 214 | "metadata": {}, 215 | "nbformat": 4, 216 | "nbformat_minor": 2 217 | } 218 | -------------------------------------------------------------------------------- /notebooks/3_online_databases.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "Getting data from the online databases with Optimade\n", 9 | "==========\n", 10 | "\n", 11 | "- **Complexity level**: intermediate\n", 12 | "- **Requirements**: crystallography, Python, understanding how the internet works\n", 13 | "\n" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": null, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "!pip install optimade[http-client]\n", 23 | "from optimade.client import OptimadeClient" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "!pip install ase \n", 33 | "import re \n", 34 | "from ase import Atom, Atoms \n", 35 | " \n", 36 | "client = OptimadeClient(use_async=False, max_results_per_provider=5)" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "def optimade_to_ase(structure, skip_disorder=False): \n", 46 | " \n", 47 | " def extract_chemical_element(str): \n", 48 | " return re.sub('\\W', '', str) \n", 49 | " \n", 50 | " if type(structure) == str: \n", 51 | " structure = json.loads(structure) \n", 52 | " \n", 53 | " if 'cartesian_site_positions' not in structure['attributes'] or \\\n", 54 | " 'lattice_vectors' not in structure['attributes']: \n", 55 | " return None, 'Invalid structure' \n", 56 | " \n", 57 | " if 'data' in structure and type(structure['data']) == list and len(structure['data']):\n", 58 | " structure = structure['data'][0] \n", 59 | " \n", 60 | " elems_src, atom_data, atom_meta = [], [], {} \n", 61 | " if 'species' in structure['attributes']: \n", 62 | " for n, specie in enumerate(structure['attributes']['species']): \n", 63 | " # account isotopes \n", 64 | " if specie['chemical_symbols'][0] == 'D': \n", 65 | " specie['chemical_symbols'][0] = 'H' \n", 66 | " atom_meta[n] = 'D' \n", 67 | " \n", 68 | " elems_src.append(specie['chemical_symbols'][0]) \n", 69 | " if not skip_disorder and len(specie['chemical_symbols']) > 1: \n", 70 | " if 'concentration' not in specie: \n", 71 | " return None, 'Atomic disorder data incomplete' \n", 72 | " return None, 'Structural disorder is not supported' \n", 73 | " \n", 74 | " if len(structure['attributes'].get('species', [])) != \\\n", 75 | " len(structure['attributes']['cartesian_site_positions']): \n", 76 | " elems_src = structure['attributes'].get('species_at_sites', \n", 77 | " structure['attributes'].get('elements', []) \n", 78 | " ) \n", 79 | " for n, pos in enumerate(structure['attributes']['cartesian_site_positions']): \n", 80 | " try: \n", 81 | " atom_data.append( \n", 82 | " Atom(extract_chemical_element(elems_src[n]), pos) \n", 83 | " ) \n", 84 | " except KeyError as exc: # TODO link *species_at_sites* <-> *species* \n", 85 | " return None, 'Unrecognized atom symbol: %s' % exc \n", 86 | " \n", 87 | " if not atom_data: \n", 88 | " return None, 'Atoms missing' \n", 89 | " \n", 90 | " return Atoms( \n", 91 | " atom_data, \n", 92 | " cell=structure['attributes']['lattice_vectors'], \n", 93 | " pbc=structure['attributes'].get('dimension_types') or True, \n", 94 | " info=dict(isotopes=atom_meta) if atom_meta else {} \n", 95 | " ), None " 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "query = '' # put your query \n", 105 | "howmany = client.count(query)\n", 106 | "from pprint import pprint \n", 107 | "pprint(howmany) " 108 | ] 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "metadata": {}, 113 | "source": [ 114 | "\n", 115 | "Let's try to prepare our results for a machine-learning task, calculating the structure descriptors. ", 116 | "Recall, the term *descriptor* stands for the compact information-rich number, allowing the convenient mathematical ", 117 | "treatment of the encoded complex data (crystalline structure, in our case). The descriptors ", 118 | "are heavily used in machine learning to predict the new information statistically based ", 119 | "on the existing information. Let's have a look at the *atomic packing factor descriptor*, ", 120 | "defined per a unit cell, as given in the function `get_apf` below. (It is up to the reader to check the other possible descriptors ", 121 | "for the crystalline structures!)\n", 122 | " \n", 123 | "Then let's try to do the following: \n", 124 | " \n", 125 | "- retrieve one or many structures for certain queries \n", 126 | "- visualize any retrieved structure using an online visualizer \n", 127 | "- calculate the atomic packing factor *descriptor* for the structures \n", 128 | "\n" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": null, 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [ 137 | "import numpy as np \n", 138 | "from ase.data import covalent_radii, chemical_symbols \n", 139 | " \n", 140 | "def get_apf(ase_obj): \n", 141 | " volume = 0.0 \n", 142 | " for atom in ase_obj: \n", 143 | " volume += 4/3 * np.pi * covalent_radii[chemical_symbols.index(atom.symbol)]**3\n", 144 | " return volume / abs(np.linalg.det(ase_obj.cell)) " 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [ 153 | "client = OptimadeClient(max_results_per_provider=5) \n", 154 | "query = 'chemical_formula_anonymous=\"ABCD4\"' \n", 155 | "results = client.get(query) \n", 156 | "for provider, answer in results['structures'][query].items():\n", 157 | " print('=' * 25, provider, '=' * 25) \n", 158 | " for optimade_item in answer['data']: \n", 159 | " ase_obj, error = optimade_to_ase(optimade_item) \n", 160 | " if error: \n", 161 | " print('=' * 25, error) \n", 162 | " continue \n", 163 | " print(ase_obj) " 164 | ] 165 | } 166 | ], 167 | "metadata": {}, 168 | "nbformat": 4, 169 | "nbformat_minor": 2 170 | } 171 | -------------------------------------------------------------------------------- /webassets/reveal/plugin/highlight/monokai.css: -------------------------------------------------------------------------------- 1 | /* 2 | Monokai style - ported by Luigi Maselli - http://grigio.org 3 | */ 4 | 5 | .hljs { 6 | display: block; 7 | overflow-x: auto; 8 | padding: 0.5em; 9 | background: #272822; 10 | color: #ddd; 11 | } 12 | 13 | .hljs-tag, 14 | .hljs-keyword, 15 | .hljs-selector-tag, 16 | .hljs-literal, 17 | .hljs-strong, 18 | .hljs-name { 19 | color: #f92672; 20 | } 21 | 22 | .hljs-code { 23 | color: #66d9ef; 24 | } 25 | 26 | .hljs-class .hljs-title { 27 | color: white; 28 | } 29 | 30 | .hljs-attribute, 31 | .hljs-symbol, 32 | .hljs-regexp, 33 | .hljs-link { 34 | color: #bf79db; 35 | } 36 | 37 | .hljs-string, 38 | .hljs-bullet, 39 | .hljs-subst, 40 | .hljs-title, 41 | .hljs-section, 42 | .hljs-emphasis, 43 | .hljs-type, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-selector-attr, 47 | .hljs-selector-pseudo, 48 | .hljs-addition, 49 | .hljs-variable, 50 | .hljs-template-tag, 51 | .hljs-template-variable { 52 | color: #a6e22e; 53 | } 54 | 55 | .hljs-comment, 56 | .hljs-quote, 57 | .hljs-deletion, 58 | .hljs-meta { 59 | color: #75715e; 60 | } 61 | 62 | .hljs-keyword, 63 | .hljs-selector-tag, 64 | .hljs-literal, 65 | .hljs-doctag, 66 | .hljs-title, 67 | .hljs-section, 68 | .hljs-type, 69 | .hljs-selector-id { 70 | font-weight: bold; 71 | } 72 | -------------------------------------------------------------------------------- /webassets/reveal/plugin/highlight/plugin.js: -------------------------------------------------------------------------------- 1 | import hljs from 'highlight.js'; 2 | 3 | /* highlightjs-line-numbers.js 2.8.0 | (C) 2018 Yauheni Pakala | MIT License | github.com/wcoder/highlightjs-line-numbers.js */ 4 | !function(r,o){"use strict";var e,i="hljs-ln",l="hljs-ln-line",h="hljs-ln-code",s="hljs-ln-numbers",c="hljs-ln-n",m="data-line-number",a=/\r\n|\r|\n/g;function u(e){for(var n=e.toString(),t=e.anchorNode;"TD"!==t.nodeName;)t=t.parentNode;for(var r=e.focusNode;"TD"!==r.nodeName;)r=r.parentNode;var o=parseInt(t.dataset.lineNumber),a=parseInt(r.dataset.lineNumber);if(o==a)return n;var i,l=t.textContent,s=r.textContent;for(a
{6}',[l,s,c,m,h,o+n.startFrom,0{1}',[i,r])}return e}(e.innerHTML,o)}function v(e){var n=e.className;if(/hljs-/.test(n)){for(var t=g(e.innerHTML),r=0,o="";r{1}\n',[n,0 { 38 | 39 | block.parentNode.classList.add('code-wrapper'); 40 | 41 | // Code can optionally be wrapped in script template to avoid 42 | // HTML being parsed by the browser (i.e. when you need to 43 | // include <, > or & in your code). 44 | let substitute = block.querySelector( 'script[type="text/template"]' ); 45 | if( substitute ) { 46 | // textContent handles the HTML entity escapes for us 47 | block.textContent = substitute.innerHTML; 48 | } 49 | 50 | // Trim whitespace if the "data-trim" attribute is present 51 | if( block.hasAttribute( 'data-trim' ) && typeof block.innerHTML.trim === 'function' ) { 52 | block.innerHTML = betterTrim( block ); 53 | } 54 | 55 | // Escape HTML tags unless the "data-noescape" attrbute is present 56 | if( config.escapeHTML && !block.hasAttribute( 'data-noescape' )) { 57 | block.innerHTML = block.innerHTML.replace( //g, '>' ); 58 | } 59 | 60 | // Re-highlight when focus is lost (for contenteditable code) 61 | block.addEventListener( 'focusout', function( event ) { 62 | hljs.highlightElement( event.currentTarget ); 63 | }, false ); 64 | 65 | } ); 66 | 67 | // Triggers a callback function before we trigger highlighting 68 | if( typeof config.beforeHighlight === 'function' ) { 69 | config.beforeHighlight( hljs ); 70 | } 71 | 72 | // Run initial highlighting for all code 73 | if( config.highlightOnLoad ) { 74 | Array.from( reveal.getRevealElement().querySelectorAll( 'pre code' ) ).forEach( block => { 75 | Plugin.highlightBlock( block ); 76 | } ); 77 | } 78 | 79 | // If we're printing to PDF, scroll the code highlights of 80 | // all blocks in the deck into view at once 81 | reveal.on( 'pdf-ready', function() { 82 | [].slice.call( reveal.getRevealElement().querySelectorAll( 'pre code[data-line-numbers].current-fragment' ) ).forEach( function( block ) { 83 | Plugin.scrollHighlightedLineIntoView( block, {}, true ); 84 | } ); 85 | } ); 86 | 87 | }, 88 | 89 | /** 90 | * Highlights a code block. If the node has the 91 | * 'data-line-numbers' attribute we also generate slide 92 | * numbers. 93 | * 94 | * If the block contains multiple line highlight steps, 95 | * we clone the block and create a fragment for each step. 96 | */ 97 | highlightBlock: function( block ) { 98 | 99 | hljs.highlightElement( block ); 100 | 101 | // Don't generate line numbers for empty code blocks 102 | if( block.innerHTML.trim().length === 0 ) return; 103 | 104 | if( block.hasAttribute( 'data-line-numbers' ) ) { 105 | hljs.lineNumbersBlock( block, { singleLine: true } ); 106 | 107 | var scrollState = { currentBlock: block }; 108 | 109 | // If there is more than one highlight step, generate 110 | // fragments 111 | var highlightSteps = Plugin.deserializeHighlightSteps( block.getAttribute( 'data-line-numbers' ) ); 112 | if( highlightSteps.length > 1 ) { 113 | 114 | // If the original code block has a fragment-index, 115 | // each clone should follow in an incremental sequence 116 | var fragmentIndex = parseInt( block.getAttribute( 'data-fragment-index' ), 10 ); 117 | 118 | if( typeof fragmentIndex !== 'number' || isNaN( fragmentIndex ) ) { 119 | fragmentIndex = null; 120 | } 121 | 122 | // Generate fragments for all steps except the original block 123 | highlightSteps.slice(1).forEach( function( highlight ) { 124 | 125 | var fragmentBlock = block.cloneNode( true ); 126 | fragmentBlock.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlight ] ) ); 127 | fragmentBlock.classList.add( 'fragment' ); 128 | block.parentNode.appendChild( fragmentBlock ); 129 | Plugin.highlightLines( fragmentBlock ); 130 | 131 | if( typeof fragmentIndex === 'number' ) { 132 | fragmentBlock.setAttribute( 'data-fragment-index', fragmentIndex ); 133 | fragmentIndex += 1; 134 | } 135 | else { 136 | fragmentBlock.removeAttribute( 'data-fragment-index' ); 137 | } 138 | 139 | // Scroll highlights into view as we step through them 140 | fragmentBlock.addEventListener( 'visible', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock, scrollState ) ); 141 | fragmentBlock.addEventListener( 'hidden', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock.previousSibling, scrollState ) ); 142 | 143 | } ); 144 | 145 | block.removeAttribute( 'data-fragment-index' ); 146 | block.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlightSteps[0] ] ) ); 147 | 148 | } 149 | 150 | // Scroll the first highlight into view when the slide 151 | // becomes visible. Note supported in IE11 since it lacks 152 | // support for Element.closest. 153 | var slide = typeof block.closest === 'function' ? block.closest( 'section:not(.stack)' ) : null; 154 | if( slide ) { 155 | var scrollFirstHighlightIntoView = function() { 156 | Plugin.scrollHighlightedLineIntoView( block, scrollState, true ); 157 | slide.removeEventListener( 'visible', scrollFirstHighlightIntoView ); 158 | } 159 | slide.addEventListener( 'visible', scrollFirstHighlightIntoView ); 160 | } 161 | 162 | Plugin.highlightLines( block ); 163 | 164 | } 165 | 166 | }, 167 | 168 | /** 169 | * Animates scrolling to the first highlighted line 170 | * in the given code block. 171 | */ 172 | scrollHighlightedLineIntoView: function( block, scrollState, skipAnimation ) { 173 | 174 | cancelAnimationFrame( scrollState.animationFrameID ); 175 | 176 | // Match the scroll position of the currently visible 177 | // code block 178 | if( scrollState.currentBlock ) { 179 | block.scrollTop = scrollState.currentBlock.scrollTop; 180 | } 181 | 182 | // Remember the current code block so that we can match 183 | // its scroll position when showing/hiding fragments 184 | scrollState.currentBlock = block; 185 | 186 | var highlightBounds = this.getHighlightedLineBounds( block ) 187 | var viewportHeight = block.offsetHeight; 188 | 189 | // Subtract padding from the viewport height 190 | var blockStyles = getComputedStyle( block ); 191 | viewportHeight -= parseInt( blockStyles.paddingTop ) + parseInt( blockStyles.paddingBottom ); 192 | 193 | // Scroll position which centers all highlights 194 | var startTop = block.scrollTop; 195 | var targetTop = highlightBounds.top + ( Math.min( highlightBounds.bottom - highlightBounds.top, viewportHeight ) - viewportHeight ) / 2; 196 | 197 | // Account for offsets in position applied to the 198 | // that holds our lines of code 199 | var lineTable = block.querySelector( '.hljs-ln' ); 200 | if( lineTable ) targetTop += lineTable.offsetTop - parseInt( blockStyles.paddingTop ); 201 | 202 | // Make sure the scroll target is within bounds 203 | targetTop = Math.max( Math.min( targetTop, block.scrollHeight - viewportHeight ), 0 ); 204 | 205 | if( skipAnimation === true || startTop === targetTop ) { 206 | block.scrollTop = targetTop; 207 | } 208 | else { 209 | 210 | // Don't attempt to scroll if there is no overflow 211 | if( block.scrollHeight <= viewportHeight ) return; 212 | 213 | var time = 0; 214 | var animate = function() { 215 | time = Math.min( time + 0.02, 1 ); 216 | 217 | // Update our eased scroll position 218 | block.scrollTop = startTop + ( targetTop - startTop ) * Plugin.easeInOutQuart( time ); 219 | 220 | // Keep animating unless we've reached the end 221 | if( time < 1 ) { 222 | scrollState.animationFrameID = requestAnimationFrame( animate ); 223 | } 224 | }; 225 | 226 | animate(); 227 | 228 | } 229 | 230 | }, 231 | 232 | /** 233 | * The easing function used when scrolling. 234 | */ 235 | easeInOutQuart: function( t ) { 236 | 237 | // easeInOutQuart 238 | return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t; 239 | 240 | }, 241 | 242 | getHighlightedLineBounds: function( block ) { 243 | 244 | var highlightedLines = block.querySelectorAll( '.highlight-line' ); 245 | if( highlightedLines.length === 0 ) { 246 | return { top: 0, bottom: 0 }; 247 | } 248 | else { 249 | var firstHighlight = highlightedLines[0]; 250 | var lastHighlight = highlightedLines[ highlightedLines.length -1 ]; 251 | 252 | return { 253 | top: firstHighlight.offsetTop, 254 | bottom: lastHighlight.offsetTop + lastHighlight.offsetHeight 255 | } 256 | } 257 | 258 | }, 259 | 260 | /** 261 | * Visually emphasize specific lines within a code block. 262 | * This only works on blocks with line numbering turned on. 263 | * 264 | * @param {HTMLElement} block a block 265 | * @param {String} [linesToHighlight] The lines that should be 266 | * highlighted in this format: 267 | * "1" = highlights line 1 268 | * "2,5" = highlights lines 2 & 5 269 | * "2,5-7" = highlights lines 2, 5, 6 & 7 270 | */ 271 | highlightLines: function( block, linesToHighlight ) { 272 | 273 | var highlightSteps = Plugin.deserializeHighlightSteps( linesToHighlight || block.getAttribute( 'data-line-numbers' ) ); 274 | 275 | if( highlightSteps.length ) { 276 | 277 | highlightSteps[0].forEach( function( highlight ) { 278 | 279 | var elementsToHighlight = []; 280 | 281 | // Highlight a range 282 | if( typeof highlight.end === 'number' ) { 283 | elementsToHighlight = [].slice.call( block.querySelectorAll( 'table tr:nth-child(n+'+highlight.start+'):nth-child(-n+'+highlight.end+')' ) ); 284 | } 285 | // Highlight a single line 286 | else if( typeof highlight.start === 'number' ) { 287 | elementsToHighlight = [].slice.call( block.querySelectorAll( 'table tr:nth-child('+highlight.start+')' ) ); 288 | } 289 | 290 | if( elementsToHighlight.length ) { 291 | elementsToHighlight.forEach( function( lineElement ) { 292 | lineElement.classList.add( 'highlight-line' ); 293 | } ); 294 | 295 | block.classList.add( 'has-highlights' ); 296 | } 297 | 298 | } ); 299 | 300 | } 301 | 302 | }, 303 | 304 | /** 305 | * Parses and formats a user-defined string of line 306 | * numbers to highlight. 307 | * 308 | * @example 309 | * Plugin.deserializeHighlightSteps( '1,2|3,5-10' ) 310 | * // [ 311 | * // [ { start: 1 }, { start: 2 } ], 312 | * // [ { start: 3 }, { start: 5, end: 10 } ] 313 | * // ] 314 | */ 315 | deserializeHighlightSteps: function( highlightSteps ) { 316 | 317 | // Remove whitespace 318 | highlightSteps = highlightSteps.replace( /\s/g, '' ); 319 | 320 | // Divide up our line number groups 321 | highlightSteps = highlightSteps.split( Plugin.HIGHLIGHT_STEP_DELIMITER ); 322 | 323 | return highlightSteps.map( function( highlights ) { 324 | 325 | return highlights.split( Plugin.HIGHLIGHT_LINE_DELIMITER ).map( function( highlight ) { 326 | 327 | // Parse valid line numbers 328 | if( /^[\d-]+$/.test( highlight ) ) { 329 | 330 | highlight = highlight.split( Plugin.HIGHLIGHT_LINE_RANGE_DELIMITER ); 331 | 332 | var lineStart = parseInt( highlight[0], 10 ), 333 | lineEnd = parseInt( highlight[1], 10 ); 334 | 335 | if( isNaN( lineEnd ) ) { 336 | return { 337 | start: lineStart 338 | }; 339 | } 340 | else { 341 | return { 342 | start: lineStart, 343 | end: lineEnd 344 | }; 345 | } 346 | 347 | } 348 | // If no line numbers are provided, no code will be highlighted 349 | else { 350 | 351 | return {}; 352 | 353 | } 354 | 355 | } ); 356 | 357 | } ); 358 | 359 | }, 360 | 361 | /** 362 | * Serializes parsed line number data into a string so 363 | * that we can store it in the DOM. 364 | */ 365 | serializeHighlightSteps: function( highlightSteps ) { 366 | 367 | return highlightSteps.map( function( highlights ) { 368 | 369 | return highlights.map( function( highlight ) { 370 | 371 | // Line range 372 | if( typeof highlight.end === 'number' ) { 373 | return highlight.start + Plugin.HIGHLIGHT_LINE_RANGE_DELIMITER + highlight.end; 374 | } 375 | // Single line 376 | else if( typeof highlight.start === 'number' ) { 377 | return highlight.start; 378 | } 379 | // All lines 380 | else { 381 | return ''; 382 | } 383 | 384 | } ).join( Plugin.HIGHLIGHT_LINE_DELIMITER ); 385 | 386 | } ).join( Plugin.HIGHLIGHT_STEP_DELIMITER ); 387 | 388 | } 389 | 390 | } 391 | 392 | // Function to perform a better "data-trim" on code snippets 393 | // Will slice an indentation amount on each line of the snippet (amount based on the line having the lowest indentation length) 394 | function betterTrim(snippetEl) { 395 | // Helper functions 396 | function trimLeft(val) { 397 | // Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill 398 | return val.replace(/^[\s\uFEFF\xA0]+/g, ''); 399 | } 400 | function trimLineBreaks(input) { 401 | var lines = input.split('\n'); 402 | 403 | // Trim line-breaks from the beginning 404 | for (var i = 0; i < lines.length; i++) { 405 | if (lines[i].trim() === '') { 406 | lines.splice(i--, 1); 407 | } else break; 408 | } 409 | 410 | // Trim line-breaks from the end 411 | for (var i = lines.length-1; i >= 0; i--) { 412 | if (lines[i].trim() === '') { 413 | lines.splice(i, 1); 414 | } else break; 415 | } 416 | 417 | return lines.join('\n'); 418 | } 419 | 420 | // Main function for betterTrim() 421 | return (function(snippetEl) { 422 | var content = trimLineBreaks(snippetEl.innerHTML); 423 | var lines = content.split('\n'); 424 | // Calculate the minimum amount to remove on each line start of the snippet (can be 0) 425 | var pad = lines.reduce(function(acc, line) { 426 | if (line.length > 0 && trimLeft(line).length > 0 && acc > line.length - trimLeft(line).length) { 427 | return line.length - trimLeft(line).length; 428 | } 429 | return acc; 430 | }, Number.POSITIVE_INFINITY); 431 | // Slice each line with this amount 432 | return lines.map(function(line, index) { 433 | return line.slice(pad); 434 | }) 435 | .join('\n'); 436 | })(snippetEl); 437 | } 438 | 439 | export default () => Plugin; 440 | -------------------------------------------------------------------------------- /webassets/reveal/plugin/highlight/zenburn.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Zenburn style from voldmar.ru (c) Vladimir Epifanov 4 | based on dark.css by Ivan Sagalaev 5 | 6 | */ 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #3f3f3f; 13 | color: #dcdcdc; 14 | } 15 | 16 | .hljs-keyword, 17 | .hljs-selector-tag, 18 | .hljs-tag { 19 | color: #e3ceab; 20 | } 21 | 22 | .hljs-template-tag { 23 | color: #dcdcdc; 24 | } 25 | 26 | .hljs-number { 27 | color: #8cd0d3; 28 | } 29 | 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-attribute { 33 | color: #efdcbc; 34 | } 35 | 36 | .hljs-literal { 37 | color: #efefaf; 38 | } 39 | 40 | .hljs-subst { 41 | color: #8f8f8f; 42 | } 43 | 44 | .hljs-title, 45 | .hljs-name, 46 | .hljs-selector-id, 47 | .hljs-selector-class, 48 | .hljs-section, 49 | .hljs-type { 50 | color: #efef8f; 51 | } 52 | 53 | .hljs-symbol, 54 | .hljs-bullet, 55 | .hljs-link { 56 | color: #dca3a3; 57 | } 58 | 59 | .hljs-deletion, 60 | .hljs-string, 61 | .hljs-built_in, 62 | .hljs-builtin-name { 63 | color: #cc9393; 64 | } 65 | 66 | .hljs-addition, 67 | .hljs-comment, 68 | .hljs-quote, 69 | .hljs-meta { 70 | color: #7f9f7f; 71 | } 72 | 73 | 74 | .hljs-emphasis { 75 | font-style: italic; 76 | } 77 | 78 | .hljs-strong { 79 | font-weight: bold; 80 | } 81 | -------------------------------------------------------------------------------- /webassets/reveal/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v4.0 | 20180602 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | main, menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, main, menu, nav, section { 29 | display: block; 30 | } -------------------------------------------------------------------------------- /webassets/reveal/reveal.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * reveal.js 4.3.1 3 | * https://revealjs.com 4 | * MIT licensed 5 | * 6 | * Copyright (C) 2011-2022 Hakim El Hattab, https://hakim.se 7 | */ 8 | .reveal .r-stretch,.reveal .stretch{max-width:none;max-height:none}.reveal pre.r-stretch code,.reveal pre.stretch code{height:100%;max-height:100%;box-sizing:border-box}.reveal .r-fit-text{display:inline-block;white-space:nowrap}.reveal .r-stack{display:grid}.reveal .r-stack>*{grid-area:1/1;margin:auto}.reveal .r-hstack,.reveal .r-vstack{display:flex}.reveal .r-hstack img,.reveal .r-hstack video,.reveal .r-vstack img,.reveal .r-vstack video{min-width:0;min-height:0;-o-object-fit:contain;object-fit:contain}.reveal .r-vstack{flex-direction:column;align-items:center;justify-content:center}.reveal .r-hstack{flex-direction:row;align-items:center;justify-content:center}.reveal .items-stretch{align-items:stretch}.reveal .items-start{align-items:flex-start}.reveal .items-center{align-items:center}.reveal .items-end{align-items:flex-end}.reveal .justify-between{justify-content:space-between}.reveal .justify-around{justify-content:space-around}.reveal .justify-start{justify-content:flex-start}.reveal .justify-center{justify-content:center}.reveal .justify-end{justify-content:flex-end}html.reveal-full-page{width:100%;height:100%;height:100vh;height:calc(var(--vh,1vh) * 100);overflow:hidden}.reveal-viewport{height:100%;overflow:hidden;position:relative;line-height:1;margin:0;background-color:#fff;color:#000}.reveal-viewport:-webkit-full-screen{top:0!important;left:0!important;width:100%!important;height:100%!important;transform:none!important}.reveal-viewport:-ms-fullscreen{top:0!important;left:0!important;width:100%!important;height:100%!important;transform:none!important}.reveal-viewport:fullscreen{top:0!important;left:0!important;width:100%!important;height:100%!important;transform:none!important}.reveal .slides section .fragment{opacity:0;visibility:hidden;transition:all .2s ease;will-change:opacity}.reveal .slides section .fragment.visible{opacity:1;visibility:inherit}.reveal .slides section .fragment.disabled{transition:none}.reveal .slides section .fragment.grow{opacity:1;visibility:inherit}.reveal .slides section .fragment.grow.visible{transform:scale(1.3)}.reveal .slides section .fragment.shrink{opacity:1;visibility:inherit}.reveal .slides section .fragment.shrink.visible{transform:scale(.7)}.reveal .slides section .fragment.zoom-in{transform:scale(.1)}.reveal .slides section .fragment.zoom-in.visible{transform:none}.reveal .slides section .fragment.fade-out{opacity:1;visibility:inherit}.reveal .slides section .fragment.fade-out.visible{opacity:0;visibility:hidden}.reveal .slides section .fragment.semi-fade-out{opacity:1;visibility:inherit}.reveal .slides section .fragment.semi-fade-out.visible{opacity:.5;visibility:inherit}.reveal .slides section .fragment.strike{opacity:1;visibility:inherit}.reveal .slides section .fragment.strike.visible{text-decoration:line-through}.reveal .slides section .fragment.fade-up{transform:translate(0,40px)}.reveal .slides section .fragment.fade-up.visible{transform:translate(0,0)}.reveal .slides section .fragment.fade-down{transform:translate(0,-40px)}.reveal .slides section .fragment.fade-down.visible{transform:translate(0,0)}.reveal .slides section .fragment.fade-right{transform:translate(-40px,0)}.reveal .slides section .fragment.fade-right.visible{transform:translate(0,0)}.reveal .slides section .fragment.fade-left{transform:translate(40px,0)}.reveal .slides section .fragment.fade-left.visible{transform:translate(0,0)}.reveal .slides section .fragment.current-visible,.reveal .slides section .fragment.fade-in-then-out{opacity:0;visibility:hidden}.reveal .slides section .fragment.current-visible.current-fragment,.reveal .slides section .fragment.fade-in-then-out.current-fragment{opacity:1;visibility:inherit}.reveal .slides section .fragment.fade-in-then-semi-out{opacity:0;visibility:hidden}.reveal .slides section .fragment.fade-in-then-semi-out.visible{opacity:.5;visibility:inherit}.reveal .slides section .fragment.fade-in-then-semi-out.current-fragment{opacity:1;visibility:inherit}.reveal .slides section .fragment.highlight-blue,.reveal .slides section .fragment.highlight-current-blue,.reveal .slides section .fragment.highlight-current-green,.reveal .slides section .fragment.highlight-current-red,.reveal .slides section .fragment.highlight-green,.reveal .slides section .fragment.highlight-red{opacity:1;visibility:inherit}.reveal .slides section .fragment.highlight-red.visible{color:#ff2c2d}.reveal .slides section .fragment.highlight-green.visible{color:#17ff2e}.reveal .slides section .fragment.highlight-blue.visible{color:#1b91ff}.reveal .slides section .fragment.highlight-current-red.current-fragment{color:#ff2c2d}.reveal .slides section .fragment.highlight-current-green.current-fragment{color:#17ff2e}.reveal .slides section .fragment.highlight-current-blue.current-fragment{color:#1b91ff}.reveal:after{content:"";font-style:italic}.reveal iframe{z-index:1}.reveal a{position:relative}@keyframes bounce-right{0%,10%,25%,40%,50%{transform:translateX(0)}20%{transform:translateX(10px)}30%{transform:translateX(-5px)}}@keyframes bounce-left{0%,10%,25%,40%,50%{transform:translateX(0)}20%{transform:translateX(-10px)}30%{transform:translateX(5px)}}@keyframes bounce-down{0%,10%,25%,40%,50%{transform:translateY(0)}20%{transform:translateY(10px)}30%{transform:translateY(-5px)}}.reveal .controls{display:none;position:absolute;top:auto;bottom:12px;right:12px;left:auto;z-index:11;color:#000;pointer-events:none;font-size:10px}.reveal .controls button{position:absolute;padding:0;background-color:transparent;border:0;outline:0;cursor:pointer;color:currentColor;transform:scale(.9999);transition:color .2s ease,opacity .2s ease,transform .2s ease;z-index:2;pointer-events:auto;font-size:inherit;visibility:hidden;opacity:0;-webkit-appearance:none;-webkit-tap-highlight-color:transparent}.reveal .controls .controls-arrow:after,.reveal .controls .controls-arrow:before{content:"";position:absolute;top:0;left:0;width:2.6em;height:.5em;border-radius:.25em;background-color:currentColor;transition:all .15s ease,background-color .8s ease;transform-origin:.2em 50%;will-change:transform}.reveal .controls .controls-arrow{position:relative;width:3.6em;height:3.6em}.reveal .controls .controls-arrow:before{transform:translateX(.5em) translateY(1.55em) rotate(45deg)}.reveal .controls .controls-arrow:after{transform:translateX(.5em) translateY(1.55em) rotate(-45deg)}.reveal .controls .controls-arrow:hover:before{transform:translateX(.5em) translateY(1.55em) rotate(40deg)}.reveal .controls .controls-arrow:hover:after{transform:translateX(.5em) translateY(1.55em) rotate(-40deg)}.reveal .controls .controls-arrow:active:before{transform:translateX(.5em) translateY(1.55em) rotate(36deg)}.reveal .controls .controls-arrow:active:after{transform:translateX(.5em) translateY(1.55em) rotate(-36deg)}.reveal .controls .navigate-left{right:6.4em;bottom:3.2em;transform:translateX(-10px)}.reveal .controls .navigate-left.highlight{animation:bounce-left 2s 50 both ease-out}.reveal .controls .navigate-right{right:0;bottom:3.2em;transform:translateX(10px)}.reveal .controls .navigate-right .controls-arrow{transform:rotate(180deg)}.reveal .controls .navigate-right.highlight{animation:bounce-right 2s 50 both ease-out}.reveal .controls .navigate-up{right:3.2em;bottom:6.4em;transform:translateY(-10px)}.reveal .controls .navigate-up .controls-arrow{transform:rotate(90deg)}.reveal .controls .navigate-down{right:3.2em;bottom:-1.4em;padding-bottom:1.4em;transform:translateY(10px)}.reveal .controls .navigate-down .controls-arrow{transform:rotate(-90deg)}.reveal .controls .navigate-down.highlight{animation:bounce-down 2s 50 both ease-out}.reveal .controls[data-controls-back-arrows=faded] .navigate-up.enabled{opacity:.3}.reveal .controls[data-controls-back-arrows=faded] .navigate-up.enabled:hover{opacity:1}.reveal .controls[data-controls-back-arrows=hidden] .navigate-up.enabled{opacity:0;visibility:hidden}.reveal .controls .enabled{visibility:visible;opacity:.9;cursor:pointer;transform:none}.reveal .controls .enabled.fragmented{opacity:.5}.reveal .controls .enabled.fragmented:hover,.reveal .controls .enabled:hover{opacity:1}.reveal:not(.rtl) .controls[data-controls-back-arrows=faded] .navigate-left.enabled{opacity:.3}.reveal:not(.rtl) .controls[data-controls-back-arrows=faded] .navigate-left.enabled:hover{opacity:1}.reveal:not(.rtl) .controls[data-controls-back-arrows=hidden] .navigate-left.enabled{opacity:0;visibility:hidden}.reveal.rtl .controls[data-controls-back-arrows=faded] .navigate-right.enabled{opacity:.3}.reveal.rtl .controls[data-controls-back-arrows=faded] .navigate-right.enabled:hover{opacity:1}.reveal.rtl .controls[data-controls-back-arrows=hidden] .navigate-right.enabled{opacity:0;visibility:hidden}.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-down,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-up{display:none}.reveal:not(.has-vertical-slides) .controls .navigate-left,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-left{bottom:1.4em;right:5.5em}.reveal:not(.has-vertical-slides) .controls .navigate-right,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-right{bottom:1.4em;right:.5em}.reveal:not(.has-horizontal-slides) .controls .navigate-up{right:1.4em;bottom:5em}.reveal:not(.has-horizontal-slides) .controls .navigate-down{right:1.4em;bottom:.5em}.reveal.has-dark-background .controls{color:#fff}.reveal.has-light-background .controls{color:#000}.reveal.no-hover .controls .controls-arrow:active:before,.reveal.no-hover .controls .controls-arrow:hover:before{transform:translateX(.5em) translateY(1.55em) rotate(45deg)}.reveal.no-hover .controls .controls-arrow:active:after,.reveal.no-hover .controls .controls-arrow:hover:after{transform:translateX(.5em) translateY(1.55em) rotate(-45deg)}@media screen and (min-width:500px){.reveal .controls[data-controls-layout=edges]{top:0;right:0;bottom:0;left:0}.reveal .controls[data-controls-layout=edges] .navigate-down,.reveal .controls[data-controls-layout=edges] .navigate-left,.reveal .controls[data-controls-layout=edges] .navigate-right,.reveal .controls[data-controls-layout=edges] .navigate-up{bottom:auto;right:auto}.reveal .controls[data-controls-layout=edges] .navigate-left{top:50%;left:.8em;margin-top:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-right{top:50%;right:.8em;margin-top:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-up{top:.8em;left:50%;margin-left:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-down{bottom:-.3em;left:50%;margin-left:-1.8em}}.reveal .progress{position:absolute;display:none;height:3px;width:100%;bottom:0;left:0;z-index:10;background-color:rgba(0,0,0,.2);color:#fff}.reveal .progress:after{content:"";display:block;position:absolute;height:10px;width:100%;top:-10px}.reveal .progress span{display:block;height:100%;width:100%;background-color:currentColor;transition:transform .8s cubic-bezier(.26,.86,.44,.985);transform-origin:0 0;transform:scaleX(0)}.reveal .slide-number{position:absolute;display:block;right:8px;bottom:8px;z-index:31;font-family:Helvetica,sans-serif;font-size:12px;line-height:1;color:#fff;background-color:rgba(0,0,0,.4);padding:5px}.reveal .slide-number a{color:currentColor}.reveal .slide-number-delimiter{margin:0 3px}.reveal{position:relative;width:100%;height:100%;overflow:hidden;touch-action:pinch-zoom}.reveal.embedded{touch-action:pan-y}.reveal .slides{position:absolute;width:100%;height:100%;top:0;right:0;bottom:0;left:0;margin:auto;pointer-events:none;overflow:visible;z-index:1;text-align:center;perspective:600px;perspective-origin:50% 40%}.reveal .slides>section{perspective:600px}.reveal .slides>section,.reveal .slides>section>section{display:none;position:absolute;width:100%;pointer-events:auto;z-index:10;transform-style:flat;transition:transform-origin .8s cubic-bezier(.26,.86,.44,.985),transform .8s cubic-bezier(.26,.86,.44,.985),visibility .8s cubic-bezier(.26,.86,.44,.985),opacity .8s cubic-bezier(.26,.86,.44,.985)}.reveal[data-transition-speed=fast] .slides section{transition-duration:.4s}.reveal[data-transition-speed=slow] .slides section{transition-duration:1.2s}.reveal .slides section[data-transition-speed=fast]{transition-duration:.4s}.reveal .slides section[data-transition-speed=slow]{transition-duration:1.2s}.reveal .slides>section.stack{padding-top:0;padding-bottom:0;pointer-events:none;height:100%}.reveal .slides>section.present,.reveal .slides>section>section.present{display:block;z-index:11;opacity:1}.reveal .slides>section:empty,.reveal .slides>section>section:empty,.reveal .slides>section>section[data-background-interactive],.reveal .slides>section[data-background-interactive]{pointer-events:none}.reveal.center,.reveal.center .slides,.reveal.center .slides section{min-height:0!important}.reveal .slides>section:not(.present),.reveal .slides>section>section:not(.present){pointer-events:none}.reveal.overview .slides>section,.reveal.overview .slides>section>section{pointer-events:auto}.reveal .slides>section.future,.reveal .slides>section.past,.reveal .slides>section>section.future,.reveal .slides>section>section.past{opacity:0}.reveal .slides>section[data-transition=slide].past,.reveal .slides>section[data-transition~=slide-out].past,.reveal.slide .slides>section:not([data-transition]).past{transform:translate(-150%,0)}.reveal .slides>section[data-transition=slide].future,.reveal .slides>section[data-transition~=slide-in].future,.reveal.slide .slides>section:not([data-transition]).future{transform:translate(150%,0)}.reveal .slides>section>section[data-transition=slide].past,.reveal .slides>section>section[data-transition~=slide-out].past,.reveal.slide .slides>section>section:not([data-transition]).past{transform:translate(0,-150%)}.reveal .slides>section>section[data-transition=slide].future,.reveal .slides>section>section[data-transition~=slide-in].future,.reveal.slide .slides>section>section:not([data-transition]).future{transform:translate(0,150%)}.reveal .slides>section[data-transition=linear].past,.reveal .slides>section[data-transition~=linear-out].past,.reveal.linear .slides>section:not([data-transition]).past{transform:translate(-150%,0)}.reveal .slides>section[data-transition=linear].future,.reveal .slides>section[data-transition~=linear-in].future,.reveal.linear .slides>section:not([data-transition]).future{transform:translate(150%,0)}.reveal .slides>section>section[data-transition=linear].past,.reveal .slides>section>section[data-transition~=linear-out].past,.reveal.linear .slides>section>section:not([data-transition]).past{transform:translate(0,-150%)}.reveal .slides>section>section[data-transition=linear].future,.reveal .slides>section>section[data-transition~=linear-in].future,.reveal.linear .slides>section>section:not([data-transition]).future{transform:translate(0,150%)}.reveal .slides section[data-transition=default].stack,.reveal.default .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=default].past,.reveal .slides>section[data-transition~=default-out].past,.reveal.default .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=default].future,.reveal .slides>section[data-transition~=default-in].future,.reveal.default .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=default].past,.reveal .slides>section>section[data-transition~=default-out].past,.reveal.default .slides>section>section:not([data-transition]).past{transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0)}.reveal .slides>section>section[data-transition=default].future,.reveal .slides>section>section[data-transition~=default-in].future,.reveal.default .slides>section>section:not([data-transition]).future{transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0)}.reveal .slides section[data-transition=convex].stack,.reveal.convex .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=convex].past,.reveal .slides>section[data-transition~=convex-out].past,.reveal.convex .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=convex].future,.reveal .slides>section[data-transition~=convex-in].future,.reveal.convex .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=convex].past,.reveal .slides>section>section[data-transition~=convex-out].past,.reveal.convex .slides>section>section:not([data-transition]).past{transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0)}.reveal .slides>section>section[data-transition=convex].future,.reveal .slides>section>section[data-transition~=convex-in].future,.reveal.convex .slides>section>section:not([data-transition]).future{transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0)}.reveal .slides section[data-transition=concave].stack,.reveal.concave .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=concave].past,.reveal .slides>section[data-transition~=concave-out].past,.reveal.concave .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=concave].future,.reveal .slides>section[data-transition~=concave-in].future,.reveal.concave .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=concave].past,.reveal .slides>section>section[data-transition~=concave-out].past,.reveal.concave .slides>section>section:not([data-transition]).past{transform:translate3d(0,-80%,0) rotateX(-70deg) translate3d(0,-80%,0)}.reveal .slides>section>section[data-transition=concave].future,.reveal .slides>section>section[data-transition~=concave-in].future,.reveal.concave .slides>section>section:not([data-transition]).future{transform:translate3d(0,80%,0) rotateX(70deg) translate3d(0,80%,0)}.reveal .slides section[data-transition=zoom],.reveal.zoom .slides section:not([data-transition]){transition-timing-function:ease}.reveal .slides>section[data-transition=zoom].past,.reveal .slides>section[data-transition~=zoom-out].past,.reveal.zoom .slides>section:not([data-transition]).past{visibility:hidden;transform:scale(16)}.reveal .slides>section[data-transition=zoom].future,.reveal .slides>section[data-transition~=zoom-in].future,.reveal.zoom .slides>section:not([data-transition]).future{visibility:hidden;transform:scale(.2)}.reveal .slides>section>section[data-transition=zoom].past,.reveal .slides>section>section[data-transition~=zoom-out].past,.reveal.zoom .slides>section>section:not([data-transition]).past{transform:scale(16)}.reveal .slides>section>section[data-transition=zoom].future,.reveal .slides>section>section[data-transition~=zoom-in].future,.reveal.zoom .slides>section>section:not([data-transition]).future{transform:scale(.2)}.reveal.cube .slides{perspective:1300px}.reveal.cube .slides section{padding:30px;min-height:700px;-webkit-backface-visibility:hidden;backface-visibility:hidden;box-sizing:border-box;transform-style:preserve-3d}.reveal.center.cube .slides section{min-height:0}.reveal.cube .slides section:not(.stack):before{content:"";position:absolute;display:block;width:100%;height:100%;left:0;top:0;background:rgba(0,0,0,.1);border-radius:4px;transform:translateZ(-20px)}.reveal.cube .slides section:not(.stack):after{content:"";position:absolute;display:block;width:90%;height:30px;left:5%;bottom:0;background:0 0;z-index:1;border-radius:4px;box-shadow:0 95px 25px rgba(0,0,0,.2);transform:translateZ(-90px) rotateX(65deg)}.reveal.cube .slides>section.stack{padding:0;background:0 0}.reveal.cube .slides>section.past{transform-origin:100% 0;transform:translate3d(-100%,0,0) rotateY(-90deg)}.reveal.cube .slides>section.future{transform-origin:0 0;transform:translate3d(100%,0,0) rotateY(90deg)}.reveal.cube .slides>section>section.past{transform-origin:0 100%;transform:translate3d(0,-100%,0) rotateX(90deg)}.reveal.cube .slides>section>section.future{transform-origin:0 0;transform:translate3d(0,100%,0) rotateX(-90deg)}.reveal.page .slides{perspective-origin:0 50%;perspective:3000px}.reveal.page .slides section{padding:30px;min-height:700px;box-sizing:border-box;transform-style:preserve-3d}.reveal.page .slides section.past{z-index:12}.reveal.page .slides section:not(.stack):before{content:"";position:absolute;display:block;width:100%;height:100%;left:0;top:0;background:rgba(0,0,0,.1);transform:translateZ(-20px)}.reveal.page .slides section:not(.stack):after{content:"";position:absolute;display:block;width:90%;height:30px;left:5%;bottom:0;background:0 0;z-index:1;border-radius:4px;box-shadow:0 95px 25px rgba(0,0,0,.2);-webkit-transform:translateZ(-90px) rotateX(65deg)}.reveal.page .slides>section.stack{padding:0;background:0 0}.reveal.page .slides>section.past{transform-origin:0 0;transform:translate3d(-40%,0,0) rotateY(-80deg)}.reveal.page .slides>section.future{transform-origin:100% 0;transform:translate3d(0,0,0)}.reveal.page .slides>section>section.past{transform-origin:0 0;transform:translate3d(0,-40%,0) rotateX(80deg)}.reveal.page .slides>section>section.future{transform-origin:0 100%;transform:translate3d(0,0,0)}.reveal .slides section[data-transition=fade],.reveal.fade .slides section:not([data-transition]),.reveal.fade .slides>section>section:not([data-transition]){transform:none;transition:opacity .5s}.reveal.fade.overview .slides section,.reveal.fade.overview .slides>section>section{transition:none}.reveal .slides section[data-transition=none],.reveal.none .slides section:not([data-transition]){transform:none;transition:none}.reveal .pause-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;visibility:hidden;opacity:0;z-index:100;transition:all 1s ease}.reveal .pause-overlay .resume-button{position:absolute;bottom:20px;right:20px;color:#ccc;border-radius:2px;padding:6px 14px;border:2px solid #ccc;font-size:16px;background:0 0;cursor:pointer}.reveal .pause-overlay .resume-button:hover{color:#fff;border-color:#fff}.reveal.paused .pause-overlay{visibility:visible;opacity:1}.reveal .no-transition,.reveal .no-transition *,.reveal .slides.disable-slide-transitions section{transition:none!important}.reveal .slides.disable-slide-transitions section{transform:none!important}.reveal .backgrounds{position:absolute;width:100%;height:100%;top:0;left:0;perspective:600px}.reveal .slide-background{display:none;position:absolute;width:100%;height:100%;opacity:0;visibility:hidden;overflow:hidden;background-color:rgba(0,0,0,0);transition:all .8s cubic-bezier(.26,.86,.44,.985)}.reveal .slide-background-content{position:absolute;width:100%;height:100%;background-position:50% 50%;background-repeat:no-repeat;background-size:cover}.reveal .slide-background.stack{display:block}.reveal .slide-background.present{opacity:1;visibility:visible;z-index:2}.print-pdf .reveal .slide-background{opacity:1!important;visibility:visible!important}.reveal .slide-background video{position:absolute;width:100%;height:100%;max-width:none;max-height:none;top:0;left:0;-o-object-fit:cover;object-fit:cover}.reveal .slide-background[data-background-size=contain] video{-o-object-fit:contain;object-fit:contain}.reveal>.backgrounds .slide-background[data-background-transition=none],.reveal[data-background-transition=none]>.backgrounds .slide-background:not([data-background-transition]){transition:none}.reveal>.backgrounds .slide-background[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background:not([data-background-transition]){opacity:1}.reveal>.backgrounds .slide-background.past[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background.past:not([data-background-transition]){transform:translate(-100%,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background.future:not([data-background-transition]){transform:translate(100%,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){transform:translate(0,-100%)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){transform:translate(0,100%)}.reveal>.backgrounds .slide-background.past[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(0,-100%,0) rotateX(90deg) translate3d(0,-100%,0)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(0,100%,0) rotateX(-90deg) translate3d(0,100%,0)}.reveal>.backgrounds .slide-background.past[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(0,-100%,0) rotateX(-90deg) translate3d(0,-100%,0)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(0,100%,0) rotateX(90deg) translate3d(0,100%,0)}.reveal>.backgrounds .slide-background[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background:not([data-background-transition]){transition-timing-function:ease}.reveal>.backgrounds .slide-background.past[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(16)}.reveal>.backgrounds .slide-background.future[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(.2)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(16)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(.2)}.reveal[data-transition-speed=fast]>.backgrounds .slide-background{transition-duration:.4s}.reveal[data-transition-speed=slow]>.backgrounds .slide-background{transition-duration:1.2s}.reveal [data-auto-animate-target^=unmatched]{will-change:opacity}.reveal section[data-auto-animate]:not(.stack):not([data-auto-animate=running]) [data-auto-animate-target^=unmatched]{opacity:0}.reveal.overview{perspective-origin:50% 50%;perspective:700px}.reveal.overview .slides{-moz-transform-style:preserve-3d}.reveal.overview .slides section{height:100%;top:0!important;opacity:1!important;overflow:hidden;visibility:visible!important;cursor:pointer;box-sizing:border-box}.reveal.overview .slides section.present,.reveal.overview .slides section:hover{outline:10px solid rgba(150,150,150,.4);outline-offset:10px}.reveal.overview .slides section .fragment{opacity:1;transition:none}.reveal.overview .slides section:after,.reveal.overview .slides section:before{display:none!important}.reveal.overview .slides>section.stack{padding:0;top:0!important;background:0 0;outline:0;overflow:visible}.reveal.overview .backgrounds{perspective:inherit;-moz-transform-style:preserve-3d}.reveal.overview .backgrounds .slide-background{opacity:1;visibility:visible;outline:10px solid rgba(150,150,150,.1);outline-offset:10px}.reveal.overview .backgrounds .slide-background.stack{overflow:visible}.reveal.overview .slides section,.reveal.overview-deactivating .slides section{transition:none}.reveal.overview .backgrounds .slide-background,.reveal.overview-deactivating .backgrounds .slide-background{transition:none}.reveal.rtl .slides,.reveal.rtl .slides h1,.reveal.rtl .slides h2,.reveal.rtl .slides h3,.reveal.rtl .slides h4,.reveal.rtl .slides h5,.reveal.rtl .slides h6{direction:rtl;font-family:sans-serif}.reveal.rtl code,.reveal.rtl pre{direction:ltr}.reveal.rtl ol,.reveal.rtl ul{text-align:right}.reveal.rtl .progress span{transform-origin:100% 0}.reveal.has-parallax-background .backgrounds{transition:all .8s ease}.reveal.has-parallax-background[data-transition-speed=fast] .backgrounds{transition-duration:.4s}.reveal.has-parallax-background[data-transition-speed=slow] .backgrounds{transition-duration:1.2s}.reveal>.overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1000;background:rgba(0,0,0,.9);transition:all .3s ease}.reveal>.overlay .spinner{position:absolute;display:block;top:50%;left:50%;width:32px;height:32px;margin:-16px 0 0 -16px;z-index:10;background-image:url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D);visibility:visible;opacity:.6;transition:all .3s ease}.reveal>.overlay header{position:absolute;left:0;top:0;width:100%;padding:5px;z-index:2;box-sizing:border-box}.reveal>.overlay header a{display:inline-block;width:40px;height:40px;line-height:36px;padding:0 10px;float:right;opacity:.6;box-sizing:border-box}.reveal>.overlay header a:hover{opacity:1}.reveal>.overlay header a .icon{display:inline-block;width:20px;height:20px;background-position:50% 50%;background-size:100%;background-repeat:no-repeat}.reveal>.overlay header a.close .icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC)}.reveal>.overlay header a.external .icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==)}.reveal>.overlay .viewport{position:absolute;display:flex;top:50px;right:0;bottom:0;left:0}.reveal>.overlay.overlay-preview .viewport iframe{width:100%;height:100%;max-width:100%;max-height:100%;border:0;opacity:0;visibility:hidden;transition:all .3s ease}.reveal>.overlay.overlay-preview.loaded .viewport iframe{opacity:1;visibility:visible}.reveal>.overlay.overlay-preview.loaded .viewport-inner{position:absolute;z-index:-1;left:0;top:45%;width:100%;text-align:center;letter-spacing:normal}.reveal>.overlay.overlay-preview .x-frame-error{opacity:0;transition:opacity .3s ease .3s}.reveal>.overlay.overlay-preview.loaded .x-frame-error{opacity:1}.reveal>.overlay.overlay-preview.loaded .spinner{opacity:0;visibility:hidden;transform:scale(.2)}.reveal>.overlay.overlay-help .viewport{overflow:auto;color:#fff}.reveal>.overlay.overlay-help .viewport .viewport-inner{width:600px;margin:auto;padding:20px 20px 80px 20px;text-align:center;letter-spacing:normal}.reveal>.overlay.overlay-help .viewport .viewport-inner .title{font-size:20px}.reveal>.overlay.overlay-help .viewport .viewport-inner table{border:1px solid #fff;border-collapse:collapse;font-size:16px}.reveal>.overlay.overlay-help .viewport .viewport-inner table td,.reveal>.overlay.overlay-help .viewport .viewport-inner table th{width:200px;padding:14px;border:1px solid #fff;vertical-align:middle}.reveal>.overlay.overlay-help .viewport .viewport-inner table th{padding-top:20px;padding-bottom:20px}.reveal .playback{position:absolute;left:15px;bottom:20px;z-index:30;cursor:pointer;transition:all .4s ease;-webkit-tap-highlight-color:transparent}.reveal.overview .playback{opacity:0;visibility:hidden}.reveal .hljs{min-height:100%}.reveal .hljs table{margin:initial}.reveal .hljs-ln-code,.reveal .hljs-ln-numbers{padding:0;border:0}.reveal .hljs-ln-numbers{opacity:.6;padding-right:.75em;text-align:right;vertical-align:top}.reveal .hljs.has-highlights tr:not(.highlight-line){opacity:.4}.reveal .hljs:not(:first-child).fragment{position:absolute;top:0;left:0;width:100%;box-sizing:border-box}.reveal pre[data-auto-animate-target]{overflow:hidden}.reveal pre[data-auto-animate-target] code{height:100%}.reveal .roll{display:inline-block;line-height:1.2;overflow:hidden;vertical-align:top;perspective:400px;perspective-origin:50% 50%}.reveal .roll:hover{background:0 0;text-shadow:none}.reveal .roll span{display:block;position:relative;padding:0 2px;pointer-events:none;transition:all .4s ease;transform-origin:50% 0;transform-style:preserve-3d;-webkit-backface-visibility:hidden;backface-visibility:hidden}.reveal .roll:hover span{background:rgba(0,0,0,.5);transform:translate3d(0,0,-45px) rotateX(90deg)}.reveal .roll span:after{content:attr(data-title);display:block;position:absolute;left:0;top:0;padding:0 2px;-webkit-backface-visibility:hidden;backface-visibility:hidden;transform-origin:50% 0;transform:translate3d(0,110%,0) rotateX(-90deg)}.reveal aside.notes{display:none}.reveal .speaker-notes{display:none;position:absolute;width:33.3333333333%;height:100%;top:0;left:100%;padding:14px 18px 14px 18px;z-index:1;font-size:18px;line-height:1.4;border:1px solid rgba(0,0,0,.05);color:#222;background-color:#f5f5f5;overflow:auto;box-sizing:border-box;text-align:left;font-family:Helvetica,sans-serif;-webkit-overflow-scrolling:touch}.reveal .speaker-notes .notes-placeholder{color:#ccc;font-style:italic}.reveal .speaker-notes:focus{outline:0}.reveal .speaker-notes:before{content:"Speaker notes";display:block;margin-bottom:10px;opacity:.5}.reveal.show-notes{max-width:75%;overflow:visible}.reveal.show-notes .speaker-notes{display:block}@media screen and (min-width:1600px){.reveal .speaker-notes{font-size:20px}}@media screen and (max-width:1024px){.reveal.show-notes{border-left:0;max-width:none;max-height:70%;max-height:70vh;overflow:visible}.reveal.show-notes .speaker-notes{top:100%;left:0;width:100%;height:30vh;border:0}}@media screen and (max-width:600px){.reveal.show-notes{max-height:60%;max-height:60vh}.reveal.show-notes .speaker-notes{top:100%;height:40vh}.reveal .speaker-notes{font-size:14px}}.zoomed .reveal *,.zoomed .reveal :after,.zoomed .reveal :before{-webkit-backface-visibility:visible!important;backface-visibility:visible!important}.zoomed .reveal .controls,.zoomed .reveal .progress{opacity:0}.zoomed .reveal .roll span{background:0 0}.zoomed .reveal .roll span:after{visibility:hidden}html.print-pdf *{-webkit-print-color-adjust:exact}html.print-pdf{width:100%;height:100%;overflow:visible}html.print-pdf body{margin:0 auto!important;border:0;padding:0;float:none!important;overflow:visible}html.print-pdf .nestedarrow,html.print-pdf .reveal .controls,html.print-pdf .reveal .playback,html.print-pdf .reveal .progress,html.print-pdf .reveal.overview,html.print-pdf .state-background{display:none!important}html.print-pdf .reveal pre code{overflow:hidden!important;font-family:Courier,"Courier New",monospace!important}html.print-pdf .reveal{width:auto!important;height:auto!important;overflow:hidden!important}html.print-pdf .reveal .slides{position:static;width:100%!important;height:auto!important;zoom:1!important;pointer-events:initial;left:auto;top:auto;margin:0!important;padding:0!important;overflow:visible;display:block;perspective:none;perspective-origin:50% 50%}html.print-pdf .reveal .slides .pdf-page{position:relative;overflow:hidden;z-index:1;page-break-after:always}html.print-pdf .reveal .slides section{visibility:visible!important;display:block!important;position:absolute!important;margin:0!important;padding:0!important;box-sizing:border-box!important;min-height:1px;opacity:1!important;transform-style:flat!important;transform:none!important}html.print-pdf .reveal section.stack{position:relative!important;margin:0!important;padding:0!important;page-break-after:avoid!important;height:auto!important;min-height:auto!important}html.print-pdf .reveal img{box-shadow:none}html.print-pdf .reveal .backgrounds{display:none}html.print-pdf .reveal .slide-background{display:block!important;position:absolute;top:0;left:0;width:100%;height:100%;z-index:auto!important}html.print-pdf .reveal.show-notes{max-width:none;max-height:none}html.print-pdf .reveal .speaker-notes-pdf{display:block;width:100%;height:auto;max-height:none;top:auto;right:auto;bottom:auto;left:auto;z-index:100}html.print-pdf .reveal .speaker-notes-pdf[data-layout=separate-page]{position:relative;color:inherit;background-color:transparent;padding:20px;page-break-after:always;border:0}html.print-pdf .reveal .slide-number-pdf{display:block;position:absolute;font-size:14px}html.print-pdf .aria-status{display:none}@media print{html:not(.print-pdf){background:#fff;width:auto;height:auto;overflow:visible}html:not(.print-pdf) body{background:#fff;font-size:20pt;width:auto;height:auto;border:0;margin:0 5%;padding:0;overflow:visible;float:none!important}html:not(.print-pdf) .controls,html:not(.print-pdf) .fork-reveal,html:not(.print-pdf) .nestedarrow,html:not(.print-pdf) .reveal .backgrounds,html:not(.print-pdf) .reveal .progress,html:not(.print-pdf) .reveal .slide-number,html:not(.print-pdf) .share-reveal,html:not(.print-pdf) .state-background{display:none!important}html:not(.print-pdf) body,html:not(.print-pdf) li,html:not(.print-pdf) p,html:not(.print-pdf) td{font-size:20pt!important;color:#000}html:not(.print-pdf) h1,html:not(.print-pdf) h2,html:not(.print-pdf) h3,html:not(.print-pdf) h4,html:not(.print-pdf) h5,html:not(.print-pdf) h6{color:#000!important;height:auto;line-height:normal;text-align:left;letter-spacing:normal}html:not(.print-pdf) h1{font-size:28pt!important}html:not(.print-pdf) h2{font-size:24pt!important}html:not(.print-pdf) h3{font-size:22pt!important}html:not(.print-pdf) h4{font-size:22pt!important;font-variant:small-caps}html:not(.print-pdf) h5{font-size:21pt!important}html:not(.print-pdf) h6{font-size:20pt!important;font-style:italic}html:not(.print-pdf) a:link,html:not(.print-pdf) a:visited{color:#000!important;font-weight:700;text-decoration:underline}html:not(.print-pdf) div,html:not(.print-pdf) ol,html:not(.print-pdf) p,html:not(.print-pdf) ul{visibility:visible;position:static;width:auto;height:auto;display:block;overflow:visible;margin:0;text-align:left!important}html:not(.print-pdf) .reveal pre,html:not(.print-pdf) .reveal table{margin-left:0;margin-right:0}html:not(.print-pdf) .reveal pre code{padding:20px}html:not(.print-pdf) .reveal blockquote{margin:20px 0}html:not(.print-pdf) .reveal .slides{position:static!important;width:auto!important;height:auto!important;left:0!important;top:0!important;margin-left:0!important;margin-top:0!important;padding:0!important;zoom:1!important;transform:none!important;overflow:visible!important;display:block!important;text-align:left!important;perspective:none;perspective-origin:50% 50%}html:not(.print-pdf) .reveal .slides section{visibility:visible!important;position:static!important;width:auto!important;height:auto!important;display:block!important;overflow:visible!important;left:0!important;top:0!important;margin-left:0!important;margin-top:0!important;padding:60px 20px!important;z-index:auto!important;opacity:1!important;page-break-after:always!important;transform-style:flat!important;transform:none!important;transition:none!important}html:not(.print-pdf) .reveal .slides section.stack{padding:0!important}html:not(.print-pdf) .reveal section:last-of-type{page-break-after:avoid!important}html:not(.print-pdf) .reveal section .fragment{opacity:1!important;visibility:visible!important;transform:none!important}html:not(.print-pdf) .reveal .r-fit-text{white-space:normal!important}html:not(.print-pdf) .reveal section img{display:block;margin:15px 0;background:#fff;border:1px solid #666;box-shadow:none}html:not(.print-pdf) .reveal section small{font-size:.8em}html:not(.print-pdf) .reveal .hljs{max-height:100%;white-space:pre-wrap;word-wrap:break-word;word-break:break-word;font-size:15pt}html:not(.print-pdf) .reveal .hljs .hljs-ln-numbers{white-space:nowrap}html:not(.print-pdf) .reveal .hljs td{font-size:inherit!important;color:inherit!important}} -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/LICENSE: -------------------------------------------------------------------------------- 1 | SIL Open Font License 2 | 3 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 4 | 5 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 6 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 7 | 8 | —————————————————————————————- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | —————————————————————————————- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. 14 | 15 | The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. 16 | 17 | DEFINITIONS 18 | “Font Software” refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. 19 | 20 | “Reserved Font Name” refers to any names specified as such after the copyright statement(s). 21 | 22 | “Original Version” refers to the collection of Font Software components as distributed by the Copyright Holder(s). 23 | 24 | “Modified Version” refers to any derivative made by adding to, deleting, or substituting—in part or in whole—any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. 25 | 26 | “Author” refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. 27 | 28 | PERMISSION & CONDITIONS 29 | Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 30 | 31 | 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 32 | 33 | 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 34 | 35 | 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 36 | 37 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 38 | 39 | 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. 40 | 41 | TERMINATION 42 | This license becomes null and void if any of the above conditions are not met. 43 | 44 | DISCLAIMER 45 | THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-italic.eot -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-italic.ttf -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-italic.woff -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-regular.eot -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-regular.ttf -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-regular.woff -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibold.eot -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibold.ttf -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibold.woff -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.eot -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.ttf -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blokhin/materials-informatics-tutorial/51eb2c9bae5eefc992c17179f736a0a77ad4d14c/webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.woff -------------------------------------------------------------------------------- /webassets/reveal/theme/fonts/source-sans-pro/source-sans-pro.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Source Sans Pro'; 3 | src: url('./source-sans-pro-regular.eot'); 4 | src: url('./source-sans-pro-regular.eot?#iefix') format('embedded-opentype'), 5 | url('./source-sans-pro-regular.woff') format('woff'), 6 | url('./source-sans-pro-regular.ttf') format('truetype'); 7 | font-weight: normal; 8 | font-style: normal; 9 | } 10 | 11 | @font-face { 12 | font-family: 'Source Sans Pro'; 13 | src: url('./source-sans-pro-italic.eot'); 14 | src: url('./source-sans-pro-italic.eot?#iefix') format('embedded-opentype'), 15 | url('./source-sans-pro-italic.woff') format('woff'), 16 | url('./source-sans-pro-italic.ttf') format('truetype'); 17 | font-weight: normal; 18 | font-style: italic; 19 | } 20 | 21 | @font-face { 22 | font-family: 'Source Sans Pro'; 23 | src: url('./source-sans-pro-semibold.eot'); 24 | src: url('./source-sans-pro-semibold.eot?#iefix') format('embedded-opentype'), 25 | url('./source-sans-pro-semibold.woff') format('woff'), 26 | url('./source-sans-pro-semibold.ttf') format('truetype'); 27 | font-weight: 600; 28 | font-style: normal; 29 | } 30 | 31 | @font-face { 32 | font-family: 'Source Sans Pro'; 33 | src: url('./source-sans-pro-semibolditalic.eot'); 34 | src: url('./source-sans-pro-semibolditalic.eot?#iefix') format('embedded-opentype'), 35 | url('./source-sans-pro-semibolditalic.woff') format('woff'), 36 | url('./source-sans-pro-semibolditalic.ttf') format('truetype'); 37 | font-weight: 600; 38 | font-style: italic; 39 | } 40 | -------------------------------------------------------------------------------- /webassets/reveal/theme/reveal.css: -------------------------------------------------------------------------------- 1 | /** 2 | * White theme for reveal.js. This is the opposite of the 'black' theme. 3 | * 4 | * By Hakim El Hattab, http://hakim.se 5 | */ 6 | @import url(./fonts/source-sans-pro/source-sans-pro.css); 7 | section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { 8 | color: #fff; 9 | } 10 | 11 | /********************************************* 12 | * GLOBAL STYLES 13 | *********************************************/ 14 | :root { 15 | --r-background-color: #fff; 16 | --r-main-font: Source Sans Pro, Helvetica, sans-serif; 17 | --r-main-font-size: 42px; 18 | --r-main-color: #222; 19 | --r-block-margin: 20px; 20 | --r-heading-margin: 0 0 20px 0; 21 | --r-heading-font: Source Sans Pro, Helvetica, sans-serif; 22 | --r-heading-color: #222; 23 | --r-heading-line-height: 1.2; 24 | --r-heading-letter-spacing: normal; 25 | --r-heading-text-transform: uppercase; 26 | --r-heading-text-shadow: none; 27 | --r-heading-font-weight: 600; 28 | --r-heading1-text-shadow: none; 29 | --r-heading1-size: 2.5em; 30 | --r-heading2-size: 1.6em; 31 | --r-heading3-size: 1.3em; 32 | --r-heading4-size: 1em; 33 | --r-code-font: monospace; 34 | --r-link-color: #2a76dd; 35 | --r-link-color-dark: #1a53a1; 36 | --r-link-color-hover: #6ca0e8; 37 | --r-selection-background-color: #98bdef; 38 | --r-selection-color: #fff; 39 | } 40 | 41 | .reveal-viewport { 42 | background: #fff; 43 | background-color: var(--r-background-color); 44 | } 45 | 46 | .reveal { 47 | font-family: var(--r-main-font); 48 | font-size: var(--r-main-font-size); 49 | font-weight: normal; 50 | color: var(--r-main-color); 51 | } 52 | 53 | .reveal ::selection { 54 | color: var(--r-selection-color); 55 | background: var(--r-selection-background-color); 56 | text-shadow: none; 57 | } 58 | 59 | .reveal ::-moz-selection { 60 | color: var(--r-selection-color); 61 | background: var(--r-selection-background-color); 62 | text-shadow: none; 63 | } 64 | 65 | .reveal .slides section, 66 | .reveal .slides section > section { 67 | line-height: 1.3; 68 | font-weight: inherit; 69 | } 70 | 71 | /********************************************* 72 | * HEADERS 73 | *********************************************/ 74 | .reveal h1, 75 | .reveal h2, 76 | .reveal h3, 77 | .reveal h4, 78 | .reveal h5, 79 | .reveal h6 { 80 | margin: var(--r-heading-margin); 81 | color: var(--r-heading-color); 82 | font-family: var(--r-heading-font); 83 | font-weight: var(--r-heading-font-weight); 84 | line-height: var(--r-heading-line-height); 85 | letter-spacing: var(--r-heading-letter-spacing); 86 | text-transform: var(--r-heading-text-transform); 87 | text-shadow: var(--r-heading-text-shadow); 88 | word-wrap: break-word; 89 | } 90 | 91 | .reveal h1 { 92 | font-size: var(--r-heading1-size); 93 | } 94 | 95 | .reveal h2 { 96 | font-size: var(--r-heading2-size); 97 | } 98 | 99 | .reveal h3 { 100 | font-size: var(--r-heading3-size); 101 | } 102 | 103 | .reveal h4 { 104 | font-size: var(--r-heading4-size); 105 | } 106 | 107 | .reveal h1 { 108 | text-shadow: var(--r-heading1-text-shadow); 109 | } 110 | 111 | /********************************************* 112 | * OTHER 113 | *********************************************/ 114 | .reveal p { 115 | margin: var(--r-block-margin) 0; 116 | line-height: 1.3; 117 | } 118 | 119 | /* Remove trailing margins after titles */ 120 | .reveal h1:last-child, 121 | .reveal h2:last-child, 122 | .reveal h3:last-child, 123 | .reveal h4:last-child, 124 | .reveal h5:last-child, 125 | .reveal h6:last-child { 126 | margin-bottom: 0; 127 | } 128 | 129 | /* Ensure certain elements are never larger than the slide itself */ 130 | .reveal img, 131 | .reveal video, 132 | .reveal iframe { 133 | max-width: 95%; 134 | max-height: 95%; 135 | } 136 | 137 | .reveal strong, 138 | .reveal b { 139 | font-weight: bold; 140 | } 141 | 142 | .reveal em { 143 | font-style: italic; 144 | } 145 | 146 | .reveal ol, 147 | .reveal dl, 148 | .reveal ul { 149 | display: inline-block; 150 | text-align: left; 151 | margin: 0 0 0 1em; 152 | } 153 | 154 | .reveal ol { 155 | list-style-type: decimal; 156 | } 157 | 158 | .reveal ul { 159 | list-style-type: disc; 160 | } 161 | 162 | .reveal ul ul { 163 | list-style-type: square; 164 | } 165 | 166 | .reveal ul ul ul { 167 | list-style-type: circle; 168 | } 169 | 170 | .reveal ul ul, 171 | .reveal ul ol, 172 | .reveal ol ol, 173 | .reveal ol ul { 174 | display: block; 175 | margin-left: 40px; 176 | } 177 | 178 | .reveal dt { 179 | font-weight: bold; 180 | } 181 | 182 | .reveal dd { 183 | margin-left: 40px; 184 | } 185 | 186 | .reveal blockquote { 187 | display: block; 188 | position: relative; 189 | width: 70%; 190 | margin: var(--r-block-margin) auto; 191 | padding: 5px; 192 | font-style: italic; 193 | background: rgba(255, 255, 255, 0.05); 194 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); 195 | } 196 | 197 | .reveal blockquote p:first-child, 198 | .reveal blockquote p:last-child { 199 | display: inline-block; 200 | } 201 | 202 | .reveal q { 203 | font-style: italic; 204 | } 205 | 206 | .reveal pre { 207 | display: block; 208 | position: relative; 209 | width: 90%; 210 | margin: var(--r-block-margin) auto; 211 | text-align: left; 212 | font-size: 0.55em; 213 | font-family: var(--r-code-font); 214 | line-height: 1.2em; 215 | word-wrap: break-word; 216 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); 217 | } 218 | 219 | .reveal code { 220 | font-family: var(--r-code-font); 221 | text-transform: none; 222 | tab-size: 2; 223 | } 224 | 225 | .reveal pre code { 226 | display: block; 227 | padding: 5px; 228 | overflow: auto; 229 | max-height: 400px; 230 | word-wrap: normal; 231 | } 232 | 233 | .reveal .code-wrapper { 234 | white-space: normal; 235 | } 236 | 237 | .reveal .code-wrapper code { 238 | white-space: pre; 239 | } 240 | 241 | .reveal table { 242 | margin: auto; 243 | border-collapse: collapse; 244 | border-spacing: 0; 245 | } 246 | 247 | .reveal table th { 248 | font-weight: bold; 249 | } 250 | 251 | .reveal table th, 252 | .reveal table td { 253 | text-align: left; 254 | padding: 0.2em 0.5em 0.2em 0.5em; 255 | border-bottom: 1px solid; 256 | } 257 | 258 | .reveal table th[align=center], 259 | .reveal table td[align=center] { 260 | text-align: center; 261 | } 262 | 263 | .reveal table th[align=right], 264 | .reveal table td[align=right] { 265 | text-align: right; 266 | } 267 | 268 | .reveal table tbody tr:last-child th, 269 | .reveal table tbody tr:last-child td { 270 | border-bottom: none; 271 | } 272 | 273 | .reveal sup { 274 | vertical-align: super; 275 | font-size: smaller; 276 | } 277 | 278 | .reveal sub { 279 | vertical-align: sub; 280 | font-size: smaller; 281 | } 282 | 283 | .reveal small { 284 | display: inline-block; 285 | font-size: 0.6em; 286 | line-height: 1.2em; 287 | vertical-align: top; 288 | } 289 | 290 | .reveal small * { 291 | vertical-align: top; 292 | } 293 | 294 | .reveal img { 295 | margin: var(--r-block-margin) 0; 296 | } 297 | 298 | /********************************************* 299 | * LINKS 300 | *********************************************/ 301 | .reveal a { 302 | color: var(--r-link-color); 303 | text-decoration: none; 304 | transition: color 0.15s ease; 305 | } 306 | 307 | .reveal a:hover { 308 | color: var(--r-link-color-hover); 309 | text-shadow: none; 310 | border: none; 311 | } 312 | 313 | .reveal .roll span:after { 314 | color: #fff; 315 | background: var(--r-link-color-dark); 316 | } 317 | 318 | /********************************************* 319 | * Frame helper 320 | *********************************************/ 321 | .reveal .r-frame { 322 | border: 4px solid var(--r-main-color); 323 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 324 | } 325 | 326 | .reveal a .r-frame { 327 | transition: all 0.15s linear; 328 | } 329 | 330 | .reveal a:hover .r-frame { 331 | border-color: var(--r-link-color); 332 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); 333 | } 334 | 335 | /********************************************* 336 | * NAVIGATION CONTROLS 337 | *********************************************/ 338 | .reveal .controls { 339 | color: var(--r-link-color); 340 | } 341 | 342 | /********************************************* 343 | * PROGRESS BAR 344 | *********************************************/ 345 | .reveal .progress { 346 | background: rgba(0, 0, 0, 0.2); 347 | color: var(--r-link-color); 348 | } 349 | 350 | /********************************************* 351 | * PRINT BACKGROUND 352 | *********************************************/ 353 | @media print { 354 | .backgrounds { 355 | background-color: var(--r-background-color); 356 | } 357 | } -------------------------------------------------------------------------------- /webassets/reveal/theme/white.css: -------------------------------------------------------------------------------- 1 | /** 2 | * White theme for reveal.js. This is the opposite of the 'black' theme. 3 | * 4 | * By Hakim El Hattab, http://hakim.se 5 | */ 6 | @import url(./fonts/source-sans-pro/source-sans-pro.css); 7 | section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { 8 | color: #fff; 9 | } 10 | 11 | /********************************************* 12 | * GLOBAL STYLES 13 | *********************************************/ 14 | :root { 15 | --r-background-color: #fff; 16 | --r-main-font: Source Sans Pro, Helvetica, sans-serif; 17 | --r-main-font-size: 42px; 18 | --r-main-color: #222; 19 | --r-block-margin: 20px; 20 | --r-heading-margin: 0 0 20px 0; 21 | --r-heading-font: Source Sans Pro, Helvetica, sans-serif; 22 | --r-heading-color: #222; 23 | --r-heading-line-height: 1.2; 24 | --r-heading-letter-spacing: normal; 25 | --r-heading-text-transform: uppercase; 26 | --r-heading-text-shadow: none; 27 | --r-heading-font-weight: 600; 28 | --r-heading1-text-shadow: none; 29 | --r-heading1-size: 2.5em; 30 | --r-heading2-size: 1.6em; 31 | --r-heading3-size: 1.3em; 32 | --r-heading4-size: 1em; 33 | --r-code-font: monospace; 34 | --r-link-color: #2a76dd; 35 | --r-link-color-dark: #1a53a1; 36 | --r-link-color-hover: #6ca0e8; 37 | --r-selection-background-color: #98bdef; 38 | --r-selection-color: #fff; 39 | } 40 | 41 | .reveal-viewport { 42 | background: #fff; 43 | background-color: var(--r-background-color); 44 | } 45 | 46 | .reveal { 47 | font-family: var(--r-main-font); 48 | font-size: var(--r-main-font-size); 49 | font-weight: normal; 50 | color: var(--r-main-color); 51 | } 52 | 53 | .reveal ::selection { 54 | color: var(--r-selection-color); 55 | background: var(--r-selection-background-color); 56 | text-shadow: none; 57 | } 58 | 59 | .reveal ::-moz-selection { 60 | color: var(--r-selection-color); 61 | background: var(--r-selection-background-color); 62 | text-shadow: none; 63 | } 64 | 65 | .reveal .slides section, 66 | .reveal .slides section > section { 67 | line-height: 1.3; 68 | font-weight: inherit; 69 | } 70 | 71 | /********************************************* 72 | * HEADERS 73 | *********************************************/ 74 | .reveal h1, 75 | .reveal h2, 76 | .reveal h3, 77 | .reveal h4, 78 | .reveal h5, 79 | .reveal h6 { 80 | margin: var(--r-heading-margin); 81 | color: var(--r-heading-color); 82 | font-family: var(--r-heading-font); 83 | font-weight: var(--r-heading-font-weight); 84 | line-height: var(--r-heading-line-height); 85 | letter-spacing: var(--r-heading-letter-spacing); 86 | text-transform: var(--r-heading-text-transform); 87 | text-shadow: var(--r-heading-text-shadow); 88 | word-wrap: break-word; 89 | } 90 | 91 | .reveal h1 { 92 | font-size: var(--r-heading1-size); 93 | } 94 | 95 | .reveal h2 { 96 | font-size: var(--r-heading2-size); 97 | } 98 | 99 | .reveal h3 { 100 | font-size: var(--r-heading3-size); 101 | } 102 | 103 | .reveal h4 { 104 | font-size: var(--r-heading4-size); 105 | } 106 | 107 | .reveal h1 { 108 | text-shadow: var(--r-heading1-text-shadow); 109 | } 110 | 111 | /********************************************* 112 | * OTHER 113 | *********************************************/ 114 | .reveal p { 115 | margin: var(--r-block-margin) 0; 116 | line-height: 1.3; 117 | } 118 | 119 | /* Remove trailing margins after titles */ 120 | .reveal h1:last-child, 121 | .reveal h2:last-child, 122 | .reveal h3:last-child, 123 | .reveal h4:last-child, 124 | .reveal h5:last-child, 125 | .reveal h6:last-child { 126 | margin-bottom: 0; 127 | } 128 | 129 | /* Ensure certain elements are never larger than the slide itself */ 130 | .reveal img, 131 | .reveal video, 132 | .reveal iframe { 133 | max-width: 95%; 134 | max-height: 95%; 135 | } 136 | 137 | .reveal strong, 138 | .reveal b { 139 | font-weight: bold; 140 | } 141 | 142 | .reveal em { 143 | font-style: italic; 144 | } 145 | 146 | .reveal ol, 147 | .reveal dl, 148 | .reveal ul { 149 | display: inline-block; 150 | text-align: left; 151 | margin: 0 0 0 1em; 152 | } 153 | 154 | .reveal ol { 155 | list-style-type: decimal; 156 | } 157 | 158 | .reveal ul { 159 | list-style-type: disc; 160 | } 161 | 162 | .reveal ul ul { 163 | list-style-type: square; 164 | } 165 | 166 | .reveal ul ul ul { 167 | list-style-type: circle; 168 | } 169 | 170 | .reveal ul ul, 171 | .reveal ul ol, 172 | .reveal ol ol, 173 | .reveal ol ul { 174 | display: block; 175 | margin-left: 40px; 176 | } 177 | 178 | .reveal dt { 179 | font-weight: bold; 180 | } 181 | 182 | .reveal dd { 183 | margin-left: 40px; 184 | } 185 | 186 | .reveal blockquote { 187 | display: block; 188 | position: relative; 189 | width: 70%; 190 | margin: var(--r-block-margin) auto; 191 | padding: 5px; 192 | font-style: italic; 193 | background: rgba(255, 255, 255, 0.05); 194 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); 195 | } 196 | 197 | .reveal blockquote p:first-child, 198 | .reveal blockquote p:last-child { 199 | display: inline-block; 200 | } 201 | 202 | .reveal q { 203 | font-style: italic; 204 | } 205 | 206 | .reveal pre { 207 | display: block; 208 | position: relative; 209 | width: 90%; 210 | margin: var(--r-block-margin) auto; 211 | text-align: left; 212 | font-size: 0.55em; 213 | font-family: var(--r-code-font); 214 | line-height: 1.2em; 215 | word-wrap: break-word; 216 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); 217 | } 218 | 219 | .reveal code { 220 | font-family: var(--r-code-font); 221 | text-transform: none; 222 | tab-size: 2; 223 | } 224 | 225 | .reveal pre code { 226 | display: block; 227 | padding: 5px; 228 | overflow: auto; 229 | max-height: 400px; 230 | word-wrap: normal; 231 | } 232 | 233 | .reveal .code-wrapper { 234 | white-space: normal; 235 | } 236 | 237 | .reveal .code-wrapper code { 238 | white-space: pre; 239 | } 240 | 241 | .reveal table { 242 | margin: auto; 243 | border-collapse: collapse; 244 | border-spacing: 0; 245 | } 246 | 247 | .reveal table th { 248 | font-weight: bold; 249 | } 250 | 251 | .reveal table th, 252 | .reveal table td { 253 | text-align: left; 254 | padding: 0.2em 0.5em 0.2em 0.5em; 255 | border-bottom: 1px solid; 256 | } 257 | 258 | .reveal table th[align=center], 259 | .reveal table td[align=center] { 260 | text-align: center; 261 | } 262 | 263 | .reveal table th[align=right], 264 | .reveal table td[align=right] { 265 | text-align: right; 266 | } 267 | 268 | .reveal table tbody tr:last-child th, 269 | .reveal table tbody tr:last-child td { 270 | border-bottom: none; 271 | } 272 | 273 | .reveal sup { 274 | vertical-align: super; 275 | font-size: smaller; 276 | } 277 | 278 | .reveal sub { 279 | vertical-align: sub; 280 | font-size: smaller; 281 | } 282 | 283 | .reveal small { 284 | display: inline-block; 285 | font-size: 0.6em; 286 | line-height: 1.2em; 287 | vertical-align: top; 288 | } 289 | 290 | .reveal small * { 291 | vertical-align: top; 292 | } 293 | 294 | .reveal img { 295 | margin: var(--r-block-margin) 0; 296 | } 297 | 298 | /********************************************* 299 | * LINKS 300 | *********************************************/ 301 | .reveal a { 302 | color: var(--r-link-color); 303 | text-decoration: none; 304 | transition: color 0.15s ease; 305 | } 306 | 307 | .reveal a:hover { 308 | color: var(--r-link-color-hover); 309 | text-shadow: none; 310 | border: none; 311 | } 312 | 313 | .reveal .roll span:after { 314 | color: #fff; 315 | background: var(--r-link-color-dark); 316 | } 317 | 318 | /********************************************* 319 | * Frame helper 320 | *********************************************/ 321 | .reveal .r-frame { 322 | border: 4px solid var(--r-main-color); 323 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 324 | } 325 | 326 | .reveal a .r-frame { 327 | transition: all 0.15s linear; 328 | } 329 | 330 | .reveal a:hover .r-frame { 331 | border-color: var(--r-link-color); 332 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); 333 | } 334 | 335 | /********************************************* 336 | * NAVIGATION CONTROLS 337 | *********************************************/ 338 | .reveal .controls { 339 | color: var(--r-link-color); 340 | } 341 | 342 | /********************************************* 343 | * PROGRESS BAR 344 | *********************************************/ 345 | .reveal .progress { 346 | background: rgba(0, 0, 0, 0.2); 347 | color: var(--r-link-color); 348 | } 349 | 350 | /********************************************* 351 | * PRINT BACKGROUND 352 | *********************************************/ 353 | @media print { 354 | .backgrounds { 355 | background-color: var(--r-background-color); 356 | } 357 | } --------------------------------------------------------------------------------