[pypy-commit] pypy.org nikola: add plugin to import blogger xml export; bring in css from web-pypy

mattip pypy.commits at gmail.com
Mon Dec 30 08:32:03 EST 2019


Author: Matti Picus <matti.picus at gmail.com>
Branch: nikola
Changeset: r967:0594e0c3b286
Date: 2019-12-29 18:29 +0200
http://bitbucket.org/pypy/pypy.org/changeset/0594e0c3b286/

Log:	add plugin to import blogger xml export; bring in css from web-pypy

diff too long, truncating to 2000 out of 2163 lines

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -3,18 +3,42 @@
 endif
 .RECIPEPREFIX = >
 
-.PHONY: clean build help
+all: build
+
+.PHONY: clean build help import_blogger
+
 
 venv_nikola/bin/nikola:  ## create a virtualenv to build the website
-> virtualenv -ppython3 ./venv_nikola
-> venv_nikola/bin/python -mpip install nikola==8.0.3 jinja2
+> @virtualenv -ppython3 ./venv_nikola
+> @venv_nikola/bin/python -mpip install nikola==8.0.3 jinja2 aiohttp watchdog
+
+plugins/import_blogger: venv_nikola/bin/nikola
+> venv_nikola/bin/nikola plugin -i import_blogger
+> venv_nikola/bin/pip install feedparser
 
 build: venv_nikola/bin/nikola  ## build the website if needed, the result is in ./public
 > venv_nikola/bin/nikola build
 
+auto: venv_nikola/bin/nikola ## build and serve the website, autoupdate on changes
+> venv_nikola/bin/nikola auto
+
 clean:  venv_nikola/bin/nikola  ## clean the website, usually not needed at all
 > venv_nikola/bin/nikola clean
 
+import_blogger: plugins/import_blogger  ## download and import the content from morepypy.blogspot.com
+> @if [ -z "${BLOGGER_XML}" ] || [ ! -s "${BLOGGER_XML}" ]; then \
+     echo "ERROR: BLOGGER_XML not defined or not a file"; \
+     echo "    Log into www.blogger.com, go to the morepypy settings,"; \
+     echo "    settings -> other -> Import & back up -> Back up content"; \
+     echo "    save to a location, then rerun this as"; \
+     echo "    \"BLOGGER_XML=location make import_blogger\""; \
+     exit 255; \
+  fi
+> @echo "\nImporting from ${BLOGGER_XML}"
+# TODO: improve import script with --export-comments (see static_comments plugin)
+> venv_nikola/bin/nikola import_blogger -o . -d ${BLOGGER_XML}
+> @echo Done. Don\'t forget to build the site
+
 # Add help text after each target name starting with '\#\#'
 help:   ## Show this help.
 > @echo "\nHelp for building the website, based on nikola"
diff --git a/conf.py b/conf.py
--- a/conf.py
+++ b/conf.py
@@ -139,7 +139,7 @@
 
 NAVIGATION_LINKS = {
     DEFAULT_LANG: (
-        ('/index.html', 'Home'),
+        ('/index.html', '<image src="images/pypy-logo-nav.png" alt=PyPy/>'),
         ('/features.html', 'What is PyPy?'),
         ('/download.html', 'Download'),
         ('/compat.html', 'Compatibility'),
@@ -224,9 +224,9 @@
 #     )
 
 POSTS = (
+    ("posts/*.txt", "posts", "post.tmpl"),
     ("posts/*.rst", "posts", "post.tmpl"),
     ("posts/*.md", "posts", "post.tmpl"),
-    ("posts/*.txt", "posts", "post.tmpl"),
     ("posts/*.html", "posts", "post.tmpl"),
 )
 PAGES = (
@@ -350,7 +350,6 @@
 # Final output is <img src="LOGO_URL" id="logo" alt="BLOG_TITLE">.
 # The URL may be relative to the site root.
 # LOGO_URL = ''
-LOGO_URL = 'images/pypy-logo.png'
 
 # If you want to hide the title of your website (for example, if your logo
 # already contains the text), set this to False.
@@ -663,7 +662,7 @@
 # Where the output site should be located
 # If you don't use an absolute path, it will be considered as relative
 # to the location of conf.py
-#OUTPUT_FOLDER = 'output'
+# OUTPUT_FOLDER = 'output'
 OUTPUT_FOLDER = 'public'
 
 # where the "cache" of partial generated content should be located
@@ -896,11 +895,10 @@
 # FAVICONS contains (name, file, size) tuples.
 # Used to create favicon link like this:
 # <link rel="name" href="file" sizes="size"/>
-#FAVICONS = (
+# FAVICONS = (
 #     ("icon", "/favicon.ico", "16x16"),
 #     ("icon", "/icon_128x128.png", "128x128"),
-#      ("shortcut icon", "/favicon.ico", "16x16"),
-#)
+# )
 
 # Show teasers (instead of full posts) in indexes? Defaults to False.
 # INDEX_TEASERS = False
@@ -1298,6 +1296,7 @@
 # environment but is not recommended for HTTP/2.0 when caching is used.
 # Defaults to True.
 # USE_BUNDLES = True
+USE_BUNDLES = False
 
 # Plugins you don't want to use. Be careful :-)
 # DISABLED_PLUGINS = ["render_galleries"]
diff --git a/files/favicon.ico b/files/favicon.ico
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..00cf381e7e01e4603affa3da5a27d99b17943bc0
GIT binary patch

[cut]

diff --git a/image/pypy-logo-nav.png b/image/pypy-logo-nav.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a148179fdec1a217eea30534a8790214e8d3ad9e
GIT binary patch

[cut]

diff --git a/pages/download.rst b/pages/download.rst
--- a/pages/download.rst
+++ b/pages/download.rst
@@ -427,6 +427,8 @@
     eac1308b7d523003a5f6d20f58406d52ab14611bcec750122ae513a5a35110db  pypy2.7-v7.3.0-linux32.tar.bz2
     f4950a54378ac637da2a6defa52d6ffed96af12fcd5d74e1182fb834883c9826  pypy2.7-v7.3.0-linux64.tar.bz2
     ca7b056b243a6221ad04fa7fc8696e36a2fb858396999dcaa31dbbae53c54474  pypy2.7-v7.3.0-osx64.tar.bz2
+    82e62869812aa2953a4f83e96c813cbc52973dfa5e42605e72b6610ac13f2481  pypy2.7-v7.3.0-ppc64.tar.bz2
+    592a6db77270b922ffa13cbeced9eabbc36c532ded9fc145f6a19073d3e78499  pypy2.7-v7.3.0-ppc64le.tar.bz2
     d254b82a00021339762198e41ba7f72316010d0f9bd4dcd7b0755185da9c005e  pypy2.7-v7.3.0-s390x.tar.bz2
     b0b25c7f8938ab0fedd8dedf26b9e73c490913b002b484c1b2f19d5844a518de  pypy2.7-v7.3.0-src.tar.bz2
     42dc84a277e7a5e635fe39bbd745f06135902c229a257123332b7555800d915b  pypy2.7-v7.3.0-src.zip
@@ -438,6 +440,8 @@
     7045b295d38ba0b5ee65bd3f078ca249fcf1de73fedeaab2d6ad78de2eab0f0e  pypy3.6-v7.3.0-linux32.tar.bz2
     d3d549e8f43de820ac3385b698b83fa59b4d7dd6cf3fe34c115f731e26ad8856  pypy3.6-v7.3.0-linux64.tar.bz2
     87b2545dad75fe3027b4b2108aceb9fdadcdd24e61ae312ac48b449fdd452bf3  pypy3.6-v7.3.0-osx64.tar.bz2
+    e2587e8da2abb12a86bf75941ce739124d2a1156367a9a3d729ac31d0841c300  pypy3.6-v7.3.0-ppc64.tar.bz2
+    d6f3b701313df69483b43ebdd21b9652ae5e808b2eea5fbffe3b74b82d2e7433  pypy3.6-v7.3.0-ppc64le.tar.bz2
     0fe2f7bbf42ea88b40954d7de773a43179a44f40656f2f58201524be70699544  pypy3.6-v7.3.0-s390x.tar.bz2
     48d12c15fbcbcf4a32882a883195e1f922997cde78e7a16d4342b9b521eefcfa  pypy3.6-v7.3.0-src.tar.bz2
     8ae9efd0a2aadb19e892bbd07eca8ef51536296a3ef93964149aceba511e79ca  pypy3.6-v7.3.0-src.zip
diff --git a/pages/features.rst b/pages/features.rst
--- a/pages/features.rst
+++ b/pages/features.rst
@@ -6,9 +6,6 @@
 .. link: 
 .. description: 
 
-What is PyPy?
-===========================================================
-
 PyPy is a replacement for CPython.  It is built using the RPython
 language that was co-developed with it.  The main reason to use it
 instead of CPython is speed: it runs generally faster (see next section).
diff --git a/plugins/__init__.py b/plugins/__init__.py
new file mode 100644
--- /dev/null
+++ b/plugins/__init__.py
@@ -0,0 +1,1 @@
+# Plugin modules go here.
\ No newline at end of file
diff --git a/plugins/import_blogger/README.md b/plugins/import_blogger/README.md
new file mode 100644
--- /dev/null
+++ b/plugins/import_blogger/README.md
@@ -0,0 +1,16 @@
+This plugin will do a quick and dirty import of your Blogger site.
+
+To use it if you already have a Nikola site:
+
+```
+$ nikola plugin -i import_blogger
+$ nikola import_blogger your_blogger_dump_file
+```
+
+To use it if you don't already have a Nikola site:
+
+```
+$ nikola plugin -i import_blogger --user
+$ nikola import_blogger -o output_folder your_blogger_dump_file 
+```
+
diff --git a/plugins/import_blogger/import_blogger.plugin b/plugins/import_blogger/import_blogger.plugin
new file mode 100644
--- /dev/null
+++ b/plugins/import_blogger/import_blogger.plugin
@@ -0,0 +1,12 @@
+[Core]
+Name = import_blogger
+Module = import_blogger
+
+[Nikola]
+PluginCategory = Command
+
+[Documentation]
+Author = Roberto Alsina
+Version = 0.3
+Website = http://plugins.getnikola.com/#import_blogger
+Description = Import a blogger site from a XML dump.
diff --git a/plugins/import_blogger/import_blogger.py b/plugins/import_blogger/import_blogger.py
new file mode 100644
--- /dev/null
+++ b/plugins/import_blogger/import_blogger.py
@@ -0,0 +1,234 @@
+# -*- coding: utf-8 -*-
+
+# Copyright © 2012-2014 Roberto Alsina and others.
+
+# Permission is hereby granted, free of charge, to any
+# person obtaining a copy of this software and associated
+# documentation files (the "Software"), to deal in the
+# Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the
+# Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice
+# shall be included in all copies or substantial portions of
+# the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import print_function, unicode_literals
+
+import datetime
+import os
+import time
+
+
+try:
+    from urlparse import urlparse
+except ImportError:
+    from urllib.parse import urlparse  # NOQA
+
+try:
+    import feedparser
+except ImportError:
+    feedparser = None  # NOQA
+
+from nikola.plugin_categories import Command
+from nikola import utils
+from nikola.utils import req_missing
+from nikola.plugins.basic_import import ImportMixin
+from nikola.plugins.command.init import SAMPLE_CONF, prepare_config
+
+LOGGER = utils.get_logger('import_blogger', utils.STDERR_HANDLER)
+
+
+class CommandImportBlogger(Command, ImportMixin):
+    """Import a blogger dump."""
+
+    name = "import_blogger"
+    needs_config = False
+    doc_usage = "[options] blogger_export_file"
+    doc_purpose = "import a blogger dump"
+    cmd_options = ImportMixin.cmd_options + [
+        {
+            'name': 'exclude_drafts',
+            'long': 'no-drafts',
+            'short': 'd',
+            'default': False,
+            'type': bool,
+            'help': "Don't import drafts",
+        },
+    ]
+
+    def _execute(self, options, args):
+        """Import a Blogger blog from an export file into a Nikola site."""
+        # Parse the data
+        if feedparser is None:
+            req_missing(['feedparser'], 'import Blogger dumps')
+            return
+
+        if not args:
+            print(self.help())
+            return
+
+        options['filename'] = args[0]
+        self.blogger_export_file = options['filename']
+        self.output_folder = options['output_folder']
+        self.import_into_existing_site = False
+        self.exclude_drafts = options['exclude_drafts']
+        self.url_map = {}
+        channel = self.get_channel_from_file(self.blogger_export_file)
+        self.context = self.populate_context(channel)
+        conf_template = self.generate_base_site()
+        self.context['REDIRECTIONS'] = self.configure_redirections(
+            self.url_map)
+
+        self.import_posts(channel)
+        self.write_urlmap_csv(
+            os.path.join(self.output_folder, 'url_map.csv'), self.url_map)
+
+        conf_out_path = self.get_configuration_output_path()
+        # if it tracebacks here, look a comment in
+        # basic_import.Import_Mixin.generate_base_site
+        conf_template_render = conf_template.render(**prepare_config(self.context))
+        self.write_configuration(conf_out_path, conf_template_render)
+
+    @classmethod
+    def get_channel_from_file(cls, filename):
+        if not os.path.isfile(filename):
+            raise Exception("Missing file: %s" % filename)
+        return feedparser.parse(filename)
+
+    @staticmethod
+    def populate_context(channel):
+        context = SAMPLE_CONF.copy()
+        # blogger doesn't include the language in the dump
+        context['DEFAULT_LANG'] = 'en'
+        context['BLOG_TITLE'] = channel.feed.title
+
+        context['BLOG_DESCRIPTION'] = ''  # Missing in the dump
+        if not channel.feed.link.endswith('/'):
+            context['SITE_URL'] = channel.feed.link + '/'
+        else:
+            context['SITE_URL'] = channel.feed.link
+
+        context['BLOG_EMAIL'] = channel.feed.author_detail.email
+        context['BLOG_AUTHOR'] = channel.feed.author_detail.name
+        context['POSTS'] = '''(
+            ("posts/*.txt", "posts", "post.tmpl"),
+            ("posts/*.rst", "posts", "post.tmpl"),
+            ("posts/*.html", "posts", "post.tmpl"),
+            )'''
+        context['PAGES'] = '''(
+            ("articles/*.txt", "articles", "story.tmpl"),
+            ("articles/*.rst", "articles", "story.tmpl"),
+            )'''
+        context['COMPILERS'] = '''{
+            "rest": ('.txt', '.rst'),
+            "markdown": ('.md', '.mdown', '.markdown', '.wp'),
+            "html": ('.html', '.htm')
+            }
+            '''
+
+        return context
+
+    def import_item(self, item, out_folder=None):
+        """Takes an item from the feed and creates a post file."""
+        if out_folder is None:
+            out_folder = 'posts'
+
+        # link is something like http://foo.com/2012/09/01/hello-world/
+        # So, take the path, utils.slugify it, and that's our slug
+        link = item.link
+        link_path = urlparse(link).path
+
+        title = item.title
+
+        # blogger supports empty titles, which Nikola doesn't
+        if not title:
+            LOGGER.warn("Empty title in post with URL {0}. Using NO_TITLE "
+                        "as placeholder, please fix.".format(link))
+            title = "NO_TITLE"
+
+        if link_path.lower().endswith('.html'):
+            link_path = link_path[:-5]
+        link_path = link_path.lstrip('/')
+
+        out_path = os.path.join(self.output_folder, out_folder, link_path)
+        link_fragments = link_path.split('/')
+        slug = utils.slugify(link_fragments[-1])
+
+        if not slug:  # should never happen
+            LOGGER.error("Error converting post:", title)
+            return
+
+        description = ''
+        post_date = datetime.datetime.fromtimestamp(time.mktime(
+            item.published_parsed))
+
+        for candidate in item.content:
+            if candidate.type == 'text/html':
+                content = candidate.value
+                break
+                #  FIXME: handle attachments
+
+        tags = []
+        for tag in item.tags:
+            if tag.scheme == 'http://www.blogger.com/atom/ns#':
+                tags.append(tag.term)
+
+        if item.get('app_draft'):
+            tags.append('draft')
+            is_draft = True
+        else:
+            is_draft = False
+
+        self.url_map[link] = (self.context['SITE_URL'] + out_folder + '/' + link_path + '.html')
+        if is_draft and self.exclude_drafts:
+            LOGGER.notice('Draft "{0}" will not be imported.'.format(title))
+        elif content.strip():
+            # If no content is found, no files are written.
+            content = self.transform_content(content)
+
+            self.write_metadata(
+                out_path + '.meta', title, slug, post_date, description, tags
+            )
+            self.write_content(out_path + '.html', content)
+        else:
+            LOGGER.warn('Not going to import "{0}" because it seems to contain'
+                        ' no content.'.format(title))
+
+    POST_TYPE_SCHEMAS = {
+        'http://schemas.google.com/blogger/2008/kind#post': 'posts',
+        'http://schemas.google.com/blogger/2008/kind#page': 'pages',
+        'http://schemas.google.com/blogger/2008/kind#settings': '',
+        'http://schemas.google.com/blogger/2008/kind#template': '',
+        'http://schemas.google.com/blogger/2008/kind#comment': '',
+    }
+
+    def process_item(self, item):
+        terms = set([tag.term for tag in item.tags])
+        post_types = terms & set(self.POST_TYPE_SCHEMAS.keys())
+
+        if not post_types:
+            LOGGER.warn("Unknown post_type for {0}".format(item.title))
+
+        elif len(post_types) == 1:
+            out_folder = self.POST_TYPE_SCHEMAS[post_types.pop()]
+            if out_folder:
+                self.import_item(item, out_folder)
+
+        else:
+            LOGGER.warn("Too many post_types for {0}".format(item.title))
+
+    def import_posts(self, channel):
+        for item in channel.entries:
+            self.process_item(item)
diff --git a/themes/pypy/assets/css/styles.css b/themes/pypy/assets/css/styles.css
new file mode 100644
--- /dev/null
+++ b/themes/pypy/assets/css/styles.css
@@ -0,0 +1,1387 @@
+/*! sanitize.css v8.0.0 | CC0 License | github.com/csstools/sanitize.css */
+*,
+::before,
+::after {
+  background-repeat: no-repeat;
+  box-sizing: border-box; }
+
+::before,
+::after {
+  text-decoration: inherit;
+  vertical-align: inherit; }
+
+html {
+  cursor: default;
+  font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+  line-height: 1.15;
+  -moz-tab-size: 4;
+  tab-size: 4;
+  -ms-text-size-adjust: 100%;
+  -webkit-text-size-adjust: 100%;
+  word-break: break-word; }
+
+body {
+  margin: 0; }
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0; }
+
+hr {
+  height: 0;
+  overflow: visible; }
+
+main {
+  display: block; }
+
+nav ol,
+nav ul {
+  list-style: none; }
+
+pre {
+  font-family: Menlo, Consolas, Roboto Mono, Ubuntu Monospace, Noto Mono, Oxygen Mono, Liberation Mono, monospace;
+  font-size: 1em; }
+
+a {
+  background-color: transparent; }
+
+abbr[title] {
+  text-decoration: underline;
+  text-decoration: underline dotted; }
+
+b,
+strong {
+  font-weight: bolder; }
+
+code,
+kbd,
+samp {
+  font-family: Menlo, Consolas, Roboto Mono, Ubuntu Monospace, Noto Mono, Oxygen Mono, Liberation Mono, monospace;
+  font-size: 1em; }
+
+small {
+  font-size: 80%; }
+
+::-moz-selection {
+  background-color: #b3d4fc;
+  color: #000;
+  text-shadow: none; }
+
+::selection {
+  background-color: #b3d4fc;
+  color: #000;
+  text-shadow: none; }
+
+audio,
+canvas,
+iframe,
+img,
+svg,
+video {
+  vertical-align: middle; }
+
+audio,
+video {
+  display: inline-block; }
+
+audio:not([controls]) {
+  display: none;
+  height: 0; }
+
+img {
+  border-style: none; }
+
+svg:not([fill]) {
+  fill: currentColor; }
+
+svg:not(:root) {
+  overflow: hidden; }
+
+table {
+  border-collapse: collapse; }
+
+button,
+input,
+select,
+textarea {
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit; }
+
+button,
+input,
+select {
+  margin: 0; }
+
+button {
+  overflow: visible;
+  text-transform: none; }
+
+button,
+[type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button; }
+
+fieldset {
+  padding: 0.35em 0.75em 0.625em; }
+
+input {
+  overflow: visible; }
+
+legend {
+  color: inherit;
+  display: table;
+  max-width: 100%;
+  white-space: normal; }
+
+progress {
+  display: inline-block;
+  vertical-align: baseline; }
+
+select {
+  text-transform: none; }
+
+textarea {
+  margin: 0;
+  overflow: auto;
+  resize: vertical; }
+
+[type="checkbox"],
+[type="radio"] {
+  padding: 0; }
+
+[type="search"] {
+  -webkit-appearance: textfield;
+  outline-offset: -2px; }
+
+::-webkit-inner-spin-button,
+::-webkit-outer-spin-button {
+  height: auto; }
+
+::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.54; }
+
+::-webkit-search-decoration {
+  -webkit-appearance: none; }
+
+::-webkit-file-upload-button {
+  -webkit-appearance: button;
+  font: inherit; }
+
+::-moz-focus-inner {
+  border-style: none;
+  padding: 0; }
+
+:-moz-focusring {
+  outline: 1px dotted ButtonText; }
+
+details {
+  display: block; }
+
+dialog {
+  background-color: white;
+  border: solid;
+  color: black;
+  display: block;
+  height: -moz-fit-content;
+  height: -webkit-fit-content;
+  height: fit-content;
+  left: 0;
+  margin: auto;
+  padding: 1em;
+  position: absolute;
+  right: 0;
+  width: -moz-fit-content;
+  width: -webkit-fit-content;
+  width: fit-content; }
+
+dialog:not([open]) {
+  display: none; }
+
+summary {
+  display: list-item; }
+
+canvas {
+  display: inline-block; }
+
+template {
+  display: none; }
+
+a,
+area,
+button,
+input,
+label,
+select,
+summary,
+textarea,
+[tabindex] {
+  -ms-touch-action: manipulation;
+  touch-action: manipulation; }
+
+[hidden] {
+  display: none; }
+
+[aria-busy="true"] {
+  cursor: progress; }
+
+[aria-controls] {
+  cursor: pointer; }
+
+[aria-disabled="true"],
+[disabled] {
+  cursor: not-allowed; }
+
+[aria-hidden="false"][hidden]:not(:focus) {
+  clip: rect(0, 0, 0, 0);
+  display: inherit;
+  position: absolute; }
+
+/*! Based on https://github.com/milligram/milligram */
+*,
+*:after,
+*:before {
+  box-sizing: inherit; }
+
+html {
+  box-sizing: border-box;
+  font-size: 62.5%; }
+
+body {
+  font-size: 1.6em;
+  font-weight: 300;
+  letter-spacing: .01em;
+  line-height: 1.6;
+  background-color: #fcfcfc; }
+
+body {
+  color: #4B545C;
+  font-family: 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; }
+
+b,
+strong {
+  font-weight: bold; }
+
+p {
+  margin-top: 0; }
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  font-weight: 300;
+  letter-spacing: -.1rem;
+  margin-bottom: 2.0rem;
+  margin-top: 0; }
+
+h1 {
+  font-size: 4.6rem;
+  line-height: 1.2; }
+
+h2 {
+  font-size: 3.6rem;
+  line-height: 1.25; }
+
+h3 {
+  font-size: 2.8rem;
+  line-height: 1.3; }
+
+h4 {
+  font-size: 2.2rem;
+  letter-spacing: -.08rem;
+  line-height: 1.35; }
+
+h5 {
+  font-size: 1.8rem;
+  letter-spacing: -.05rem;
+  line-height: 1.5; }
+
+h6 {
+  font-size: 1.6rem;
+  letter-spacing: 0;
+  line-height: 1.4; }
+
+blockquote {
+  border-left: 0.3rem solid #d1d1d1;
+  margin-left: 0;
+  margin-right: 0;
+  padding: 1rem 1.5rem; }
+  blockquote *:last-child {
+    margin-bottom: 0; }
+
+.button,
+button,
+input[type='button'],
+input[type='reset'],
+input[type='submit'] {
+  background-color: #1890ff;
+  border: 0.1rem solid #1890ff;
+  border-radius: .4rem;
+  color: #fcfcfc;
+  cursor: pointer;
+  display: inline-block;
+  font-size: 1.1rem;
+  font-weight: 700;
+  height: 3.8rem;
+  letter-spacing: .1rem;
+  line-height: 3.8rem;
+  padding: 0 3.0rem;
+  text-align: center;
+  text-decoration: none;
+  text-transform: uppercase;
+  white-space: nowrap;
+  -webkit-box-shadow: 0px 5px 10px 0px rgba(24, 144, 255, 0.2);
+    -webkit-box-shadow--moz-box-shadow: 0px 5px 10px 0px rgba(24, 144, 255, 0.2);
+    -webkit-box-shadow-box-shadow: 0px 5px 10px 0px rgba(24, 144, 255, 0.2); }
+  .button:focus, .button:hover,
+  button:focus,
+  button:hover,
+  input[type='button']:focus,
+  input[type='button']:hover,
+  input[type='reset']:focus,
+  input[type='reset']:hover,
+  input[type='submit']:focus,
+  input[type='submit']:hover {
+    background-color: #4B545C;
+    border-color: #4B545C;
+    color: #fcfcfc;
+    outline: 0;
+    -webkit-box-shadow: 0px 5px 10px 0px rgba(75, 84, 92, 0.2);
+      -webkit-box-shadow--moz-box-shadow: 0px 5px 10px 0px rgba(75, 84, 92, 0.2);
+      -webkit-box-shadow-box-shadow: 0px 5px 10px 0px rgba(75, 84, 92, 0.2); }
+  .button[disabled],
+  button[disabled],
+  input[type='button'][disabled],
+  input[type='reset'][disabled],
+  input[type='submit'][disabled] {
+    cursor: default;
+    opacity: .5; }
+    .button[disabled]:focus, .button[disabled]:hover,
+    button[disabled]:focus,
+    button[disabled]:hover,
+    input[type='button'][disabled]:focus,
+    input[type='button'][disabled]:hover,
+    input[type='reset'][disabled]:focus,
+    input[type='reset'][disabled]:hover,
+    input[type='submit'][disabled]:focus,
+    input[type='submit'][disabled]:hover {
+      background-color: #1890ff;
+      border-color: #1890ff; }
+  .button.button-outline,
+  button.button-outline,
+  input[type='button'].button-outline,
+  input[type='reset'].button-outline,
+  input[type='submit'].button-outline {
+    background-color: transparent;
+    color: #1890ff; }
+    .button.button-outline:focus, .button.button-outline:hover,
+    button.button-outline:focus,
+    button.button-outline:hover,
+    input[type='button'].button-outline:focus,
+    input[type='button'].button-outline:hover,
+    input[type='reset'].button-outline:focus,
+    input[type='reset'].button-outline:hover,
+    input[type='submit'].button-outline:focus,
+    input[type='submit'].button-outline:hover {
+      background-color: transparent;
+      border-color: #4B545C;
+      color: #4B545C; }
+    .button.button-outline[disabled]:focus, .button.button-outline[disabled]:hover,
+    button.button-outline[disabled]:focus,
+    button.button-outline[disabled]:hover,
+    input[type='button'].button-outline[disabled]:focus,
+    input[type='button'].button-outline[disabled]:hover,
+    input[type='reset'].button-outline[disabled]:focus,
+    input[type='reset'].button-outline[disabled]:hover,
+    input[type='submit'].button-outline[disabled]:focus,
+    input[type='submit'].button-outline[disabled]:hover {
+      border-color: inherit;
+      color: #1890ff; }
+  .button.button-clear,
+  button.button-clear,
+  input[type='button'].button-clear,
+  input[type='reset'].button-clear,
+  input[type='submit'].button-clear {
+    background-color: transparent;
+    border-color: transparent;
+    color: #1890ff; }
+    .button.button-clear:focus, .button.button-clear:hover,
+    button.button-clear:focus,
+    button.button-clear:hover,
+    input[type='button'].button-clear:focus,
+    input[type='button'].button-clear:hover,
+    input[type='reset'].button-clear:focus,
+    input[type='reset'].button-clear:hover,
+    input[type='submit'].button-clear:focus,
+    input[type='submit'].button-clear:hover {
+      background-color: transparent;
+      border-color: transparent;
+      color: #4B545C; }
+    .button.button-clear[disabled]:focus, .button.button-clear[disabled]:hover,
+    button.button-clear[disabled]:focus,
+    button.button-clear[disabled]:hover,
+    input[type='button'].button-clear[disabled]:focus,
+    input[type='button'].button-clear[disabled]:hover,
+    input[type='reset'].button-clear[disabled]:focus,
+    input[type='reset'].button-clear[disabled]:hover,
+    input[type='submit'].button-clear[disabled]:focus,
+    input[type='submit'].button-clear[disabled]:hover {
+      color: #1890ff; }
+
+code {
+  background: #f4f5f6;
+  border-radius: .4rem;
+  font-size: 86%;
+  margin: 0 .2rem;
+  padding: 0.8rem 1rem;
+  white-space: normal; }
+
+pre {
+  border-left: 0.3rem solid #1890ff;
+  padding-left: 2rem;
+  background: #f4f5f6;
+  overflow-y: hidden; }
+  pre > code {
+    border-radius: 0;
+    display: block;
+    padding: 1rem 1.5rem;
+    white-space: pre; }
+
+hr {
+  border: 0;
+  border-top: 0.1rem solid #d1d1d1;
+  margin: 3.0rem 0; }
+
+input[type='email'],
+input[type='number'],
+input[type='password'],
+input[type='search'],
+input[type='tel'],
+input[type='text'],
+input[type='url'],
+input[type='color'],
+input[type='date'],
+input[type='month'],
+input[type='week'],
+input[type='datetime'],
+input[type='datetime-local'],
+input:not([type]),
+textarea,
+select {
+  -webkit-appearance: none;
+    -webkit-appearance--moz-appearance: none;
+  appearance: none;
+  background-color: transparent;
+  color: #4B545C;
+  border: 0.1rem solid #d1d1d1;
+  border-radius: .4rem;
+  box-shadow: none;
+  box-sizing: inherit;
+  height: 3.8rem;
+  padding: .6rem 1.0rem;
+  width: 100%; }
+  input[type='email']:focus,
+  input[type='number']:focus,
+  input[type='password']:focus,
+  input[type='search']:focus,
+  input[type='tel']:focus,
+  input[type='text']:focus,
+  input[type='url']:focus,
+  input[type='color']:focus,
+  input[type='date']:focus,
+  input[type='month']:focus,
+  input[type='week']:focus,
+  input[type='datetime']:focus,
+  input[type='datetime-local']:focus,
+  input:not([type]):focus,
+  textarea:focus,
+  select:focus {
+    border-color: #1890ff;
+    outline: 0; }
+
+select {
+  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="%23d1d1d1" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>') center right no-repeat;
+  padding-right: 3.0rem; }
+  select:focus {
+    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="%239b4dca" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>'); }
+
+textarea {
+  min-height: 6.5rem; }
+
+label,
+legend {
+  display: block;
+  font-size: 1.6rem;
+  font-weight: 700;
+  margin-bottom: .5rem; }
+
+fieldset {
+  border-width: 0;
+  padding: 0; }
+
+input[type='checkbox'],
+input[type='radio'] {
+  display: inline; }
+
+.label-inline {
+  display: inline-block;
+  font-weight: normal;
+  margin-left: .5rem; }
+
+a {
+  color: #1890ff;
+  text-decoration: none; }
+  a:focus, a:hover {
+    color: #4B545C; }
+
+dl,
+ol,
+ul {
+  list-style: none;
+  margin-top: 0;
+  padding-left: 3rem; }
+  dl dl,
+  dl ol,
+  dl ul,
+  ol dl,
+  ol ol,
+  ol ul,
+  ul dl,
+  ul ol,
+  ul ul {
+    font-size: 90%;
+    margin: 1.5rem 0 1.5rem 3.0rem; }
+
+ol {
+  list-style: decimal inside;
+  list-style-position: outside; }
+
+ul {
+  list-style: circle inside;
+  list-style-position: outside; }
+
+.button,
+button,
+dd,
+dt,
+li {
+  margin-bottom: 1.0rem; }
+
+fieldset,
+input,
+select,
+textarea {
+  margin-bottom: 1.5rem; }
+
+blockquote,
+dl,
+figure,
+form,
+ol,
+p,
+pre,
+table,
+ul {
+  margin-bottom: 2.5rem; }
+
+table {
+  border-spacing: 0;
+  width: 100%; }
+
+td,
+th {
+  border-bottom: 0.1rem solid #e1e1e1;
+  padding: 1.2rem 1.5rem;
+  text-align: left; }
+  td:first-child,
+  th:first-child {
+    padding-left: 0; }
+  td:last-child,
+  th:last-child {
+    padding-right: 0; }
+
+ at media screen and (max-width: 40rem) {
+  table {
+    border-spacing: 0;
+    display: flex;
+    width: 100%; }
+    table thead {
+      border-right: solid 0.1rem #e1e1e1; }
+      table thead td,
+      table thead th {
+        padding-left: 0; }
+        table thead td:first-child,
+        table thead th:first-child {
+          padding-left: 0; }
+        table thead td:last-child,
+        table thead th:last-child {
+          padding-right: 1.2rem; }
+    table tbody {
+      display: flex;
+      overflow-x: auto;
+      white-space: nowrap; }
+      table tbody tr {
+        border-right: solid 0.1rem #e1e1e1; }
+        table tbody tr:last-child {
+          border-right: none; }
+    table td,
+    table th {
+      display: block; }
+      table td:first-child,
+      table th:first-child {
+        padding-left: 1.2rem; }
+      table td:last-child,
+      table th:last-child {
+        padding-right: 1.2rem; } }
+
+img {
+  max-width: 100%; }
+
+.p-0 {
+  padding: 0; }
+
+.pt-0 {
+  padding-top: 0; }
+
+.pb-0 {
+  padding-bottom: 0; }
+
+.pl-0 {
+  padding-left: 0; }
+
+.pr-0 {
+  padding-right: 0; }
+
+.py-0 {
+  padding-top: 0;
+  padding-bottom: 0; }
+
+.px-0 {
+  padding-left: 0;
+  padding-right: 0; }
+
+.p-1 {
+  padding: 1rem; }
+
+.pt-1 {
+  padding-top: 1rem; }
+
+.pb-1 {
+  padding-bottom: 1rem; }
+
+.pl-1 {
+  padding-left: 1rem; }
+
+.pr-1 {
+  padding-right: 1rem; }
+
+.py-1 {
+  padding-top: 1rem;
+  padding-bottom: 1rem; }
+
+.px-1 {
+  padding-left: 1rem;
+  padding-right: 1rem; }
+
+.p-2 {
+  padding: 2rem; }
+
+.pt-2 {
+  padding-top: 2rem; }
+
+.pb-2 {
+  padding-bottom: 2rem; }
+
+.pl-2 {
+  padding-left: 2rem; }
+
+.pr-2 {
+  padding-right: 2rem; }
+
+.py-2 {
+  padding-top: 2rem;
+  padding-bottom: 2rem; }
+
+.px-2 {
+  padding-left: 2rem;
+  padding-right: 2rem; }
+
+.p-3 {
+  padding: 3rem; }
+
+.pt-3 {
+  padding-top: 3rem; }
+
+.pb-3 {
+  padding-bottom: 3rem; }
+
+.pl-3 {
+  padding-left: 3rem; }
+
+.pr-3 {
+  padding-right: 3rem; }
+
+.py-3 {
+  padding-top: 3rem;
+  padding-bottom: 3rem; }
+
+.px-3 {
+  padding-left: 3rem;
+  padding-right: 3rem; }
+
+.p-4 {
+  padding: 6rem; }
+
+.pt-4 {
+  padding-top: 6rem; }
+
+.pb-4 {
+  padding-bottom: 6rem; }
+
+.pl-4 {
+  padding-left: 6rem; }
+
+.pr-4 {
+  padding-right: 6rem; }
+
+.py-4 {
+  padding-top: 6rem;
+  padding-bottom: 6rem; }
+
+.px-4 {
+  padding-left: 6rem;
+  padding-right: 6rem; }
+
+.p-5 {
+  padding: 8rem; }
+
+.pt-5 {
+  padding-top: 8rem; }
+
+.pb-5 {
+  padding-bottom: 8rem; }
+
+.pl-5 {
+  padding-left: 8rem; }
+
+.pr-5 {
+  padding-right: 8rem; }
+
+.py-5 {
+  padding-top: 8rem;
+  padding-bottom: 8rem; }
+
+.px-5 {
+  padding-left: 8rem;
+  padding-right: 8rem; }
+
+.m-0 {
+  margin: 0; }
+
+.mt-0 {
+  margin-top: 0; }
+
+.mb-0 {
+  margin-bottom: 0; }
+
+.ml-0 {
+  margin-left: 0; }
+
+.mr-0 {
+  margin-right: 0; }
+
+.my-0 {
+  margin-top: 0;
+  margin-bottom: 0; }
+
+.mx-0 {
+  margin-left: 0;
+  margin-right: 0; }
+
+.m-1 {
+  margin: 1rem; }
+
+.mt-1 {
+  margin-top: 1rem; }
+
+.mb-1 {
+  margin-bottom: 1rem; }
+
+.ml-1 {
+  margin-left: 1rem; }
+
+.mr-1 {
+  margin-right: 1rem; }
+
+.my-1 {
+  margin-top: 1rem;
+  margin-bottom: 1rem; }
+
+.mx-1 {
+  margin-left: 1rem;
+  margin-right: 1rem; }
+
+.m-2 {
+  margin: 2rem; }
+
+.mt-2 {
+  margin-top: 2rem; }
+
+.mb-2 {
+  margin-bottom: 2rem; }
+
+.ml-2 {
+  margin-left: 2rem; }
+
+.mr-2 {
+  margin-right: 2rem; }
+
+.my-2 {
+  margin-top: 2rem;
+  margin-bottom: 2rem; }
+
+.mx-2 {
+  margin-left: 2rem;
+  margin-right: 2rem; }
+
+.m-3 {
+  margin: 3rem; }
+
+.mt-3 {
+  margin-top: 3rem; }
+
+.mb-3 {
+  margin-bottom: 3rem; }
+
+.ml-3 {
+  margin-left: 3rem; }
+
+.mr-3 {
+  margin-right: 3rem; }
+
+.my-3 {
+  margin-top: 3rem;
+  margin-bottom: 3rem; }
+
+.mx-3 {
+  margin-left: 3rem;
+  margin-right: 3rem; }
+
+.m-4 {
+  margin: 6rem; }
+
+.mt-4 {
+  margin-top: 6rem; }
+
+.mb-4 {
+  margin-bottom: 6rem; }
+
+.ml-4 {
+  margin-left: 6rem; }
+
+.mr-4 {
+  margin-right: 6rem; }
+
+.my-4 {
+  margin-top: 6rem;
+  margin-bottom: 6rem; }
+
+.mx-4 {
+  margin-left: 6rem;
+  margin-right: 6rem; }
+
+.m-5 {
+  margin: 8rem; }
+
+.mt-5 {
+  margin-top: 8rem; }
+
+.mb-5 {
+  margin-bottom: 8rem; }
+
+.ml-5 {
+  margin-left: 8rem; }
+
+.mr-5 {
+  margin-right: 8rem; }
+
+.my-5 {
+  margin-top: 8rem;
+  margin-bottom: 8rem; }
+
+.mx-5 {
+  margin-left: 8rem;
+  margin-right: 8rem; }
+
+.mx-auto {
+  margin-left: auto;
+  margin-right: auto; }
+
+.text-justify {
+  text-align: justify; }
+
+.text-left {
+  text-align: left; }
+
+.text-center {
+  text-align: center; }
+
+.text-left {
+  text-align: right; }
+
+.text-sm {
+  font-size: 1rem; }
+
+.text-lg {
+  font-size: 2rem; }
+
+.text-xl {
+  font-size: 2.5rem; }
+
+.display-none {
+  display: none; }
+
+.display-inline {
+  display: inline; }
+
+.display-inline-block {
+  display: inline-block; }
+
+.display-block {
+  display: block; }
+
+.display-flex {
+  display: flex; }
+
+.display-inline-flex {
+  display: inline-flex; }
+
+.display-table {
+  display: table; }
+
+.clearfix:after {
+  clear: both;
+  content: ' ';
+  display: table; }
+
+.float-left {
+  float: left; }
+
+.float-right {
+  float: right; }
+
+.container {
+  margin: 0 auto;
+  max-width: 112.0rem;
+  padding: 0 2.0rem;
+  position: relative;
+  width: 100%; }
+
+.row {
+  display: flex;
+  flex-direction: column;
+  padding: 0;
+  width: 100%; }
+  .row.row-no-padding {
+    padding: 0; }
+    .row.row-no-padding > .column {
+      padding: 0; }
+  .row.row-wrap {
+    flex-wrap: wrap; }
+  .row.row-top {
+    align-items: flex-start; }
+  .row.row-bottom {
+    align-items: flex-end; }
+  .row.row-center {
+    align-items: center; }
+  .row.row-stretch {
+    align-items: stretch; }
+  .row.row-baseline {
+    align-items: baseline; }
+  .row .column {
+    display: block;
+    flex: 1 1 auto;
+    margin-left: 0;
+    max-width: 100%;
+    width: 100%; }
+    .row .column.column-offset-10 {
+      margin-left: 10%; }
+    .row .column.column-offset-20 {
+      margin-left: 20%; }
+    .row .column.column-offset-25 {
+      margin-left: 25%; }
+    .row .column.column-offset-33, .row .column.column-offset-34 {
+      margin-left: 33.3333%; }
+    .row .column.column-offset-50 {
+      margin-left: 50%; }
+    .row .column.column-offset-66, .row .column.column-offset-67 {
+      margin-left: 66.6666%; }
+    .row .column.column-offset-75 {
+      margin-left: 75%; }
+    .row .column.column-offset-80 {
+      margin-left: 80%; }
+    .row .column.column-offset-90 {
+      margin-left: 90%; }
+    .row .column.column-10 {
+      flex: 0 0 10%;
+      max-width: 10%; }
+    .row .column.column-20 {
+      flex: 0 0 20%;
+      max-width: 20%; }
+    .row .column.column-25 {
+      flex: 0 0 25%;
+      max-width: 25%; }
+    .row .column.column-33, .row .column.column-34 {
+      flex: 0 0 33.3333%;
+      max-width: 33.3333%; }
+    .row .column.column-40 {
+      flex: 0 0 40%;
+      max-width: 40%; }
+    .row .column.column-50 {
+      flex: 0 0 50%;
+      max-width: 50%; }
+    .row .column.column-60 {
+      flex: 0 0 60%;
+      max-width: 60%; }
+    .row .column.column-66, .row .column.column-67 {
+      flex: 0 0 66.6666%;
+      max-width: 66.6666%; }
+    .row .column.column-75 {
+      flex: 0 0 75%;
+      max-width: 75%; }
+    .row .column.column-80 {
+      flex: 0 0 80%;
+      max-width: 80%; }
+    .row .column.column-90 {
+      flex: 0 0 90%;
+      max-width: 90%; }
+    .row .column .column-top {
+      align-self: flex-start; }
+    .row .column .column-bottom {
+      align-self: flex-end; }
+    .row .column .column-center {
+      align-self: center; }
+
+ at media (min-width: 40rem) {
+  .row {
+    flex-direction: row;
+    margin-left: -1.0rem;
+    width: calc(100% + 2.0rem); }
+    .row .column {
+      margin-bottom: inherit;
+      padding: 0 1.0rem; } }
+
+ at font-face {
+  font-family: 'ico';
+  src: url("../font/ico.eot?13319731");
+  src: url("../font/ico.eot?13319731#iefix") format("embedded-opentype"), url("../font/ico.woff2?13319731") format("woff2"), url("../font/ico.woff?13319731") format("woff"), url("../font/ico.ttf?13319731") format("truetype"), url("../font/ico.svg?13319731#ico") format("svg");
+  font-weight: normal;
+  font-style: normal; }
+
+/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
+/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
+/*
+  @media screen and (-webkit-min-device-pixel-ratio:0) {
+    @font-face {
+      font-family: 'ico';
+      src: url('../font/ico.svg?13319731#ico') format('svg');
+    }
+  }
+  */
+[class^="icon-"]:before, [class*=" icon-"]:before {
+  font-family: "ico";
+  font-style: normal;
+  font-weight: normal;
+  speak: none;
+  display: inline-block;
+  text-decoration: inherit;
+  width: 1em;
+  margin-right: .2em;
+  text-align: center;
+  /* opacity: .8; */
+  /* For safety - reset parent styles, that can break glyph codes*/
+  font-variant: normal;
+  text-transform: none;
+  /* fix buttons height, for twitter bootstrap */
+  line-height: 1em;
+  /* Animation center compensation - margins should be symmetric */
+  /* remove if not needed */
+  margin-left: .2em;
+  /* you can be more comfortable with increased icons size */
+  /* font-size: 120%; */
+  /* Font smoothing. That was taken from TWBS */
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  /* Uncomment for 3D effect */
+  /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ }
+
+/*
+     Animation example, for spinners
+  */
+.animate-spin {
+  -moz-animation: spin 2s infinite linear;
+  -o-animation: spin 2s infinite linear;
+  -webkit-animation: spin 2s infinite linear;
+  animation: spin 2s infinite linear;
+  display: inline-block; }
+
+ at -moz-keyframes spin {
+  0% {
+    -moz-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg); }
+  100% {
+    -moz-transform: rotate(359deg);
+    -o-transform: rotate(359deg);
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg); } }
+
+ at -webkit-keyframes spin {
+  0% {
+    -moz-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg); }
+  100% {
+    -moz-transform: rotate(359deg);
+    -o-transform: rotate(359deg);
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg); } }
+
+ at -o-keyframes spin {
+  0% {
+    -moz-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg); }
+  100% {
+    -moz-transform: rotate(359deg);
+    -o-transform: rotate(359deg);
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg); } }
+
+ at -ms-keyframes spin {
+  0% {
+    -moz-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg); }
+  100% {
+    -moz-transform: rotate(359deg);
+    -o-transform: rotate(359deg);
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg); } }
+
+ at keyframes spin {
+  0% {
+    -moz-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg); }
+  100% {
+    -moz-transform: rotate(359deg);
+    -o-transform: rotate(359deg);
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg); } }
+
+.icon-menu-outline:before {
+  content: '\e800'; }
+
+.icon-github-circled:before {
+  content: '\f09b'; }
+
+.icon-rss:before {
+  content: '\f09e'; }
+
+.icon-menu:before {
+  content: '\f0c9'; }
+
+.icon-spinner:before {
+  content: '\f110'; }
+
+.icon-code:before {
+  content: '\f121'; }
+
+.icon-bitbucket:before {
+  content: '\f171'; }
+
+.icon-circle-notch:before {
+  content: '\f1ce'; }
+
+.icon-github-text:before {
+  content: '\f307'; }
+
+.navbar {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  margin-top: 2rem;
+  padding-left: 0;
+  padding-inline-start: 0; }
+
+.navbar-item {
+  padding: 0.5rem 0.66rem;
+  margin: 0 0.2rem; }
+
+.nav-item-active {
+  border-radius: .4rem;
+  border: 0.1rem solid #1890ff; }
+  .nav-item-active:hover {
+    border-color: #4B545C; }
+
+.navbar-menu {
+  display: none;
+  position: fixed;
+  right: 0;
+  top: 0;
+  z-index: 100;
+  padding: 0.5rem 0.66rem;
+  margin-top: 2rem;
+  margin-right: 2rem;
+  border-radius: 50%;
+  background-color: #fff; }
+
+ at media screen and (max-width: 60rem) {
+  .navbar {
+    justify-content: center; } }
+
+.navbar-smart {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  margin-top: 2rem;
+  padding-left: 0;
+  padding-inline-start: 0; }
+
+ at media screen and (max-width: 60rem) {
+  .navbar-menu-on {
+    display: block; }
+  .navbar-smart {
+    display: none;
+    flex-direction: column;
+    align-items: flex-start;
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 100%;
+    z-index: 100;
+    padding: 1rem;
+    background-color: rgba(255, 255, 255, 0.98); }
+  .navbar-open {
+    display: flex; } }
+
+.shadow {
+  -webkit-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3);
+  -moz-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3);
+  box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3); }
+
+.shadow-lg {
+  -webkit-box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.8);
+  -moz-box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.8);
+  box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.8); }
+
+.active {
+  -webkit-box-shadow: 0px 5px 10px 0px rgba(24, 144, 255, 0.2);
+  -moz-box-shadow: 0px 5px 10px 0px rgba(24, 144, 255, 0.2);
+  box-shadow: 0px 5px 10px 0px rgba(24, 144, 255, 0.2); }
+
+.shadow-secondary {
+  -webkit-box-shadow: 0px 5px 10px 0px rgba(75, 84, 92, 0.2);
+  -moz-box-shadow: 0px 5px 10px 0px rgba(75, 84, 92, 0.2);
+  box-shadow: 0px 5px 10px 0px rgba(75, 84, 92, 0.2); }
+
+.muted {
+  color: #8B9298; }
+
+ at media screen and (max-width: 40rem) {
+  .row .column {
+    text-align: center; } }
+
+.person {
+  min-height: 190px;
+  margin-bottom: 8rem; }
+  .person h3 {
+    margin-bottom: 1rem; }
+  .person img {
+    float: left;
+    max-width: 150px;
+    margin-right: 2rem;
+    margin-bottom: 1rem; }
+  .person p {
+    margin-left: 150px; }
+
+ at media screen and (max-width: 40rem) {
+  .person img {
+    float: none; }
+  .person p {
+    margin-left: 0; } }
+
+.hljs {
+  display: block;
+  overflow-x: auto;
+  padding: 0.5em;
+  color: #9006b3;
+  background: #f4f5f6; }
+
+.hljs-comment,
+.hljs-quote {
+  color: #bbbcc2;
+  font-style: italic; }
+
+.hljs-doctag,
+.hljs-keyword,
+.hljs-formula {
+  color: #dd4600; }
+
+.hljs-section,
+.hljs-name,
+.hljs-selector-tag,
+.hljs-deletion,
+.hljs-subst {
+  color: #e45649; }
+
+.hljs-literal {
+  color: #009c15; }
+
+.hljs-string,
+.hljs-regexp,
+.hljs-addition,
+.hljs-attribute,
+.hljs-meta-string {
+  color: #2e912c; }
+
+.hljs-built_in,
+.hljs-class .hljs-title {
+  color: #c1ae01; }
+
+.hljs-attr,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-type,
+.hljs-selector-class,
+.hljs-selector-attr,
+.hljs-selector-pseudo,
+.hljs-number {
+  color: #b97f00; }
+
+.hljs-symbol,
+.hljs-bullet,
+.hljs-link,
+.hljs-meta,
+.hljs-selector-id,
+.hljs-title {
+  color: #2263f0; }
+
+.hljs-emphasis {
+  font-style: italic; }
+
+.hljs-strong {
+  font-weight: bold; }
+
+.hljs-link {
+  text-decoration: underline; }
diff --git a/themes/pypy/assets/css/styles.min.css b/themes/pypy/assets/css/styles.min.css
new file mode 100644
--- /dev/null
+++ b/themes/pypy/assets/css/styles.min.css
@@ -0,0 +1,1 @@
+/*! sanitize.css v8.0.0 | CC0 License | github.com/csstools/sanitize.css */*,::after,::before{background-repeat:no-repeat;box-sizing:border-box}::after,::before{text-decoration:inherit;vertical-align:inherit}html{cursor:default;font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";line-height:1.15;-moz-tab-size:4;tab-size:4;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;word-break:break-word}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{height:0;overflow:visible}main{display:block}nav ol,nav ul{list-style:none}pre{font-family:Menlo,Consolas,Roboto Mono,Ubuntu Monospace,Noto Mono,Oxygen Mono,Liberation Mono,monospace;font-size:1em}a{background-color:transparent}abbr[title]{text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:Menlo,Consolas,Roboto Mono,Ubuntu Monospace,Noto Mono,Oxygen Mono,Liberation Mono,monospace;font-size:1em}small{font-size:80%}::-moz-selection{background-color:#b3d4fc;color:#000;text-shadow:none}::selection{background-color:#b3d4fc;color:#000;text-shadow:none}audio,canvas,iframe,img,svg,video{vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not([fill]){fill:currentColor}svg:not(:root){overflow:hidden}table{border-collapse:collapse}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}button,input,select{margin:0}button{overflow:visible;text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}fieldset{padding:.35em .75em .625em}input{overflow:visible}legend{color:inherit;display:table;max-width:100%;white-space:normal}progress{display:inline-block;vertical-align:baseline}select{text-transform:none}textarea{margin:0;overflow:auto;resize:vertical}[type=checkbox],[type=radio]{padding:0}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}details{display:block}dialog{background-color:#fff;border:solid;color:#000;display:block;height:-moz-fit-content;height:-webkit-fit-content;height:fit-content;left:0;margin:auto;padding:1em;position:absolute;right:0;width:-moz-fit-content;width:-webkit-fit-content;width:fit-content}dialog:not([open]){display:none}summary{display:list-item}canvas{display:inline-block}template{display:none}[tabindex],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}[hidden]{display:none}[aria-busy=true]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true],[disabled]{cursor:not-allowed}[aria-hidden=false][hidden]:not(:focus){clip:rect(0,0,0,0);display:inherit;position:absolute}/*! Based on https://github.com/milligram/milligram */*,:after,:before{box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{font-size:1.6em;font-weight:300;letter-spacing:.01em;line-height:1.6;background-color:#fcfcfc}body{color:#4b545c;font-family:Roboto,'Helvetica Neue',Helvetica,Arial,sans-serif}b,strong{font-weight:700}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;letter-spacing:-.1rem;margin-bottom:2rem;margin-top:0}h1{font-size:4.6rem;line-height:1.2}h2{font-size:3.6rem;line-height:1.25}h3{font-size:2.8rem;line-height:1.3}h4{font-size:2.2rem;letter-spacing:-.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}blockquote{border-left:.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote :last-child{margin-bottom:0}.button,button,input[type=button],input[type=reset],input[type=submit]{background-color:#1890ff;border:.1rem solid #1890ff;border-radius:.4rem;color:#fcfcfc;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap;-webkit-box-shadow:0 5px 10px 0 rgba(24,144,255,.2);-webkit-box-shadow--moz-box-shadow:0 5px 10px 0 rgba(24,144,255,.2);-webkit-box-shadow-box-shadow:0 5px 10px 0 rgba(24,144,255,.2)}.button:focus,.button:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background-color:#4b545c;border-color:#4b545c;color:#fcfcfc;outline:0;-webkit-box-shadow:0 5px 10px 0 rgba(75,84,92,.2);-webkit-box-shadow--moz-box-shadow:0 5px 10px 0 rgba(75,84,92,.2);-webkit-box-shadow-box-shadow:0 5px 10px 0 rgba(75,84,92,.2)}.button[disabled],button[disabled],input[type=button][disabled],input[type=reset][disabled],input[type=submit][disabled]{cursor:default;opacity:.5}.button[disabled]:focus,.button[disabled]:hover,button[disabled]:focus,button[disabled]:hover,input[type=button][disabled]:focus,input[type=button][disabled]:hover,input[type=reset][disabled]:focus,input[type=reset][disabled]:hover,input[type=submit][disabled]:focus,input[type=submit][disabled]:hover{background-color:#1890ff;border-color:#1890ff}.button.button-outline,button.button-outline,input[type=button].button-outline,input[type=reset].button-outline,input[type=submit].button-outline{background-color:transparent;color:#1890ff}.button.button-outline:focus,.button.button-outline:hover,button.button-outline:focus,button.button-outline:hover,input[type=button].button-outline:focus,input[type=button].button-outline:hover,input[type=reset].button-outline:focus,input[type=reset].button-outline:hover,input[type=submit].button-outline:focus,input[type=submit].button-outline:hover{background-color:transparent;border-color:#4b545c;color:#4b545c}.button.button-outline[disabled]:focus,.button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,button.button-outline[disabled]:hover,input[type=button].button-outline[disabled]:focus,input[type=button].button-outline[disabled]:hover,input[type=reset].button-outline[disabled]:focus,input[type=reset].button-outline[disabled]:hover,input[type=submit].button-outline[disabled]:focus,input[type=submit].button-outline[disabled]:hover{border-color:inherit;color:#1890ff}.button.button-clear,button.button-clear,input[type=button].button-clear,input[type=reset].button-clear,input[type=submit].button-clear{background-color:transparent;border-color:transparent;color:#1890ff}.button.button-clear:focus,.button.button-clear:hover,button.button-clear:focus,button.button-clear:hover,input[type=button].button-clear:focus,input[type=button].button-clear:hover,input[type=reset].button-clear:focus,input[type=reset].button-clear:hover,input[type=submit].button-clear:focus,input[type=submit].button-clear:hover{background-color:transparent;border-color:transparent;color:#4b545c}.button.button-clear[disabled]:focus,.button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,button.button-clear[disabled]:hover,input[type=button].button-clear[disabled]:focus,input[type=button].button-clear[disabled]:hover,input[type=reset].button-clear[disabled]:focus,input[type=reset].button-clear[disabled]:hover,input[type=submit].button-clear[disabled]:focus,input[type=submit].button-clear[disabled]:hover{color:#1890ff}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;margin:0 .2rem;padding:.8rem 1rem;white-space:normal}pre{border-left:.3rem solid #1890ff;padding-left:2rem;background:#f4f5f6;overflow-y:hidden}pre>code{border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:.1rem solid #d1d1d1;margin:3rem 0}input:not([type]),input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=url],input[type=week],select,textarea{-webkit-appearance:none;-webkit-appearance--moz-appearance:none;appearance:none;background-color:transparent;color:#4b545c;border:.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;box-sizing:inherit;height:3.8rem;padding:.6rem 1rem;width:100%}input:not([type]):focus,input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=url]:focus,input[type=week]:focus,select:focus,textarea:focus{border-color:#1890ff;outline:0}select{background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="%23d1d1d1" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>') center right no-repeat;padding-right:3rem}select:focus{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="%239b4dca" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>')}textarea{min-height:6.5rem}label,legend{display:block;font-size:1.6rem;font-weight:700;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type=checkbox],input[type=radio]{display:inline}.label-inline{display:inline-block;font-weight:400;margin-left:.5rem}a{color:#1890ff;text-decoration:none}a:focus,a:hover{color:#4b545c}dl,ol,ul{list-style:none;margin-top:0;padding-left:3rem}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{font-size:90%;margin:1.5rem 0 1.5rem 3rem}ol{list-style:decimal inside;list-style-position:outside}ul{list-style:circle inside;list-style-position:outside}.button,button,dd,dt,li{margin-bottom:1rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}table{border-spacing:0;width:100%}td,th{border-bottom:.1rem solid #e1e1e1;padding:1.2rem 1.5rem;text-align:left}td:first-child,th:first-child{padding-left:0}td:last-child,th:last-child{padding-right:0}@media screen and (max-width:40rem){table{border-spacing:0;display:flex;width:100%}table thead{border-right:solid .1rem #e1e1e1}table thead td,table thead th{padding-left:0}table thead td:first-child,table thead th:first-child{padding-left:0}table thead td:last-child,table thead th:last-child{padding-right:1.2rem}table tbody{display:flex;overflow-x:auto;white-space:nowrap}table tbody tr{border-right:solid .1rem #e1e1e1}table tbody tr:last-child{border-right:none}table td,table th{display:block}table td:first-child,table th:first-child{padding-left:1.2rem}table td:last-child,table th:last-child{padding-right:1.2rem}}img{max-width:100%}.p-0{padding:0}.pt-0{padding-top:0}.pb-0{padding-bottom:0}.pl-0{padding-left:0}.pr-0{padding-right:0}.py-0{padding-top:0;padding-bottom:0}.px-0{padding-left:0;padding-right:0}.p-1{padding:1rem}.pt-1{padding-top:1rem}.pb-1{padding-bottom:1rem}.pl-1{padding-left:1rem}.pr-1{padding-right:1rem}.py-1{padding-top:1rem;padding-bottom:1rem}.px-1{padding-left:1rem;padding-right:1rem}.p-2{padding:2rem}.pt-2{padding-top:2rem}.pb-2{padding-bottom:2rem}.pl-2{padding-left:2rem}.pr-2{padding-right:2rem}.py-2{padding-top:2rem;padding-bottom:2rem}.px-2{padding-left:2rem;padding-right:2rem}.p-3{padding:3rem}.pt-3{padding-top:3rem}.pb-3{padding-bottom:3rem}.pl-3{padding-left:3rem}.pr-3{padding-right:3rem}.py-3{padding-top:3rem;padding-bottom:3rem}.px-3{padding-left:3rem;padding-right:3rem}.p-4{padding:6rem}.pt-4{padding-top:6rem}.pb-4{padding-bottom:6rem}.pl-4{padding-left:6rem}.pr-4{padding-right:6rem}.py-4{padding-top:6rem;padding-bottom:6rem}.px-4{padding-left:6rem;padding-right:6rem}.p-5{padding:8rem}.pt-5{padding-top:8rem}.pb-5{padding-bottom:8rem}.pl-5{padding-left:8rem}.pr-5{padding-right:8rem}.py-5{padding-top:8rem;padding-bottom:8rem}.px-5{padding-left:8rem;padding-right:8rem}.m-0{margin:0}.mt-0{margin-top:0}.mb-0{margin-bottom:0}.ml-0{margin-left:0}.mr-0{margin-right:0}.my-0{margin-top:0;margin-bottom:0}.mx-0{margin-left:0;margin-right:0}.m-1{margin:1rem}.mt-1{margin-top:1rem}.mb-1{margin-bottom:1rem}.ml-1{margin-left:1rem}.mr-1{margin-right:1rem}.my-1{margin-top:1rem;margin-bottom:1rem}.mx-1{margin-left:1rem;margin-right:1rem}.m-2{margin:2rem}.mt-2{margin-top:2rem}.mb-2{margin-bottom:2rem}.ml-2{margin-left:2rem}.mr-2{margin-right:2rem}.my-2{margin-top:2rem;margin-bottom:2rem}.mx-2{margin-left:2rem;margin-right:2rem}.m-3{margin:3rem}.mt-3{margin-top:3rem}.mb-3{margin-bottom:3rem}.ml-3{margin-left:3rem}.mr-3{margin-right:3rem}.my-3{margin-top:3rem;margin-bottom:3rem}.mx-3{margin-left:3rem;margin-right:3rem}.m-4{margin:6rem}.mt-4{margin-top:6rem}.mb-4{margin-bottom:6rem}.ml-4{margin-left:6rem}.mr-4{margin-right:6rem}.my-4{margin-top:6rem;margin-bottom:6rem}.mx-4{margin-left:6rem;margin-right:6rem}.m-5{margin:8rem}.mt-5{margin-top:8rem}.mb-5{margin-bottom:8rem}.ml-5{margin-left:8rem}.mr-5{margin-right:8rem}.my-5{margin-top:8rem;margin-bottom:8rem}.mx-5{margin-left:8rem;margin-right:8rem}.mx-auto{margin-left:auto;margin-right:auto}.text-justify{text-align:justify}.text-left{text-align:left}.text-center{text-align:center}.text-left{text-align:right}.text-sm{font-size:1rem}.text-lg{font-size:2rem}.text-xl{font-size:2.5rem}.display-none{display:none}.display-inline{display:inline}.display-inline-block{display:inline-block}.display-block{display:block}.display-flex{display:flex}.display-inline-flex{display:inline-flex}.display-table{display:table}.clearfix:after{clear:both;content:' ';display:table}.float-left{float:left}.float-right{float:right}.container{margin:0 auto;max-width:112rem;padding:0 2rem;position:relative;width:100%}.row{display:flex;flex-direction:column;padding:0;width:100%}.row.row-no-padding{padding:0}.row.row-no-padding>.column{padding:0}.row.row-wrap{flex-wrap:wrap}.row.row-top{align-items:flex-start}.row.row-bottom{align-items:flex-end}.row.row-center{align-items:center}.row.row-stretch{align-items:stretch}.row.row-baseline{align-items:baseline}.row .column{display:block;flex:1 1 auto;margin-left:0;max-width:100%;width:100%}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}.row .column .column-top{align-self:flex-start}.row .column .column-bottom{align-self:flex-end}.row .column .column-center{align-self:center}@media (min-width:40rem){.row{flex-direction:row;margin-left:-1rem;width:calc(100% + 2rem)}.row .column{margin-bottom:inherit;padding:0 1rem}}@font-face{font-family:ico;src:url(../font/ico.eot?13319731);src:url(../font/ico.eot?13319731#iefix) format("embedded-opentype"),url(../font/ico.woff2?13319731) format("woff2"),url(../font/ico.woff?13319731) format("woff"),url(../font/ico.ttf?13319731) format("truetype"),url(../font/ico.svg?13319731#ico) format("svg");font-weight:400;font-style:normal}[class*=" icon-"]:before,[class^=icon-]:before{font-family:ico;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.animate-spin{-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear;display:inline-block}@-moz-keyframes spin{0%{-moz-transform:rotate(0);-o-transform:rotate(0);-webkit-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-moz-transform:rotate(0);-o-transform:rotate(0);-webkit-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-o-keyframes spin{0%{-moz-transform:rotate(0);-o-transform:rotate(0);-webkit-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-ms-keyframes spin{0%{-moz-transform:rotate(0);-o-transform:rotate(0);-webkit-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-moz-transform:rotate(0);-o-transform:rotate(0);-webkit-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.icon-menu-outline:before{content:'\e800'}.icon-github-circled:before{content:'\f09b'}.icon-rss:before{content:'\f09e'}.icon-menu:before{content:'\f0c9'}.icon-spinner:before{content:'\f110'}.icon-code:before{content:'\f121'}.icon-bitbucket:before{content:'\f171'}.icon-circle-notch:before{content:'\f1ce'}.icon-github-text:before{content:'\f307'}.navbar{display:flex;flex-wrap:wrap;justify-content:space-between;margin-top:2rem;padding-left:0;padding-inline-start:0}.navbar-item{padding:.5rem .66rem;margin:0 .2rem}.nav-item-active{border-radius:.4rem;border:.1rem solid #1890ff}.nav-item-active:hover{border-color:#4b545c}.navbar-menu{display:none;position:fixed;right:0;top:0;z-index:100;padding:.5rem .66rem;margin-top:2rem;margin-right:2rem;border-radius:50%;background-color:#fff}@media screen and (max-width:60rem){.navbar{justify-content:center}}.navbar-smart{display:flex;flex-wrap:wrap;justify-content:space-between;margin-top:2rem;padding-left:0;padding-inline-start:0}@media screen and (max-width:60rem){.navbar-menu-on{display:block}.navbar-smart{display:none;flex-direction:column;align-items:flex-start;position:fixed;left:0;top:0;width:100%;z-index:100;padding:1rem;background-color:rgba(255,255,255,.98)}.navbar-open{display:flex}}.shadow{-webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.3);-moz-box-shadow:0 5px 10px 0 rgba(0,0,0,.3);box-shadow:0 5px 10px 0 rgba(0,0,0,.3)}.shadow-lg{-webkit-box-shadow:0 10px 20px 0 rgba(0,0,0,.8);-moz-box-shadow:0 10px 20px 0 rgba(0,0,0,.8);box-shadow:0 10px 20px 0 rgba(0,0,0,.8)}.shadow-primary{-webkit-box-shadow:0 5px 10px 0 rgba(24,144,255,.2);-moz-box-shadow:0 5px 10px 0 rgba(24,144,255,.2);box-shadow:0 5px 10px 0 rgba(24,144,255,.2)}.shadow-secondary{-webkit-box-shadow:0 5px 10px 0 rgba(75,84,92,.2);-moz-box-shadow:0 5px 10px 0 rgba(75,84,92,.2);box-shadow:0 5px 10px 0 rgba(75,84,92,.2)}.muted{color:#8b9298}@media screen and (max-width:40rem){.row .column{text-align:center}}.person{min-height:190px;margin-bottom:8rem}.person h3{margin-bottom:1rem}.person img{float:left;max-width:150px;margin-right:2rem;margin-bottom:1rem}.person p{margin-left:150px}@media screen and (max-width:40rem){.person img{float:none}.person p{margin-left:0}}.hljs{display:block;overflow-x:auto;padding:.5em;color:#9006b3;background:#f4f5f6}.hljs-comment,.hljs-quote{color:#bbbcc2;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#dd4600}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e45649}.hljs-literal{color:#009c15}.hljs-addition,.hljs-attribute,.hljs-meta-string,.hljs-regexp,.hljs-string{color:#2e912c}.hljs-built_in,.hljs-class .hljs-title{color:#c1ae01}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#b97f00}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#2263f0}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
\ No newline at end of file
diff --git a/themes/pypy/assets/fonts/LICENSE.txt b/themes/pypy/assets/fonts/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/themes/pypy/assets/fonts/LICENSE.txt
@@ -0,0 +1,30 @@
+Font license info
+
+
+## Typicons
+
+   (c) Stephen Hutchings 2012
+
+   Author:    Stephen Hutchings
+   License:   SIL (http://scripts.sil.org/OFL)
+   Homepage:  http://typicons.com/
+
+
+## Font Awesome
+
+   Copyright (C) 2016 by Dave Gandy
+
+   Author:    Dave Gandy
+   License:   SIL ()
+   Homepage:  http://fortawesome.github.com/Font-Awesome/
+
+
+## Brandico
+
+   (C) 2012 by Vitaly Puzrin
+
+   Author:    Crowdsourced, for Fontello project
+   License:   SIL (http://scripts.sil.org/OFL)
+   Homepage:  
+
+
diff --git a/themes/pypy/assets/fonts/ico.eot b/themes/pypy/assets/fonts/ico.eot
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9be00157fd7c5d5ae45005c33da9417fea83df46
GIT binary patch

[cut]

diff --git a/themes/pypy/assets/fonts/ico.svg b/themes/pypy/assets/fonts/ico.svg
new file mode 100644
--- /dev/null
+++ b/themes/pypy/assets/fonts/ico.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>Copyright (C) 2019 by original authors @ fontello.com</metadata>
+<defs>
+<font id="ico" horiz-adv-x="1000" >
+<font-face font-family="ico" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
+<missing-glyph horiz-adv-x="1000" />
+<glyph glyph-name="menu-outline" unicode="&#xe800;" d="M885 38l-729 0q-21 0-37-16t-15-37 15-36 37-15l729 0q21 0 37 15t16 36-16 37-37 16z m0 104q65 0 111-46t45-111-45-110-111-46l-729 0q-65 0-110 46t-46 110 46 111 110 46l729 0z m0 261l-729 0q-21 0-37-16t-15-37 15-37 37-15l729 0q21 0 37 15t16 37-16 37-37 16z m0 104q65 0 111-46t45-111-45-110-111-46l-729 0q-65 0-110 46t-46 110 46 111 110 46l729 0z m0 260l-729 0q-21 0-37-15t-15-37 15-37 37-15l729 0q21 0 37 15t16 37-16 37-37 15z m0 105q65 0 111-46t45-111-45-110-111-46l-729 0q-65 0-110 46t-46 110 46 111 110 46l729 0z" horiz-adv-x="1041" />
+
+<glyph glyph-name="github-circled" unicode="&#xf09b;" d="M429 779q116 0 215-58t156-156 57-215q0-140-82-252t-211-155q-15-3-22 4t-7 17q0 1 0 43t0 75q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 67-44 115 21 51-4 114-16 5-46-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-47 7q-25-63-5-114-44-48-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-21-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l6-13q7-21 24-34t37-17 39-3 31 1l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58z m-267-616q2 4-3 7-6 1-8-1-1-4 4-7 5-3 7 1z m18-19q4 3-1 9-6 5-9 2-4-3 1-9 5-6 9-2z m16-25q6 4 0 11-4 7-9 3-5-3 0-10t9-4z m24-23q4 4-2 10-7 7-11 2-5-5 2-11 6-6 11-1z m32-14q1 6-8 9-8 2-10-4t7-9q8-3 11 4z m35-3q0 7-10 6-9 0-9-6 0-7 10-6 9 0 9 6z m32 5q-1 7-10 5-9-1-8-8t10-4 8 7z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="rss" unicode="&#xf09e;" d="M214 100q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m286-69q1-15-9-26-10-12-27-12h-75q-14 0-24 9t-11 23q-12 128-103 219t-219 103q-14 1-23 11t-9 24v75q0 16 12 26 9 10 24 10h3q89-7 170-45t145-101q63-63 101-145t45-171z m286-1q1-15-10-26-10-11-26-11h-80q-14 0-25 10t-10 23q-7 120-57 228t-129 188-188 129-227 57q-14 1-24 11t-10 24v80q0 16 11 26 10 10 25 10h1q147-8 280-67t238-164q104-104 164-238t67-280z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="menu" unicode="&#xf0c9;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="spinner" unicode="&#xf110;" d="M294 72q0-29-21-50t-51-21q-29 0-50 21t-21 50q0 30 21 51t50 21 51-21 21-51z m277-115q0-29-20-50t-51-21-50 21-21 50 21 51 50 21 51-21 20-51z m-392 393q0-30-21-50t-51-21-50 21-21 50 21 51 50 20 51-20 21-51z m670-278q0-29-21-50t-50-21q-30 0-51 21t-20 50 20 51 51 21 50-21 21-51z m-538 556q0-37-26-63t-63-26-63 26-26 63 26 63 63 26 63-26 26-63z m653-278q0-30-21-50t-50-21-51 21-21 50 21 51 51 20 50-20 21-51z m-357 393q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m296-115q0-52-37-88t-88-37q-52 0-88 37t-37 88q0 51 37 88t88 37q51 0 88-37t37-88z" horiz-adv-x="1000" />
+
+<glyph glyph-name="code" unicode="&#xf121;" d="M344 69l-28-28q-5-5-12-5t-13 5l-260 261q-6 5-6 12t6 13l260 260q5 6 13 6t12-6l28-28q6-5 6-13t-6-12l-219-220 219-219q6-6 6-13t-6-13z m330 596l-208-721q-2-7-9-11t-13-1l-34 9q-8 3-11 9t-2 14l209 720q2 8 8 11t13 2l35-10q7-2 11-9t1-13z m367-363l-260-261q-6-5-13-5t-13 5l-28 28q-5 6-5 13t5 13l219 219-219 220q-5 5-5 12t5 13l28 28q6 6 13 6t13-6l260-260q5-5 5-13t-5-12z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="bitbucket" unicode="&#xf171;" d="M455 371q4-35-28-57t-63-3q-21 9-29 32t-1 46 29 32q20 11 41 7t36-20 15-37z m62 11q-8 60-63 92t-110 7q-35-15-56-49t-20-72q3-51 44-87t92-31q51 4 85 47t28 93z m133 303q-11 15-31 25t-32 12-40 7q-162 26-316-1-24-4-37-7t-30-12-28-24q16-16 42-26t41-12 49-6q127-16 250-1 35 5 50 7t40 12 42 26z m32-578q-4-14-9-42t-7-47-16-39-33-32q-48-27-106-40t-112-12-113 10q-25 5-45 10t-43 15-41 25-29 34q-14 54-31 163l3 9 10 5q124-83 283-83t283 83q12-3 13-13t-3-25-4-21z m101 537q-15-94-62-366-3-17-15-31t-24-23-31-17q-140-70-340-49-139 15-220 78-8 6-14 14t-10 20-5 19-3 22-3 20q-5 27-15 83t-16 90-13 83-12 88q2 14 10 27t17 21 26 17 25 12 27 10q70 26 175 36 211 21 377-28 86-25 120-68 9-11 9-28t-3-30z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="circle-notch" unicode="&#xf1ce;" d="M982 350q0-98-38-187t-103-154-153-103-188-38-187 38-154 103-103 154-38 187q0 119 54 222t148 171 209 84v-127q-124-25-205-123t-81-227q0-72 28-139t77-113 113-77 139-28 139 28 114 77 76 113 28 139q0 128-81 227t-205 123v127q115-17 209-84t148-171 54-222z" horiz-adv-x="1000" />
+
+<glyph glyph-name="github-text" unicode="&#xf307;" d="M527 850c-21 0-39-8-54-24-15-16-22-35-22-58 0-22 7-41 22-57 15-16 33-24 54-24 20 0 38 8 53 24 15 16 22 35 22 57 0 23-7 42-22 58-15 16-33 24-53 24z m164-156c2-13 3-29 3-49l0-43-53 0 0-106c15 2 27 3 37 3l16-1 0-2-1 0 0-196c0-61 8-106 23-134 20-38 57-57 110-57 38 0 71 7 98 22l0 109c-18-12-39-19-61-19-33 0-49 25-49 74l0 203 47 0c9 0 19 0 28-1 10-1 17-1 21-1l0 106-96 0 0 45c0 17 2 33 4 47l-127 0 0 0z m-501-87c-49 0-92-16-128-49-37-35-55-79-55-131 0-35 10-68 30-98 18-29 39-47 63-55l0-2c-24-10-35-36-35-77 0-31 12-54 37-70l0-2c-68-23-102-64-102-126 0-53 23-92 68-117 36-19 81-29 136-29 135 0 203 56 203 169 0 71-52 114-157 130-24 4-42 13-54 27-10 9-14 19-14 28 0 27 14 43 43 47 45 7 81 27 109 62 28 34 42 75 42 122 0 14-3 30-9 47 19 4 34 8 44 12l0 112c-46-17-86-26-121-26-31 18-64 26-100 26l0 0z m275-5c1-13 2-37 2-71l0-340c0-35-1-60-2-74l123 0c-1 16-2 43-2 80l0 336c0 32 1 55 2 69l-123 0z m-270-95c22 0 39-9 51-25 10-16 15-34 15-55 0-51-22-77-66-77-46 0-69 26-69 76 0 54 23 81 69 81z m7-445c62 0 92-19 92-56 0-39-28-59-84-59-64 0-96 19-96 57 0 39 29 58 88 58l0 0z" horiz-adv-x="924" />
+</font>
+</defs>
+</svg>
\ No newline at end of file
diff --git a/themes/pypy/assets/fonts/ico.ttf b/themes/pypy/assets/fonts/ico.ttf
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f1f9a002caadb4bbdce52838a486b42a2e06afee
GIT binary patch

[cut]

diff --git a/themes/pypy/assets/fonts/ico.woff b/themes/pypy/assets/fonts/ico.woff
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9c26d205664af8aa2ebc6ab7d7671d7cfc064377
GIT binary patch

[cut]

diff --git a/themes/pypy/assets/fonts/ico.woff2 b/themes/pypy/assets/fonts/ico.woff2
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bcadeef9cac1ee1931ae4be92a9ba11a8a4d8fe6
GIT binary patch

[cut]

diff --git a/themes/pypy/assets/js/styles.js b/themes/pypy/assets/js/styles.js
new file mode 100644
--- /dev/null
+++ b/themes/pypy/assets/js/styles.js
@@ -0,0 +1,43 @@
+'use strict';
+
+// Navbar
+(function () {
+    // Swap simple navbar for smart navbar
+    function swapNavbars() {
+        var navbars = document.getElementsByClassName("js-navbar");
+        [].forEach.call(navbars, function (navbar) {
+            if (navbar.classList.contains("navbar")) {
+                navbar.classList.remove("navbar");
+                navbar.classList.add("navbar-smart");
+                // also turn on the menu button
+                var menuButtons = navbar.parentNode.getElementsByClassName("js-navbar-toggler");
+                [].forEach.call(menuButtons, function (menuButton) {
+                    menuButton.classList.add("navbar-menu-on");
+                });
+            }
+        });
+    }
+
+    // Add event to show or hide the navbar menu when icon is clicked
+    function toggleNavbarMenu() {
+        var navbars = document.getElementsByClassName("js-navbar");
+
+        [].forEach.call(navbars, function (navbar) {
+            // only works with "navbar-smart"
+            if (navbar.classList.contains("navbar-smart")) {
+                var menuButtons = navbar.parentNode.getElementsByClassName("js-navbar-toggler");
+                [].forEach.call(menuButtons, function (menuButton) {
+                    menuButton.addEventListener('click', function (e) {
+                        e.preventDefault();
+                        var related_navbar = navbar;
+                        related_navbar.classList.toggle('navbar-open');
+                    });
+                });
+            }
+        });
+    }
+    document.addEventListener("DOMContentLoaded", function () {
+        swapNavbars();
+        toggleNavbarMenu();
+    });
+})();
diff --git a/themes/pypy/bundles b/themes/pypy/bundles
--- a/themes/pypy/bundles
+++ b/themes/pypy/bundles
@@ -4,11 +4,13 @@
     nikola_rst.css,
     code.css,
     theme.css,
+    styles.css,
 assets/css/all-nocdn.css=
     rst_base.css,
     nikola_rst.css,
     code.css,
     theme.css,
+    styles.css,
 
 ; javascript bundles
 assets/js/all.js=
diff --git a/themes/pypy/pypy.theme b/themes/pypy/pypy.theme
--- a/themes/pypy/pypy.theme


More information about the pypy-commit mailing list